添加框架内容
This commit is contained in:
8
src/pages/announce/announceInfo.tsx
Normal file
8
src/pages/announce/announceInfo.tsx
Normal 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
17
src/pages/index/Link.tsx
Normal 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;
|
53
src/pages/index/index.less
Normal file
53
src/pages/index/index.less
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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
194
src/pages/login/login.less
Normal 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
134
src/pages/login/login.tsx
Normal 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;
|
8
src/pages/notice/noticeInfo.tsx
Normal file
8
src/pages/notice/noticeInfo.tsx
Normal 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;
|
190
src/pages/register/expert.tsx
Normal file
190
src/pages/register/expert.tsx
Normal 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;
|
162
src/pages/register/register.less
Normal file
162
src/pages/register/register.less
Normal 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;
|
||||
}
|
||||
}
|
136
src/pages/register/supplier.tsx
Normal file
136
src/pages/register/supplier.tsx
Normal 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;
|
Reference in New Issue
Block a user