feat:二维码及日志
This commit is contained in:
parent
fdd657a1b3
commit
a2eb3d0473
|
@ -24,7 +24,8 @@
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-virtualized": "^9.22.6",
|
"react-virtualized": "^9.22.6",
|
||||||
"sass": "^1.77.3",
|
"sass": "^1.77.3",
|
||||||
"tailwindcss": "3.3.3"
|
"tailwindcss": "3.3.3",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
"@types/react-big-calendar": "^1.8.9",
|
"@types/react-big-calendar": "^1.8.9",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
"@types/react-virtualized": "^9.22.2",
|
"@types/react-virtualized": "^9.22.2",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
"@vercel/style-guide": "^5.0.1",
|
"@vercel/style-guide": "^5.0.1",
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "14.2.29",
|
"eslint-config-next": "14.2.29",
|
||||||
|
@ -1670,6 +1672,12 @@
|
||||||
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/warning": {
|
"node_modules/@types/warning": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/warning/-/warning-3.0.3.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/warning/-/warning-3.0.3.tgz",
|
||||||
|
@ -7534,6 +7542,18 @@
|
||||||
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "11.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-11.1.0.tgz",
|
||||||
|
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/esm/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/validate-npm-package-license": {
|
"node_modules/validate-npm-package-license": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
"resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||||
|
@ -8969,6 +8989,12 @@
|
||||||
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/warning": {
|
"@types/warning": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/warning/-/warning-3.0.3.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/warning/-/warning-3.0.3.tgz",
|
||||||
|
@ -13420,6 +13446,11 @@
|
||||||
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
},
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "11.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-11.1.0.tgz",
|
||||||
|
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="
|
||||||
|
},
|
||||||
"validate-npm-package-license": {
|
"validate-npm-package-license": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
"resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-virtualized": "^9.22.6",
|
"react-virtualized": "^9.22.6",
|
||||||
"sass": "^1.77.3",
|
"sass": "^1.77.3",
|
||||||
"tailwindcss": "3.3.3"
|
"tailwindcss": "3.3.3",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
"@types/react-big-calendar": "^1.8.9",
|
"@types/react-big-calendar": "^1.8.9",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
"@types/react-virtualized": "^9.22.2",
|
"@types/react-virtualized": "^9.22.2",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
"@vercel/style-guide": "^5.0.1",
|
"@vercel/style-guide": "^5.0.1",
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "14.2.29",
|
"eslint-config-next": "14.2.29",
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 103 KiB |
|
@ -1,15 +1,14 @@
|
||||||
'use client'
|
'use client'
|
||||||
import {ProConfigProvider} from "@ant-design/pro-components";
|
import {ProConfigProvider} from "@ant-design/pro-components";
|
||||||
import React, {lazy, Suspense} from "react";
|
import React, {lazy, Suspense} from "react";
|
||||||
import Page from "@/ui/login/Page";
|
|
||||||
import Loading from "@/app/loading";
|
import Loading from "@/app/loading";
|
||||||
// const Page = lazy(() => import('@/ui/login/Page'));
|
import XcxLoginPage from "@/ui/login/XcxLoginPage";
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<Loading/>}>
|
<Suspense fallback={<Loading/>}>
|
||||||
<ProConfigProvider dark>
|
<ProConfigProvider dark>
|
||||||
<Page/>
|
<XcxLoginPage/>
|
||||||
</ProConfigProvider>
|
</ProConfigProvider>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import { Avatar, List, message } from 'antd';
|
||||||
|
import VirtualList from 'rc-virtual-list';
|
||||||
|
import { Button, Drawer } from 'antd';
|
||||||
|
interface UserItem {
|
||||||
|
email: string;
|
||||||
|
gender: string;
|
||||||
|
name: string;
|
||||||
|
avatar: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CONTAINER_HEIGHT = 400;
|
||||||
|
const PAGE_SIZE = 20;
|
||||||
|
|
||||||
|
const DiaryOption = () => {
|
||||||
|
// 抽屉 start
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const showDrawer = () => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
const onClose = () => {
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
// 抽屉 end
|
||||||
|
|
||||||
|
// 数据 start
|
||||||
|
const [data, setData] = useState<UserItem[]>([]);
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
|
||||||
|
const appendData = (showMessage = true) => {
|
||||||
|
const fakeDataUrl = `https://660d2bd96ddfa2943b33731c.mockapi.io/api/users/?page=${page}&limit=${PAGE_SIZE}`;
|
||||||
|
fetch(fakeDataUrl)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((body) => {
|
||||||
|
const results = Array.isArray(body) ? body : [];
|
||||||
|
setData(data.concat(results));
|
||||||
|
setPage(page + 1);
|
||||||
|
showMessage && message.success(`${results.length} more items loaded!`);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
appendData(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onScroll = (e: React.UIEvent<HTMLElement, UIEvent>) => {
|
||||||
|
// Refer to: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#problems_and_solutions
|
||||||
|
if (
|
||||||
|
Math.abs(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - CONTAINER_HEIGHT) <= 1
|
||||||
|
) {
|
||||||
|
appendData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 数据 end
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button type="primary" onClick={showDrawer}>
|
||||||
|
日志心得
|
||||||
|
</Button>
|
||||||
|
<Drawer
|
||||||
|
mask={false}
|
||||||
|
title="Basic Drawer"
|
||||||
|
closable={{ 'aria-label': 'Close Button' }}
|
||||||
|
onClose={onClose}
|
||||||
|
open={open}
|
||||||
|
>
|
||||||
|
<div className="displayFlexRow">
|
||||||
|
<Button type="primary">全部</Button>
|
||||||
|
<Button type="primary">失效</Button>
|
||||||
|
<Button type="primary">生效</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<List>
|
||||||
|
<VirtualList
|
||||||
|
data={data}
|
||||||
|
height={CONTAINER_HEIGHT}
|
||||||
|
itemHeight={47}
|
||||||
|
itemKey="email"
|
||||||
|
onScroll={onScroll}
|
||||||
|
>
|
||||||
|
{item => (
|
||||||
|
<List.Item key={item.email}>
|
||||||
|
<List.Item.Meta
|
||||||
|
avatar={<Avatar src={item.avatar} />}
|
||||||
|
title={<a href="https://ant.design">{item.name}</a>}
|
||||||
|
description={item.email}
|
||||||
|
/>
|
||||||
|
<div>Content</div>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
</VirtualList>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default DiaryOption;
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* 复制文本到剪贴板
|
||||||
|
* // 使用示例
|
||||||
|
* copyToClipboard('要复制的文本')
|
||||||
|
* .then(() => console.log('复制成功'))
|
||||||
|
* .catch(() => console.error('复制失败'));
|
||||||
|
* @param text 要复制的文本
|
||||||
|
* @returns 返回 Promise,成功时 resolve(true),失败时 reject(false)
|
||||||
|
*/
|
||||||
|
export const copyToClipboard = (text: string): Promise<boolean> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// 方案1: 使用现代 Clipboard API
|
||||||
|
if (navigator.clipboard && window.isSecureContext) {
|
||||||
|
navigator.clipboard.writeText(text)
|
||||||
|
.then(() => resolve(true))
|
||||||
|
.catch(() => {
|
||||||
|
// 现代 API 失败时回退到传统方法
|
||||||
|
fallbackCopy(text) ? resolve(true) : reject(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 方案2: 传统 document.execCommand 方法
|
||||||
|
else {
|
||||||
|
fallbackCopy(text) ? resolve(true) : reject(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 传统复制方法兼容方案
|
||||||
|
const fallbackCopy = (text: string): boolean => {
|
||||||
|
try {
|
||||||
|
// 创建临时文本域
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = text;
|
||||||
|
|
||||||
|
// 隐藏文本域(不在视口中显示)
|
||||||
|
textArea.style.position = 'fixed';
|
||||||
|
textArea.style.top = '-9999px';
|
||||||
|
textArea.style.left = '-9999px';
|
||||||
|
textArea.style.opacity = '0';
|
||||||
|
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
|
||||||
|
// 选择并复制
|
||||||
|
textArea.select();
|
||||||
|
const successful = document.execCommand('copy');
|
||||||
|
|
||||||
|
// 清理DOM
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
|
||||||
|
return successful;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('复制失败:', err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
import {httpReq} from "@/utils/axiosReq";
|
||||||
|
|
||||||
|
export const generateQrcodeAPI = (data:{}) => {
|
||||||
|
return httpReq.post(process.env.NEXT_PUBLIC_SECURITY_REQUEST_URL + "/V2/wx/login/generate/qrcode",
|
||||||
|
data)
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
'use client'
|
||||||
|
import {
|
||||||
|
LoginFormPage,
|
||||||
|
} from '@ant-design/pro-components';
|
||||||
|
|
||||||
|
import {message, theme, Modal, Button, Skeleton, Image, QRCode} from 'antd';
|
||||||
|
import React, {useLayoutEffect} from 'react';
|
||||||
|
import {useState} from 'react';
|
||||||
|
import {CaptchaLoginSuccess, LoginObject} from "@/lib/login/definitions";
|
||||||
|
import {useRouter} from 'next/navigation'
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import {generateQrcodeAPI} from "@/lib/login/service";
|
||||||
|
|
||||||
|
export default function XcxLoginPage() {
|
||||||
|
const [loaded, setLoaded] = useState(false);
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
setLoaded(true);
|
||||||
|
})
|
||||||
|
// 二维码 start
|
||||||
|
const [qrCodeShow, setQrCodeShow] = useState<boolean>(false);
|
||||||
|
const [qrCodeStatus, setQrCodeStatus] = useState<'active' | 'expired' | 'loading' | 'scanned'>();
|
||||||
|
const [qrCodeValue, setQrCodeValue] = useState<string>("-");
|
||||||
|
const generateQrcode = () => {
|
||||||
|
// 不在二维码页面直接返回
|
||||||
|
if (!qrCodeShow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (qrCodeStatus=='loading') {
|
||||||
|
message.info({content:"请耐心等待"})
|
||||||
|
}else if (qrCodeStatus=='expired') {
|
||||||
|
generateQrCode()
|
||||||
|
}else if (qrCodeStatus=='active') {
|
||||||
|
|
||||||
|
}else if (qrCodeStatus=='scanned') {
|
||||||
|
|
||||||
|
}else {
|
||||||
|
generateQrCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function generateQrCode(){
|
||||||
|
// 生成唯一id
|
||||||
|
const clientId: string = uuidv4();
|
||||||
|
generateQrcodeAPI({clientId}).then(res=>{
|
||||||
|
setQrCodeValue(JSON.stringify({
|
||||||
|
clientId,serverId:res.data.data
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 二维码 end
|
||||||
|
|
||||||
|
const {token} = theme.useToken();
|
||||||
|
const router = useRouter()
|
||||||
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [captchaLoginSuccessList, setCaptchaLoginSuccessList] = useState([]);
|
||||||
|
const captchaUserNameConfirm = (captchaLoginSuccess: CaptchaLoginSuccess) => {
|
||||||
|
messageApi.open({
|
||||||
|
type: 'info',
|
||||||
|
content: "使用帐号" + captchaLoginSuccess.username + "登录成功"
|
||||||
|
})
|
||||||
|
localStorage.setItem('platform-security', captchaLoginSuccess.token)
|
||||||
|
router.push('/task/project')
|
||||||
|
setOpen(false)
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'white',
|
||||||
|
height: '100vh',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{contextHolder}
|
||||||
|
<Modal
|
||||||
|
open={open}
|
||||||
|
title="发现您注册有多个帐号,请选择需要登录的账号"
|
||||||
|
footer={
|
||||||
|
captchaLoginSuccessList.map((label: CaptchaLoginSuccess, index) => (
|
||||||
|
<Button key={label.username} onClick={() => captchaUserNameConfirm(label)}>
|
||||||
|
{label.username}
|
||||||
|
</Button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
</Modal>
|
||||||
|
{loaded ? <LoginFormPage
|
||||||
|
backgroundImageUrl="/20-1733751222585.jpg"
|
||||||
|
title="马上行计划管理"
|
||||||
|
containerStyle={{
|
||||||
|
backgroundColor: 'rgba(0, 0, 0,0.65)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
}}
|
||||||
|
onFinish={(formData: LoginObject) => {
|
||||||
|
// 二维码和小程序扫码来回切换
|
||||||
|
setQrCodeShow(!qrCodeShow)
|
||||||
|
// 生成二维码
|
||||||
|
generateQrcode()
|
||||||
|
}}
|
||||||
|
submitter={{ searchConfig: { submitText: qrCodeShow?"在我的-PC扫码登录或者返回":"已打开微信小程序,生成登录码。",resetText: '重置2'}}}
|
||||||
|
>
|
||||||
|
<div className="displayFlexColumn" style={{margin:'20px'}}>
|
||||||
|
{
|
||||||
|
qrCodeShow?<QRCode value={qrCodeValue} size={300} status={qrCodeStatus} onRefresh={() => console.log('refresh')} />:
|
||||||
|
<Image width={300} src="/static/pc-Web.png"/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</LoginFormPage> : <Skeleton/>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -9,6 +9,7 @@ import dayjs from "dayjs";
|
||||||
import {getTaskState, taskPriorityList} from "@/lib/task/project/data";
|
import {getTaskState, taskPriorityList} from "@/lib/task/project/data";
|
||||||
import 'react-virtualized/styles.css';
|
import 'react-virtualized/styles.css';
|
||||||
import RightOption from "@/ui/task/RightOption";
|
import RightOption from "@/ui/task/RightOption";
|
||||||
|
import {CopyOutlined} from "@ant-design/icons";
|
||||||
|
|
||||||
interface DroppableTableProps {
|
interface DroppableTableProps {
|
||||||
tableCode: string,
|
tableCode: string,
|
||||||
|
@ -70,7 +71,7 @@ export const DroppableTable = React.memo((props: DroppableTableProps) => {
|
||||||
<ConfigProvider>
|
<ConfigProvider>
|
||||||
{/* 表头 */}
|
{/* 表头 */}
|
||||||
<div style={headerStyle} className='displayFlexRow'>
|
<div style={headerStyle} className='displayFlexRow'>
|
||||||
<div style={{width: '20%'}} className='displayFlexRow'>{stateName}</div>
|
<div style={{width: '20%',paddingLeft:"1rem"}} className='displayFlexRow'>{stateName}</div>
|
||||||
<div style={{width: '45%'}} className='displayFlexRow'>任务描述</div>
|
<div style={{width: '45%'}} className='displayFlexRow'>任务描述</div>
|
||||||
<div style={{width: '15%'}} className='displayFlexRow'>任务状态</div>
|
<div style={{width: '15%'}} className='displayFlexRow'>任务状态</div>
|
||||||
<div style={{width: '20%'}} className='displayFlexRow'>期望时间</div>
|
<div style={{width: '20%'}} className='displayFlexRow'>期望时间</div>
|
||||||
|
@ -89,7 +90,7 @@ export const DroppableTable = React.memo((props: DroppableTableProps) => {
|
||||||
style={getItemStyle(snapshot.isDragging, {...provided.draggableProps.style})}
|
style={getItemStyle(snapshot.isDragging, {...provided.draggableProps.style})}
|
||||||
className="virtualized-row displayFlexRow"
|
className="virtualized-row displayFlexRow"
|
||||||
>
|
>
|
||||||
<div style={{width: '20%'}} className='displayFlexRow'>
|
<div style={{width: '20%',paddingLeft:"1rem"}} className='displayFlexRow'>
|
||||||
<Tooltip placement="topLeft" title={record.name}
|
<Tooltip placement="topLeft" title={record.name}
|
||||||
className='displayFlexRow'>
|
className='displayFlexRow'>
|
||||||
<div className='displayFlexRow'>{record.name}</div>
|
<div className='displayFlexRow'>{record.name}</div>
|
||||||
|
|
|
@ -17,37 +17,38 @@ import {
|
||||||
} from "@/lib/task/project/data";
|
} from "@/lib/task/project/data";
|
||||||
import {DataType} from "@/lib/definitions";
|
import {DataType} from "@/lib/definitions";
|
||||||
import dayjs, {Dayjs} from "dayjs";
|
import dayjs, {Dayjs} from "dayjs";
|
||||||
|
import DiaryOption from "@/components/DiaryOption";
|
||||||
|
|
||||||
export type DetailModelFormProps={
|
export type DetailModelFormProps = {
|
||||||
// 当前内容id
|
// 当前内容id
|
||||||
itemId?: string,
|
itemId?: string,
|
||||||
pid?:string,
|
pid?: string,
|
||||||
// 祖宗任务id
|
// 祖宗任务id
|
||||||
pPid?:string,
|
pPid?: string,
|
||||||
// 操作id
|
// 操作id
|
||||||
operationId: OPERATION_BUTTON_TYPE,
|
operationId: OPERATION_BUTTON_TYPE,
|
||||||
// 标题描述
|
// 标题描述
|
||||||
description:string,
|
description: string,
|
||||||
// 是否打开界面,用于非按钮操作
|
// 是否打开界面,用于非按钮操作
|
||||||
open:boolean,
|
open: boolean,
|
||||||
// 使用按钮操作
|
// 使用按钮操作
|
||||||
haveButton:boolean,
|
haveButton: boolean,
|
||||||
expectedStartTime?:Dayjs,
|
expectedStartTime?: Dayjs,
|
||||||
expectedEndTime?:Dayjs,
|
expectedEndTime?: Dayjs,
|
||||||
// 重新加载数据
|
// 重新加载数据
|
||||||
reloadData?: () => void
|
reloadData?: () => void
|
||||||
}
|
}
|
||||||
export type PidSelectTree= { label: string; value: string;pid:string; children?: PidSelectTree[] }
|
export type PidSelectTree = { label: string; value: string; pid: string; children?: PidSelectTree[] }
|
||||||
|
|
||||||
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
console.log("DetailModelForm:props:",props)
|
console.log("DetailModelForm:props:", props)
|
||||||
const [form] = Form.useForm<DataType>();
|
const [form] = Form.useForm<DataType>();
|
||||||
const [pid, setPid] = useState<string>(props.pid?props.pid:'0');
|
const [pid, setPid] = useState<string>(props.pid ? props.pid : '0');
|
||||||
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
||||||
// 团队第一层 pid必须为0
|
// 团队第一层 pid必须为0
|
||||||
const [taskType, setTaskType] = useState('0')
|
const [taskType, setTaskType] = useState('0')
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.itemId!=undefined&&(
|
if (props.itemId != undefined && (
|
||||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
||||||
getTask(props.itemId).then(task => {
|
getTask(props.itemId).then(task => {
|
||||||
console.log('DetailModelForm:getTask(props.itemId)', props.itemId, task);
|
console.log('DetailModelForm:getTask(props.itemId)', props.itemId, task);
|
||||||
|
@ -60,38 +61,43 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
task.data.expectedTimeRange = [task.data.expectedStartTime ? dayjs(task.data.expectedStartTime) : undefined,
|
task.data.expectedTimeRange = [task.data.expectedStartTime ? dayjs(task.data.expectedStartTime) : undefined,
|
||||||
task.data.expectedEndTime ? dayjs(task.data.expectedEndTime) : undefined];
|
task.data.expectedEndTime ? dayjs(task.data.expectedEndTime) : undefined];
|
||||||
form.setFieldsValue(task.data)
|
form.setFieldsValue(task.data)
|
||||||
console.log("form.setFieldsValue(task.data)"+JSON.stringify(task.data))
|
console.log("form.setFieldsValue(task.data)" + JSON.stringify(task.data))
|
||||||
} else {
|
} else {
|
||||||
message.error(task.status.message);
|
message.error(task.status.message);
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}else if(props.operationId === OPERATION_BUTTON_TYPE.ADD|| props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD){
|
} else if (props.operationId === OPERATION_BUTTON_TYPE.ADD || props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD) {
|
||||||
let data={'expectedTimeRange':[props.expectedStartTime?props.expectedStartTime:dayjs(), props.expectedEndTime],'pid':props.pid};
|
let data = {
|
||||||
|
'expectedTimeRange': [props.expectedStartTime ? props.expectedStartTime : dayjs(), props.expectedEndTime],
|
||||||
|
'pid': props.pid
|
||||||
|
};
|
||||||
form.setFieldsValue(data)
|
form.setFieldsValue(data)
|
||||||
}
|
}
|
||||||
}, [props])
|
}, [props])
|
||||||
function childReduce(child:DataType[]):PidSelectTree[]{
|
|
||||||
const result:PidSelectTree[] = [];
|
function childReduce(child: DataType[]): PidSelectTree[] {
|
||||||
child.map(data=> {
|
const result: PidSelectTree[] = [];
|
||||||
const resultData:PidSelectTree = {label:data.name,value:data.id,pid:data.pid};
|
child.map(data => {
|
||||||
if (data.children){
|
const resultData: PidSelectTree = {label: data.name, value: data.id, pid: data.pid};
|
||||||
resultData.children=childReduce(data.children);
|
if (data.children) {
|
||||||
|
resultData.children = childReduce(data.children);
|
||||||
}
|
}
|
||||||
result.push(resultData);
|
result.push(resultData);
|
||||||
})
|
})
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不是添加任务需要回显
|
// 如果不是添加任务需要回显
|
||||||
return (
|
return (
|
||||||
<ModalForm<DataType>
|
<ModalForm<DataType>
|
||||||
title={props.description}
|
title={props.description}
|
||||||
open={props.open&&!props.haveButton}
|
open={props.open && !props.haveButton}
|
||||||
trigger={props.haveButton?
|
trigger={props.haveButton ?
|
||||||
<Button type="primary">
|
<Button type="primary">
|
||||||
<PlusOutlined />
|
<PlusOutlined/>
|
||||||
{props.description}
|
{props.description}
|
||||||
</Button>:undefined
|
</Button> : undefined
|
||||||
}
|
}
|
||||||
form={form}
|
form={form}
|
||||||
autoFocusFirstInput
|
autoFocusFirstInput
|
||||||
|
@ -102,10 +108,10 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
props.reloadData?.();
|
props.reloadData?.();
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
submitter={props.itemId!==undefined&&props.itemId!=='-1'?{
|
submitter={props.itemId !== undefined && props.itemId !== '-1' ? {
|
||||||
render: (prop, defaultDoms) => {
|
render: (prop, defaultDoms) => {
|
||||||
return [
|
return [
|
||||||
editFormDisable?<Button
|
editFormDisable ? <Button
|
||||||
key="edit"
|
key="edit"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// props.submit();
|
// props.submit();
|
||||||
|
@ -113,52 +119,55 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
</Button>:undefined,
|
</Button> : undefined,
|
||||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL||props.operationId === OPERATION_BUTTON_TYPE.UPDATE?<Popconfirm
|
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE ?
|
||||||
key ='delete'
|
<Popconfirm
|
||||||
title="删除任务"
|
key='delete'
|
||||||
description="确认要删除任务?"
|
title="删除任务"
|
||||||
icon={<QuestionCircleOutlined style={{color: 'red'}}/>}
|
description="确认要删除任务?"
|
||||||
okText="确认"
|
icon={<QuestionCircleOutlined style={{color: 'red'}}/>}
|
||||||
cancelText="取消"
|
okText="确认"
|
||||||
onConfirm={() => {
|
cancelText="取消"
|
||||||
if (props.itemId!==undefined) {
|
onConfirm={() => {
|
||||||
deleteTask(props.itemId).then((response => {
|
if (props.itemId !== undefined) {
|
||||||
console.log('response', response)
|
deleteTask(props.itemId).then((response => {
|
||||||
if (response.status.success) {
|
console.log('response', response)
|
||||||
message.success("删除任务成功:" + response.data)
|
if (response.status.success) {
|
||||||
props.reloadData?.()
|
message.success("删除任务成功:" + response.data)
|
||||||
}
|
props.reloadData?.()
|
||||||
}));
|
}
|
||||||
}
|
}));
|
||||||
}}
|
}
|
||||||
><Button type="primary" danger>
|
}}
|
||||||
删除
|
>
|
||||||
</Button>
|
<Button type="primary" danger>
|
||||||
</Popconfirm>:undefined
|
删除
|
||||||
|
</Button>
|
||||||
|
</Popconfirm> : undefined
|
||||||
,
|
,
|
||||||
|
<DiaryOption/>,
|
||||||
...defaultDoms
|
...defaultDoms
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
}:undefined}
|
} : undefined}
|
||||||
onFinish={async (values) => {
|
onFinish={async (values) => {
|
||||||
console.log('Received values of form: ', values);
|
console.log('Received values of form: ', values);
|
||||||
if (values.pid===undefined){
|
if (values.pid === undefined) {
|
||||||
values.pid='0'
|
values.pid = '0'
|
||||||
}
|
}
|
||||||
if (values.expectedTimeRange?.[0]!=undefined) {
|
if (values.expectedTimeRange?.[0] != undefined) {
|
||||||
values.expectedStartTime=dayjs(values.expectedTimeRange[0]).format()
|
values.expectedStartTime = dayjs(values.expectedTimeRange[0]).format()
|
||||||
}
|
}
|
||||||
if (values.expectedTimeRange?.[1]!=undefined) {
|
if (values.expectedTimeRange?.[1] != undefined) {
|
||||||
values.expectedEndTime=dayjs(values.expectedTimeRange[1]).format()
|
values.expectedEndTime = dayjs(values.expectedTimeRange[1]).format()
|
||||||
}
|
}
|
||||||
if (values.actualTimeRange?.[0]!=undefined) {
|
if (values.actualTimeRange?.[0] != undefined) {
|
||||||
values.actualStartTime=dayjs(values.actualTimeRange[0]).toDate()
|
values.actualStartTime = dayjs(values.actualTimeRange[0]).toDate()
|
||||||
}
|
}
|
||||||
if (values.actualTimeRange?.[1]!=undefined) {
|
if (values.actualTimeRange?.[1] != undefined) {
|
||||||
values.actualEndTime=dayjs(values.actualTimeRange[1]).toDate()
|
values.actualEndTime = dayjs(values.actualTimeRange[1]).toDate()
|
||||||
}
|
}
|
||||||
var result:boolean=false;
|
var result: boolean = false;
|
||||||
|
|
||||||
let state = taskStateList.find(taskState => taskState.name === values.state?.toString());
|
let state = taskStateList.find(taskState => taskState.name === values.state?.toString());
|
||||||
if (state) {
|
if (state) {
|
||||||
|
@ -169,7 +178,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
values.priority = priority.code
|
values.priority = priority.code
|
||||||
}
|
}
|
||||||
// todo 修改
|
// todo 修改
|
||||||
if (props.operationId === OPERATION_BUTTON_TYPE.UPDATE||(props.operationId === OPERATION_BUTTON_TYPE.DETAIL&&!editFormDisable)) {
|
if (props.operationId === OPERATION_BUTTON_TYPE.UPDATE || (props.operationId === OPERATION_BUTTON_TYPE.DETAIL && !editFormDisable)) {
|
||||||
await updateTask(values).then(response => {
|
await updateTask(values).then(response => {
|
||||||
console.log('response', response)
|
console.log('response', response)
|
||||||
if (response.status.success) {
|
if (response.status.success) {
|
||||||
|
@ -177,16 +186,16 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
// 树任务重新刷新
|
// 树任务重新刷新
|
||||||
// 四象限任务重新刷新
|
// 四象限任务重新刷新
|
||||||
// 如果可以直接更新列表而不请求。。。。。。
|
// 如果可以直接更新列表而不请求。。。。。。
|
||||||
console.log('props.reloadData?.()',props.reloadData)
|
console.log('props.reloadData?.()', props.reloadData)
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
result= true
|
result = true
|
||||||
}else {
|
} else {
|
||||||
message.error(response.status.message)
|
message.error(response.status.message)
|
||||||
result= false
|
result = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}else {
|
} else {
|
||||||
await addTask(values).then(response => {
|
await addTask(values).then(response => {
|
||||||
console.log('response', response)
|
console.log('response', response)
|
||||||
if (response.status.success) {
|
if (response.status.success) {
|
||||||
|
@ -194,12 +203,12 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
// 树任务重新刷新
|
// 树任务重新刷新
|
||||||
// 四象限任务重新刷新
|
// 四象限任务重新刷新
|
||||||
// 如果可以直接更新列表而不请求。。。。。。
|
// 如果可以直接更新列表而不请求。。。。。。
|
||||||
console.log('props.reloadData?.()',props.reloadData)
|
console.log('props.reloadData?.()', props.reloadData)
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
result= true
|
result = true
|
||||||
}else {
|
} else {
|
||||||
message.error(response.status.message)
|
message.error(response.status.message)
|
||||||
result= false
|
result = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -207,9 +216,9 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
return result;
|
return result;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProFormText width="sm" name="id" hidden={true} label="主键" />
|
<ProFormText width="sm" name="id" hidden={true} label="主键"/>
|
||||||
<ProFormText width="sm" name="code" initialValue={props.itemId} hidden={true} label="任务编码" />
|
<ProFormText width="sm" name="code" initialValue={props.itemId} hidden={true} label="任务编码"/>
|
||||||
<ProFormText width="sm" name="pPid" initialValue={props.pPid} hidden={true} label="祖宗id" />
|
<ProFormText width="sm" name="pPid" initialValue={props.pPid} hidden={true} label="祖宗id"/>
|
||||||
<ProForm.Group>
|
<ProForm.Group>
|
||||||
<ProFormSelect
|
<ProFormSelect
|
||||||
required={true}
|
required={true}
|
||||||
|
@ -218,38 +227,52 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
name="taskType"
|
name="taskType"
|
||||||
label="任务类型"
|
label="任务类型"
|
||||||
initialValue='0'
|
initialValue='0'
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
onChange={(value:string, option)=>{
|
onChange={(value: string, option) => {
|
||||||
setTaskType(value)
|
setTaskType(value)
|
||||||
}}
|
}}
|
||||||
rules={[
|
rules={[
|
||||||
{required:true,
|
{
|
||||||
message:"请输入计划类型"
|
required: true,
|
||||||
|
message: "请输入计划类型"
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<ProFormText
|
<ProFormText
|
||||||
required={true}
|
required={true}
|
||||||
hidden={taskType!='1'}
|
hidden={taskType != '1'}
|
||||||
width="sm"
|
width="sm"
|
||||||
name="fName"
|
name="fName"
|
||||||
label="团队名称"
|
label="团队名称"
|
||||||
tooltip="最长为 10 位"
|
tooltip="最长为 10 位"
|
||||||
placeholder="请输入团队名称"
|
placeholder="请输入团队名称"
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
/>
|
/>
|
||||||
<ProFormTreeSelect
|
<ProFormTreeSelect
|
||||||
hidden={taskType=='1'}
|
hidden={taskType == '1'}
|
||||||
width="sm"
|
width="sm"
|
||||||
request={() =>{
|
request={() => {
|
||||||
return getTaskTreeResult(JSON.stringify(
|
return getTaskTreeResult(JSON.stringify(
|
||||||
{pageSize:1000,pageNumber:1,data:[{code:'pid',value:'0',operateType:'='},{code:'state',value:'8,9',operateType:'IN'},{code:'',value:true,operateType: "TREE"}]}
|
{
|
||||||
)).then(result=> childReduce(result.data.content))
|
pageSize: 1000,
|
||||||
|
pageNumber: 1,
|
||||||
|
data: [{code: 'pid', value: '0', operateType: '='}, {
|
||||||
|
code: 'state',
|
||||||
|
value: '8,9',
|
||||||
|
operateType: 'IN'
|
||||||
|
}, {code: '', value: true, operateType: "TREE"}]
|
||||||
|
}
|
||||||
|
)).then(result => childReduce(result.data.content))
|
||||||
}}
|
}}
|
||||||
name="pid"
|
name="pid"
|
||||||
label="父级任务"
|
label="父级任务"
|
||||||
fieldProps={{onSelect: (e,node) => {console.log('onSelect',e,node);setPid(e)}}}
|
fieldProps={{
|
||||||
disabled ={editFormDisable}
|
onSelect: (e, node) => {
|
||||||
|
console.log('onSelect', e, node);
|
||||||
|
setPid(e)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={editFormDisable}
|
||||||
/>
|
/>
|
||||||
<ProFormText
|
<ProFormText
|
||||||
required={true}
|
required={true}
|
||||||
|
@ -258,13 +281,14 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
label="任务名称"
|
label="任务名称"
|
||||||
tooltip="最长为 10 位"
|
tooltip="最长为 10 位"
|
||||||
placeholder="请输入任务名称"
|
placeholder="请输入任务名称"
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
rules={[
|
rules={[
|
||||||
{required:true,
|
{
|
||||||
message:"请输入计划名称"
|
required: true,
|
||||||
},{
|
message: "请输入计划名称"
|
||||||
max:10,
|
}, {
|
||||||
message:"名称长度不易超过10个字"
|
max: 10,
|
||||||
|
message: "名称长度不易超过10个字"
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -275,7 +299,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
label="任务描述"
|
label="任务描述"
|
||||||
// tooltip="最长为 24 位"
|
// tooltip="最长为 24 位"
|
||||||
placeholder="请输入任务描述"
|
placeholder="请输入任务描述"
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ProForm.Group>
|
<ProForm.Group>
|
||||||
|
@ -290,10 +314,11 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
name="priority"
|
name="priority"
|
||||||
label="任务优先级"
|
label="任务优先级"
|
||||||
initialValue='3'
|
initialValue='3'
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
rules={[
|
rules={[
|
||||||
{required:true,
|
{
|
||||||
message:"请选择计划优先级"
|
required: true,
|
||||||
|
message: "请选择计划优先级"
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -308,10 +333,11 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
name="state"
|
name="state"
|
||||||
label="任务状态"
|
label="任务状态"
|
||||||
initialValue='8'
|
initialValue='8'
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
rules={[
|
rules={[
|
||||||
{required:true,
|
{
|
||||||
message:"请选择计划状态"
|
required: true,
|
||||||
|
message: "请选择计划状态"
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -322,16 +348,16 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
initialValue={[dayjs(), undefined]}
|
initialValue={[dayjs(), undefined]}
|
||||||
name="expectedTimeRange"
|
name="expectedTimeRange"
|
||||||
label="期望时间"
|
label="期望时间"
|
||||||
fieldProps={{allowEmpty:[true, true],showTime:true,needConfirm:true}}
|
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
||||||
placeholder={['开始时间','结束时间']}
|
placeholder={['开始时间', '结束时间']}
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
/>
|
/>
|
||||||
<ProFormDateTimeRangePicker
|
<ProFormDateTimeRangePicker
|
||||||
name="actualTimeRange"
|
name="actualTimeRange"
|
||||||
label="实际时间"
|
label="实际时间"
|
||||||
fieldProps={ {allowEmpty:[true, true],showTime:true,needConfirm:true}}
|
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
||||||
placeholder={['开始时间','结束时间']}
|
placeholder={['开始时间', '结束时间']}
|
||||||
disabled ={editFormDisable}
|
disabled={editFormDisable}
|
||||||
/>
|
/>
|
||||||
</ProForm.Group>
|
</ProForm.Group>
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ httpReq.interceptors.request.use((config) => {
|
||||||
if (token) {
|
if (token) {
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
}
|
}
|
||||||
|
config.headers.set("source-client","web")
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
|
Loading…
Reference in New Issue