添加框架内容

This commit is contained in:
linxd
2025-06-16 16:22:26 +08:00
parent 1eabd737a6
commit c7b9ffac10
37 changed files with 2328 additions and 41 deletions

View File

@ -0,0 +1,8 @@
import React from 'react';
import { useLocation } from 'umi';
const AnnounceInfo: React.FC = () => {
const location = useLocation();
const id = new URLSearchParams(location.search).get("id")
return <>AnnounceInfo -------- {id}</>;
};
export default AnnounceInfo;

17
src/pages/index/Link.tsx Normal file
View File

@ -0,0 +1,17 @@
import React from 'react';
const LinkComponent: React.FC = () => {
return (
<div className="link">
<div></div>
<div className="flex">
<a href="https://www.baidu.com"></a>
<a href="https://www.baidu.com"></a>
<a href="https://www.baidu.com"></a>
<a href="https://www.baidu.com"></a>
<a href="https://www.baidu.com"></a>
</div>
</div>
);
};
export default LinkComponent;

View File

@ -0,0 +1,53 @@
@import '../../baseStyle.less';
.lastDate {
color: @main-danger-color;
}
.tableAddress {
color: @main-color;
font-weight: 600;
}
.tableLoadMore {
margin-top: 15px;
text-align: center;
}
.blockTitle {
font-weight: 600;
font-size: 16px;
line-height: 30px;
}
.questionItem {
line-height: 40px;
.icon {
margin-right: 10px;
font-size: 18px;
}
}
.cardContent {
color: @main-text-color-2;
}
.card {
.ant-card-head {
min-height: 40px;
padding: 0 15px;
.ant-card-head-title,
.ant-card-extra {
padding: 10px 0;
}
}
.ant-card-body {
min-height: 150px;
text-indent: 26px;
}
}
.link {
display: flex;
margin-top: 10px;
.flex {
margin-left: 10px;
display: flex;
flex: 1;
a{
margin: 0 10px;
}
}
}

View File

@ -1,10 +1,247 @@
import React, { useState } from 'react';
import { Card, Row, Col, Tabs, Table } from 'antd';
import { useIntl, Link } from 'umi';
import SpaceBlock from '@/components/SpaceBlock/SpaceBlock';
import './index.less';
import IconFont from '@/components/IconFont/IconFont';
import LinkComponent from './Link';
const IndexPage: React.FC = () => {
const intl = useIntl();
const [noticeLoading, setNoticeLoading] = useState(false);
const [noticeList, setNoticeList] = useState([
{
title: 'CA使用通知',
id: '1',
content: '系统将于2022年5月27日期开始对全流程使用CA服务届时全部投标供应商需办理CA。',
},
{
title: '5月27日系统优化升级通知',
id: '2',
content:
'系统将于2022年5月27日周五22:00--2022年5月28日周六6:00进行系统优化升级届时系统将暂停服务。',
},
{
title: '测试标题123123',
id: '3',
content: '测试内容124145',
},
{
title: '测试标题45435',
id: '4',
content: '测试内容6666',
},
]);
const tabList = [
{
key: '1',
label: intl.formatMessage({ id: '采购需求公示' }),
},
{
key: '2',
label: intl.formatMessage({ id: '招标采购公告' }),
},
{
key: '3',
label: intl.formatMessage({ id: '非招标采购公告' }),
},
{
key: '4',
label: intl.formatMessage({ id: '资格预审公告' }),
},
{
key: '5',
label: intl.formatMessage({ id: '招募公告' }),
},
{
key: '6',
label: intl.formatMessage({ id: '变更公告' }),
},
{
key: '7',
label: intl.formatMessage({ id: '中标(中选)候选人公示' }),
},
{
key: '8',
label: intl.formatMessage({ id: '中标(中选)结果公示' }),
},
{
key: '9',
label: intl.formatMessage({ id: '采购失败(流标)公告' }),
},
];
//tab 切换事件
const tabChange = (key: string) => {
console.log(key);
};
const [tableLoading, setTableLoading] = useState(false);
const dataSource = [
{
key: '1',
title: '中远海运空运北方物流基地标识制作及安装服务',
address: '西湖区湖底公园1号',
date: '2025年01月23日',
lastDate: '剩余3天4小时',
},
{
key: '2',
title: '中远海运空运北方物流基地标识制作及安装服务',
address: '西湖区湖底公园1号',
date: '2025年01月23日',
lastDate: '剩余3天4小时',
},
{
key: '2',
title: '中远海运空运北方物流基地标识制作及安装服务',
address: '西湖区湖底公园1号',
date: '2025年01月23日',
lastDate: '剩余3天4小时',
},
{
key: '2',
title: '中远海运空运北方物流基地标识制作及安装服务',
address: '西湖区湖底公园1号',
date: '2025年01月23日',
lastDate: '剩余3天4小时',
},
{
key: '2',
title: '中远海运空运北方物流基地标识制作及安装服务',
address: '西湖区湖底公园1号',
date: '2025年01月23日',
lastDate: '剩余3天4小时',
},
{
key: '2',
title: '中远海运空运北方物流基地标识制作及安装服务',
address: '西湖区湖底公园1号',
date: '2025年01月23日',
lastDate: '剩余3天4小时',
},
];
const columns = [
{
title: '项目所在地',
dataIndex: 'address',
key: 'address',
},
{
title: '公告标题',
dataIndex: 'title',
key: 'title',
render: (text: string, record) => (
<Link
to={{
pathname: '/announce/announceInfo',
search: '?id=' + record.id,
}}
>
{text}
</Link>
),
},
{
title: '发布时间',
dataIndex: 'date',
key: 'date',
},
{
title: '文件购买截止时间',
dataIndex: 'lastDate',
key: 'lastDate',
render: (text: string) => <span className="lastDate">{text}</span>,
},
];
import React from 'react';
const IndexPage:React.FC = () => {
return (
<div>IndexPage</div>
)
}
<div>
{/* 通知列表 */}
<Row gutter={20}>
{noticeList.map((item) => (
<Col span={6} key={item.id}>
<Card
title={item.title}
loading={noticeLoading}
hoverable
className="card"
bodyStyle={{ padding: 10 }}
extra={
<Link
to={{
pathname: '/notice/noticeInfo',
search: '?id=' + item.id,
}}
>
{intl.formatMessage({ id: '查看' })}
</Link>
}
>
<p className="cardContent">{item.content}</p>
</Card>
</Col>
))}
</Row>
<SpaceBlock />
<Tabs onChange={tabChange}>
{tabList.map((item) => (
<Tabs.TabPane tab={item.label} key={item.key} />
))}
</Tabs>
<Table loading={tableLoading} dataSource={dataSource} columns={columns} pagination={false} />
export default IndexPage;
<div className="tableLoadMore">
<Link
to={{
pathname: '/announce',
}}
>
{intl.formatMessage({ id: '加载更多' })}
</Link>
</div>
<Row style={{ marginTop: '20px' }}>
<Col span={12}>
<div className="blockTitle"></div>
<img src="" alt="" />
<div className="questionItem">
<IconFont type="icon-dizhi" className="icon" />
173
</div>
<div className="questionItem">
<IconFont type="icon-dianhua" className="icon" />
17676373746
</div>
<div className="questionItem">
<IconFont type="icon-youxiang" className="icon" />
i723648723@383.com
</div>
</Col>
<Col span={12}>
<div className="blockTitle">CA服务</div>
<Row>
<Col span={6} offset={6}>
<span>CA办理</span>
</Col>
<Col span={6}>
<span>CA客服</span>
</Col>
</Row>
<div className="blockTitle"></div>
<p style={{ marginTop: 20 }}>客服1: 400-300-9989</p>
<p>客服1: 400-300-9989</p>
<p>客服1: 400-300-9989</p>
<p>客服1: 400-300-9989</p>
</Col>
</Row>
<SpaceBlock />
<div>
<LinkComponent />
</div>
</div>
);
};
export default IndexPage;

View File

@ -1,10 +0,0 @@
import React from 'react';
const LoginPage:React.FC = () => {
return (
<div>LoginPage</div>
)
}
export default LoginPage;

194
src/pages/login/login.less Normal file
View File

@ -0,0 +1,194 @@
@import '~@/baseStyle.less';
// 登录页面整体布局
.login-page {
display: flex;
align-items: center;
justify-content: flex-end;
min-height: 100vh;
padding-right: 10%;
background: #f0f2f5;
background-image: url('~@/assets/img/loginBg.jpg');
background-position: center;
background-size: cover;
}
// 登录容器
.login-container {
position: relative;
width: 400px;
padding: 30px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
// 标题样式
.login-title {
margin-bottom: 20px;
color: @main-color;
font-weight: bold;
font-size: 24px;
text-align: center;
}
// 返回首页链接
.back-home {
position: absolute;
top: 10px;
left: 10px;
a {
display: flex;
align-items: center;
color: @main-color;
font-size: 14px;
&:hover {
color: lighten(@main-color, 10%);
}
.anticon {
margin-right: 4px;
}
}
}
// Tab 容器
.login-tab-container {
margin-bottom: 30px;
}
// Tab 样式
.login-tabs {
border-radius: 15px;
.ant-tabs-nav {
margin: 0;
}
.ant-tabs-nav::before {
display: none;
}
.ant-tabs-tab {
flex: 1;
height: 44px;
margin: 0;
padding: 0;
font-weight: bold;
font-size: 16px;
line-height: 44px;
text-align: center;
background-color: #f5f5f5;
border: none;
transition: none;
.ant-tabs-tab-btn {
width: 100%;
height: 100%;
color: #333;
}
}
.ant-tabs-nav-list {
display: flex;
width: 100%;
overflow: hidden;
}
.ant-tabs-tab-active {
background-color: @main-color;
border-radius: 15px;
.ant-tabs-tab-btn {
color: #fff !important;
font-weight: bold;
}
}
.ant-tabs-ink-bar {
display: none;
}
}
// 登录表单
.login-form {
.ant-form-item {
margin-bottom: 20px;
}
.ant-input-affix-wrapper {
border-radius: 10px;
&:focus,
&-focused,
&:hover {
border-color: @main-color;
}
}
}
// 登录选项区域(记住密码和忘记密码)
.login-options {
display: flex;
align-items: center;
justify-content: space-between;
.ant-checkbox-checked .ant-checkbox-inner {
background-color: @main-color;
border-color: @main-color;
}
.login-form-forgot {
color: @main-color;
&:hover {
color: lighten(@main-color, 10%);
}
}
}
// 登录按钮
.login-form-button {
width: 100%;
height: 40px;
margin-top: 10px;
background-color: @main-color;
border-color: @main-color;
border-radius: 4px;
&:hover,
&:focus {
background-color: lighten(@main-color, 10%);
border-color: lighten(@main-color, 10%);
}
}
// 注册链接
.register-link {
margin-top: 15px;
text-align: center;
a {
margin-left: 5px;
color: @main-color;
&:hover {
color: lighten(@main-color, 10%);
}
}
}
// 响应式布局
@media (max-width: 768px) {
.login-page {
justify-content: center;
padding-right: 0;
}
.login-container {
width: 90%;
max-width: 400px;
padding: 20px;
}
}

134
src/pages/login/login.tsx Normal file
View File

@ -0,0 +1,134 @@
import React, { useState } from 'react';
import { Form, Input, Button, Checkbox, Tabs, message } from 'antd';
import { UserOutlined, LockOutlined, EyeInvisibleOutlined, EyeTwoTone, HomeOutlined } from '@ant-design/icons';
import { history, useIntl } from 'umi';
import './login.less';
const { TabPane } = Tabs;
const LoginPage: React.FC = () => {
const [activeKey, setActiveKey] = useState('supplier');
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const intl = useIntl();
const onFinish = (values: any) => {
setLoading(true);
console.log('登录信息:', values);
// 这里添加登录逻辑
setTimeout(() => {
setLoading(false);
message.success('登录成功');
history.push('/index');
}, 1000);
};
const handleTabChange = (key: string) => {
setActiveKey(key);
form.resetFields();
};
// 根据当前选中的Tab决定跳转到哪个注册页面
const handleRegister = () => {
switch(activeKey) {
case 'supplier':
history.push('/register/supplier');
break;
case 'expert':
history.push('/register/expert');
break;
default:
// 招标代理不提供注册功能
break;
}
};
// 渲染注册链接只在供应商和专家Tab下显示
const renderRegisterLink = () => {
if (activeKey === 'agent') {
return null; // 招标代理不显示注册链接
}
return (
<div className="register-link">
{intl.formatMessage({ id: 'login.register.tip' })}
<a onClick={handleRegister}>
{intl.formatMessage({ id: 'login.register.action' })}
</a>
</div>
);
};
return (
<div className='login-page'>
<div className='login-container'>
<div className='back-home'>
<a onClick={() => history.push('/index')}>
<HomeOutlined /> {intl.formatMessage({ id: 'login.back.home' })}
</a>
</div>
<div className='login-title'>{intl.formatMessage({ id: 'login.title' })}</div>
<div className="login-tab-container">
<Tabs activeKey={activeKey} onChange={handleTabChange} className='login-tabs'>
<TabPane tab={intl.formatMessage({ id: 'login.tab.supplier' })} key="supplier" />
<TabPane tab={intl.formatMessage({ id: 'login.tab.expert' })} key="expert" />
<TabPane tab={intl.formatMessage({ id: 'login.tab.agent' })} key="agent" />
</Tabs>
</div>
<Form
form={form}
name="login"
className='login-form'
initialValues={{ remember: false }}
onFinish={onFinish}
>
<Form.Item
name="username"
rules={[{ required: true, message: intl.formatMessage({ id: 'login.username.placeholder' }) + '!' }]}
>
<Input
prefix={<UserOutlined className="site-form-item-icon" />}
placeholder={intl.formatMessage({ id: 'login.username.placeholder' })}
size="large"
/>
</Form.Item>
<Form.Item
name="password"
rules={[{ required: true, message: intl.formatMessage({ id: 'login.password.placeholder' }) + '!' }]}
>
<Input.Password
prefix={<LockOutlined className="site-form-item-icon" />}
placeholder={intl.formatMessage({ id: 'login.password.placeholder' })}
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
size="large"
/>
</Form.Item>
<Form.Item>
<div className='login-options'>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox>{intl.formatMessage({ id: 'login.remember' })}</Checkbox>
</Form.Item>
<a className="login-form-forgot" href="">
{intl.formatMessage({ id: 'login.forgot' })}
</a>
</div>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="login-form-button" loading={loading} size="large">
{intl.formatMessage({ id: 'login.button' })}
</Button>
{renderRegisterLink()}
</Form.Item>
</Form>
</div>
</div>
);
};
export default LoginPage;

View File

@ -0,0 +1,8 @@
import React from 'react';
import { useLocation } from 'umi';
const NoticeInfo: React.FC = () => {
const location = useLocation();
const id = new URLSearchParams(location.search).get("id")
return <>NoticeInfo -------- {id}</>;
};
export default NoticeInfo;

View File

@ -0,0 +1,190 @@
import React, { useState } from 'react';
import { useIntl, history } from 'umi';
import { Form, Input, Button, message, Card, Select, Row, Col } from 'antd';
import { UserOutlined, LockOutlined, MobileOutlined, IdcardOutlined, HomeOutlined } from '@ant-design/icons';
import './register.less';
const { Option } = Select;
const ExpertRegister: React.FC = () => {
const [form] = Form.useForm();
const intl = useIntl();
const [loading, setLoading] = useState(false);
const [countdown, setCountdown] = useState(0);
// 获取短信验证码
const handleGetCaptcha = () => {
form.validateFields(['phone']).then(values => {
message.success(`验证码已发送至 ${values.phone}`);
let count = 60;
setCountdown(count);
const timer = setInterval(() => {
count--;
setCountdown(count);
if (count === 0) {
clearInterval(timer);
}
}, 1000);
}).catch(errorInfo => {
message.error('请先输入正确的手机号');
});
};
const onFinish = (values: any) => {
setLoading(true);
console.log('专家注册信息:', values);
// 这里添加注册逻辑
setTimeout(() => {
setLoading(false);
message.success('注册成功,请登录');
history.push('/login');
}, 1000);
};
return (
<div className="register-page">
<div className="register-container">
<div className='back-home'>
<a onClick={() => history.push('/index')}>
<HomeOutlined /> {intl.formatMessage({ id: 'login.back.home' })}
</a>
</div>
<div className="register-title">
{intl.formatMessage({ id: 'register.expert.title' })}
</div>
<Card className="register-card">
<Form
form={form}
name="expert_register"
className="register-form"
onFinish={onFinish}
layout="vertical"
>
<Form.Item
name="username"
label={<span className="required-label">{intl.formatMessage({ id: 'register.username.label' })}</span>}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.username.required' }) },
{ min: 4, message: intl.formatMessage({ id: 'register.username.min' }) }
]}
>
<Input prefix={<UserOutlined />} placeholder={intl.formatMessage({ id: 'register.username.placeholder' })} />
</Form.Item>
<Form.Item
name="phone"
label={<span className="required-label">{intl.formatMessage({ id: 'register.phone.label' })}</span>}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.phone.required' }) },
{ pattern: /^1[3-9]\d{9}$/, message: intl.formatMessage({ id: 'register.phone.invalid' }) }
]}
>
<Input prefix={<MobileOutlined />} placeholder={intl.formatMessage({ id: 'register.phone.placeholder' })} />
</Form.Item>
<Form.Item
name="idType"
label={intl.formatMessage({ id: 'register.expert.idType.label' })}
>
<Select placeholder={intl.formatMessage({ id: 'register.expert.idType.placeholder' })}>
<Option value="idcard"></Option>
<Option value="passport"></Option>
<Option value="other"></Option>
</Select>
</Form.Item>
<Form.Item
name="idCard"
label={<span className="required-label">{intl.formatMessage({ id: 'register.expert.idCard.label' })}</span>}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.expert.idCard.required' }) }
]}
>
<Input prefix={<IdcardOutlined />} placeholder={intl.formatMessage({ id: 'register.expert.idCard.placeholder' })} />
</Form.Item>
<Form.Item
name="password"
label={<span className="required-label">{intl.formatMessage({ id: 'register.password.label' })}</span>}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.password.required' }) },
{ min: 6, message: intl.formatMessage({ id: 'register.password.min' }) },
{ pattern: /^[a-zA-Z0-9]{6,16}$/, message: intl.formatMessage({ id: 'register.password.pattern' }) }
]}
>
<Input.Password
prefix={<LockOutlined />}
placeholder={intl.formatMessage({ id: 'register.password.placeholder' })}
/>
</Form.Item>
<Form.Item
name="confirmPassword"
label={<span className="required-label">{intl.formatMessage({ id: 'register.confirmPassword.label' })}</span>}
dependencies={['password']}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.confirmPassword.required' }) },
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject(new Error(intl.formatMessage({ id: 'register.confirmPassword.notMatch' })));
},
}),
]}
>
<Input.Password
prefix={<LockOutlined />}
placeholder={intl.formatMessage({ id: 'register.confirmPassword.placeholder' })}
/>
</Form.Item>
<Form.Item
name="captcha"
label={<span className="required-label">{intl.formatMessage({ id: 'register.captcha.label' })}</span>}
rules={[{ required: true, message: intl.formatMessage({ id: 'register.captcha.required' }) }]}
>
<Row gutter={8}>
<Col span={16}>
<Input placeholder={intl.formatMessage({ id: 'register.captcha.placeholder' })} />
</Col>
<Col span={8}>
<Button
className="captcha-button"
disabled={countdown > 0}
onClick={handleGetCaptcha}
>
{countdown > 0 ? `${countdown}s` : intl.formatMessage({ id: 'register.captcha.get' })}
</Button>
</Col>
</Row>
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
className="register-button"
loading={loading}
>
{intl.formatMessage({ id: 'register.submit' })}
</Button>
<div className="login-link">
{intl.formatMessage({ id: 'register.hasAccount' })}
<a onClick={() => history.push('/login')}>
{intl.formatMessage({ id: 'register.login' })}
</a>
</div>
</Form.Item>
</Form>
</Card>
</div>
</div>
);
};
export default ExpertRegister;

View File

@ -0,0 +1,162 @@
@import '~@/baseStyle.less';
// 注册页面整体布局
.register-page {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #f0f2f5;
background-image: url('~@/assets/img/loginBg.jpg');
background-size: cover;
background-position: center;
}
// 注册容器
.register-container {
width: 600px;
padding: 30px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
position: relative;
margin: 40px 0;
}
// 标题样式
.register-title {
margin-bottom: 20px;
color: @main-color;
font-weight: bold;
font-size: 24px;
text-align: center;
}
// 返回首页链接
.back-home {
position: absolute;
top: 10px;
left: 10px;
a {
display: flex;
align-items: center;
color: @main-color;
font-size: 14px;
&:hover {
color: lighten(@main-color, 10%);
}
.anticon {
margin-right: 4px;
}
}
}
// 注册卡片
.register-card {
border-radius: 8px;
box-shadow: none;
.ant-card-body {
padding: 20px 0;
}
}
// 必填字段标记
.required-label::before {
display: inline-block;
margin-right: 4px;
color: #ff4d4f;
font-size: 14px;
font-family: SimSun, sans-serif;
line-height: 1;
content: '*';
}
// 注册表单
.register-form {
.ant-form-item {
margin-bottom: 20px;
}
.ant-input,
.ant-input-affix-wrapper,
.ant-select-selector {
border-radius: 6px;
&:focus,
&-focused,
&:hover {
border-color: @main-color;
}
}
.ant-form-item-label > label {
font-weight: 500;
}
}
// 验证码按钮
.captcha-button {
width: 100%;
height: 40px;
background-color: @main-color;
border-color: @main-color;
color: #fff;
&:hover,
&:focus {
background-color: lighten(@main-color, 10%);
border-color: lighten(@main-color, 10%);
color: #fff;
}
&:disabled {
color: rgba(0, 0, 0, 0.25);
background-color: #f5f5f5;
border-color: #d9d9d9;
}
}
// 注册按钮
.register-button {
width: 100%;
height: 40px;
margin-top: 10px;
background-color: @main-color;
border-color: @main-color;
border-radius: 6px;
&:hover,
&:focus {
background-color: lighten(@main-color, 10%);
border-color: lighten(@main-color, 10%);
}
}
// 登录链接
.login-link {
margin-top: 15px;
text-align: center;
a {
margin-left: 5px;
color: @main-color;
&:hover {
color: lighten(@main-color, 10%);
}
}
}
// 响应式布局
@media (max-width: 768px) {
.register-container {
width: 90%;
max-width: 500px;
padding: 20px;
margin: 20px 0;
}
}

View File

@ -0,0 +1,136 @@
import React from 'react';
import { useIntl, history } from 'umi';
import { Form, Input, Button, message, Card } from 'antd';
import { UserOutlined, LockOutlined, MobileOutlined, MailOutlined, HomeOutlined } from '@ant-design/icons';
import './register.less';
const SupplierRegister: React.FC = () => {
const [form] = Form.useForm();
const intl = useIntl();
const onFinish = (values: any) => {
console.log('供应商注册信息:', values);
// 这里添加注册逻辑
message.success('注册成功,请登录');
history.push('/login');
};
return (
<div className="register-page">
<div className="register-container">
<div className='back-home'>
<a onClick={() => history.push('/index')}>
<HomeOutlined /> {intl.formatMessage({ id: 'login.back.home' })}
</a>
</div>
<div className="register-title">
{intl.formatMessage({ id: 'register.supplier.title' })}
</div>
<Card className="register-card">
<Form
form={form}
name="supplier_register"
className="register-form"
onFinish={onFinish}
layout="vertical"
>
<Form.Item
name="username"
label={intl.formatMessage({ id: 'register.username.label' })}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.username.required' }) },
{ min: 4, message: intl.formatMessage({ id: 'register.username.min' }) }
]}
>
<Input prefix={<UserOutlined />} placeholder={intl.formatMessage({ id: 'register.username.placeholder' })} />
</Form.Item>
<Form.Item
name="password"
label={intl.formatMessage({ id: 'register.password.label' })}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.password.required' }) },
{ min: 6, message: intl.formatMessage({ id: 'register.password.min' }) }
]}
>
<Input.Password prefix={<LockOutlined />} placeholder={intl.formatMessage({ id: 'register.password.placeholder' })} />
</Form.Item>
<Form.Item
name="confirmPassword"
label={intl.formatMessage({ id: 'register.confirmPassword.label' })}
dependencies={['password']}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.confirmPassword.required' }) },
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject(new Error(intl.formatMessage({ id: 'register.confirmPassword.notMatch' })));
},
}),
]}
>
<Input.Password prefix={<LockOutlined />} placeholder={intl.formatMessage({ id: 'register.confirmPassword.placeholder' })} />
</Form.Item>
<Form.Item
name="companyName"
label={intl.formatMessage({ id: 'register.supplier.companyName.label' })}
rules={[{ required: true, message: intl.formatMessage({ id: 'register.supplier.companyName.required' }) }]}
>
<Input placeholder={intl.formatMessage({ id: 'register.supplier.companyName.placeholder' })} />
</Form.Item>
<Form.Item
name="contactPerson"
label={intl.formatMessage({ id: 'register.supplier.contactPerson.label' })}
rules={[{ required: true, message: intl.formatMessage({ id: 'register.supplier.contactPerson.required' }) }]}
>
<Input placeholder={intl.formatMessage({ id: 'register.supplier.contactPerson.placeholder' })} />
</Form.Item>
<Form.Item
name="phone"
label={intl.formatMessage({ id: 'register.phone.label' })}
rules={[
{ required: true, message: intl.formatMessage({ id: 'register.phone.required' }) },
{ pattern: /^1[3-9]\d{9}$/, message: intl.formatMessage({ id: 'register.phone.invalid' }) }
]}
>
<Input prefix={<MobileOutlined />} placeholder={intl.formatMessage({ id: 'register.phone.placeholder' })} />
</Form.Item>
<Form.Item
name="email"
label={intl.formatMessage({ id: 'register.email.label' })}
rules={[
{ type: 'email', message: intl.formatMessage({ id: 'register.email.invalid' }) },
{ required: true, message: intl.formatMessage({ id: 'register.email.required' }) }
]}
>
<Input prefix={<MailOutlined />} placeholder={intl.formatMessage({ id: 'register.email.placeholder' })} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="register-button">
{intl.formatMessage({ id: 'register.submit' })}
</Button>
<div className="login-link">
{intl.formatMessage({ id: 'register.hasAccount' })}
<a onClick={() => history.push('/login')}>
{intl.formatMessage({ id: 'register.login' })}
</a>
</div>
</Form.Item>
</Form>
</Card>
</div>
</div>
);
};
export default SupplierRegister;