完善页面功能
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 Head from './layout/head/Head.tsx';
|
||||||
import Body from './layout/body/Body.tsx';
|
import Body from './layout/body/Body.tsx';
|
||||||
import Foot from './layout/foot/Foot.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 App: React.FC = () => {
|
||||||
|
const globalDataReducer = (state: GlobalData, action: GlobalDataAction) => {
|
||||||
const globalData: GlobalData = {
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<GlobalContext.Provider value={globalData}>
|
<GlobalContext.Provider value={globalData}>
|
||||||
|
<GlobalDispatchContext.Provider value={dispatch}>
|
||||||
<Head/>
|
<Head/>
|
||||||
<Body/>
|
<Body/>
|
||||||
<Foot/>
|
<Foot/>
|
||||||
|
</GlobalDispatchContext.Provider>
|
||||||
</GlobalContext.Provider>
|
</GlobalContext.Provider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import './balance-head.css'
|
import './balance-head.css'
|
||||||
|
import {useContext} from "react";
|
||||||
|
import {GlobalContext} from "../../context/GlobalContext.ts";
|
||||||
|
|
||||||
export default function BalanceHead() {
|
export default function BalanceHead() {
|
||||||
|
const globalContext = useContext(GlobalContext);
|
||||||
const handleClick = () => {
|
|
||||||
console.log('查看余额')
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="head-item balance-head">
|
<div className="head-item balance-head">
|
||||||
<span className="label">余额¥:</span>
|
<span className="label">余额¥:</span>
|
||||||
<span className="balance" onClick={handleClick}>800</span>
|
<span className="balance" onClick={() => {
|
||||||
|
console.log('查看余额')
|
||||||
|
}}>{globalContext.user.balance}</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,48 +1,51 @@
|
|||||||
import './card-proj.css';
|
import './card-proj.css';
|
||||||
import {
|
import {
|
||||||
|
CheckOutlined,
|
||||||
|
ClockCircleOutlined,
|
||||||
|
CloseCircleOutlined,
|
||||||
|
CreditCardOutlined,
|
||||||
DownloadOutlined,
|
DownloadOutlined,
|
||||||
EditOutlined,
|
EditOutlined,
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
FolderOutlined,
|
FolderOutlined,
|
||||||
|
LoadingOutlined,
|
||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
ClockCircleOutlined,
|
WarningOutlined
|
||||||
LoadingOutlined,
|
|
||||||
CheckOutlined,
|
|
||||||
WarningOutlined,
|
|
||||||
CloseCircleOutlined,
|
|
||||||
CreditCardOutlined
|
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {Button, ConfigProvider, Tag} from 'antd';
|
import {Button, ConfigProvider, Tag} from 'antd';
|
||||||
import {GenerateStatus, IProj, PayStatus} from "../../interfaces/proj/IProj.ts";
|
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 }) {
|
export default function CardProj(props: { item: IProj }) {
|
||||||
|
const nav = useNavigate();
|
||||||
const data = props.item;
|
const data = props.item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成状态
|
* 生成状态
|
||||||
*/
|
*/
|
||||||
const renderGenerateStatus = () => {
|
const renderGenerateStatus = () => {
|
||||||
if (data.generateStatus == GenerateStatus.PENDING) {
|
if (data.generate.generateStatus == GenerateStatus.PENDING) {
|
||||||
return <Tag color="cyan"><ClockCircleOutlined/> 等待生成</Tag>
|
return <Tag color="cyan"><ClockCircleOutlined/> 等待生成</Tag>
|
||||||
}
|
}
|
||||||
if (data.generateStatus == GenerateStatus.GENERATING) {
|
if (data.generate.generateStatus == GenerateStatus.GENERATING) {
|
||||||
return <Tag color="magenta"><LoadingOutlined/> 正在生成</Tag>
|
return <Tag color="magenta"><LoadingOutlined/> 正在生成</Tag>
|
||||||
}
|
}
|
||||||
if (data.generateStatus == GenerateStatus.SUCCESS) {
|
if (data.generate.generateStatus == GenerateStatus.SUCCESS) {
|
||||||
return <Tag color="green"><CheckOutlined/> 生成成功</Tag>
|
return <Tag color="green"><CheckOutlined/> 生成成功</Tag>
|
||||||
}
|
}
|
||||||
if (data.generateStatus == GenerateStatus.FAILED) {
|
if (data.generate.generateStatus == GenerateStatus.FAILED) {
|
||||||
return <Tag color="red"><WarningOutlined/> 生成失败</Tag>
|
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="cyan">未生成</Tag>
|
||||||
}
|
}
|
||||||
return <Tag color="red"><CloseCircleOutlined/> 错误</Tag>
|
return <Tag color="red"><CloseCircleOutlined/> 错误</Tag>
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderOption = () => {
|
const renderOption = () => {
|
||||||
if(data.payStatus == PayStatus.UNPAID) {
|
if(data.pay.payStatus == PayStatus.UNPAID) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="option">
|
<div className="option">
|
||||||
@ -54,17 +57,44 @@ export default function CardProj(props: { item: IProj }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="option">
|
<div className="option">
|
||||||
<Button size="small" type="text"><SettingOutlined/> 登录界面设置</Button>
|
<Button size="small" type="text" onClick={() => {
|
||||||
<Button size="small" type="text"><SettingOutlined/> 系统菜单管理(0)</Button>
|
if(data.generate.generateStatus == GenerateStatus.SUCCESS) {
|
||||||
<Button size="small" type="text"><SettingOutlined/> 菜单排序(0)</Button>
|
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>
|
</div>
|
||||||
{
|
{
|
||||||
data.generateStatus == GenerateStatus.SUCCESS ? (
|
data.generate.generateStatus == GenerateStatus.SUCCESS ? (
|
||||||
<div className="option">
|
<div className="option">
|
||||||
<Button size="small" type="text"><DownloadOutlined/> 申请表</Button>
|
<Button size="small" type="text" onClick={() => {
|
||||||
<Button size="small" type="text"><DownloadOutlined/> 操作手册</Button>
|
window.open(`${Axios.defaults?.baseURL}/route/proj/download/apply/${data.projId}`)
|
||||||
<Button size="small" type="text"><DownloadOutlined/> 代码压缩包</Button>
|
}}><DownloadOutlined/> 申请表</Button>
|
||||||
<Button size="small" type="text"><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>
|
</div>
|
||||||
) : <></>
|
) : <></>
|
||||||
}
|
}
|
||||||
@ -88,22 +118,33 @@ export default function CardProj(props: { item: IProj }) {
|
|||||||
<div className="body">
|
<div className="body">
|
||||||
<div className="line">
|
<div className="line">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
<span>金额¥:{data.payment / 100}</span>
|
<span>金额¥:{data.pay.payment / 100}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="right">
|
<div className="right">
|
||||||
<span>
|
{
|
||||||
<EditOutlined/>
|
data.generate.generateStatus == GenerateStatus.SUCCESS ? (
|
||||||
<a href="/#">编辑</a>
|
|
||||||
</span>
|
|
||||||
<span>
|
<span>
|
||||||
<SearchOutlined/>
|
<SearchOutlined/>
|
||||||
<a href="/#">查看</a>
|
<a href="/#" onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
nav(`/proj-edit/${data.projId}`)
|
||||||
|
}}>查看</a>
|
||||||
</span>
|
</span>
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
<EditOutlined/>
|
||||||
|
<a href="/#" onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
nav(`/proj-edit/${data.projId}`)
|
||||||
|
}}>编辑</a>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
<span>
|
<span>
|
||||||
<EyeOutlined/>
|
<EyeOutlined/>
|
||||||
<a href="/#" onClick={(e) => {
|
<a href="/#" onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
window.open(data.previewUrl, '_blank')
|
window.open(`${Axios.defaults?.baseURL}/${data.previewUrl}`, '_blank')
|
||||||
}}>预览</a>
|
}}>预览</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,12 +5,21 @@ export default function CardProjDownload(props: IProjDownload) {
|
|||||||
return (
|
return (
|
||||||
<div className="card-proj-download">
|
<div className="card-proj-download">
|
||||||
<div className="title">{props.title}</div>
|
<div className="title">{props.title}</div>
|
||||||
<div className="desc">请完善软件的介绍,详细介绍等基本信息</div>
|
<div className="desc">{props.desc}</div>
|
||||||
<div className="option">
|
<div className="option">
|
||||||
|
{
|
||||||
|
props.canBtnClick ? (
|
||||||
<a href="/#" className="edit" onClick={(e) => {
|
<a href="/#" className="edit" onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
props.handleDownload();
|
props.handleDownload();
|
||||||
}}>下载</a>
|
}}>下载</a>
|
||||||
|
) : (
|
||||||
|
<a href="/#" className="edit" style={{color: 'var(--color-border)'}} onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
}}>下载</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</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 {
|
export interface IProjDownload {
|
||||||
title: string;
|
title: string;
|
||||||
desc: string;
|
desc: string;
|
||||||
|
canBtnClick?: boolean;
|
||||||
|
|
||||||
handleDownload(): void;
|
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 {
|
export interface IProj {
|
||||||
|
|
||||||
projId: string,
|
projId: string,
|
||||||
projName: string;
|
projName: string;
|
||||||
projContext: string;
|
projContext: string;
|
||||||
projCodeType: ProjCodeType,
|
projCodeType: ProjCodeType;
|
||||||
payStatus: PayStatus,
|
projStyleType: ProjStyleType;
|
||||||
payment: number,
|
previewUrl: string;
|
||||||
projStyleType: ProjStyleType,
|
gmtCreate: string;
|
||||||
previewUrl: string,
|
|
||||||
gmtCreate: string,
|
generate: IProjGenerate;
|
||||||
generateStatus: GenerateStatus
|
pay: IProjPay;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,41 @@
|
|||||||
import './head.css'
|
import './head.css'
|
||||||
import BalanceHead from '../../components/balance/BalanceHead.tsx';
|
import BalanceHead from '../../components/balance/BalanceHead.tsx';
|
||||||
import RechargeHead from '../../components/recharge/RechargeHead.tsx';
|
import RechargeHead from '../../components/recharge/RechargeHead.tsx';
|
||||||
import MessageHead from '../../components/message/MessageHead.tsx';
|
import {Divider, Dropdown, MenuProps, message, Modal, Space, Spin} from "antd";
|
||||||
import {Divider, Dropdown, MenuProps, Space} from "antd";
|
|
||||||
import {DownOutlined, UserOutlined, KeyOutlined, LogoutOutlined} from "@ant-design/icons";
|
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() {
|
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'] = [
|
const items: MenuProps['items'] = [
|
||||||
{
|
{
|
||||||
@ -16,6 +46,9 @@ export default function Head() {
|
|||||||
<span className="title">个人信息</span>
|
<span className="title">个人信息</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
onClick: () => {
|
||||||
|
setIsSelfModalOpen(true);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'changePass',
|
key: 'changePass',
|
||||||
@ -38,6 +71,7 @@ export default function Head() {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div className="head">
|
<div className="head">
|
||||||
<div className="center">
|
<div className="center">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
@ -48,13 +82,13 @@ export default function Head() {
|
|||||||
<div className="right">
|
<div className="right">
|
||||||
<BalanceHead/>
|
<BalanceHead/>
|
||||||
<RechargeHead/>
|
<RechargeHead/>
|
||||||
<MessageHead/>
|
{/*<MessageHead/>*/}
|
||||||
<div style={{display: 'flex', alignContent: 'center', padding: '0 10px', cursor: 'pointer'}}>
|
<div style={{display: 'flex', alignContent: 'center', padding: '0 10px', cursor: 'pointer'}}>
|
||||||
<Dropdown menu={{
|
<Dropdown menu={{
|
||||||
items: items
|
items: items
|
||||||
}}>
|
}}>
|
||||||
<Space>
|
<Space>
|
||||||
您好:18888888
|
您好:{globalContext.user.nickname}
|
||||||
<DownOutlined/>
|
<DownOutlined/>
|
||||||
</Space>
|
</Space>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
@ -62,5 +96,51 @@ export default function Head() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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="资料下载">
|
descTitle="资料下载">
|
||||||
<CardProjDownload title="申请表"
|
<CardProjDownload title="申请表"
|
||||||
desc="点击下载申请表"
|
desc="点击下载申请表"
|
||||||
|
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||||
handleDownload={() => {
|
handleDownload={() => {
|
||||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/apply/${pathParams.projId}`)
|
window.open(`${Axios.defaults?.baseURL}/route/proj/download/apply/${pathParams.projId}`)
|
||||||
console.log('下载')
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CardProjDownload title="操作手册"
|
<CardProjDownload title="操作手册"
|
||||||
desc="点击下载操作手册"
|
desc="点击下载操作手册"
|
||||||
|
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||||
handleDownload={() => {
|
handleDownload={() => {
|
||||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/manual/${pathParams.projId}`)
|
window.open(`${Axios.defaults?.baseURL}/route/proj/download/manual/${pathParams.projId}`)
|
||||||
console.log('下载')
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CardProjDownload title="代码压缩包"
|
<CardProjDownload title="代码压缩包"
|
||||||
desc="点击下载代码压缩包"
|
desc="点击下载代码压缩包"
|
||||||
|
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||||
handleDownload={() => {
|
handleDownload={() => {
|
||||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code-zip/${pathParams.projId}`)
|
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code-zip/${pathParams.projId}`)
|
||||||
console.log('下载')
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CardProjDownload title="代码文档"
|
<CardProjDownload title="代码文档"
|
||||||
desc="点击下载代码文档"
|
desc="点击下载代码文档"
|
||||||
|
canBtnClick={generateStatus == GenerateStatus.SUCCESS}
|
||||||
handleDownload={() => {
|
handleDownload={() => {
|
||||||
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code/${pathParams.projId}`)
|
window.open(`${Axios.defaults?.baseURL}/route/proj/download/code/${pathParams.projId}`)
|
||||||
console.log('下载')
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CardProjJump title="跳转"
|
<CardProjJump title="跳转"
|
||||||
|
@ -84,7 +84,7 @@ export default function ProjConfigLoginpage() {
|
|||||||
form.setFieldValue('adminPassword', data.adminPassword);
|
form.setFieldValue('adminPassword', data.adminPassword);
|
||||||
if (data.logo) {
|
if (data.logo) {
|
||||||
const url = downloadUrl(data.logo);
|
const url = downloadUrl(data.logo);
|
||||||
logoImgArray.push({
|
logoImgArray.splice(0, 1, {
|
||||||
uid: data.logo,
|
uid: data.logo,
|
||||||
name: 'logo.png',
|
name: 'logo.png',
|
||||||
status: 'done',
|
status: 'done',
|
||||||
@ -97,7 +97,7 @@ export default function ProjConfigLoginpage() {
|
|||||||
}
|
}
|
||||||
if (data.bgImgs) {
|
if (data.bgImgs) {
|
||||||
const url = downloadUrl(data.bgImgs);
|
const url = downloadUrl(data.bgImgs);
|
||||||
bgImgArray.push({
|
bgImgArray.splice(0, 1, {
|
||||||
uid: data.bgImgs,
|
uid: data.bgImgs,
|
||||||
name: 'bg.png',
|
name: 'bg.png',
|
||||||
status: 'done',
|
status: 'done',
|
||||||
@ -201,13 +201,13 @@ export default function ProjConfigLoginpage() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
const fileId = info.file.response.data.fileId;
|
const fileId = info.file.response.data.fileId;
|
||||||
const url = downloadUrl(fileId);
|
const url = downloadUrl(fileId);
|
||||||
logoImgArray[0] = {
|
logoImgArray.splice(0, 1, {
|
||||||
uid: info.file.response.data.fileId,
|
uid: info.file.response.data.fileId,
|
||||||
name: 'logo.png',
|
name: 'logo.png',
|
||||||
status: 'done',
|
status: 'done',
|
||||||
url: url,
|
url: url,
|
||||||
thumbUrl: url,
|
thumbUrl: url,
|
||||||
}
|
})
|
||||||
setLogoImgArray([
|
setLogoImgArray([
|
||||||
...logoImgArray
|
...logoImgArray
|
||||||
])
|
])
|
||||||
@ -246,13 +246,13 @@ export default function ProjConfigLoginpage() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
const fileId = info.file.response.data.fileId;
|
const fileId = info.file.response.data.fileId;
|
||||||
const url = downloadUrl(fileId);
|
const url = downloadUrl(fileId);
|
||||||
bgImgArray[0] = {
|
bgImgArray.splice(0, 1, {
|
||||||
uid: info.file.response.data.fileId,
|
uid: info.file.response.data.fileId,
|
||||||
name: 'bg.png',
|
name: 'bg.png',
|
||||||
status: 'done',
|
status: 'done',
|
||||||
url: url,
|
url: url,
|
||||||
thumbUrl: url,
|
thumbUrl: url,
|
||||||
}
|
})
|
||||||
setBgImgArray([
|
setBgImgArray([
|
||||||
...bgImgArray
|
...bgImgArray
|
||||||
])
|
])
|
||||||
|
@ -34,7 +34,7 @@ export default function ProjEditStep2() {
|
|||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
projSubName: data.projSubName,
|
projSubName: data.projSubName,
|
||||||
projVersion: data.projVersion,
|
projVersion: data.projVersion,
|
||||||
projDevCompleteDate: dayjs(data.projDevCompleteDate, 'YYYY-MM-DD'),
|
projDevCompleteDate: data.projDevCompleteDate ? dayjs(data.projDevCompleteDate, 'YYYY-MM-DD') : '',
|
||||||
companyName: data.companyName,
|
companyName: data.companyName,
|
||||||
companyNameEn: data.companyNameEn,
|
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