Skip to content

Commit

Permalink
feat: umi blocks
Browse files Browse the repository at this point in the history
feat: umi blocks
  • Loading branch information
xiaohuoni authored Dec 8, 2023
2 parents 8ebc292 + c464bfd commit 5f3a898
Show file tree
Hide file tree
Showing 21 changed files with 16,065 additions and 10,495 deletions.
7 changes: 7 additions & 0 deletions examples/alita/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ import { defineConfig } from 'alita';

export default defineConfig({
presets: [require.resolve('@mongchhi/preset-mongchhi')],
plugins: [require.resolve('@mongchhi/plugin-blocks')],
appType: 'h5',
keepalive: [/users/],
aconsole: {
console: {},
inspx: {},
},
mobileLayout: 'mobile5',
block: {
defaultGitUrl: 'https://github.com/ant-design/pro-blocks',
npmClient: 'pnpm',
closeFastGithub: true,
homedir: false,
},
mfsu: false,
hash: false,
});
5 changes: 5 additions & 0 deletions examples/alita/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@
"name": "@examples/alita",
"private": true,
"scripts": {
"block": "alita block add https://github.com/ant-design/pro-blocks/tree/feat-antd5/UserRegister --path=/user/register --skip-dependencies --page --branch=feat-antd5 --skip-modify-routes",
"build": "alita build",
"dev": "alita dev",
"start": "alita dev"
},
"dependencies": {
"@alita/flow": "*",
"@mongchhi/plugin-blocks": "workspace:*",
"@mongchhi/preset-mongchhi": "workspace:*",
"alita": "^3.3.7",
"antd-mobile": "^5.15.1",
"classnames": "^2.2.6",
"moment": "^2.22.2",
"nzh": "^1.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
Expand Down
18 changes: 18 additions & 0 deletions examples/alita/src/pages/asd/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Button, Result } from 'antd';
import { Link } from 'umi';

export default () => (
<Result
status="403"
title="403"
style={{
background: 'none',
}}
subTitle="Sorry, you don't have access to this page."
extra={
<Link to="/">
<Button type="primary">Back to home</Button>
</Link>
}
/>
);
10 changes: 10 additions & 0 deletions examples/alita/src/pages/user/register/_mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @ts-nocheck
import type { Request, Response } from 'express';

export default {
'POST /api/register': (_: Request, res: Response) => {
res.send({
data: { status: 'ok', currentAuthority: 'user' },
});
},
};
306 changes: 306 additions & 0 deletions examples/alita/src/pages/user/register/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
import {
Button,
Col,
Form,
Input,
message,
Popover,
Progress,
Row,
Select,
} from 'antd';
import type { Store } from 'antd/es/form/interface';
import type { FC } from 'react';
import { useEffect, useState } from 'react';
import { history, Link, useRequest } from 'umi';
import type { StateType } from './service';
import { fakeRegister } from './service';

import useStyles from './style.style';

const FormItem = Form.Item;
const { Option } = Select;
const InputGroup = Input.Group;

const passwordProgressMap: {
ok: 'success';
pass: 'normal';
poor: 'exception';
} = {
ok: 'success',
pass: 'normal',
poor: 'exception',
};

const Register: FC = () => {
const { styles } = useStyles();

const passwordStatusMap = {
ok: (
<div className={styles.success}>
<span>强度:强</span>
</div>
),

pass: (
<div className={styles.warning}>
<span>强度:中</span>
</div>
),

poor: (
<div className={styles.error}>
<span>强度:太短</span>
</div>
),
};
const [count, setCount]: [number, any] = useState(0);
const [visible, setVisible]: [boolean, any] = useState(false);
const [prefix, setPrefix]: [string, any] = useState('86');
const [popover, setPopover]: [boolean, any] = useState(false);
const confirmDirty = false;
let interval: number | undefined;
const [form] = Form.useForm();

useEffect(
() => () => {
clearInterval(interval);
},
[interval],
);

const onGetCaptcha = () => {
let counts = 59;
setCount(counts);
interval = window.setInterval(() => {
counts -= 1;
setCount(counts);
if (counts === 0) {
clearInterval(interval);
}
}, 1000);
};

const getPasswordStatus = () => {
const value = form.getFieldValue('password');
if (value && value.length > 9) {
return 'ok';
}
if (value && value.length > 5) {
return 'pass';
}
return 'poor';
};

const { loading: submitting, run: register } = useRequest<{
data: StateType;
}>(fakeRegister, {
manual: true,
onSuccess: (data, params) => {
if (data.status === 'ok') {
message.success('注册成功!');
history.push({
pathname: `/user/register-result?account=${params.email}`,
});
}
},
});
const onFinish = (values: Store) => {
register(values);
};

const checkConfirm = (_: any, value: string) => {
const promise = Promise;
if (value && value !== form.getFieldValue('password')) {
return promise.reject('两次输入的密码不匹配!');
}
return promise.resolve();
};

const checkPassword = (_: any, value: string) => {
const promise = Promise;
// 没有值的情况
if (!value) {
setVisible(!!value);
return promise.reject('请输入密码!');
}
// 有值的情况
if (!visible) {
setVisible(!!value);
}
setPopover(!popover);
if (value.length < 6) {
return promise.reject('');
}
if (value && confirmDirty) {
form.validateFields(['confirm']);
}
return promise.resolve();
};

const changePrefix = (value: string) => {
setPrefix(value);
};

const renderPasswordProgress = () => {
const value = form.getFieldValue('password');
const passwordStatus = getPasswordStatus();
return value && value.length ? (
// @ts-ignore
<div className={styles[`progress-${passwordStatus}`]}>
<Progress
status={passwordProgressMap[passwordStatus]}
strokeWidth={6}
percent={value.length * 10 > 100 ? 100 : value.length * 10}
showInfo={false}
/>
</div>
) : null;
};

return (
<div className={styles.main}>
<h3>注册</h3>
<Form form={form} name="UserRegister" onFinish={onFinish}>
<FormItem
name="mail"
rules={[
{
required: true,
message: '请输入邮箱地址!',
},
{
type: 'email',
message: '邮箱地址格式错误!',
},
]}
>
<Input size="large" placeholder="邮箱" />
</FormItem>
<Popover
getPopupContainer={(node) => {
if (node && node.parentNode) {
return node.parentNode as HTMLElement;
}
return node;
}}
content={
visible && (
<div style={{ padding: '4px 0' }}>
{passwordStatusMap[getPasswordStatus()]}
{renderPasswordProgress()}
<div style={{ marginTop: 10 }}>
<span>请至少输入 6 个字符。请不要使用容易被猜到的密码。</span>
</div>
</div>
)
}
overlayStyle={{ width: 240 }}
placement="right"
visible={visible}
>
<FormItem
name="password"
className={
form.getFieldValue('password') &&
form.getFieldValue('password').length > 0 &&
styles.password
}
rules={[
{
validator: checkPassword,
},
]}
>
<Input
size="large"
type="password"
placeholder="至少6位密码,区分大小写"
/>
</FormItem>
</Popover>
<FormItem
name="confirm"
rules={[
{
required: true,
message: '确认密码',
},
{
validator: checkConfirm,
},
]}
>
<Input size="large" type="password" placeholder="确认密码" />
</FormItem>
<InputGroup compact>
<Select
size="large"
value={prefix}
onChange={changePrefix}
style={{ width: '20%' }}
>
<Option value="86">+86</Option>
<Option value="87">+87</Option>
</Select>
<FormItem
style={{ width: '80%' }}
name="mobile"
rules={[
{
required: true,
message: '请输入手机号!',
},
{
pattern: /^\d{11}$/,
message: '手机号格式错误!',
},
]}
>
<Input size="large" placeholder="手机号" />
</FormItem>
</InputGroup>
<Row gutter={8}>
<Col span={16}>
<FormItem
name="captcha"
rules={[
{
required: true,
message: '请输入验证码!',
},
]}
>
<Input size="large" placeholder="验证码" />
</FormItem>
</Col>
<Col span={8}>
<Button
size="large"
disabled={!!count}
className={styles.getCaptcha}
onClick={onGetCaptcha}
>
{count ? `${count} s` : '获取验证码'}
</Button>
</Col>
</Row>
<FormItem>
<Button
size="large"
loading={submitting}
className={styles.submit}
type="primary"
htmlType="submit"
>
<span>注册</span>
</Button>
<Link className={styles.login} to="/user/login">
<span>使用已有账户登录</span>
</Link>
</FormItem>
</Form>
</div>
);
};
export default Register;
Loading

0 comments on commit 5f3a898

Please sign in to comment.