feat:1.根据路径展示2.设置主线任务
This commit is contained in:
parent
55ffba0953
commit
09d4357719
|
@ -107,7 +107,7 @@ const ShareOption = (props: { taskId: string }) => {
|
|||
onClick={() => doDownload("/static/pc-Web.png", '微信小程序马上行计划管理.png')}>下载</Button>
|
||||
</div>
|
||||
<div className="displayFlexColumn" id="myqrcode">
|
||||
<div className="title">小程序扫描二维码,有效期7天</div>
|
||||
<div className="title">小程序扫描二维码,有效期1天</div>
|
||||
<QRCode type="svg" value={qrCodeValue} size={300} status={qrCodeStatus}
|
||||
onRefresh={generateQrcode}/>
|
||||
<Button onClick={downloadSvgQRCode}>下载</Button>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.localDiv{
|
||||
margin-bottom: 24px;
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
import styles from "@/components/TaskRemind.module.css";
|
||||
import {CascaderProps, ConfigProvider} from 'antd';
|
||||
import {Cascader} from 'antd';
|
||||
import React, {useState} from "react";
|
||||
|
||||
interface ITaskRemind {
|
||||
remindTypeList: string[],
|
||||
setRemindTypeList: (taskTypeList: string[]) => void,
|
||||
readonly: boolean,
|
||||
}
|
||||
|
||||
interface Option {
|
||||
value?: string | number | null;
|
||||
label: React.ReactNode;
|
||||
children?: Option[];
|
||||
isLeaf?: boolean;
|
||||
}
|
||||
|
||||
const optionLists: Option[] = [
|
||||
{
|
||||
label: "期望开始",
|
||||
value: "expect_start",
|
||||
isLeaf: false,
|
||||
},
|
||||
{
|
||||
label: "期望结束",
|
||||
value: "expect_end",
|
||||
isLeaf: false,
|
||||
},
|
||||
];
|
||||
|
||||
const TaskRemindComponent = (props: ITaskRemind) => {
|
||||
const [options, setOptions] = useState<Option[]>(optionLists);
|
||||
const cascaderOnChange: CascaderProps<Option>['onChange'] = (value: (string | number)[], selectedOptions: Option[]) => {
|
||||
console.log(value, selectedOptions);
|
||||
};
|
||||
const cascaderLoadData = (selectedOptions: Option[]) => {
|
||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
||||
if (targetOption.value === "expect_start" || targetOption.value === "expect_end") {
|
||||
targetOption.children = [
|
||||
{
|
||||
label: `前`,
|
||||
value: 'before',
|
||||
isLeaf: false,
|
||||
},
|
||||
{
|
||||
label: `后`,
|
||||
value: 'after',
|
||||
isLeaf: false,
|
||||
},
|
||||
];
|
||||
} else if (targetOption.value === "before" || targetOption.value === "after") {
|
||||
targetOption.children = Array.from({length: 60}, (_, i) => ({
|
||||
label: i.toString().padStart(2, '0'), // 显示为 "00", "01", ..., "59"
|
||||
value: i,
|
||||
isLeaf: false,
|
||||
}))
|
||||
} else {
|
||||
targetOption.children = [
|
||||
{
|
||||
label: "分钟",
|
||||
value: "m",
|
||||
isLeaf: true,
|
||||
},
|
||||
{
|
||||
label: "小时",
|
||||
value: "h",
|
||||
isLeaf: false,
|
||||
},
|
||||
{
|
||||
label: "天",
|
||||
value: "d",
|
||||
isLeaf: false,
|
||||
}
|
||||
]
|
||||
}
|
||||
setOptions([...options]);
|
||||
}
|
||||
|
||||
return (<div className={styles.localDiv}>
|
||||
<div style={{marginBottom: "8px"}}>提醒</div>
|
||||
{/*{props.readonly ?*/}
|
||||
{/* (props.remindTypeList.length == 0 ? <div>-</div> : props.remindTypeList.map(remindType => {*/}
|
||||
{/* <div>remindType.split(",")</div>*/}
|
||||
{/* })) :*/}
|
||||
{/* (props.remindTypeList.length == 0 ? <Space wrap>*/}
|
||||
{/* <Select*/}
|
||||
{/* style={{width: 120}}*/}
|
||||
{/* allowClear*/}
|
||||
{/* // defaultValue={onceConsumeChange[0]}*/}
|
||||
{/* onChange={(value) => {*/}
|
||||
{/* }}*/}
|
||||
{/* options={[{*/}
|
||||
{/* label: "期望开始",*/}
|
||||
{/* value: "expect_start",*/}
|
||||
{/* }, {*/}
|
||||
{/* label: "期望结束",*/}
|
||||
{/* value: "expect_end",*/}
|
||||
{/* }*/}
|
||||
{/* ]}*/}
|
||||
{/* />*/}
|
||||
{/* <Select*/}
|
||||
{/* style={{width: 120}}*/}
|
||||
{/* allowClear*/}
|
||||
{/* // defaultValue={onceConsumeChange[0]}*/}
|
||||
{/* onChange={(value) => {*/}
|
||||
{/* }}*/}
|
||||
{/* options={[{*/}
|
||||
{/* label: "前",*/}
|
||||
{/* value: "before",*/}
|
||||
{/* }, {*/}
|
||||
{/* label: "后",*/}
|
||||
{/* value: "after",*/}
|
||||
{/* }*/}
|
||||
{/* ]}*/}
|
||||
{/* />*/}
|
||||
{/* <Select*/}
|
||||
{/* style={{width: 120}}*/}
|
||||
{/* allowClear*/}
|
||||
{/* onChange={(value) => {*/}
|
||||
{/* }}*/}
|
||||
{/* options={onceConsumeList}*/}
|
||||
{/* />*/}
|
||||
{/* <Select*/}
|
||||
{/* style={{width: 120}}*/}
|
||||
{/* allowClear*/}
|
||||
{/* // defaultValue={onceConsumeChange[1]}*/}
|
||||
{/* onChange={(value) => {*/}
|
||||
|
||||
{/* }}*/}
|
||||
{/* options={[{label: "分钟", value: "m"}, {label: "小时", value: "h"}, {*/}
|
||||
{/* label: "天",*/}
|
||||
{/* value: "d"*/}
|
||||
{/* }]}*/}
|
||||
{/* />*/}
|
||||
{/* </Space>:props.remindTypeList.map(remindType => {*/}
|
||||
{/* <div>remindType.split(",")</div>*/}
|
||||
{/* }))}*/}
|
||||
|
||||
|
||||
{props.readonly ? (
|
||||
props.remindTypeList.length === 0 ? (
|
||||
<div>-</div>
|
||||
) : (
|
||||
props.remindTypeList.map((remindType, index) => (
|
||||
<div key={index}>{remindType.split(",").join(", ")}</div>
|
||||
))
|
||||
)
|
||||
) : props.remindTypeList.length === 0 ? (
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
Cascader: {
|
||||
/* 这里是你的组件 token */
|
||||
controlWidth:300
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Cascader options={options} loadData={cascaderLoadData} onChange={cascaderOnChange} changeOnSelect defaultValue={["expect_start","after","1","h"]} />
|
||||
</ConfigProvider>
|
||||
) : (
|
||||
props.remindTypeList.map((remindType, index) => (
|
||||
<div key={index}>{remindType.split(",").join(", ")}</div>
|
||||
))
|
||||
)}
|
||||
</div>)
|
||||
}
|
||||
export default TaskRemindComponent
|
|
@ -1,13 +1,13 @@
|
|||
import React, {Fragment, useEffect, useRef, useState} from "react";
|
||||
import {Button, Modal, TablePaginationConfig} from "antd";
|
||||
import {Button, message, Modal, TablePaginationConfig} from "antd";
|
||||
import {ActionType, ProColumns, ProTable} from "@ant-design/pro-components";
|
||||
|
||||
import {Params} from "next/dist/shared/lib/router/utils/route-matcher";
|
||||
import {TeamMemberVO} from "@/components/type/Share.d";
|
||||
import type {FilterValue, SorterResult, TableCurrentDataSource} from "antd/es/table/interface";
|
||||
import {listTeamMemberAPI} from "@/components/service/Share";
|
||||
import {allowAddTeamAPI, listTeamMemberAPI, quitTeamAPI, removeTeamAPI} from "@/components/service/Share";
|
||||
|
||||
const TeamMember = (props: { taskId: string }) => {
|
||||
const TeamMember = (props: { taskId: string,closeOpen?: () => void,reloadData?: () => void }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const onClose = () => {
|
||||
setOpen(false);
|
||||
|
@ -18,20 +18,57 @@ const TeamMember = (props: { taskId: string }) => {
|
|||
const [totalUserList, setTotalUserList] = React.useState<TeamMemberVO[]>([]);
|
||||
const [totalElement, setTotalElement] = React.useState(0);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const [buttonLoading, setButtonLoading] = React.useState(false);
|
||||
const [currentUser, setCurrentUser] =
|
||||
React.useState<{ username: string, adminFlag: boolean }>();
|
||||
const [page,setPage]=React.useState({pageSize:10, pageIndex:1});
|
||||
|
||||
useEffect(() => {
|
||||
if (open){
|
||||
if (open) {
|
||||
setLoading(true);
|
||||
listTeamMemberAPI(props.taskId).then((res)=>{
|
||||
if (res.data.status.success){
|
||||
setUserList(res.data.data.splice(0,10))
|
||||
listTeamMemberAPI(props.taskId).then((res) => {
|
||||
if (res.data.status.success) {
|
||||
setUserList(res.data.data.splice(0, 10))
|
||||
setTotalUserList(res.data.data)
|
||||
setTotalElement(res.data.data.length)
|
||||
setTimeout(()=>{ref.current?.reload()},100)
|
||||
setTimeout(() => {
|
||||
ref.current?.reload()
|
||||
}, 100)
|
||||
}
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
},[open])
|
||||
}, [open])
|
||||
const removeTeam = (teamMember: TeamMemberVO) => {
|
||||
removeTeamAPI(teamMember).then(res => {
|
||||
if (res.data.status.success) {
|
||||
message.success("移除成功")
|
||||
setTotalUserList(res.data.data)
|
||||
setUserList(res.data.data.splice((page.pageIndex - 1) * (page.pageSize), page.pageSize))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const quitTeam = (teamMember: TeamMemberVO) => {
|
||||
quitTeamAPI(teamMember).then(res => {
|
||||
if (res.data.status.success) {
|
||||
message.success('退出成功,随后返回首页')
|
||||
props.reloadData?.()
|
||||
setOpen(!open)
|
||||
props.closeOpen?.()
|
||||
}
|
||||
})
|
||||
}
|
||||
const allowAddTeam = (teamMember: TeamMemberVO) => {
|
||||
allowAddTeamAPI({
|
||||
userId: [teamMember.userId],
|
||||
taskId: props.taskId
|
||||
}).then(res=>{
|
||||
message.success("添加成功")
|
||||
setTotalUserList(res.data.data)
|
||||
setUserList(res.data.data.splice((page.pageIndex - 1) * (page.pageSize), page.pageSize))
|
||||
})
|
||||
}
|
||||
const columns: ProColumns<TeamMemberVO>[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
|
@ -50,7 +87,22 @@ const TeamMember = (props: { taskId: string }) => {
|
|||
key: 'operate',
|
||||
width: 120,
|
||||
valueType: 'option',
|
||||
render: () => [<Button key="1">操作</Button>],
|
||||
render: (node, entity) => {
|
||||
// 管理员可展示提出,普通用户自己展示退出
|
||||
if (currentUser?.adminFlag && entity.userState == '1' && entity.username != currentUser.username) {
|
||||
return <Button key={`${entity.id}remove`} loading={buttonLoading} danger
|
||||
onClick={(event) => removeTeam(entity)}>移出</Button>
|
||||
} else if (currentUser?.adminFlag && entity.userState == '1' && entity.username != currentUser.username) {
|
||||
return <Button key={`${entity.id}myself`} loading={buttonLoading} color='default'>我自己</Button>
|
||||
} else if (!currentUser?.adminFlag && entity.userState == '1' && entity.username != currentUser?.username) {
|
||||
return <Button key={`${entity.id}team`} loading={buttonLoading} color='default'>团队中</Button>
|
||||
} else if (!currentUser?.adminFlag && entity.userState == '1' && entity.username == currentUser?.username) {
|
||||
return <Button key={`${entity.id}quit`} loading={buttonLoading} danger onClick={(event) => quitTeam(entity)}>退出</Button>
|
||||
} else if (entity.userState == '0') {
|
||||
return <Button key={`${entity.id}allow`} loading={buttonLoading} color='primary' onClick={(event) => allowAddTeam(entity)}>允许加入</Button>
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
];
|
||||
return (
|
||||
|
@ -83,8 +135,8 @@ const TeamMember = (props: { taskId: string }) => {
|
|||
// }}
|
||||
/* Pagination */
|
||||
pagination={{
|
||||
defaultPageSize:10,
|
||||
defaultCurrent:1,
|
||||
defaultPageSize: page.pageSize,
|
||||
defaultCurrent: page.pageIndex,
|
||||
total: totalElement,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
|
@ -93,7 +145,11 @@ const TeamMember = (props: { taskId: string }) => {
|
|||
onChange={(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>,
|
||||
sorter: SorterResult<TeamMemberVO> | SorterResult<TeamMemberVO>[], extra:
|
||||
TableCurrentDataSource<TeamMemberVO>) => {
|
||||
setUserList(totalUserList.splice((pagination.current??1-1)*(pagination.pageSize??10),pagination.pageSize))
|
||||
setPage({
|
||||
pageSize: pagination.pageSize||10,
|
||||
pageIndex: pagination.current||1,
|
||||
})
|
||||
setUserList(totalUserList.splice((pagination.current ?? 1 - 1) * (pagination.pageSize ?? 10), pagination.pageSize))
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,4 +9,13 @@ export const addTaskPassAPI= (data:ShareVO):Promise<AxiosResponse<ResponseVO<Sha
|
|||
}
|
||||
export const listTeamMemberAPI = (taskId:string):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
|
||||
return httpReq.get(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/list?taskId=${taskId}`)
|
||||
}
|
||||
export const removeTeamAPI = (teamMember: TeamMemberVO):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
|
||||
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/remove`,teamMember)
|
||||
}
|
||||
export const quitTeamAPI = (teamMember: TeamMemberVO):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
|
||||
return httpReq.delete(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/quite/${teamMember.id}`)
|
||||
}
|
||||
export const allowAddTeamAPI = (teamAllow:any):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
|
||||
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/allow`,teamAllow)
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import React from "react";
|
||||
import {Dayjs} from "dayjs";
|
||||
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
||||
import {Data} from "@dnd-kit/core";
|
||||
|
||||
export type Request<T>={
|
||||
data:T,
|
||||
|
@ -58,7 +57,7 @@ export type DataType = TaskMessage&{
|
|||
actualTimeRange?:(string|Dayjs|undefined)[]
|
||||
children: DataType[]|undefined;
|
||||
sortNo?:number;
|
||||
|
||||
remindType?:string[]
|
||||
}
|
||||
export type DictType={
|
||||
id:number;
|
||||
|
|
|
@ -12,7 +12,9 @@ import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
|||
|
||||
export interface OperationButtonProps {
|
||||
itemId: string,
|
||||
fId:string|undefined,
|
||||
itemName:string,
|
||||
fName:string|undefined,
|
||||
priority?:string,
|
||||
pid: string,
|
||||
pPid: string,
|
||||
|
@ -162,15 +164,15 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
|||
},
|
||||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_TREE,
|
||||
label: <Link href={`/task/project?pid=${this.props.itemId}&pName=${this.props.itemName}`}>树任务显示子任务</Link>,
|
||||
label: <Link href={`/task/project?pid=${this.props.itemId}&pName=${this.props.itemName}${this.props.fId?('&fId='+this.props.fId+"&fName="+this.props.fName):""}`}>树任务显示子任务</Link>,
|
||||
},
|
||||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_FOUR,
|
||||
label: <Link href={`/task/drag?pid=${this.props.itemId}&pName=${this.props.itemName}`}>四象限显示子任务</Link>,
|
||||
label: <Link href={`/task/drag?pid=${this.props.itemId}&pName=${this.props.itemName}${this.props.fId?('&fId='+this.props.fId+"&fName="+this.props.fName):""}`}>四象限显示子任务</Link>,
|
||||
},
|
||||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR,
|
||||
label: <Link href={`/task/calendar?pid=${this.props.itemId}&pName=${this.props.itemName}`}>日历显示子任务</Link>,
|
||||
label: <Link href={`/task/calendar?pid=${this.props.itemId}&pName=${this.props.itemName}${this.props.fId?('&fId='+this.props.fId+"&fName="+this.props.fName):""}`}>日历显示子任务</Link>,
|
||||
}
|
||||
];
|
||||
return <Fragment>
|
||||
|
|
|
@ -7,8 +7,10 @@ import Link from "next/link";
|
|||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||
interface OperationButtonProps {
|
||||
itemId: string,
|
||||
fId:string|undefined,
|
||||
taskType?:string,
|
||||
itemName: string,
|
||||
fName:string|undefined,
|
||||
priority?:string,
|
||||
pid: string,
|
||||
pPid: string,
|
||||
|
@ -89,15 +91,15 @@ const RightOption: React.FC<OperationButtonProps> = (props) => {
|
|||
},
|
||||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_TREE,
|
||||
label: <Link href={`/task/project?pid=${props.itemId}&pName=${props.itemName}`}>树任务显示子任务</Link>,
|
||||
label: <Link href={`/task/project?pid=${props.itemId}&pName=${props.itemName}${props.fId?('&fId='+props.fId+"&fName="+props.fName):""}`}>树任务显示子任务</Link>,
|
||||
},
|
||||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_FOUR,
|
||||
label: <Link href={`/task/drag?pid=${props.itemId}&pName=${props.itemName}`}>四象限显示子任务</Link>,
|
||||
label: <Link href={`/task/drag?pid=${props.itemId}&pName=${props.itemName}${props.fId?('&fId='+props.fId+"&fName="+props.fName):""}`}>四象限显示子任务</Link>,
|
||||
},
|
||||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR,
|
||||
label: <Link href={`/task/calendar?pid=${props.itemId}&pName=${props.itemName}`}>日历显示子任务</Link>,
|
||||
label: <Link href={`/task/calendar?pid=${props.itemId}&pName=${props.itemName}${props.fId?('&fId='+props.fId+"&fName="+props.fName):""}`}>日历显示子任务</Link>,
|
||||
}
|
||||
];
|
||||
// 获取系统样式
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client'
|
||||
import React, {Fragment, useContext, useEffect} from "react";
|
||||
import {Button, Checkbox, CheckboxOptionType, DatePicker, Select, Space} from "antd";
|
||||
import React, {Fragment, useContext, useEffect, useState} from "react";
|
||||
import {Button, Checkbox, CheckboxOptionType, DatePicker, MenuProps, message, Select, Space} from "antd";
|
||||
import {usePathname, useRouter} from "next/navigation";
|
||||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||
import {OPERATION_BUTTON_TYPE, taskStateList} from "@/lib/task/project/data";
|
||||
|
@ -9,6 +9,7 @@ import LocalContext from "@/ui/LocalContent";
|
|||
import {RequestDateType} from "@/ui/task/RequestDateType";
|
||||
import dayjs, {Dayjs} from "dayjs";
|
||||
import {useSearchParams} from "next/dist/client/components/navigation";
|
||||
import Dropdown from "antd/es/dropdown/dropdown";
|
||||
|
||||
interface TitleOperationProps {
|
||||
setTaskState: (value: string) => void;
|
||||
|
@ -22,8 +23,14 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
refreshData
|
||||
}: TitleOperationProps) => {
|
||||
const {replace} = useRouter();
|
||||
console.log('usePathname()', usePathname());
|
||||
console.log('useSearchParams()', useSearchParams().get('pid'));
|
||||
const searchParams = useSearchParams();
|
||||
const pathname = usePathname();
|
||||
|
||||
const [pathParam, setPathParam] = useState<string | undefined>(searchParams.toString());
|
||||
const [pathName, setPathName] = useState(pathname);
|
||||
|
||||
console.log('usePathname()', pathname);
|
||||
console.log('useSearchParams()',searchParams.toString(),searchParams.get('pName'), searchParams.get('pid'));
|
||||
const data = useContext(LocalContext);
|
||||
const {RangePicker} = DatePicker;
|
||||
const expectStartTimeParseResult: RequestDateType[] = data.expectedStartTime.length > 0 ? JSON.parse(data.expectedStartTime) : [undefined, undefined]
|
||||
|
@ -32,17 +39,48 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
expectStartTimeParseResult[0] && expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined,
|
||||
expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
|
||||
];
|
||||
const pName = useSearchParams().get("pName");
|
||||
|
||||
const typeList: CheckboxOptionType<string>[] = [
|
||||
{ label: '计划', value: '0,1,2,3', },
|
||||
{ label: '打卡', value: '4', },
|
||||
{ label: '事件', value: '5', },
|
||||
];
|
||||
|
||||
// ✅ 监听 searchParams 变化
|
||||
useEffect(() => {
|
||||
const pName = searchParams.get("pName");
|
||||
if(pName&&pName!=document.title){
|
||||
document.title = pName;
|
||||
}
|
||||
}, [pName]);
|
||||
setPathParam(searchParams.toString());
|
||||
}, [searchParams]); // searchParams 变化时触发
|
||||
|
||||
const onClick: MenuProps['onClick'] = ({ key }) => {
|
||||
if (key == "1"){
|
||||
|
||||
}else if (key == "2"){
|
||||
replace(pathName)
|
||||
setPathParam(undefined)
|
||||
}
|
||||
};
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
label: '退出登录',
|
||||
key: '1',
|
||||
},
|
||||
];
|
||||
const itemsPid: MenuProps['items'] = [
|
||||
{
|
||||
label: '退出登录',
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
label: '从顶级任务查看',
|
||||
key: '2',
|
||||
},
|
||||
];
|
||||
|
||||
return <div className={style.container}>
|
||||
<Space style={{marginTop: 0, "height": "42px", "alignContent": "center"}}>
|
||||
<DetailModelForm haveButton={true} open={false} operationId={OPERATION_BUTTON_TYPE.ADD}
|
||||
|
@ -50,21 +88,21 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
{
|
||||
!usePathname().startsWith("/task/project") &&
|
||||
<Button type="primary" onClick={() => {
|
||||
replace("/task/project");
|
||||
replace(`/task/project${pathParam?('?'+pathParam):""}`);
|
||||
// setCurrentPath("/task/project")
|
||||
}}>任务树</Button>
|
||||
}
|
||||
{
|
||||
!usePathname().startsWith("/task/drag") &&
|
||||
<Button type="primary" onClick={() => {
|
||||
replace("/task/drag");
|
||||
replace(`/task/drag${pathParam?('?'+pathParam):""}`);
|
||||
// setCurrentPath("/task/four");
|
||||
}}>四象限显示</Button>
|
||||
}
|
||||
{
|
||||
!usePathname().startsWith("/task/calendar") &&
|
||||
<Button type="primary" onClick={() => {
|
||||
replace("/task/calendar");
|
||||
replace(`/task/calendar${pathParam?('?'+pathParam):""}`);
|
||||
// setCurrentPath("/task/project")
|
||||
}}>日历显示</Button>
|
||||
}
|
||||
|
@ -139,8 +177,10 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
</Fragment>
|
||||
}
|
||||
</Space>
|
||||
<Dropdown menu={{ items:pathParam?itemsPid:items, onClick }}>
|
||||
<svg style={{height: "32px", width: "32px", alignItems: "center"}} className="icon" aria-hidden="true">
|
||||
<use xlinkHref="#icon-user__easyico"></use>
|
||||
</svg>
|
||||
</Dropdown>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import dayjs from "dayjs";
|
|||
import {getTaskState, taskPriorityList} from "@/lib/task/project/data";
|
||||
import 'react-virtualized/styles.css';
|
||||
import RightOption from "@/ui/task/RightOption";
|
||||
import {CopyOutlined} from "@ant-design/icons";
|
||||
|
||||
|
||||
interface DroppableTableProps {
|
||||
tableCode: string,
|
||||
|
@ -83,6 +83,7 @@ export const DroppableTable = React.memo((props: DroppableTableProps) => {
|
|||
{(provided, snapshot) => (
|
||||
<RightOption refreshDate={props.refreshDate} itemId={record.id}
|
||||
itemName={record.name} pid={record.pid}
|
||||
fId={record.fId} fName={record.fName}
|
||||
taskType={record.taskType}
|
||||
pPid={record.pPid} children={<div
|
||||
ref={provided.innerRef}
|
||||
|
|
|
@ -152,7 +152,9 @@ const TreeTable: React.FC<TableSearchType> = (props) => {
|
|||
columns={columns}
|
||||
// rowSelection={{ ...rowSelection, checkStrictly}}
|
||||
dataSource={props.resultDataTypeList.filter(resultDataType=>{
|
||||
resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name} pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/>
|
||||
resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name}
|
||||
fId={resultDataType.fId} fName={resultDataType.fName}
|
||||
pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/>
|
||||
if (dataLocalContext.expectedStartTime.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,9 @@ const TreeTable: React.FC<TableSearchType> = (props) => {
|
|||
columns={columns}
|
||||
// rowSelection={{ ...rowSelection, checkStrictly}}
|
||||
dataSource={props.resultDataTypeList.filter(resultDataType=>{
|
||||
resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name} priority={resultDataType.priority} pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/>
|
||||
resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name}
|
||||
fId={resultDataType.fId} fName={resultDataType.fName}
|
||||
priority={resultDataType.priority} pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/>
|
||||
if (dataLocalContext.expectedStartTime.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.localDiv{
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,9 @@ import onceConsumeList from "@/components/constant/onceConsumeList.json"
|
|||
import {onceConsumerRead} from "@/utils/codeToReadName";
|
||||
import style from "@/ui/task/project/DetailModelForm.module.css"
|
||||
import TeamMember from "@/components/TeamMember";
|
||||
import {useSearchParams} from "next/dist/client/components/navigation";
|
||||
import TaskRemindComponent from "@/components/TaskRemindComponent";
|
||||
|
||||
export type DetailModelFormProps = {
|
||||
// 当前内容id
|
||||
itemId?: string,
|
||||
|
@ -49,19 +52,71 @@ export type DetailModelFormProps = {
|
|||
// 重新加载数据
|
||||
reloadData?: () => void
|
||||
}
|
||||
export type PidSelectTree = { label: string; value: string; pid: string; children?: PidSelectTree[] }
|
||||
|
||||
export type PidSelectTree = {
|
||||
label: string;
|
||||
value: string;
|
||||
pid: string;
|
||||
fId: string | undefined,
|
||||
fName: string | undefined,
|
||||
children?: PidSelectTree[]
|
||||
}
|
||||
export type ParentTaskVO = {
|
||||
pid: string,
|
||||
pName: string | undefined,
|
||||
fId: string | undefined,
|
||||
fName: string | undefined,
|
||||
}
|
||||
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||
|
||||
const [form] = Form.useForm<DataType>();
|
||||
const searchParams = useSearchParams();
|
||||
const [requestTask, setRequestTask] = useState<DataType>()
|
||||
console.log("DetailModelForm:props:", props,requestTask)
|
||||
console.log("DetailModelForm:props:", props, requestTask)
|
||||
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
||||
// 团队第一层 pid必须为0
|
||||
const [taskType, setTaskType] = useState('0')
|
||||
const [spinning, setSpinning] = useState(true)
|
||||
const [operationRequest, setOperationRequest] = useState(false)
|
||||
const [onceConsumeChange, setOnceConsumeChange] = useState<string[]>(["1", "h"])
|
||||
const [defaultPTask, setDefaultPTask] = useState<ParentTaskVO>({
|
||||
pid: '0',
|
||||
pName: undefined,
|
||||
fId: undefined,
|
||||
fName: undefined,
|
||||
})
|
||||
const [pTaskMap, setPTaskMap] = useState<Record<string, ParentTaskVO>>()
|
||||
|
||||
const [remindTypeList,setRemindTypeList] = useState<string[]>([])
|
||||
function initData(){
|
||||
form.resetFields()
|
||||
setTaskType('0')
|
||||
setOnceConsumeChange(["1", "h"])
|
||||
setRequestTask(undefined);
|
||||
setDefaultPTask({
|
||||
pid: '0',
|
||||
pName: undefined,
|
||||
fId: undefined,
|
||||
fName: undefined,
|
||||
})
|
||||
}
|
||||
useEffect(() => {
|
||||
if (searchParams && searchParams.get("pid")) {
|
||||
setDefaultPTask({
|
||||
pid: searchParams.get("pid")!,
|
||||
pName: searchParams.get("pName")!,
|
||||
fId: searchParams.get("fId")!,
|
||||
fName: searchParams.get("fName")!,
|
||||
})
|
||||
} else {
|
||||
setDefaultPTask({
|
||||
pid: '0',
|
||||
pName: undefined,
|
||||
fId: undefined,
|
||||
fName: undefined,
|
||||
})
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.itemId != undefined && (
|
||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
||||
|
@ -78,19 +133,26 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
form.setFieldsValue(task.data)
|
||||
if (task.data.pid == "0") {
|
||||
form.setFieldValue("pid", undefined)
|
||||
}else if (searchParams){
|
||||
form.setFieldValue("pid", task.data.pName)
|
||||
}
|
||||
if (task.data.taskType) {
|
||||
setTaskType(task.data.taskType)
|
||||
}
|
||||
setRequestTask(task.data)
|
||||
setDefaultPTask({
|
||||
pid: task.data.pid,
|
||||
pName: task.data.pName,
|
||||
fId: task.data.fId,
|
||||
fName: task.data.fName,
|
||||
})
|
||||
if (task.data.onceConsume) {
|
||||
setOnceConsumeChange(task.data.onceConsume.split(","))
|
||||
}
|
||||
console.log("form.setFieldsValue(task.data)" + JSON.stringify(task.data))
|
||||
} else {
|
||||
message.error(task.status.message);
|
||||
setRequestTask(undefined)
|
||||
form.resetFields()
|
||||
initData()
|
||||
props.reloadData?.()
|
||||
}
|
||||
}).finally(() => {
|
||||
|
@ -111,13 +173,19 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
|
||||
function childReduce(child: DataType[]): PidSelectTree[] {
|
||||
const result: PidSelectTree[] = [];
|
||||
const parentTaskMap: Record<string, ParentTaskVO> = {};
|
||||
child.map(data => {
|
||||
const resultData: PidSelectTree = {label: data.name, value: data.id, pid: data.pid};
|
||||
const resultData: PidSelectTree = {
|
||||
label: data.name, value: data.id, pid: data.pid,
|
||||
fId: data.fId, fName: data.fName
|
||||
};
|
||||
parentTaskMap[data.id] = {pid: data.pid, pName: data.pName, fId: data.fId, fName: data.fName};
|
||||
if (data.children) {
|
||||
resultData.children = childReduce(data.children);
|
||||
}
|
||||
result.push(resultData);
|
||||
})
|
||||
setPTaskMap({...pTaskMap, ...parentTaskMap})
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -145,8 +213,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
destroyOnClose: true,
|
||||
maskClosable: false,
|
||||
onCancel: () => {
|
||||
setRequestTask(undefined)
|
||||
form.resetFields()
|
||||
initData()
|
||||
props.reloadData?.();
|
||||
},
|
||||
}}
|
||||
|
@ -176,8 +243,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
console.log('response', response)
|
||||
if (response.status.success) {
|
||||
message.success("删除任务成功:" + response.data)
|
||||
setRequestTask(undefined)
|
||||
form.resetFields()
|
||||
initData()
|
||||
props.reloadData?.()
|
||||
}
|
||||
}));
|
||||
|
@ -199,7 +265,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
} else {
|
||||
if (editFormDisable && taskType == '1') {
|
||||
result.push(<ShareOption taskId={props.itemId!}/>)
|
||||
result.push(<TeamMember taskId={props.itemId!}/> )
|
||||
result.push(<TeamMember taskId={props.itemId!} closeOpen={props.closeOpen}
|
||||
reloadData={props.reloadData}/>)
|
||||
}
|
||||
result.push(<Button type="primary" key="close"
|
||||
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
||||
|
@ -236,14 +303,15 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
}
|
||||
}
|
||||
onFinish={async (values) => {
|
||||
{/* onFinish 返回true关闭窗口,范湖false不关闭窗口 */
|
||||
}
|
||||
console.log('Received values of form: ', values, {...requestTask, ...values});
|
||||
console.log('Received values of form: ', values,defaultPTask, {...requestTask, ...values});
|
||||
setOperationRequest(true)
|
||||
if (requestTask) {
|
||||
const {sortNo} = requestTask;
|
||||
values.sortNo = sortNo;
|
||||
}
|
||||
values.pid = defaultPTask.pid;
|
||||
values.fId = defaultPTask.fId;
|
||||
values.fName = defaultPTask.fName;
|
||||
if (values.pid === undefined) {
|
||||
values.pid = '0'
|
||||
}
|
||||
|
@ -260,6 +328,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
values.actualEndTime = dayjs(values.actualTimeRange[1]).toDate()
|
||||
}
|
||||
var result: boolean = false;
|
||||
values.remindType=remindTypeList;
|
||||
|
||||
let state = taskStateList.find(taskState => taskState.name === values.state?.toString());
|
||||
if (state) {
|
||||
|
@ -278,8 +347,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
// 树任务重新刷新
|
||||
// 四象限任务重新刷新
|
||||
// 如果可以直接更新列表而不请求。。。。。。
|
||||
setRequestTask(undefined)
|
||||
form.resetFields()
|
||||
initData()
|
||||
props.reloadData?.()
|
||||
result = true
|
||||
} else {
|
||||
|
@ -293,15 +361,15 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
console.log('response', response)
|
||||
if (response.data.status.success) {
|
||||
setRequestTask(response.data.data)
|
||||
|
||||
message.success(`添加计划${response.data.data.name}成功`)
|
||||
// 树任务重新刷新
|
||||
// 四象限任务重新刷新
|
||||
// 如果可以直接更新列表而不请求。。。。。。
|
||||
console.log('props.reloadData?.()', props.reloadData)
|
||||
result = (taskType != '1')
|
||||
setRequestTask(undefined)
|
||||
form.resetFields()
|
||||
if(result){
|
||||
initData()
|
||||
}
|
||||
props.reloadData?.()
|
||||
} else {
|
||||
message.error(response.data.status.message)
|
||||
|
@ -310,6 +378,12 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
}
|
||||
);
|
||||
}
|
||||
setDefaultPTask({
|
||||
pid: '0',
|
||||
pName: undefined,
|
||||
fId: undefined,
|
||||
fName: undefined,
|
||||
})
|
||||
setOperationRequest(false)
|
||||
return result;
|
||||
}}
|
||||
|
@ -322,7 +396,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
required={true}
|
||||
options={TASK_TYPE.map(task =>
|
||||
(task.value == '1' && (requestTask?.id)) ? {...task, disabled: true} : task)}
|
||||
// (task.value == '1' ) ? {...task, disabled: true} : task)}
|
||||
// (task.value == '1' ) ? {...task, disabled: true} : task)}
|
||||
width="sm"
|
||||
name="taskType"
|
||||
label="任务类型"
|
||||
|
@ -353,12 +427,13 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
<ProFormTreeSelect
|
||||
hidden={taskType == '1'}
|
||||
width="sm"
|
||||
initialValue={defaultPTask.pName}
|
||||
request={() => {
|
||||
return getTaskTreeResult(JSON.stringify(
|
||||
{
|
||||
pageSize: 1000,
|
||||
pageNumber: 1,
|
||||
data: [{code: 'pid', value: '0', operateType: '='},
|
||||
data: [{code: 'pid', value: defaultPTask.pid, operateType: '='},
|
||||
// 如果父任务完成会导致父任务不展示
|
||||
// {
|
||||
// code: 'state',
|
||||
|
@ -374,8 +449,21 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
fieldProps={{
|
||||
onSelect: (e, node) => {
|
||||
console.log('onSelect', e, node);
|
||||
// setPid(e)
|
||||
setDefaultPTask(pTaskMap?.[e] || {
|
||||
pid: '0',
|
||||
pName: undefined,
|
||||
fId: undefined,
|
||||
fName: undefined,
|
||||
})
|
||||
},
|
||||
onClear: () => {
|
||||
setDefaultPTask({
|
||||
pid: '0',
|
||||
pName: undefined,
|
||||
fId: undefined,
|
||||
fName: undefined,
|
||||
})
|
||||
}
|
||||
}}
|
||||
disabled={editFormDisable}
|
||||
/>
|
||||
|
@ -406,52 +494,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
placeholder="请输入任务描述"
|
||||
disabled={editFormDisable}
|
||||
/>
|
||||
<div className={style.localDiv}>
|
||||
<Space wrap>
|
||||
<text>提醒:</text>
|
||||
<Select
|
||||
style={{width: 120}}
|
||||
allowClear
|
||||
// defaultValue={onceConsumeChange[0]}
|
||||
onChange={(value) => {
|
||||
}}
|
||||
options={[{label: "期望开始",
|
||||
value: "expect_start",},{label: "期望结束",
|
||||
value: "expect_end",}
|
||||
]}
|
||||
/>
|
||||
<Select
|
||||
style={{width: 120}}
|
||||
allowClear
|
||||
// defaultValue={onceConsumeChange[0]}
|
||||
onChange={(value) => {
|
||||
}}
|
||||
options={[{label: "前",
|
||||
value: "before",},{label: "后",
|
||||
value: "after",}
|
||||
]}
|
||||
/>
|
||||
<Select
|
||||
style={{width: 120}}
|
||||
allowClear
|
||||
onChange={(value) => {
|
||||
}}
|
||||
options={onceConsumeList}
|
||||
/>
|
||||
<Select
|
||||
style={{width: 120}}
|
||||
allowClear
|
||||
// defaultValue={onceConsumeChange[1]}
|
||||
onChange={(value) => {
|
||||
|
||||
}}
|
||||
options={[{label: "分钟", value: "m"}, {label: "小时", value: "h"}, {
|
||||
label: "天",
|
||||
value: "d"
|
||||
}]}
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
<TaskRemindComponent remindTypeList={remindTypeList} setRemindTypeList={(a:string[])=>setRemindTypeList(a)} readonly={editFormDisable} />
|
||||
<ProForm.Group>
|
||||
<ProFormSelect
|
||||
request={async () =>
|
||||
|
@ -520,7 +563,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
{taskType == "3" &&
|
||||
<Fragment>
|
||||
{editFormDisable ?
|
||||
<div className={style.localDiv} >
|
||||
<div className={style.localDiv}>
|
||||
<text>单次耗时:{onceConsumerRead(requestTask?.onceConsume)}</text>
|
||||
</div> :
|
||||
<div className={style.localDiv}>
|
||||
|
|
|
@ -156,7 +156,9 @@ const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
|||
key: 'option',
|
||||
title: '操作',
|
||||
valueType: 'option',
|
||||
render: (_, record) => <OperationButton itemId={record.id} itemName={record.name} pid={record.pid} pPid={record.pPid}
|
||||
render: (_, record) => <OperationButton itemId={record.id} itemName={record.name}
|
||||
fId={record.fId} fName={record.fName}
|
||||
pid={record.pid} pPid={record.pPid}
|
||||
priority={record.priority}
|
||||
refreshDate={() => {
|
||||
actionRef.current?.reload(false);
|
||||
|
|
Loading…
Reference in New Issue