Compare commits
No commits in common. "b90b63853f3fcc3d95ed66024fe437771332b647" and "4e3bc8ddc20f6ba3204747a7cdb5f9c17b7b6fd8" have entirely different histories.
b90b63853f
...
4e3bc8ddc2
|
@ -1,23 +1,18 @@
|
||||||
'use client'
|
'use client'
|
||||||
import {usePathname,useSearchParams, useRouter} from "next/navigation";
|
import { useRouter} from "next/navigation";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {useEffect} from "react";
|
import {useEffect} from "react";
|
||||||
export default function Home() {
|
import { isMobile } from 'react-device-detect';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
const {replace} = useRouter();
|
const {replace} = useRouter();
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
const pathName = usePathname()
|
|
||||||
const searchParams = useSearchParams()
|
|
||||||
console.log({pathName},{searchParams})
|
|
||||||
if(localStorage.getItem('platform-security')){
|
if(localStorage.getItem('platform-security')){
|
||||||
if (!pathName){
|
if (isMobile){
|
||||||
var callBack = searchParams.get("callBack");
|
replace('/mobile/')
|
||||||
if (callBack){
|
|
||||||
replace(decodeURI(callBack))
|
|
||||||
}else {
|
}else {
|
||||||
replace("/task/project")
|
replace("/task/project")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}else {
|
}else {
|
||||||
replace("/login")
|
replace("/login")
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,6 @@ const DiaryOption = (props: SelectDiary) => {
|
||||||
const [diaryList, setDiaryList] = useState<ListDiary[]>([]);
|
const [diaryList, setDiaryList] = useState<ListDiary[]>([]);
|
||||||
const [diaryReduceList, setDiaryReduceList] = useState<ListDiary[]>([])
|
const [diaryReduceList, setDiaryReduceList] = useState<ListDiary[]>([])
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [selectLoading,setSelectLoading]=useState<boolean>(false);
|
|
||||||
const noMore = {
|
const noMore = {
|
||||||
id: '0',
|
id: '0',
|
||||||
keyId: 'o0',
|
keyId: 'o0',
|
||||||
|
@ -100,7 +99,6 @@ const DiaryOption = (props: SelectDiary) => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setSendValueFlag(true)
|
|
||||||
const fakeDataUrl = process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/message/diary/select`;
|
const fakeDataUrl = process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/message/diary/select`;
|
||||||
fetch(fakeDataUrl, {
|
fetch(fakeDataUrl, {
|
||||||
method: 'POST', headers: {
|
method: 'POST', headers: {
|
||||||
|
@ -123,7 +121,6 @@ const DiaryOption = (props: SelectDiary) => {
|
||||||
listRef.current.scrollTo({top: 9999999});
|
listRef.current.scrollTo({top: 9999999});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setSendValueFlag(false)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,9 +134,9 @@ const DiaryOption = (props: SelectDiary) => {
|
||||||
diaryList.filter(taskLog => {
|
diaryList.filter(taskLog => {
|
||||||
if (currentIndex === 0) {
|
if (currentIndex === 0) {
|
||||||
return true
|
return true
|
||||||
} else if (currentIndex === 1 && taskLog.enableFlag !== "0") {
|
} else if (currentIndex === 1 && taskLog.enableFlag === "1") {
|
||||||
return true
|
return true
|
||||||
} else if (currentIndex === 2 && taskLog.enableFlag !== "1") {
|
} else if (currentIndex === 2 && taskLog.enableFlag === "0") {
|
||||||
return true
|
return true
|
||||||
} else return false;
|
} else return false;
|
||||||
}).reduce((map, taskLog) => {
|
}).reduce((map, taskLog) => {
|
||||||
|
@ -291,6 +288,7 @@ const DiaryOption = (props: SelectDiary) => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
// 点击操作 end
|
// 点击操作 end
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Button type={open?"primary":"default"} onClick={() => setOpen(!open)}>
|
<Button type={open?"primary":"default"} onClick={() => setOpen(!open)}>
|
||||||
|
@ -368,7 +366,7 @@ const DiaryOption = (props: SelectDiary) => {
|
||||||
<Button style={{flexGrow: 1}} onClick={() => setCurrentIndex(2)}
|
<Button style={{flexGrow: 1}} onClick={() => setCurrentIndex(2)}
|
||||||
type={currentIndex == 2 ? "primary" : "default"}>失效</Button>
|
type={currentIndex == 2 ? "primary" : "default"}>失效</Button>
|
||||||
</div>
|
</div>
|
||||||
<List loading={sendValueFlag}>
|
<List>
|
||||||
<VirtualList
|
<VirtualList
|
||||||
data={diaryReduceList}
|
data={diaryReduceList}
|
||||||
height={containerHeight}
|
height={containerHeight}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import React, {Fragment, useEffect, useState} from 'react';
|
import React, {Fragment, useEffect, useState} from 'react';
|
||||||
import {Button, Image, Input, message, Modal, QRCode, Space} from 'antd';
|
import {Button, Image, Input, Modal, QRCode, Space } from 'antd';
|
||||||
import {v4 as uuidv4} from 'uuid';
|
import {v4 as uuidv4} from 'uuid';
|
||||||
import {copyToClipboard} from "@/lib/copyToClipboard";
|
import {copyToClipboard} from "@/lib/copyToClipboard";
|
||||||
import {addTaskPassAPI} from "@/components/service/Share";
|
|
||||||
|
|
||||||
const ShareOption = (props: { taskId: string }) => {
|
const ShareOption = (props: { taskId: string }) => {
|
||||||
// const [loading, setLoading] = useState(false);
|
// const [loading, setLoading] = useState(false);
|
||||||
|
@ -10,7 +9,7 @@ const ShareOption = (props: { taskId: string }) => {
|
||||||
const [buttonIndex, setButtonIndex] = useState(1);
|
const [buttonIndex, setButtonIndex] = useState(1);
|
||||||
const [qrCodeValue, setQrCodeValue] = useState<string>("-");
|
const [qrCodeValue, setQrCodeValue] = useState<string>("-");
|
||||||
const [qrCodeStatus, setQrCodeStatus] = useState<'active' | 'expired' | 'loading' | 'scanned'>("loading");
|
const [qrCodeStatus, setQrCodeStatus] = useState<'active' | 'expired' | 'loading' | 'scanned'>("loading");
|
||||||
const [joinId,setJoinId] = useState("");
|
|
||||||
function doDownload(url: string, fileName: string) {
|
function doDownload(url: string, fileName: string) {
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.download = fileName;
|
a.download = fileName;
|
||||||
|
@ -38,22 +37,7 @@ const ShareOption = (props: { taskId: string }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateQrcode = () => {
|
const generateQrcode = () => {
|
||||||
const clientId: string = uuidv4().substring(0,32);
|
|
||||||
// 分享人必须有权限
|
|
||||||
// 生成分享信息同时适用链接和二维码
|
|
||||||
addTaskPassAPI({taskId:props.taskId,pass:clientId,joinCheck:'1'}).then(res=>{
|
|
||||||
if (res.data.status.success){
|
|
||||||
let qrCodeData = {
|
|
||||||
taskId: props.taskId, pass: clientId,
|
|
||||||
passId: res.data.data.id,
|
|
||||||
local: "马上行计划管理",
|
|
||||||
opType: "SHARE_OPTION"
|
|
||||||
}
|
|
||||||
setJoinId(res.data.data.id!)
|
|
||||||
setQrCodeValue(JSON.stringify(qrCodeData))
|
|
||||||
setQrCodeStatus("active")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const showModal = () => {
|
const showModal = () => {
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
|
@ -63,7 +47,14 @@ const ShareOption = (props: { taskId: string }) => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
generateQrcode()
|
// 分享人必须有权限
|
||||||
|
// 生成分享信息同时适用链接和二维码
|
||||||
|
const clientId: string = uuidv4();
|
||||||
|
let qrCodeData = {
|
||||||
|
taskId: props.taskId, pass: clientId, local: "马上行计划管理", opType: "SHARE_OPTION"
|
||||||
|
}
|
||||||
|
setQrCodeValue(JSON.stringify(qrCodeData))
|
||||||
|
setQrCodeStatus("active")
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -81,22 +72,22 @@ const ShareOption = (props: { taskId: string }) => {
|
||||||
<Button key="back" onClick={handleCancel}>
|
<Button key="back" onClick={handleCancel}>
|
||||||
返回
|
返回
|
||||||
</Button>,
|
</Button>,
|
||||||
// <Button key="qrcode"
|
<Button key="qrcode"
|
||||||
// type={buttonIndex == 1 ? "primary" : "default"}
|
type={buttonIndex == 1 ? "primary" : "default"}
|
||||||
// // loading={loading}
|
// loading={loading}
|
||||||
// onClick={() => setButtonIndex(1)}>
|
onClick={() => setButtonIndex(1)}>
|
||||||
// 使用二维码
|
使用二维码
|
||||||
// </Button>,
|
</Button>,
|
||||||
// <Button
|
<Button
|
||||||
// key="link"
|
key="link"
|
||||||
// // href="https://google.com"
|
// href="https://google.com"
|
||||||
// // target="_blank"
|
// target="_blank"
|
||||||
// type={buttonIndex == 2 ? "primary" : "default"}
|
type={buttonIndex == 2 ? "primary" : "default"}
|
||||||
// // loading={loading}
|
// loading={loading}
|
||||||
// onClick={() => setButtonIndex(2)}
|
onClick={() => setButtonIndex(2)}
|
||||||
// >
|
>
|
||||||
// 使用连接
|
使用连接
|
||||||
// </Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{buttonIndex == 1 && <div className="displayFlexRow">
|
{buttonIndex == 1 && <div className="displayFlexRow">
|
||||||
|
@ -118,8 +109,7 @@ const ShareOption = (props: { taskId: string }) => {
|
||||||
<Space.Compact style={{width: '100%'}}>
|
<Space.Compact style={{width: '100%'}}>
|
||||||
<Input defaultValue="https://www.huaruyu.com" readOnly/>
|
<Input defaultValue="https://www.huaruyu.com" readOnly/>
|
||||||
<Button loading={qrCodeStatus=="loading"}
|
<Button loading={qrCodeStatus=="loading"}
|
||||||
onClick={()=>{copyToClipboard(`https://www.huaruyu.com/task/project?joinId=${joinId}`);
|
onClick={()=>copyToClipboard("https://www.huaruyu.com")}
|
||||||
message.info("复制链接成功过")}}
|
|
||||||
type="primary">复制链接</Button>
|
type="primary">复制链接</Button>
|
||||||
</Space.Compact>
|
</Space.Compact>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import React, {CSSProperties, Fragment, useEffect, useState} from "react";
|
import React, {CSSProperties, Fragment, useState} from "react";
|
||||||
import {DragDropContext, Droppable, Draggable, DropResult, DraggingStyle, NotDraggingStyle} from "react-beautiful-dnd";
|
import {DragDropContext, Droppable, Draggable, DropResult, DraggingStyle, NotDraggingStyle} from "react-beautiful-dnd";
|
||||||
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
||||||
import {Button, Drawer, message, Modal} from "antd";
|
import {Button, Drawer} from "antd";
|
||||||
import TextArea from "antd/es/input/TextArea";
|
|
||||||
import {addStepItemAPI} from "@/components/service/StepSort";
|
// fake data generator
|
||||||
|
const getItems = (count: number, offset = 0) =>
|
||||||
|
Array.from({length: count}, (v, k) => k).map(k => ({
|
||||||
|
id: `item-${k + offset}-${new Date().getTime()}`,
|
||||||
|
stepDesc: `item ${k + offset}`,
|
||||||
|
sortIndex: k + offset,
|
||||||
|
}));
|
||||||
|
|
||||||
const reorder = (list: TaskStepSortVO[], startIndex: number, endIndex: number) => {
|
const reorder = (list: TaskStepSortVO[], startIndex: number, endIndex: number) => {
|
||||||
const result = Array.from(list);
|
const result = Array.from(list);
|
||||||
|
@ -17,33 +23,25 @@ const grid = 8;
|
||||||
const getItemStyle = (isDragging: boolean, draggableStyle: DraggingStyle | NotDraggingStyle | undefined): CSSProperties => ({
|
const getItemStyle = (isDragging: boolean, draggableStyle: DraggingStyle | NotDraggingStyle | undefined): CSSProperties => ({
|
||||||
// some basic styles to make the items look a bit nicer
|
// some basic styles to make the items look a bit nicer
|
||||||
userSelect: "none",
|
userSelect: "none",
|
||||||
// padding: grid,
|
padding: grid * 2,
|
||||||
margin: `0 0 ${grid}px 0`,
|
margin: `0 0 ${grid}px 0`,
|
||||||
background: isDragging ? "lightgreen" : "white",
|
|
||||||
|
// change background colour if dragging
|
||||||
|
background: isDragging ? "lightgreen" : "grey",
|
||||||
|
|
||||||
|
// styles we need to apply on draggables
|
||||||
...draggableStyle
|
...draggableStyle
|
||||||
});
|
});
|
||||||
const getListStyle = (isDraggingOver: boolean) => ({
|
const getListStyle = (isDraggingOver: boolean) => ({
|
||||||
background: isDraggingOver ? "lightblue" : "white",
|
background: isDraggingOver ? "lightblue" : "lightgrey",
|
||||||
width: "100%"
|
padding: grid,
|
||||||
|
width: 250
|
||||||
});
|
});
|
||||||
|
|
||||||
const StepSort = (props: { taskId: string, stepList: TaskStepSortVO[] }) => {
|
const StepSort = (props: { taskId: string }) => {
|
||||||
const [state, setState] = useState<TaskStepSortVO[]>(props.stepList);
|
const [state, setState] = useState<TaskStepSortVO[]>(getItems(5, 10));
|
||||||
// 抽屉 start
|
// 抽屉 start
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [dialogueOpen, setDialogueOpen] = useState(false);
|
|
||||||
const [sortItemList, setSortItemList] = useState<TaskStepSortVO[]>([]);
|
|
||||||
const [modalText, setModalText] = useState<TaskStepSortVO>({
|
|
||||||
id: "",
|
|
||||||
stepDesc: undefined,
|
|
||||||
sortIndex: undefined,
|
|
||||||
taskId: props.taskId,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// 根据任务id查找步骤
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function onDragEnd(result: DropResult) {
|
function onDragEnd(result: DropResult) {
|
||||||
const {source, destination} = result;
|
const {source, destination} = result;
|
||||||
|
@ -55,82 +53,14 @@ const StepSort = (props: { taskId: string, stepList: TaskStepSortVO[] }) => {
|
||||||
let newState = [...state];
|
let newState = [...state];
|
||||||
newState = items;
|
newState = items;
|
||||||
setState(newState);
|
setState(newState);
|
||||||
props.stepList.length=0
|
|
||||||
props.stepList.push(...newState)
|
|
||||||
}
|
|
||||||
|
|
||||||
const [confirmButtonLoading, setConfirmButtonLoading] = useState(false);
|
|
||||||
const confirmModalTextArea = () => {
|
|
||||||
setConfirmButtonLoading(true)
|
|
||||||
addStepItemAPI(modalText).then(res => {
|
|
||||||
if (res.data.status.success) {
|
|
||||||
message.info("添加步骤成功")
|
|
||||||
setModalText(
|
|
||||||
{...modalText, stepDesc: undefined})
|
|
||||||
setState([...state, res.data.data])
|
|
||||||
props.stepList.length=0
|
|
||||||
props.stepList.push(...state, res.data.data)
|
|
||||||
setDialogueOpen(false);
|
|
||||||
} else {
|
|
||||||
message.error(res.data.status.message)
|
|
||||||
}
|
|
||||||
}).finally(()=>{
|
|
||||||
setConfirmButtonLoading(false)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Modal
|
|
||||||
title={`步骤`}
|
|
||||||
closable={false}
|
|
||||||
open={dialogueOpen}
|
|
||||||
confirmLoading={confirmButtonLoading}
|
|
||||||
onCancel={
|
|
||||||
() => {
|
|
||||||
setDialogueOpen(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
destroyOnClose={true}
|
|
||||||
onOk={confirmModalTextArea}
|
|
||||||
>
|
|
||||||
<TextArea autoSize={{minRows: 4, maxRows: 20}}
|
|
||||||
placeholder="最大长度255"
|
|
||||||
showCount
|
|
||||||
styles={{
|
|
||||||
count: {
|
|
||||||
// color:"red",
|
|
||||||
bottom: "0px"
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
value={modalText.sortIndex}
|
|
||||||
maxLength={255} autoFocus
|
|
||||||
onChange={(e) => setModalText(
|
|
||||||
{...modalText, stepDesc: e.target.value})}
|
|
||||||
onKeyDown={event => {
|
|
||||||
if (event.ctrlKey && event.key === 'Enter') {
|
|
||||||
confirmModalTextArea();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Button type={open ? "primary" : "default"} onClick={() => setOpen(!open)}>
|
<Button type={open ? "primary" : "default"} onClick={() => setOpen(!open)}>
|
||||||
查看步骤
|
查看步骤
|
||||||
</Button>
|
</Button>
|
||||||
<Drawer
|
<Drawer>
|
||||||
style={{boxSizing: "border-box"}}
|
|
||||||
styles={{
|
|
||||||
// body: {padding: "0 24px"}
|
|
||||||
}}
|
|
||||||
mask={false}
|
|
||||||
maskClosable={false}
|
|
||||||
title="步骤列表"
|
|
||||||
closable={{'aria-label': 'Close Button'}}
|
|
||||||
onClose={() => setOpen(false)}
|
|
||||||
open={open}
|
|
||||||
footer={<Button type={"primary"} onClick={() => setDialogueOpen(true)}>添加步骤</Button>}
|
|
||||||
>
|
|
||||||
<div style={{display: "flex"}}>
|
<div style={{display: "flex"}}>
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<Droppable key="sortDroppable" droppableId="sortDroppableId">
|
<Droppable key="sortDroppable" droppableId="sortDroppableId">
|
||||||
|
@ -156,17 +86,15 @@ const StepSort = (props: { taskId: string, stepList: TaskStepSortVO[] }) => {
|
||||||
provided.draggableProps.style
|
provided.draggableProps.style
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div>
|
|
||||||
{`步骤${index + 1}`}
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-around"
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div style={{whiteSpace: 'pre-line',border: "solid",
|
|
||||||
borderRadius: grid,}}>
|
|
||||||
{item.stepDesc}
|
{item.stepDesc}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import {TaskMessage} from "@/lib/definitions";
|
|
||||||
import React, {Fragment} from "react";
|
|
||||||
|
|
||||||
const TaskNameAndIcon = (props: {task:TaskMessage}) => {
|
|
||||||
return (<Fragment>
|
|
||||||
{props.task.fId &&
|
|
||||||
<svg className="icon" aria-hidden="true">
|
|
||||||
<use xlinkHref="#icon-tuandui"></use>
|
|
||||||
</svg>
|
|
||||||
}
|
|
||||||
{props.task.taskType == '2' &&
|
|
||||||
<svg className="icon" aria-hidden="true">
|
|
||||||
<use xlinkHref="#icon-youxuliebiao"></use>
|
|
||||||
</svg>
|
|
||||||
}
|
|
||||||
{props.task.taskType == '3' &&
|
|
||||||
<svg className="icon" aria-hidden="true">
|
|
||||||
<use xlinkHref="#icon-dingshi"></use>
|
|
||||||
</svg>
|
|
||||||
}
|
|
||||||
<text>{props.task.name}</text>
|
|
||||||
</Fragment>)
|
|
||||||
}
|
|
||||||
export default TaskNameAndIcon;
|
|
|
@ -1,9 +0,0 @@
|
||||||
import {AxiosResponse} from "axios";
|
|
||||||
import {ResponseVO} from "@/lib/definitions";
|
|
||||||
import {httpReq} from "@/utils/axiosReq";
|
|
||||||
import {ShareVO} from "@/components/type/Share.d";
|
|
||||||
|
|
||||||
export const addTaskPassAPI= (data:ShareVO):Promise<AxiosResponse<ResponseVO<ShareVO>>> =>{
|
|
||||||
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + "/task/pass",
|
|
||||||
data)
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import {AxiosResponse} from "axios";
|
|
||||||
import {ResponseVO} from "@/lib/definitions";
|
|
||||||
import {httpReq} from "@/utils/axiosReq";
|
|
||||||
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
|
||||||
|
|
||||||
export const addStepItemAPI= (data:TaskStepSortVO):Promise<AxiosResponse<ResponseVO<TaskStepSortVO>>> =>{
|
|
||||||
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/step/sort/item`,
|
|
||||||
data)
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export interface ShareVO { taskId: string, pass: string, joinCheck: string ,id?:string}
|
|
|
@ -1,6 +1,5 @@
|
||||||
export type TaskStepSortVO = {
|
export type TaskStepSortVO = {
|
||||||
id: string,
|
id: string,
|
||||||
sortIndex: number|undefined,
|
sortIndex: number,
|
||||||
stepDesc: string|undefined,
|
stepDesc: string
|
||||||
taskId:string
|
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Dayjs} from "dayjs";
|
import {Dayjs} from "dayjs";
|
||||||
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
|
||||||
|
|
||||||
export type Request<T>={
|
export type Request<T>={
|
||||||
data:T,
|
data:T,
|
||||||
|
@ -37,7 +36,6 @@ export type TaskMessage ={
|
||||||
fId?:string;
|
fId?:string;
|
||||||
fName?:string;
|
fName?:string;
|
||||||
taskType?:string;
|
taskType?:string;
|
||||||
stepList?:TaskStepSortVO[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,7 +51,6 @@ export type DataType = TaskMessage&{
|
||||||
actualTimeRange?:(string|Dayjs|undefined)[]
|
actualTimeRange?:(string|Dayjs|undefined)[]
|
||||||
children: DataType[]|undefined;
|
children: DataType[]|undefined;
|
||||||
sortNo?:number;
|
sortNo?:number;
|
||||||
|
|
||||||
}
|
}
|
||||||
export type DictType={
|
export type DictType={
|
||||||
id:number;
|
id:number;
|
||||||
|
|
|
@ -52,7 +52,7 @@ export async function getTask(id: string): Promise<ResponseVO<DataType>> {
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addTask(task: DataType): Promise<AxiosResponse<ResponseVO<DataType>>> {
|
export function addTask(task: DataType): Promise<AxiosResponse<ResponseVO<TaskMessage>>> {
|
||||||
noStore();
|
noStore();
|
||||||
// 使用 Axios 发送 POST 请求添加数据
|
// 使用 Axios 发送 POST 请求添加数据
|
||||||
switch(task.taskType){
|
switch(task.taskType){
|
||||||
|
@ -68,21 +68,12 @@ export function addTask(task: DataType): Promise<AxiosResponse<ResponseVO<DataTy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateTask(task: DataType): Promise<AxiosResponse<ResponseVO<TaskMessage>>> {
|
export async function updateTask(task: DataType): Promise<ResponseVO<string>> {
|
||||||
noStore();
|
noStore();
|
||||||
// 使用 Axios 发送 PUT 请求修改数据
|
// 使用 Axios 发送 PUT 请求修改数据
|
||||||
// 使用 Axios 发送 POST 请求添加数据
|
const response: AxiosResponse<ResponseVO<string>> = await httpReq.put(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/task', task);
|
||||||
switch(task.taskType){
|
// 从响应中提取数据并返回
|
||||||
// 常规任务
|
return response.data;
|
||||||
case '0':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/V2/task', task);
|
|
||||||
// 团队任务
|
|
||||||
case '1':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/V2/task', task);
|
|
||||||
// 顺序
|
|
||||||
case '2':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/task/step/sort', task);
|
|
||||||
// 周期
|
|
||||||
case '3':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/task/schedule', task);
|
|
||||||
default:throw new Error("创建任务必选任务类型");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteTask(id: string): Promise<ResponseVO<string>> {
|
export async function deleteTask(id: string): Promise<ResponseVO<string>> {
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
export interface TaskPassVO {
|
|
||||||
taskId:string;
|
|
||||||
pass:string;
|
|
||||||
shareUser:string;
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
import {DataType, ResponseVO} from "@/lib/definitions";
|
|
||||||
import {unstable_noStore as noStore} from "next/dist/server/web/spec-extension/unstable-no-store";
|
|
||||||
import {AxiosResponse} from "axios";
|
|
||||||
import {httpReq} from "@/utils/axiosReq";
|
|
||||||
import {TaskPassVO} from "@/lib/task/project/team.d";
|
|
||||||
|
|
||||||
export async function getJoinMessageAPI(joinId: string): Promise<ResponseVO<TaskPassVO>> {
|
|
||||||
noStore();
|
|
||||||
// 使用 Axios 发送 PUT 请求获取数据
|
|
||||||
const response: AxiosResponse<ResponseVO<TaskPassVO>> = await httpReq.get(
|
|
||||||
process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/pass/${joinId}`);
|
|
||||||
// 从响应中提取数据并返回
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getTaskInSecurityAPI(requestParam: TaskPassVO): Promise<ResponseVO<DataType>> {
|
|
||||||
noStore();
|
|
||||||
// 使用 Axios 发送 PUT 请求获取数据
|
|
||||||
const response: AxiosResponse<ResponseVO<DataType>> = await httpReq.put(
|
|
||||||
process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/inSecurity/task/${requestParam.taskId}/${requestParam.pass}`);
|
|
||||||
// 从响应中提取数据并返回
|
|
||||||
return response.data;
|
|
||||||
}
|
|
|
@ -24,7 +24,7 @@ html {
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
/* em 当前元素的 font-size 值,如果元素没有显式设置 font-size,则继承父元素的 font-size。 控制与字体大小相关的属性*/
|
/* em 当前元素的 font-size 值,如果元素没有显式设置 font-size,则继承父元素的 font-size。 控制与字体大小相关的属性*/
|
||||||
width: 2em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
vertical-align: -0.15em;
|
vertical-align: -0.15em;
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import React, {useLayoutEffect} from 'react';
|
||||||
import {useState} from 'react';
|
import {useState} from 'react';
|
||||||
import {LoginObject} from "@/lib/login/definitions";
|
import {LoginObject} from "@/lib/login/definitions";
|
||||||
import {useRouter} from 'next/navigation'
|
import {useRouter} from 'next/navigation'
|
||||||
import {v4 as uuidv4} from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import {askLoginAPI, generateQrcodeAPI} from "@/lib/login/service";
|
import {askLoginAPI, generateQrcodeAPI} from "@/lib/login/service";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
|
@ -22,36 +22,33 @@ export default function XcxLoginPage() {
|
||||||
const [qrCodeStatus, setQrCodeStatus] = useState<'active' | 'expired' | 'loading' | 'scanned'>();
|
const [qrCodeStatus, setQrCodeStatus] = useState<'active' | 'expired' | 'loading' | 'scanned'>();
|
||||||
const [qrCodeValue, setQrCodeValue] = useState<string>("-");
|
const [qrCodeValue, setQrCodeValue] = useState<string>("-");
|
||||||
const generateQrcode = () => {
|
const generateQrcode = () => {
|
||||||
if (qrCodeStatus == 'loading') {
|
if (qrCodeStatus=='loading') {
|
||||||
message.info({content: "请耐心等待"})
|
message.info({content:"请耐心等待"})
|
||||||
} else if (qrCodeStatus == 'expired') {
|
}else if (qrCodeStatus=='expired') {
|
||||||
setQrCode()
|
setQrCode()
|
||||||
} else if (qrCodeStatus == 'active') {
|
}else if (qrCodeStatus=='active') {
|
||||||
|
|
||||||
} else if (qrCodeStatus == 'scanned') {
|
}else if (qrCodeStatus=='scanned') {
|
||||||
|
|
||||||
} else {
|
}else {
|
||||||
setQrCode()
|
setQrCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function setQrCode(){
|
||||||
function setQrCode() {
|
|
||||||
// 生成唯一id
|
// 生成唯一id
|
||||||
setQrCodeStatus("loading")
|
setQrCodeStatus("loading")
|
||||||
const clientId: string = uuidv4();
|
const clientId: string = uuidv4();
|
||||||
generateQrcodeAPI({clientId}).then(res => {
|
generateQrcodeAPI({clientId}).then(res=>{
|
||||||
let qrCodeData = {
|
let qrCodeData={
|
||||||
clientId, serverId: res.data.data, local: "马上行计划管理",
|
clientId,serverId:res.data.data,local:"马上行计划管理",
|
||||||
opType: "LOGIN_OPTION"
|
opType:"LOGIN_OPTION"
|
||||||
}
|
}
|
||||||
setQrCodeValue(JSON.stringify(qrCodeData))
|
setQrCodeValue(JSON.stringify(qrCodeData))
|
||||||
setQrCodeStatus("active")
|
setQrCodeStatus("active")
|
||||||
let timeout: ReturnType<typeof setTimeout> | null = null;
|
let timeout=undefined;
|
||||||
// 设置定时器,每2000毫秒(2秒)执行一次myFunction
|
// 设置定时器,每2000毫秒(2秒)执行一次myFunction
|
||||||
let timerId: ReturnType<typeof setInterval> | null = null;
|
let timerId =undefined;
|
||||||
timerId = setInterval(() => {
|
timerId = setInterval(askLogin,2000,timeout,timerId,qrCodeData);
|
||||||
askLogin(timeout, timerId, qrCodeData);
|
|
||||||
}, 2000);
|
|
||||||
// 如果需要停止定时器,可以调用 clearInterval(timerId);
|
// 如果需要停止定时器,可以调用 clearInterval(timerId);
|
||||||
// 例如:1分钟后停止定时器
|
// 例如:1分钟后停止定时器
|
||||||
timeout = setTimeout(() => {
|
timeout = setTimeout(() => {
|
||||||
|
@ -59,21 +56,16 @@ export default function XcxLoginPage() {
|
||||||
clearInterval(timerId);
|
clearInterval(timerId);
|
||||||
console.log("定时器已停止");
|
console.log("定时器已停止");
|
||||||
}, 60000);
|
}, 60000);
|
||||||
}).catch(() => {
|
}).catch(()=>{
|
||||||
setQrCodeStatus("expired")
|
setQrCodeStatus("expired")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function askLogin(timeout:any,timerId:any,qrCodeData:{}){
|
||||||
function askLogin(timeout: ReturnType<typeof setTimeout> | null, timerId: ReturnType<typeof setInterval> | null,
|
askLoginAPI(qrCodeData).then(res=>{
|
||||||
qrCodeData: {}) {
|
if (res.data.status.success&&res.data.data.length>0){
|
||||||
askLoginAPI(qrCodeData).then(res => {
|
|
||||||
if (res.data.status.success && res.data.data.length > 0) {
|
|
||||||
setQrCodeStatus("scanned")
|
setQrCodeStatus("scanned")
|
||||||
console.log({timerId}, {timeout})
|
if(timeout){
|
||||||
if (timeout) {
|
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
}
|
|
||||||
if (timerId) {
|
|
||||||
clearInterval(timerId);
|
clearInterval(timerId);
|
||||||
}
|
}
|
||||||
// localStorage.removeItem("platform-security")
|
// localStorage.removeItem("platform-security")
|
||||||
|
@ -81,28 +73,12 @@ export default function XcxLoginPage() {
|
||||||
// 删除名为 'platform-security' 的Cookie
|
// 删除名为 'platform-security' 的Cookie
|
||||||
// Cookies.remove('platform-security');
|
// Cookies.remove('platform-security');
|
||||||
// 设置一个有效期为7天的Cookie
|
// 设置一个有效期为7天的Cookie
|
||||||
Cookies.set('platform-security', res.data.data[0].token, {expires: 7});
|
Cookies.set('platform-security', res.data.data[0].token, { expires: 7 });
|
||||||
// 获取路径名 (pathname) - 这通常是你所说的“请求路径”
|
|
||||||
console.log(window.location.pathname); // 例如: "/path/to/page"
|
|
||||||
if (window.location.pathname&&window.location.pathname.indexOf("/login")==-1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 获取查询字符串(例如: "?name=John&age=30")
|
|
||||||
const queryString = window.location.search;
|
|
||||||
// 创建 URLSearchParams 对象
|
|
||||||
const urlParams = new URLSearchParams(queryString);
|
|
||||||
let callBack = urlParams.get("callBack")
|
|
||||||
if (callBack) {
|
|
||||||
console.log({queryString}, decodeURIComponent(callBack))
|
|
||||||
router.push(decodeURIComponent(callBack))
|
|
||||||
} else {
|
|
||||||
router.push('/task/project')
|
router.push('/task/project')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 二维码 end
|
// 二维码 end
|
||||||
const {token} = theme.useToken();
|
const {token} = theme.useToken();
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -121,7 +97,7 @@ export default function XcxLoginPage() {
|
||||||
{loaded ? <LoginFormPage
|
{loaded ? <LoginFormPage
|
||||||
backgroundImageUrl="/20-1733751222585.jpg"
|
backgroundImageUrl="/20-1733751222585.jpg"
|
||||||
title="马上行计划管理"
|
title="马上行计划管理"
|
||||||
subTitle={qrCodeShow ? undefined : "使用微信扫码打开小程序"}
|
subTitle={qrCodeShow?undefined:"使用微信扫码打开小程序"}
|
||||||
containerStyle={{
|
containerStyle={{
|
||||||
backgroundColor: 'rgba(0, 0, 0,0.65)',
|
backgroundColor: 'rgba(0, 0, 0,0.65)',
|
||||||
backdropFilter: 'blur(4px)',
|
backdropFilter: 'blur(4px)',
|
||||||
|
@ -134,17 +110,11 @@ export default function XcxLoginPage() {
|
||||||
}
|
}
|
||||||
setQrCodeShow(!qrCodeShow)
|
setQrCodeShow(!qrCodeShow)
|
||||||
}}
|
}}
|
||||||
submitter={{
|
submitter={{ searchConfig: { submitText: qrCodeShow?"在我的-PC扫码登录或者返回":"已打开微信小程序,生成登录码。",resetText: '重置2'}}}
|
||||||
searchConfig: {
|
|
||||||
submitText: qrCodeShow ? "在我的-PC扫码登录或者返回" : "已打开微信小程序,生成登录码。",
|
|
||||||
resetText: '重置2'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="displayFlexColumn" style={{margin: '20px'}}>
|
<div className="displayFlexColumn" style={{margin:'20px'}}>
|
||||||
{
|
{
|
||||||
qrCodeShow ?
|
qrCodeShow?<QRCode value={qrCodeValue} size={300} status={qrCodeStatus} onRefresh={generateQrcode} />:
|
||||||
<QRCode value={qrCodeValue} size={300} status={qrCodeStatus} onRefresh={generateQrcode}/> :
|
|
||||||
<Image width={300} src="/static/pc-Web.png"/>
|
<Image width={300} src="/static/pc-Web.png"/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
'use client'
|
'use client'
|
||||||
import React, {Fragment, useCallback, useContext, useEffect, useMemo, useRef, useState} from "react";
|
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from "react";
|
||||||
import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar'
|
import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar'
|
||||||
import dayjs, {Dayjs} from 'dayjs'
|
import dayjs, {Dayjs} from 'dayjs'
|
||||||
import 'react-big-calendar/lib/css/react-big-calendar.css'
|
import 'react-big-calendar/lib/css/react-big-calendar.css'
|
||||||
|
@ -14,8 +14,6 @@ import LocalContext from "@/ui/LocalContent";
|
||||||
import withDragAndDrop, {EventInteractionArgs} from "react-big-calendar/lib/addons/dragAndDrop";
|
import withDragAndDrop, {EventInteractionArgs} from "react-big-calendar/lib/addons/dragAndDrop";
|
||||||
import {TaskEvent} from "@/lib/task/calendar/data";
|
import {TaskEvent} from "@/lib/task/calendar/data";
|
||||||
import {editExpectAPI} from "@/lib/task/calendar/service";
|
import {editExpectAPI} from "@/lib/task/calendar/service";
|
||||||
import TaskNamePrefixIcon from "@/components/TaskNameAndIcon";
|
|
||||||
import TaskNameAndIcon from "@/components/TaskNameAndIcon";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/jquense/react-big-calendar?tab=readme-ov-file
|
* https://github.com/jquense/react-big-calendar?tab=readme-ov-file
|
||||||
|
@ -118,7 +116,7 @@ const CalShow: React.FC = () => {
|
||||||
return {
|
return {
|
||||||
start: dayjs(taskState.expectedStartTime).toDate(),
|
start: dayjs(taskState.expectedStartTime).toDate(),
|
||||||
end: dayjs(taskState.expectedEndTime).toDate(),
|
end: dayjs(taskState.expectedEndTime).toDate(),
|
||||||
title: <TaskNameAndIcon task={taskState}/>,
|
title: taskState.name,
|
||||||
resource: taskState.id,
|
resource: taskState.id,
|
||||||
id: taskState.id,
|
id: taskState.id,
|
||||||
state: taskState.state,
|
state: taskState.state,
|
||||||
|
@ -273,7 +271,7 @@ const CalShow: React.FC = () => {
|
||||||
haveButton={false}
|
haveButton={false}
|
||||||
itemId={itemId}
|
itemId={itemId}
|
||||||
reloadData={reloadData} expectedStartTime={expectedStartTime}
|
reloadData={reloadData} expectedStartTime={expectedStartTime}
|
||||||
closeOpen={() => setOpen(false)}
|
closeOpen={()=>setOpen(false)}
|
||||||
expectedEndTime={expectedEndTime}/>}
|
expectedEndTime={expectedEndTime}/>}
|
||||||
<DragAndDropCalendar
|
<DragAndDropCalendar
|
||||||
// 本地设置
|
// 本地设置
|
||||||
|
|
|
@ -132,7 +132,6 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
autoFocusFirstInput
|
autoFocusFirstInput
|
||||||
modalProps={{
|
modalProps={{
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
maskClosable:false,
|
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
props.reloadData?.();
|
props.reloadData?.();
|
||||||
},
|
},
|
||||||
|
@ -185,12 +184,12 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
if (editFormDisable && taskType == '1') {
|
if (editFormDisable && taskType == '1') {
|
||||||
result.push(<ShareOption taskId={props.itemId!}/>)
|
result.push(<ShareOption taskId={props.itemId!}/>)
|
||||||
}
|
}
|
||||||
|
if (editFormDisable && taskType == '2') {
|
||||||
|
result.push(<StepSort taskId={props.itemId!}/>)
|
||||||
|
}
|
||||||
result.push(<Button type="primary" key="close"
|
result.push(<Button type="primary" key="close"
|
||||||
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
||||||
}
|
}
|
||||||
if (taskType == '2') {
|
|
||||||
result.push(<StepSort taskId={props.itemId!} stepList={requestTask?.stepList||[]}/>)
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
} : {
|
} : {
|
||||||
|
@ -205,10 +204,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
// }
|
// }
|
||||||
// return defaultDoms;
|
// return defaultDoms;
|
||||||
const result = defaultDoms.filter(defaultButton => defaultButton.key == 'rest');
|
const result = defaultDoms.filter(defaultButton => defaultButton.key == 'rest');
|
||||||
// if (taskType == '2') {
|
result.push(<Button type="primary" key="create-team"
|
||||||
// result.push(<StepSort taskId={props.itemId!} stepList={requestTask?.stepList||[]}/>)
|
|
||||||
// }
|
|
||||||
result.push(<Button type="primary" key="create-team" loading={operationRequest}
|
|
||||||
onClick={() => form.submit()}>{taskType == '1' ? "创建团队" : "确认"}
|
onClick={() => form.submit()}>{taskType == '1' ? "创建团队" : "确认"}
|
||||||
</Button>)
|
</Button>)
|
||||||
return result;
|
return result;
|
||||||
|
@ -253,15 +249,16 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
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.data.status.success) {
|
if (response.status.success) {
|
||||||
message.success("修改任务成功:" + response.data.data.name)
|
message.success("修改任务成功:" + response.data)
|
||||||
// 树任务重新刷新
|
// 树任务重新刷新
|
||||||
// 四象限任务重新刷新
|
// 四象限任务重新刷新
|
||||||
// 如果可以直接更新列表而不请求。。。。。。
|
// 如果可以直接更新列表而不请求。。。。。。
|
||||||
|
console.log('props.reloadData?.()', props.reloadData)
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
result = true
|
result = true
|
||||||
} else {
|
} else {
|
||||||
message.error(response.data.status.message)
|
message.error(response.status.message)
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,8 +267,6 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
await addTask(values).then(response => {
|
await addTask(values).then(response => {
|
||||||
console.log('response', response)
|
console.log('response', response)
|
||||||
if (response.data.status.success) {
|
if (response.data.status.success) {
|
||||||
setRequestTask(response.data.data)
|
|
||||||
|
|
||||||
message.success(`添加计划${response.data.data.name}成功`)
|
message.success(`添加计划${response.data.data.name}成功`)
|
||||||
// 树任务重新刷新
|
// 树任务重新刷新
|
||||||
// 四象限任务重新刷新
|
// 四象限任务重新刷新
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
import {
|
|
||||||
ModalForm,
|
|
||||||
ProForm,
|
|
||||||
ProFormDateTimeRangePicker,
|
|
||||||
ProFormSelect,
|
|
||||||
ProFormText, ProFormTextArea,
|
|
||||||
} from '@ant-design/pro-components';
|
|
||||||
import {Button, Form, message, Spin} from 'antd';
|
|
||||||
import React, {Fragment, useEffect, useState} from "react";
|
|
||||||
import {
|
|
||||||
TASK_TYPE,
|
|
||||||
taskPriorityList,
|
|
||||||
taskStateList
|
|
||||||
} from "@/lib/task/project/data";
|
|
||||||
import {DataType} from "@/lib/definitions";
|
|
||||||
import dayjs, {Dayjs} from "dayjs";
|
|
||||||
import {getJoinMessageAPI, getTaskInSecurityAPI} from "@/lib/task/project/team";
|
|
||||||
|
|
||||||
export type JoinTeamPropsVO = {
|
|
||||||
joinId: string, reloadData: () => void, open: boolean,
|
|
||||||
closeOpen: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const JoinTeam = (props: JoinTeamPropsVO) => {
|
|
||||||
console.log("JoinTeam:props:", props)
|
|
||||||
const [form] = Form.useForm<DataType>();
|
|
||||||
const [requestTask, setRequestTask] = useState<DataType>()
|
|
||||||
const [spinning, setSpinning] = useState(true)
|
|
||||||
const [title, setTitle] = useState("");
|
|
||||||
useEffect(() => {
|
|
||||||
getJoinMessageAPI(props.joinId).then(teamRes => {
|
|
||||||
if (!teamRes.status.success) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setTitle(`来自的${teamRes.data.shareUser}协作邀请`)
|
|
||||||
getTaskInSecurityAPI(teamRes.data).then(task => {
|
|
||||||
if (task.status.success) {
|
|
||||||
setRequestTask(task.data)
|
|
||||||
task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())!.name;
|
|
||||||
task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())!.name;
|
|
||||||
task.data.actualTimeRange = [task.data.actualStartTime ? dayjs(task.data.actualStartTime) : undefined,
|
|
||||||
task.data.actualEndTime ? dayjs(task.data.actualEndTime) : undefined];
|
|
||||||
task.data.expectedTimeRange = [task.data.expectedStartTime ? dayjs(task.data.expectedStartTime) : undefined,
|
|
||||||
task.data.expectedEndTime ? dayjs(task.data.expectedEndTime) : undefined];
|
|
||||||
form.setFieldsValue(task.data)
|
|
||||||
} else {
|
|
||||||
message.error(task.status.message);
|
|
||||||
props.reloadData?.()
|
|
||||||
}
|
|
||||||
}).finally(() => {
|
|
||||||
setSpinning(false)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Fragment>
|
|
||||||
<Spin spinning={spinning} fullscreen/>
|
|
||||||
<ModalForm<DataType>
|
|
||||||
title={title}
|
|
||||||
open={!spinning && props.open}
|
|
||||||
form={form}
|
|
||||||
autoFocusFirstInput
|
|
||||||
modalProps={{
|
|
||||||
destroyOnClose: true,
|
|
||||||
onCancel: () => {
|
|
||||||
props.reloadData?.();
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
readonly={true}
|
|
||||||
submitter={{
|
|
||||||
render: (prop, defaultDoms) => {
|
|
||||||
console.log("submitter render: ", {prop})
|
|
||||||
let result = [
|
|
||||||
<Button type="primary" key="close"
|
|
||||||
onClick={() => props.closeOpen?.()}>拒绝</Button>,
|
|
||||||
<Button type="primary" key="close"
|
|
||||||
onClick={() => props.closeOpen?.()}>关闭</Button>,
|
|
||||||
<Button type="primary" key="close"
|
|
||||||
onClick={() => props.closeOpen?.()}>加入</Button>,
|
|
||||||
]
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
onFinish={async (values) => {
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ProFormText width="sm" name="id" hidden={true} label="主键"/>
|
|
||||||
<ProFormText width="sm" name="code" hidden={true} label="任务编码"/>
|
|
||||||
<ProFormText width="sm" name="pPid" hidden={true} label="祖宗id"/>
|
|
||||||
<ProForm.Group>
|
|
||||||
<ProFormSelect
|
|
||||||
required={true}
|
|
||||||
options={TASK_TYPE}
|
|
||||||
width="sm"
|
|
||||||
name="taskType"
|
|
||||||
label="任务类型"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: "请输入计划类型"
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<ProFormText
|
|
||||||
required={true}
|
|
||||||
width="sm"
|
|
||||||
name="fName"
|
|
||||||
label="团队名称"
|
|
||||||
tooltip="最长为 10 位"
|
|
||||||
placeholder="请输入团队名称"
|
|
||||||
|
|
||||||
/>
|
|
||||||
<ProFormText
|
|
||||||
required={true}
|
|
||||||
width="sm"
|
|
||||||
name="name"
|
|
||||||
label="任务名称"
|
|
||||||
tooltip="最长为 10 位"
|
|
||||||
placeholder="请输入任务名称"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: "请输入计划名称"
|
|
||||||
}, {
|
|
||||||
max: 10,
|
|
||||||
message: "名称长度不易超过10个字"
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</ProForm.Group>
|
|
||||||
<ProFormTextArea
|
|
||||||
width="xl"
|
|
||||||
name="description"
|
|
||||||
label="任务描述"
|
|
||||||
tooltip="最长255个字"
|
|
||||||
placeholder="请输入任务描述"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ProForm.Group>
|
|
||||||
<ProFormSelect
|
|
||||||
request={async () =>
|
|
||||||
taskPriorityList.map
|
|
||||||
(
|
|
||||||
taskState => {
|
|
||||||
return {'label': taskState.name, 'value': taskState.code}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
width="sm"
|
|
||||||
name="priority"
|
|
||||||
label="任务优先级"
|
|
||||||
initialValue='3'
|
|
||||||
rules={[{required: true, message: "请选择计划优先级"}]}
|
|
||||||
/>
|
|
||||||
<ProFormSelect
|
|
||||||
width="sm"
|
|
||||||
options={taskStateList.map(taskState => {
|
|
||||||
return {'label': taskState.name, 'value': taskState.code}
|
|
||||||
})}
|
|
||||||
name="state"
|
|
||||||
label="任务状态"
|
|
||||||
initialValue='8'
|
|
||||||
rules={
|
|
||||||
[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: "请选择计划状态"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ProForm.Group>
|
|
||||||
|
|
||||||
<ProForm.Group>
|
|
||||||
<ProFormDateTimeRangePicker
|
|
||||||
initialValue={[dayjs(), undefined]}
|
|
||||||
name="expectedTimeRange"
|
|
||||||
label="期望时间"
|
|
||||||
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
|
||||||
placeholder={['开始时间', '结束时间']}
|
|
||||||
/>
|
|
||||||
<ProFormDateTimeRangePicker
|
|
||||||
name="actualTimeRange"
|
|
||||||
label="实际时间"
|
|
||||||
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
|
||||||
placeholder={['开始时间', '结束时间']}
|
|
||||||
/>
|
|
||||||
</ProForm.Group>
|
|
||||||
</ModalForm>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -20,9 +20,8 @@ import dayjs from "dayjs";
|
||||||
import '@/ui/task/project/TreeTablePro.modules.css'
|
import '@/ui/task/project/TreeTablePro.modules.css'
|
||||||
import {useSearchParams} from "next/navigation";
|
import {useSearchParams} from "next/navigation";
|
||||||
import {TaskWebSelectVO} from "@/lib/task/project/definitions";
|
import {TaskWebSelectVO} from "@/lib/task/project/definitions";
|
||||||
import TaskNameAndIcon from "@/components/TaskNameAndIcon";
|
|
||||||
|
|
||||||
const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
const TreeTablePro: React.FC = () => {
|
||||||
// 刷新表格
|
// 刷新表格
|
||||||
const actionRef = useRef<ActionType>();
|
const actionRef = useRef<ActionType>();
|
||||||
// 列表和树切换
|
// 列表和树切换
|
||||||
|
@ -56,7 +55,12 @@ const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return <TaskNameAndIcon task={record}/>
|
return <Fragment>
|
||||||
|
{record.fId && <svg className="icon" aria-hidden="true">
|
||||||
|
<use xlinkHref="#icon-tuandui"></use>
|
||||||
|
</svg>}
|
||||||
|
<text>{record.name}</text>
|
||||||
|
</Fragment>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -178,12 +182,6 @@ const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
||||||
}}/></>)
|
}}/></>)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.joinId){
|
|
||||||
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
actionRef.current?.reload(false)
|
actionRef.current?.reload(false)
|
||||||
}, [useSearchParams()])
|
}, [useSearchParams()])
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import axios, {Canceler, CancelToken, CancelTokenSource} from "axios";
|
import axios, {Canceler, CancelToken, CancelTokenSource} from "axios";
|
||||||
import {message} from "antd";
|
import {message} from "antd";
|
||||||
import {usePathname, useSearchParams} from "next/navigation";
|
|
||||||
|
|
||||||
|
|
||||||
export const httpReq = axios.create({
|
export const httpReq = axios.create({
|
||||||
|
@ -54,7 +53,7 @@ httpReq.interceptors.response.use(
|
||||||
message.error('系统异常');
|
message.error('系统异常');
|
||||||
} else if (error.response.status >= 400 && error.response.status <= 500) {
|
} else if (error.response.status >= 400 && error.response.status <= 500) {
|
||||||
message.warning('无权限');
|
message.warning('无权限');
|
||||||
window.location.href = `/login?callBack=${encodeURIComponent(window.location.pathname+window.location.search)}`;
|
window.location.href = '/login';
|
||||||
}
|
}
|
||||||
// switch (error.response.status) {
|
// switch (error.response.status) {
|
||||||
// case 401:
|
// case 401:
|
||||||
|
|
Loading…
Reference in New Issue