完善页面功能
This commit is contained in:
parent
dbb8f3c924
commit
04d1905906
34
src/App.tsx
34
src/App.tsx
@ -1,20 +1,46 @@
|
||||
import Head from './layout/head/Head.tsx';
|
||||
import Body from './layout/body/Body.tsx';
|
||||
import Foot from './layout/foot/Foot.tsx';
|
||||
import {GlobalContext, GlobalData} from "./context/GlobalContext.ts";
|
||||
|
||||
import {
|
||||
GlobalContext,
|
||||
GlobalData,
|
||||
GlobalDataAction,
|
||||
GlobalDataActionType,
|
||||
GlobalDispatchContext
|
||||
} from "./context/GlobalContext.ts";
|
||||
import {Reducer, useReducer} from "react";
|
||||
|
||||
const App: React.FC = () => {
|
||||
|
||||
const globalData: GlobalData = {
|
||||
const globalDataReducer = (state: GlobalData, action: GlobalDataAction) => {
|
||||
if (action.type == GlobalDataActionType.REFRESH_SELF) {
|
||||
if(action.user) {
|
||||
state.user.balance = action.user.balance;
|
||||
state.user.nickname = action.user.nickname;
|
||||
state.user.username = action.user.username;
|
||||
state.user.hasUserInfo = action.user.hasUserInfo;
|
||||
}
|
||||
}
|
||||
return {
|
||||
...state
|
||||
}
|
||||
}
|
||||
const [globalData, dispatch] = useReducer<Reducer<GlobalData, GlobalDataAction>>(globalDataReducer, {
|
||||
user: {
|
||||
balance: '0',
|
||||
username: '',
|
||||
nickname: '',
|
||||
hasUserInfo: false
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<GlobalContext.Provider value={globalData}>
|
||||
<GlobalDispatchContext.Provider value={dispatch}>
|
||||
<Head/>
|
||||
<Body/>
|
||||
<Foot/>
|
||||
</GlobalDispatchContext.Provider>
|
||||
</GlobalContext.Provider>
|
||||
</>
|
||||
);
|
||||
|
@ -1,15 +1,16 @@
|
||||
import './balance-head.css'
|
||||
import {useContext} from "react";
|
||||
import {GlobalContext} from "../../context/GlobalContext.ts";
|
||||
|
||||
export default function BalanceHead() {
|
||||
|
||||
const handleClick = () => {
|
||||
console.log('查看余额')
|
||||
}
|
||||
const globalContext = useContext(GlobalContext);
|
||||
|
||||
return (
|
||||
<div className="head-item balance-head">
|
||||
<span className="label">余额¥:</span>
|
||||
<span className="balance" onClick={handleClick}>800</span>
|
||||
<span className="balance" onClick={() => {
|
||||
console.log('查看余额')
|
||||
}}>{globalContext.user.balance}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,48 +1,51 @@
|
||||
import './card-proj.css';
|
||||
import {
|
||||
CheckOutlined,
|
||||
ClockCircleOutlined,
|
||||
CloseCircleOutlined,
|
||||
CreditCardOutlined,
|
||||
DownloadOutlined,
|
||||
EditOutlined,
|
||||
EyeOutlined,
|
||||
FolderOutlined,
|
||||
LoadingOutlined,
|
||||
SearchOutlined,
|
||||
SettingOutlined,
|
||||
ClockCircleOutlined,
|
||||
LoadingOutlined,
|
||||
CheckOutlined,
|
||||
WarningOutlined,
|
||||
CloseCircleOutlined,
|
||||
CreditCardOutlined
|
||||
WarningOutlined
|
||||
} from '@ant-design/icons';
|
||||
import {Button, ConfigProvider, Tag} from 'antd';
|
||||
import {GenerateStatus, IProj, PayStatus} from "../../interfaces/proj/IProj.ts";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {Axios} from "../../util/AjaxUtils.ts";
|
||||
|
||||
export default function CardProj(props: { item: IProj }) {
|
||||
const nav = useNavigate();
|
||||
const data = props.item;
|
||||
|
||||
/**
|
||||
* 生成状态
|
||||
*/
|
||||
const renderGenerateStatus = () => {
|
||||
if (data.generateStatus == GenerateStatus.PENDING) {
|
||||
if (data.generate.generateStatus == GenerateStatus.PENDING) {
|
||||
return <Tag color="cyan"><ClockCircleOutlined/> 等待生成</Tag>
|
||||
}
|
||||
if (data.generateStatus == GenerateStatus.GENERATING) {
|
||||
if (data.generate.generateStatus == GenerateStatus.GENERATING) {
|
||||
return <Tag color="magenta"><LoadingOutlined/> 正在生成</Tag>
|
||||
}
|
||||
if (data.generateStatus == GenerateStatus.SUCCESS) {
|
||||
if (data.generate.generateStatus == GenerateStatus.SUCCESS) {
|
||||
return <Tag color="green"><CheckOutlined/> 生成成功</Tag>
|
||||
}
|
||||
if (data.generateStatus == GenerateStatus.FAILED) {
|
||||
if (data.generate.generateStatus == GenerateStatus.FAILED) {
|
||||
return <Tag color="red"><WarningOutlined/> 生成失败</Tag>
|
||||
}
|
||||
if (data.generateStatus == GenerateStatus.NONE) {
|
||||
if (data.generate.generateStatus == GenerateStatus.NONE) {
|
||||
return <Tag color="cyan">未生成</Tag>
|
||||
}
|
||||
return <Tag color="red"><CloseCircleOutlined/> 错误</Tag>
|
||||
}
|
||||
|
||||
const renderOption = () => {
|
||||
if(data.payStatus == PayStatus.UNPAID) {
|
||||
if(data.pay.payStatus == PayStatus.UNPAID) {
|
||||
return (
|
||||
<>
|
||||
<div className="option">
|
||||
@ -54,17 +57,44 @@ export default function CardProj(props: { item: IProj }) {
|
||||
return (
|
||||
<>
|
||||
<div className="option">
|
||||
<Button size="small" type="text"><SettingOutlined/> 登录界面设置</Button>
|
||||
<Button size="small" type="text"><SettingOutlined/> 系统菜单管理(0)</Button>
|
||||
<Button size="small" type="text"><SettingOutlined/> 菜单排序(0)</Button>
|
||||
<Button size="small" type="text" onClick={() => {
|
||||
if(data.generate.generateStatus == GenerateStatus.SUCCESS) {
|
||||
nav(`/proj-edit/config-loginpage-show/${data.projId}`)
|
||||
} else {
|
||||
nav(`/proj-edit/config-loginpage/${data.projId}`)
|
||||
}
|
||||
}}><SettingOutlined/> 登录界面设置</Button>
|
||||
<Button size="small" type="text" onClick={() => {
|
||||
if(data.generate.generateStatus == GenerateStatus.SUCCESS) {
|
||||
nav(`/proj-edit/config-mod-list-show/${data.projId}`)
|
||||
} else {
|
||||
nav(`/proj-edit/config-mod-list/${data.projId}`)
|
||||
}
|
||||
}}><SettingOutlined/> 系统菜单管理(0)</Button>
|
||||
<Button size="small" type="text" onClick={() => {
|
||||
if(data.generate.generateStatus == GenerateStatus.SUCCESS) {
|
||||
nav(`/proj-edit/config-menu-list-show/${data.projId}`)
|
||||
} else {
|
||||
nav(`/proj-edit/config-menu-list/${data.projId}`)
|
||||
|
||||
}
|
||||
}}><SettingOutlined/> 菜单排序(0)</Button>
|
||||
</div>
|
||||
{
|
||||
data.generateStatus == GenerateStatus.SUCCESS ? (
|
||||
data.generate.generateStatus == GenerateStatus.SUCCESS ? (
|
||||
<div className="option">
|
||||
<Button size="small" type="text"><DownloadOutlined/> 申请表</Button>
|
||||
<Button size="small" type="text"><DownloadOutlined/> 操作手册</Button>
|
||||
<Button size="small" type="text"><DownloadOutlined/> 代码压缩包</Button>
|
||||
<Button size="small" type="text"><DownloadOutlined/> 代码文档</Button>
|
||||
<Button size="small" type="text" onClick={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/apply/${data.projId}`)
|
||||
}}><DownloadOutlined/> 申请表</Button>
|
||||
<Button size="small" type="text" onClick={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/manual/${data.projId}`)
|
||||
}}><DownloadOutlined/> 操作手册</Button>
|
||||
<Button size="small" type="text" onClick={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code-zip/${data.projId}`)
|
||||
}}><DownloadOutlined/> 代码压缩包</Button>
|
||||
<Button size="small" type="text" onClick={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code/${data.projId}`)
|
||||
}}><DownloadOutlined/> 代码文档</Button>
|
||||
</div>
|
||||
) : <></>
|
||||
}
|
||||
@ -88,22 +118,33 @@ export default function CardProj(props: { item: IProj }) {
|
||||
<div className="body">
|
||||
<div className="line">
|
||||
<div className="left">
|
||||
<span>金额¥:{data.payment / 100}</span>
|
||||
<span>金额¥:{data.pay.payment / 100}</span>
|
||||
</div>
|
||||
<div className="right">
|
||||
<span>
|
||||
<EditOutlined/>
|
||||
<a href="/#">编辑</a>
|
||||
</span>
|
||||
{
|
||||
data.generate.generateStatus == GenerateStatus.SUCCESS ? (
|
||||
<span>
|
||||
<SearchOutlined/>
|
||||
<a href="/#">查看</a>
|
||||
<a href="/#" onClick={(e) => {
|
||||
e.preventDefault();
|
||||
nav(`/proj-edit/${data.projId}`)
|
||||
}}>查看</a>
|
||||
</span>
|
||||
) : (
|
||||
<span>
|
||||
<EditOutlined/>
|
||||
<a href="/#" onClick={(e) => {
|
||||
e.preventDefault();
|
||||
nav(`/proj-edit/${data.projId}`)
|
||||
}}>编辑</a>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
<span>
|
||||
<EyeOutlined/>
|
||||
<a href="/#" onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
window.open(data.previewUrl, '_blank')
|
||||
window.open(`${Axios.defaults?.baseURL}/${data.previewUrl}`, '_blank')
|
||||
}}>预览</a>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -5,12 +5,21 @@ export default function CardProjDownload(props: IProjDownload) {
|
||||
return (
|
||||
<div className="card-proj-download">
|
||||
<div className="title">{props.title}</div>
|
||||
<div className="desc">请完善软件的介绍,详细介绍等基本信息</div>
|
||||
<div className="desc">{props.desc}</div>
|
||||
<div className="option">
|
||||
{
|
||||
props.canBtnClick ? (
|
||||
<a href="/#" className="edit" onClick={(e) => {
|
||||
e.preventDefault();
|
||||
props.handleDownload();
|
||||
}}>下载</a>
|
||||
) : (
|
||||
<a href="/#" className="edit" style={{color: 'var(--color-border)'}} onClick={(e) => {
|
||||
e.preventDefault();
|
||||
}}>下载</a>
|
||||
)
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,8 +1,33 @@
|
||||
import {createContext} from "react";
|
||||
import {createContext, Dispatch} from "react";
|
||||
|
||||
export interface GlobalData {
|
||||
export enum GlobalDataActionType {
|
||||
REFRESH_SELF
|
||||
}
|
||||
|
||||
const Data: GlobalData = {}
|
||||
export interface User {
|
||||
balance: string;
|
||||
nickname: string;
|
||||
username: string;
|
||||
hasUserInfo: boolean;
|
||||
}
|
||||
|
||||
export const GlobalContext = createContext<GlobalData>(Data);
|
||||
export interface GlobalData {
|
||||
user: User;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface GlobalDataAction {
|
||||
type: number;
|
||||
user?: User;
|
||||
}
|
||||
|
||||
export const GlobalContext = createContext<GlobalData>({
|
||||
user: {
|
||||
balance: '0',
|
||||
nickname: '',
|
||||
username: '',
|
||||
hasUserInfo: false
|
||||
}
|
||||
});
|
||||
export const GlobalDispatchContext = createContext<Dispatch<GlobalDataAction>>(() => {});
|
||||
|
@ -32,6 +32,7 @@ export interface IProjResult {
|
||||
export interface IProjDownload {
|
||||
title: string;
|
||||
desc: string;
|
||||
canBtnClick?: boolean;
|
||||
|
||||
handleDownload(): void;
|
||||
}
|
||||
|
@ -47,18 +47,30 @@ export interface IProjCharge {
|
||||
}
|
||||
}
|
||||
|
||||
export interface IProjGenerate {
|
||||
generateStatus: GenerateStatus;
|
||||
}
|
||||
|
||||
export interface IProjPay {
|
||||
charge: string;
|
||||
gmtPay: string;
|
||||
payStatus: PayStatus;
|
||||
payment: number;
|
||||
chargeAdditionals: string;
|
||||
}
|
||||
|
||||
|
||||
export interface IProj {
|
||||
|
||||
projId: string,
|
||||
projName: string;
|
||||
projContext: string;
|
||||
projCodeType: ProjCodeType,
|
||||
payStatus: PayStatus,
|
||||
payment: number,
|
||||
projStyleType: ProjStyleType,
|
||||
previewUrl: string,
|
||||
gmtCreate: string,
|
||||
generateStatus: GenerateStatus
|
||||
projCodeType: ProjCodeType;
|
||||
projStyleType: ProjStyleType;
|
||||
previewUrl: string;
|
||||
gmtCreate: string;
|
||||
|
||||
generate: IProjGenerate;
|
||||
pay: IProjPay;
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,41 @@
|
||||
import './head.css'
|
||||
import BalanceHead from '../../components/balance/BalanceHead.tsx';
|
||||
import RechargeHead from '../../components/recharge/RechargeHead.tsx';
|
||||
import MessageHead from '../../components/message/MessageHead.tsx';
|
||||
import {Divider, Dropdown, MenuProps, Space} from "antd";
|
||||
import {Divider, Dropdown, MenuProps, message, Modal, Space, Spin} from "antd";
|
||||
import {DownOutlined, UserOutlined, KeyOutlined, LogoutOutlined} from "@ant-design/icons";
|
||||
import {useContext, useEffect, useState} from "react";
|
||||
import {get, put} from "../../util/AjaxUtils.ts";
|
||||
import {GlobalContext, GlobalDataActionType, GlobalDispatchContext} from "../../context/GlobalContext.ts";
|
||||
import UserEdit from "../../route/user/UserEdit.tsx";
|
||||
|
||||
export default function Head() {
|
||||
const globalContext = useContext(GlobalContext);
|
||||
const globalDispatchContext = useContext(GlobalDispatchContext);
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [modal, modalHolder] = Modal.useModal();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [isSelfModalOpen, setIsSelfModalOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
get({
|
||||
messageApi,
|
||||
url: '/api/user-info/get-user-self',
|
||||
onSuccess({data}) {
|
||||
globalDispatchContext({
|
||||
type: GlobalDataActionType.REFRESH_SELF,
|
||||
user: {
|
||||
balance: (Math.floor(data.accountMoney) / 100).toFixed(2),
|
||||
nickname: data.nickname,
|
||||
username: data.username,
|
||||
hasUserInfo: data.hasUserInfo,
|
||||
}
|
||||
})
|
||||
if(!data.hasUserInfo) {
|
||||
setIsSelfModalOpen(true);
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [globalContext.user]);
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
@ -16,6 +46,9 @@ export default function Head() {
|
||||
<span className="title">个人信息</span>
|
||||
</div>
|
||||
),
|
||||
onClick: () => {
|
||||
setIsSelfModalOpen(true);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'changePass',
|
||||
@ -38,6 +71,7 @@ export default function Head() {
|
||||
]
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="head">
|
||||
<div className="center">
|
||||
<div className="left">
|
||||
@ -48,13 +82,13 @@ export default function Head() {
|
||||
<div className="right">
|
||||
<BalanceHead/>
|
||||
<RechargeHead/>
|
||||
<MessageHead/>
|
||||
{/*<MessageHead/>*/}
|
||||
<div style={{display: 'flex', alignContent: 'center', padding: '0 10px', cursor: 'pointer'}}>
|
||||
<Dropdown menu={{
|
||||
items: items
|
||||
}}>
|
||||
<Space>
|
||||
您好:18888888
|
||||
您好:{globalContext.user.nickname}
|
||||
<DownOutlined/>
|
||||
</Space>
|
||||
</Dropdown>
|
||||
@ -62,5 +96,51 @@ export default function Head() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Modal open={isSelfModalOpen}
|
||||
title="个人信息"
|
||||
footer={false}
|
||||
onCancel={() => {
|
||||
if(!globalContext.user.hasUserInfo) {
|
||||
messageApi.info('请完善个人信息');
|
||||
return;
|
||||
}
|
||||
setIsSelfModalOpen(false)
|
||||
}} >
|
||||
<UserEdit handleConfirm={(data) => {
|
||||
modal.confirm({
|
||||
title: 'Confirm',
|
||||
content: '确定保存吗?',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
okButtonProps: {
|
||||
style: {
|
||||
backgroundColor: 'var(--color-primary)'
|
||||
}
|
||||
},
|
||||
onOk: () => {
|
||||
setIsSelfModalOpen(false);
|
||||
put({
|
||||
messageApi,
|
||||
url: '/api/user-info/update-self',
|
||||
body: data,
|
||||
onBefore() {
|
||||
setLoading(true);
|
||||
},
|
||||
onSuccess() {
|
||||
messageApi.success('修改成功');
|
||||
},
|
||||
onFinally() {
|
||||
setLoading(false);
|
||||
}
|
||||
})
|
||||
console.log(data);
|
||||
}
|
||||
});
|
||||
}}/>
|
||||
</Modal>
|
||||
<Spin tip="正在提交..." spinning={loading} fullscreen/>
|
||||
{contextHolder}
|
||||
{modalHolder}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -320,30 +320,30 @@ export default function ProjEdit() {
|
||||
descTitle="资料下载">
|
||||
<CardProjDownload title="申请表"
|
||||
desc="点击下载申请表"
|
||||
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||
handleDownload={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/apply/${pathParams.projId}`)
|
||||
console.log('下载')
|
||||
}}
|
||||
/>
|
||||
<CardProjDownload title="操作手册"
|
||||
desc="点击下载操作手册"
|
||||
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||
handleDownload={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/manual/${pathParams.projId}`)
|
||||
console.log('下载')
|
||||
}}
|
||||
/>
|
||||
<CardProjDownload title="代码压缩包"
|
||||
desc="点击下载代码压缩包"
|
||||
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||
handleDownload={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code-zip/${pathParams.projId}`)
|
||||
console.log('下载')
|
||||
}}
|
||||
/>
|
||||
<CardProjDownload title="代码文档"
|
||||
desc="点击下载代码文档"
|
||||
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||
handleDownload={() => {
|
||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code/${pathParams.projId}`)
|
||||
console.log('下载')
|
||||
}}
|
||||
/>
|
||||
<CardProjJump title="跳转"
|
||||
|
@ -84,7 +84,7 @@ export default function ProjConfigLoginpage() {
|
||||
form.setFieldValue('adminPassword', data.adminPassword);
|
||||
if (data.logo) {
|
||||
const url = downloadUrl(data.logo);
|
||||
logoImgArray.push({
|
||||
logoImgArray.splice(0, 1, {
|
||||
uid: data.logo,
|
||||
name: 'logo.png',
|
||||
status: 'done',
|
||||
@ -97,7 +97,7 @@ export default function ProjConfigLoginpage() {
|
||||
}
|
||||
if (data.bgImgs) {
|
||||
const url = downloadUrl(data.bgImgs);
|
||||
bgImgArray.push({
|
||||
bgImgArray.splice(0, 1, {
|
||||
uid: data.bgImgs,
|
||||
name: 'bg.png',
|
||||
status: 'done',
|
||||
@ -201,13 +201,13 @@ export default function ProjConfigLoginpage() {
|
||||
setLoading(false);
|
||||
const fileId = info.file.response.data.fileId;
|
||||
const url = downloadUrl(fileId);
|
||||
logoImgArray[0] = {
|
||||
logoImgArray.splice(0, 1, {
|
||||
uid: info.file.response.data.fileId,
|
||||
name: 'logo.png',
|
||||
status: 'done',
|
||||
url: url,
|
||||
thumbUrl: url,
|
||||
}
|
||||
})
|
||||
setLogoImgArray([
|
||||
...logoImgArray
|
||||
])
|
||||
@ -246,13 +246,13 @@ export default function ProjConfigLoginpage() {
|
||||
setLoading(false);
|
||||
const fileId = info.file.response.data.fileId;
|
||||
const url = downloadUrl(fileId);
|
||||
bgImgArray[0] = {
|
||||
bgImgArray.splice(0, 1, {
|
||||
uid: info.file.response.data.fileId,
|
||||
name: 'bg.png',
|
||||
status: 'done',
|
||||
url: url,
|
||||
thumbUrl: url,
|
||||
}
|
||||
})
|
||||
setBgImgArray([
|
||||
...bgImgArray
|
||||
])
|
||||
|
@ -34,7 +34,7 @@ export default function ProjEditStep2() {
|
||||
form.setFieldsValue({
|
||||
projSubName: data.projSubName,
|
||||
projVersion: data.projVersion,
|
||||
projDevCompleteDate: dayjs(data.projDevCompleteDate, 'YYYY-MM-DD'),
|
||||
projDevCompleteDate: data.projDevCompleteDate ? dayjs(data.projDevCompleteDate, 'YYYY-MM-DD') : '',
|
||||
companyName: data.companyName,
|
||||
companyNameEn: data.companyNameEn,
|
||||
})
|
||||
|
386
src/route/user/UserEdit.tsx
Normal file
386
src/route/user/UserEdit.tsx
Normal file
@ -0,0 +1,386 @@
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
DatePicker, Flex,
|
||||
Form,
|
||||
GetProp,
|
||||
Input,
|
||||
message,
|
||||
Radio,
|
||||
Row,
|
||||
Spin,
|
||||
Upload,
|
||||
UploadFile,
|
||||
UploadProps
|
||||
} from "antd";
|
||||
import {DevUserId, downloadUrl, get, uploadImageUrl} from "../../util/AjaxUtils.ts";
|
||||
import {useEffect, useState} from "react";
|
||||
import locale from "antd/es/date-picker/locale/zh_CN";
|
||||
import dayjs, {Dayjs} from "dayjs";
|
||||
|
||||
type FormDataType = {
|
||||
userId: string;
|
||||
userInfoId: string;
|
||||
userInfoType: string;
|
||||
userInfoName: string;
|
||||
idCardType: string;
|
||||
idCardNumber: string;
|
||||
idCardFront: string;
|
||||
idCardBack: string;
|
||||
idCardStartDate: Dayjs;
|
||||
idCardEndDate: Dayjs;
|
||||
legalPerson: string;
|
||||
establishDate: Dayjs;
|
||||
contactAddress: string;
|
||||
contactPhone: string;
|
||||
}
|
||||
|
||||
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
|
||||
|
||||
const dateFormat = 'YYYY年MM月DD日';
|
||||
|
||||
export interface IUserEditProps {
|
||||
|
||||
handleConfirm(data: FormDataType): void;
|
||||
}
|
||||
|
||||
export default function UserEdit(props: IUserEditProps) {
|
||||
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [form] = Form.useForm<FormDataType>();
|
||||
const [userInfoType, setUserInfoType] = useState('PERSONAL');
|
||||
const [idCardFrontImgArray, setIdCardFrontImgArray] = useState<UploadFile[]>([]);
|
||||
const [idCardBackImgArray, setIdCardBackImgArray] = useState<UploadFile[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const beforeUpload = (file: FileType) => {
|
||||
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
|
||||
if (!isJpgOrPng) {
|
||||
message.error('只能上传 JPG/PNG 格式文件!');
|
||||
}
|
||||
return isJpgOrPng;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
get({
|
||||
messageApi,
|
||||
url: 'api/user-info/get-self',
|
||||
onSuccess({data}) {
|
||||
form.setFieldsValue({
|
||||
userId: data.userId,
|
||||
userInfoId: data.userInfoId,
|
||||
userInfoName: data.userInfoName,
|
||||
userInfoType: data.userInfoType,
|
||||
contactAddress: data.contactAddress,
|
||||
contactPhone: data.contactPhone,
|
||||
establishDate: data.establishDate ? dayjs(data.establishDate, 'YYYY-MM-DD') : '',
|
||||
idCardNumber: data.idCardNumber,
|
||||
idCardFront: data.idCardFront,
|
||||
idCardStartDate: data.idCardStartDate ? dayjs(data.idCardStartDate, 'YYYY-MM-DD') : '',
|
||||
idCardBack: data.idCardBack,
|
||||
idCardEndDate: data.idCardEndDate ? dayjs(data.idCardEndDate, 'YYYY-MM-DD') : '',
|
||||
idCardType: data.idCardType,
|
||||
legalPerson: data.legalPerson,
|
||||
})
|
||||
if (data.idCardFront) {
|
||||
const url = downloadUrl(data.idCardFront);
|
||||
idCardFrontImgArray.splice(0, 1, {
|
||||
uid: data.idCardFront,
|
||||
name: 'front.png',
|
||||
status: 'done',
|
||||
url: url,
|
||||
thumbUrl: url,
|
||||
})
|
||||
setIdCardFrontImgArray([
|
||||
...idCardFrontImgArray,
|
||||
])
|
||||
}
|
||||
if (data.idCardBack) {
|
||||
const url = downloadUrl(data.idCardBack);
|
||||
idCardBackImgArray.splice(0, 1, {
|
||||
uid: data.idCardBack,
|
||||
name: 'back.png',
|
||||
status: 'done',
|
||||
url: url,
|
||||
thumbUrl: url,
|
||||
})
|
||||
setIdCardBackImgArray([
|
||||
...idCardBackImgArray,
|
||||
])
|
||||
}
|
||||
setUserInfoType(data.userInfoType);
|
||||
}
|
||||
})
|
||||
}, [form])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form
|
||||
layout="vertical"
|
||||
form={form}
|
||||
onFinish={() => {
|
||||
props.handleConfirm({
|
||||
userId: form.getFieldValue('userId'),
|
||||
userInfoId: form.getFieldValue('userInfoId'),
|
||||
userInfoName: form.getFieldValue('userInfoName'),
|
||||
userInfoType: form.getFieldValue('userInfoType'),
|
||||
contactAddress: form.getFieldValue('contactAddress'),
|
||||
contactPhone: form.getFieldValue('contactPhone'),
|
||||
establishDate: form.getFieldValue('establishDate') ? form.getFieldValue('establishDate').format(dateFormat) : '',
|
||||
idCardBack: form.getFieldValue('idCardBack'),
|
||||
idCardEndDate: form.getFieldValue('idCardEndDate') ? form.getFieldValue('idCardEndDate').format(dateFormat) : '',
|
||||
idCardFront: form.getFieldValue('idCardFront'),
|
||||
idCardNumber: form.getFieldValue('idCardNumber'),
|
||||
idCardStartDate: form.getFieldValue('idCardStartDate') ? form.getFieldValue('idCardStartDate').format(dateFormat) : '',
|
||||
idCardType: form.getFieldValue('idCardType'),
|
||||
legalPerson: form.getFieldValue('legalPerson'),
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Form.Item label="类型"
|
||||
name="userInfoType"
|
||||
rules={[{required: true, message: '请选择类型'}]}
|
||||
>
|
||||
<Radio.Group onChange={(e) => {
|
||||
setUserInfoType(e.target.value);
|
||||
if (e.target.value === 'PERSONAL') {
|
||||
form.setFieldValue('idCardType', 'ID_CARD');
|
||||
}
|
||||
if (e.target.value === 'ENTERPRISE') {
|
||||
form.setFieldValue('idCardType', 'ORGANIZATION_CODE');
|
||||
}
|
||||
}}>
|
||||
<Radio.Button value="PERSONAL">个人</Radio.Button>
|
||||
<Radio.Button value="ENTERPRISE">企业</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="名称"
|
||||
name="userInfoName"
|
||||
rules={[{required: true, message: '请输入名称'}]}
|
||||
>
|
||||
<Input placeholder="请输入名称"/>
|
||||
</Form.Item>
|
||||
{
|
||||
userInfoType == 'PERSONAL' ? (
|
||||
<Form.Item label="证件类型"
|
||||
name="idCardType"
|
||||
rules={[{required: true, message: '请选择证件类型'}]}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio.Button value="ID_CARD">身份证</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
) : <></>
|
||||
}
|
||||
{
|
||||
userInfoType == 'ENTERPRISE' ? (
|
||||
<Form.Item label="证件类型"
|
||||
name="idCardType"
|
||||
rules={[{required: true, message: '请选择证件类型'}]}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio.Button value="ORGANIZATION_CODE">组织机构代码证</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
) : <></>
|
||||
}
|
||||
|
||||
<Form.Item label="证件号"
|
||||
name="idCardNumber"
|
||||
rules={[{required: true, message: '请输入证件号'}]}
|
||||
>
|
||||
<Input placeholder="请输入证件号"/>
|
||||
</Form.Item>
|
||||
<Row gutter={15}>
|
||||
<Col span={12}>
|
||||
<Form.Item label="证件照正面"
|
||||
name="idCardFront"
|
||||
rules={[{required: true, message: '请上传证件照正面'}]}
|
||||
>
|
||||
<Upload
|
||||
name="image"
|
||||
listType="picture"
|
||||
maxCount={1}
|
||||
defaultFileList={idCardFrontImgArray}
|
||||
action={uploadImageUrl()}
|
||||
headers={{'X-USER-ID': DevUserId}}
|
||||
beforeUpload={beforeUpload}
|
||||
onChange={(info) => {
|
||||
if (info.file.status === 'uploading') {
|
||||
setLoading(true);
|
||||
return;
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
setLoading(false);
|
||||
const fileId = info.file.response.data.fileId;
|
||||
const url = downloadUrl(fileId);
|
||||
idCardFrontImgArray[0] = {
|
||||
uid: info.file.response.data.fileId,
|
||||
name: 'bg.png',
|
||||
status: 'done',
|
||||
url: url,
|
||||
thumbUrl: url,
|
||||
}
|
||||
setIdCardFrontImgArray([
|
||||
...idCardFrontImgArray
|
||||
])
|
||||
form.setFieldValue('idCardFront', fileId);
|
||||
return;
|
||||
}
|
||||
}}
|
||||
onRemove={() => {
|
||||
idCardFrontImgArray.splice(0)
|
||||
setIdCardFrontImgArray([
|
||||
...idCardFrontImgArray
|
||||
])
|
||||
}}
|
||||
>
|
||||
<Button size="small" type="primary"
|
||||
style={{backgroundColor: 'var(--color-primary)'}}
|
||||
disabled={idCardFrontImgArray.length > 0}>上传</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
{
|
||||
userInfoType == 'PERSONAL' ? (
|
||||
<Col span={12}>
|
||||
<Form.Item label="证件照反面"
|
||||
name="idCardBack"
|
||||
rules={[{required: true, message: '请上传证件照反面'}]}
|
||||
>
|
||||
<Upload
|
||||
name="image"
|
||||
listType="picture"
|
||||
maxCount={1}
|
||||
defaultFileList={idCardBackImgArray}
|
||||
action={uploadImageUrl()}
|
||||
headers={{'X-USER-ID': DevUserId}}
|
||||
beforeUpload={beforeUpload}
|
||||
onChange={(info) => {
|
||||
if (info.file.status === 'uploading') {
|
||||
setLoading(true);
|
||||
return;
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
setLoading(false);
|
||||
const fileId = info.file.response.data.fileId;
|
||||
const url = downloadUrl(fileId);
|
||||
idCardBackImgArray[0] = {
|
||||
uid: info.file.response.data.fileId,
|
||||
name: 'bg.png',
|
||||
status: 'done',
|
||||
url: url,
|
||||
thumbUrl: url,
|
||||
}
|
||||
setIdCardBackImgArray([
|
||||
...idCardBackImgArray
|
||||
])
|
||||
form.setFieldValue('idCardBack', fileId);
|
||||
return;
|
||||
}
|
||||
}}
|
||||
onRemove={() => {
|
||||
idCardBackImgArray.splice(0)
|
||||
setIdCardBackImgArray([
|
||||
...idCardBackImgArray
|
||||
])
|
||||
}}
|
||||
>
|
||||
<Button size="small" type="primary"
|
||||
style={{backgroundColor: 'var(--color-primary)'}}
|
||||
disabled={idCardBackImgArray.length > 0}>上传</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
) : <></>
|
||||
}
|
||||
</Row>
|
||||
<Row gutter={15}>
|
||||
<Col span={12}>
|
||||
<Form.Item<FormDataType>
|
||||
label="证件开始时间"
|
||||
name="idCardStartDate"
|
||||
rules={[{required: true, message: '请选择证件开始时间'}]}
|
||||
>
|
||||
<DatePicker placeholder="证件开始时间"
|
||||
format={dateFormat}
|
||||
locale={locale}
|
||||
style={{width: '100%'}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item<FormDataType>
|
||||
label="证件结束时间"
|
||||
name="idCardEndDate"
|
||||
rules={[{required: true, message: '请选择证件结束时间'}]}
|
||||
>
|
||||
<DatePicker placeholder="证件结束时间"
|
||||
format={dateFormat}
|
||||
locale={locale}
|
||||
style={{width: '100%'}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
{
|
||||
userInfoType == 'ENTERPRISE' ? (
|
||||
<Row gutter={15}>
|
||||
<Col span={12}>
|
||||
<Form.Item label="法人"
|
||||
name="legalPerson"
|
||||
rules={[{required: true, message: '请输入法人'}]}
|
||||
>
|
||||
<Input placeholder="请输入法人"/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item<FormDataType>
|
||||
label="成立时间"
|
||||
name="establishDate"
|
||||
rules={[{required: true, message: '请选择成立时间'}]}
|
||||
>
|
||||
<DatePicker placeholder="成立时间"
|
||||
format={dateFormat}
|
||||
locale={locale}
|
||||
style={{width: '100%'}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
) : <></>
|
||||
}
|
||||
<Row gutter={15}>
|
||||
<Col span={12}>
|
||||
<Form.Item label="联系地址"
|
||||
name="contactAddress"
|
||||
rules={[{required: true, message: '请输入联系地址'}]}
|
||||
>
|
||||
<Input placeholder="请输入联系地址"/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item label="联系电话"
|
||||
name="contactPhone"
|
||||
rules={[{required: true, message: '请输入联系电话'}]}
|
||||
>
|
||||
<Input placeholder="请输入联系电话"/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form.Item wrapperCol={{span: 24}}>
|
||||
<Flex align="center" justify="center" gap="large">
|
||||
<Button type="primary"
|
||||
htmlType="submit"
|
||||
style={{backgroundColor: 'var(--color-primary)'}}>
|
||||
保存
|
||||
</Button>
|
||||
</Flex>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Spin tip="正在提交..." spinning={loading} fullscreen/>
|
||||
{contextHolder}
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user