2024-04-17 22:38:47 -04:00
|
|
|
'use client'
|
2024-04-25 04:36:40 -04:00
|
|
|
import {
|
2025-08-18 06:52:28 -04:00
|
|
|
CheckSquareFilled, CopyOutlined,
|
2024-04-25 04:36:40 -04:00
|
|
|
QuestionCircleOutlined
|
|
|
|
} from '@ant-design/icons';
|
2024-04-28 22:50:41 -04:00
|
|
|
import type {ActionType, FormInstance, ProColumns, ProFormInstance} from '@ant-design/pro-components';
|
2024-04-22 02:47:08 -04:00
|
|
|
import {ProTable, TableDropdown} from '@ant-design/pro-components';
|
2025-08-13 06:58:05 -04:00
|
|
|
import {DatePicker, Dropdown, Space, Switch, Tag, Tooltip} from 'antd';
|
2025-06-11 06:33:27 -04:00
|
|
|
import React, {Fragment, useContext, useEffect, useRef} from 'react';
|
2024-05-10 04:00:35 -04:00
|
|
|
import {DataType} from "@/lib/definitions";
|
2024-04-24 01:54:59 -04:00
|
|
|
import {
|
2025-08-06 06:58:51 -04:00
|
|
|
getTaskTreeResultAPI,
|
2024-04-24 01:54:59 -04:00
|
|
|
OPERATION_BUTTON_TYPE,
|
|
|
|
taskPriorityList,
|
|
|
|
taskStateList,
|
2024-05-10 04:00:35 -04:00
|
|
|
} from "@/lib/task/project/data";
|
|
|
|
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
|
|
|
import OperationButton from "@/ui/task/OperationButton";
|
2024-04-28 22:50:41 -04:00
|
|
|
import dayjs from "dayjs";
|
2024-05-28 06:54:58 -04:00
|
|
|
import '@/ui/task/project/TreeTablePro.modules.css'
|
2025-01-06 05:55:20 -05:00
|
|
|
import {useSearchParams} from "next/navigation";
|
2025-06-17 07:01:54 -04:00
|
|
|
import {TaskWebSelectVO} from "@/lib/task/project/definitions";
|
2025-07-31 07:18:20 -04:00
|
|
|
import TaskNameAndIcon from "@/components/TaskNameAndIcon";
|
2025-08-18 06:52:28 -04:00
|
|
|
import {copyToClipboard} from "@/lib/copyToClipboard";
|
2025-08-25 06:49:01 -04:00
|
|
|
import LocalContext from "@/ui/LocalContent";
|
2025-06-11 06:33:27 -04:00
|
|
|
|
2025-08-13 06:58:05 -04:00
|
|
|
const TreeTablePro: React.FC = (props: { joinId?: string }) => {
|
2025-06-17 07:01:54 -04:00
|
|
|
// 刷新表格
|
2024-04-25 04:36:40 -04:00
|
|
|
const actionRef = useRef<ActionType>();
|
2025-06-17 07:01:54 -04:00
|
|
|
// 列表和树切换
|
2024-04-25 04:36:40 -04:00
|
|
|
const [switchChecked, setSwitchChecked] = React.useState(true);
|
2025-06-17 07:01:54 -04:00
|
|
|
// 树子集是否参与过滤
|
2024-04-25 04:36:40 -04:00
|
|
|
const [filterChecked, setFilterChecked] = React.useState(true);
|
2025-06-17 07:01:54 -04:00
|
|
|
// 页码信息
|
2025-09-09 06:54:05 -04:00
|
|
|
const [currentPage, setCurrentPage] = React.useState(1);
|
2025-06-17 07:01:54 -04:00
|
|
|
const [pageSize, setPageSize] = React.useState(10);
|
2025-08-25 06:49:01 -04:00
|
|
|
const {taskState: state} = useContext(LocalContext);
|
2025-06-17 07:01:54 -04:00
|
|
|
// 获取路径参数pid
|
2025-01-13 06:33:53 -05:00
|
|
|
const pathPid = useSearchParams().get('pid');
|
2025-06-17 07:01:54 -04:00
|
|
|
const pid = pathPid ? pathPid : '0';
|
|
|
|
// 时间范围选择
|
|
|
|
const {RangePicker} = DatePicker;
|
|
|
|
// 列字段定义
|
2024-04-25 04:36:40 -04:00
|
|
|
const columns: ProColumns<DataType>[] = [
|
|
|
|
{
|
2024-05-06 01:57:58 -04:00
|
|
|
key: 'name',
|
2024-04-25 04:36:40 -04:00
|
|
|
title: '任务名称',
|
|
|
|
dataIndex: 'name',
|
|
|
|
width: '15%',
|
|
|
|
copyable: true,
|
|
|
|
ellipsis: true,
|
|
|
|
tooltip: '标题过长会自动收缩',
|
|
|
|
formItemProps: {
|
|
|
|
rules: [
|
|
|
|
{
|
|
|
|
required: true,
|
|
|
|
message: '此项为必填项',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
2025-06-17 07:01:54 -04:00
|
|
|
render: (_, record) => {
|
2025-08-13 06:58:05 -04:00
|
|
|
return <TaskNameAndIcon task={record}/>
|
2025-06-11 06:33:27 -04:00
|
|
|
}
|
2024-04-22 02:47:08 -04:00
|
|
|
},
|
2024-04-25 04:36:40 -04:00
|
|
|
{
|
2024-05-06 01:57:58 -04:00
|
|
|
key: 'description',
|
2024-04-25 04:36:40 -04:00
|
|
|
title: '任务描述',
|
|
|
|
dataIndex: 'description',
|
2025-08-06 06:58:51 -04:00
|
|
|
render: (_, record) => {
|
2025-08-18 06:52:28 -04:00
|
|
|
return <Fragment>
|
|
|
|
|
|
|
|
<Tooltip placement="topLeft" title={record.description}>
|
|
|
|
<div className='text-ellipsis'>{record.description && <CopyOutlined onClick={(e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
copyToClipboard(record.description)
|
|
|
|
}}/>}{record.description}</div>
|
|
|
|
</Tooltip>
|
|
|
|
</Fragment>
|
2025-08-06 06:58:51 -04:00
|
|
|
}
|
2024-04-24 01:54:59 -04:00
|
|
|
},
|
2024-04-25 04:36:40 -04:00
|
|
|
{
|
2024-05-06 01:57:58 -04:00
|
|
|
key: 'priority',
|
2024-04-25 04:36:40 -04:00
|
|
|
title: '任务优先级',
|
|
|
|
dataIndex: 'priority',
|
2025-06-17 07:01:54 -04:00
|
|
|
order: 2,
|
2024-04-25 04:36:40 -04:00
|
|
|
valueType: 'select',
|
2025-06-17 07:01:54 -04:00
|
|
|
// 字段对应的组件的属性
|
2024-04-25 04:36:40 -04:00
|
|
|
fieldProps: {
|
2025-06-17 07:01:54 -04:00
|
|
|
mode: "tags",
|
2024-04-25 04:36:40 -04:00
|
|
|
options: taskPriorityList.map(item => {
|
|
|
|
return {label: item.name, value: item.code}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
render: (_, record) => (
|
|
|
|
<Space>
|
|
|
|
{
|
|
|
|
// <Tag color={taskPriorityList.find(item => item.code === record.priority?.toString())?.color}
|
|
|
|
// key={taskPriorityList.find(item => item.code === record.priority?.toString())?.code}>
|
|
|
|
// {taskPriorityList.find(item => item.code === record.priority?.toString())?.name}
|
|
|
|
// </Tag>
|
|
|
|
<div>
|
|
|
|
{/*< HeartFilled/>*/}
|
2025-06-17 07:01:54 -04:00
|
|
|
<CheckSquareFilled
|
|
|
|
style={{color: taskPriorityList.find(item => item.code === record.priority?.toString())?.color}}/>
|
2024-04-25 04:36:40 -04:00
|
|
|
{taskPriorityList.find(item => item.code === record.priority?.toString())?.name}
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</Space>
|
|
|
|
),
|
2024-05-06 01:57:58 -04:00
|
|
|
}, {
|
|
|
|
key: 'state',
|
2024-04-25 04:36:40 -04:00
|
|
|
title: '任务状态',
|
|
|
|
dataIndex: 'state',
|
|
|
|
valueType: 'select',
|
2025-06-17 07:01:54 -04:00
|
|
|
order: 3,
|
2025-08-25 06:49:01 -04:00
|
|
|
initialValue: state =="" ?undefined:state!.split(','),
|
2024-04-25 04:36:40 -04:00
|
|
|
fieldProps: {
|
2025-08-25 06:49:01 -04:00
|
|
|
defaultValue: state =="" ?undefined:state!.split(','),
|
2025-06-17 07:01:54 -04:00
|
|
|
mode: "tags",
|
2024-04-25 04:36:40 -04:00
|
|
|
options: taskStateList.map(item => {
|
|
|
|
return {label: item.name, value: item.code}
|
2024-05-06 01:57:58 -04:00
|
|
|
}),
|
2024-04-25 04:36:40 -04:00
|
|
|
},
|
2024-05-06 01:57:58 -04:00
|
|
|
}, {
|
|
|
|
key: 'expectedStartTime',
|
2025-06-17 07:01:54 -04:00
|
|
|
title: '期望时间',
|
2024-04-25 04:36:40 -04:00
|
|
|
dataIndex: 'expectedStartTime',
|
|
|
|
valueType: 'date',
|
2025-06-17 07:01:54 -04:00
|
|
|
order: 1,
|
|
|
|
render: (_, record) => {
|
|
|
|
return <Fragment>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<text>开始:</text>
|
|
|
|
{record.expectedStartTime ? dayjs(record.expectedStartTime).format("YYYY-MM-DD HH:mm") : "-"}
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<text>结束:</text>
|
|
|
|
{record.expectedEndTime ? dayjs(record.expectedEndTime).format("YYYY-MM-DD HH:mm") : "-"}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Fragment>
|
|
|
|
},
|
|
|
|
renderFormItem: () => <RangePicker allowEmpty={[true, true]}/>
|
2024-05-06 01:57:58 -04:00
|
|
|
}, {
|
|
|
|
key: 'actualStartTime',
|
2025-06-17 07:01:54 -04:00
|
|
|
title: '实际时间',
|
2024-04-25 04:36:40 -04:00
|
|
|
dataIndex: 'actualStartTime',
|
|
|
|
valueType: 'date',
|
2025-06-17 07:01:54 -04:00
|
|
|
render: (_, record) => {
|
|
|
|
return <Fragment>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<text>开始:</text>
|
|
|
|
{record.actualStartTime ? dayjs(record.actualStartTime).format("YYYY-MM-DD HH:mm") : "-"}
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<text>结束:</text>
|
|
|
|
{record.actualEndTime ? dayjs(record.actualEndTime).format("YYYY-MM-DD HH:mm") : "-"}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Fragment>
|
|
|
|
},
|
2024-05-06 01:57:58 -04:00
|
|
|
}, {
|
2024-04-25 04:36:40 -04:00
|
|
|
key: 'option',
|
2024-05-06 01:57:58 -04:00
|
|
|
title: '操作',
|
2024-04-25 04:36:40 -04:00
|
|
|
valueType: 'option',
|
2025-08-07 07:27:37 -04:00
|
|
|
render: (_, record) => <OperationButton itemId={record.id} itemName={record.name}
|
|
|
|
fId={record.fId} fName={record.fName}
|
|
|
|
pid={record.pid} pPid={record.pPid}
|
2025-08-06 06:58:51 -04:00
|
|
|
priority={record.priority}
|
2025-06-17 07:01:54 -04:00
|
|
|
refreshDate={() => {
|
|
|
|
actionRef.current?.reload(false);
|
|
|
|
}}/>,
|
2024-04-25 04:36:40 -04:00
|
|
|
}
|
|
|
|
];
|
|
|
|
let toolBarRenderList = [
|
2025-06-17 07:01:54 -04:00
|
|
|
<DetailModelForm open={false} haveButton={true} key={1} operationId={OPERATION_BUTTON_TYPE.ADD}
|
|
|
|
description='添加主线任务' reloadData={() => {
|
|
|
|
actionRef.current?.reload(false);
|
2024-04-28 22:50:41 -04:00
|
|
|
}}/>,
|
2024-05-06 01:57:58 -04:00
|
|
|
<Switch key={2} checkedChildren="树" unCheckedChildren="列表" checked={switchChecked}
|
2025-06-17 07:01:54 -04:00
|
|
|
onChange={(checked, event) => {
|
|
|
|
setSwitchChecked(checked);
|
2025-08-14 06:53:07 -04:00
|
|
|
actionRef.current?.reload?.();
|
2025-06-17 07:01:54 -04:00
|
|
|
}}/>,
|
2024-04-25 04:36:40 -04:00
|
|
|
];
|
2025-06-17 07:01:54 -04:00
|
|
|
if (switchChecked) {
|
|
|
|
toolBarRenderList.push(<><span>树子集是否参与过滤</span> <Tooltip
|
|
|
|
title="开启树子集过滤后儿子不满足条件,孙子满足条件,儿子和孙子都不会显示。"><QuestionCircleOutlined/></Tooltip>
|
2024-04-25 04:36:40 -04:00
|
|
|
<Switch checkedChildren="是" unCheckedChildren="否" checked={filterChecked}
|
2025-06-17 07:01:54 -04:00
|
|
|
onChange={(checked, event) => {
|
|
|
|
setFilterChecked(checked);
|
|
|
|
actionRef.current?.reload(false);
|
|
|
|
}}/></>)
|
2024-04-24 01:54:59 -04:00
|
|
|
}
|
2025-01-06 05:55:20 -05:00
|
|
|
|
2025-07-30 06:43:37 -04:00
|
|
|
useEffect(() => {
|
2025-08-13 06:58:05 -04:00
|
|
|
if (props.joinId) {
|
2025-07-30 06:43:37 -04:00
|
|
|
|
|
|
|
}
|
|
|
|
}, []);
|
|
|
|
|
2025-06-17 07:01:54 -04:00
|
|
|
useEffect(() => {
|
|
|
|
actionRef.current?.reload(false)
|
|
|
|
}, [useSearchParams()])
|
2024-04-17 22:38:47 -04:00
|
|
|
return (
|
|
|
|
<ProTable<DataType>
|
|
|
|
columns={columns}
|
2024-04-24 01:54:59 -04:00
|
|
|
actionRef={actionRef}
|
2024-04-17 22:38:47 -04:00
|
|
|
cardBordered
|
|
|
|
request={async (params, sort, filter) => {
|
2025-06-17 07:01:54 -04:00
|
|
|
// console.log('request',params,params.keyword,sort, filter);
|
|
|
|
// const searchList=[]
|
|
|
|
// if (switchChecked) {
|
|
|
|
// searchList.push({name:'tree',value:'TRUE',operateType:"TREE"})
|
|
|
|
// }
|
|
|
|
// searchList.push({name:"pid",value:pid,operateType:"="})
|
|
|
|
// if (filterChecked) {
|
|
|
|
// searchList.push({name:'tree',value:'TRUE',operateType:"TREE-FILTER"})
|
|
|
|
// }
|
|
|
|
// if (params.state instanceof Array&¶ms.state.length>0){
|
|
|
|
// searchList.push({name:'state',value:params.state.join(','),operateType:"IN"})
|
|
|
|
// }
|
|
|
|
// if (params.priority instanceof Array&¶ms.state.length>0){
|
|
|
|
// searchList.push({name:'priority',value:params.priority.join(','),operateType:"IN"})
|
|
|
|
// }
|
|
|
|
// if (params.expectedStartTime instanceof Array&¶ms.expectedStartTime.length>0){
|
|
|
|
// if (params.expectedStartTime[0]){
|
|
|
|
// searchList.push({name:'expectedStartTime',value:dayjs(params.expectedStartTime[0]),operateType:">="})
|
|
|
|
// }
|
|
|
|
// if (params.expectedStartTime[1]){
|
|
|
|
// searchList.push({name:'expectedStartTime',value:dayjs(params.expectedStartTime[1]),operateType:"<="})
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// if (params.name){
|
|
|
|
// searchList.push({name:'name',value:params.name,operateType:"LIKE"})
|
|
|
|
// }
|
|
|
|
// if (params.description){
|
|
|
|
// searchList.push({name:'description',value:params.description,operateType:"LIKE"})
|
|
|
|
// }
|
|
|
|
// if (params.code){
|
|
|
|
// searchList.push({name:'code',value:params.code,operateType:"="})
|
|
|
|
// }
|
|
|
|
// let request = JSON.stringify({
|
|
|
|
// pageSize:params.pageSize,
|
|
|
|
// pageNumber:params.current,
|
|
|
|
// data: searchList
|
|
|
|
// })
|
|
|
|
// // const response = await getTaskTreeResult(request)
|
2025-08-14 06:53:07 -04:00
|
|
|
console.log({params})
|
2025-06-17 07:01:54 -04:00
|
|
|
const search: TaskWebSelectVO =
|
|
|
|
{
|
|
|
|
pid: pid,
|
|
|
|
name: params.name,
|
|
|
|
description: params.description,
|
|
|
|
}
|
2025-08-18 06:52:28 -04:00
|
|
|
// 列表展示
|
2025-08-13 06:58:05 -04:00
|
|
|
if (!switchChecked) {
|
2025-08-18 06:52:28 -04:00
|
|
|
search.treeOrList = false;
|
|
|
|
search.treeList = true;
|
|
|
|
search.treeFilter = true;
|
|
|
|
} else {
|
2025-08-13 06:58:05 -04:00
|
|
|
// 树展示
|
2025-08-18 06:52:28 -04:00
|
|
|
search.treeOrList = true;
|
|
|
|
search.treeList = true;
|
|
|
|
search.treeFilter = filterChecked;
|
2025-08-13 06:58:05 -04:00
|
|
|
}
|
2025-06-17 07:01:54 -04:00
|
|
|
if (params.state) {
|
|
|
|
search.state = params.state.join(',');
|
2024-04-24 01:54:59 -04:00
|
|
|
}
|
2025-06-17 07:01:54 -04:00
|
|
|
if (params.priority) {
|
|
|
|
search.priority = params.priority.join(',');
|
2024-04-24 01:54:59 -04:00
|
|
|
}
|
2025-06-17 07:01:54 -04:00
|
|
|
if (params.expectedStartTime instanceof Array && params.expectedStartTime.length > 0) {
|
|
|
|
if (params.expectedStartTime[0]) {
|
|
|
|
search.expectedStartTimeStart = dayjs(params.expectedStartTime[0])
|
2024-04-28 22:50:41 -04:00
|
|
|
}
|
2025-06-17 07:01:54 -04:00
|
|
|
if (params.expectedStartTime[1]) {
|
|
|
|
search.expectedStartTimeEnd = dayjs(params.expectedStartTime[1])
|
2024-04-28 22:50:41 -04:00
|
|
|
}
|
|
|
|
}
|
2025-06-17 07:01:54 -04:00
|
|
|
|
|
|
|
const response1 = await getTaskTreeResultAPI({
|
|
|
|
pageSize: params.pageSize ? params.pageSize : pageSize,
|
2025-09-09 06:54:05 -04:00
|
|
|
pageNumber: params.current ? params.current : currentPage,
|
2025-06-17 07:01:54 -04:00
|
|
|
data: search
|
2024-04-24 01:54:59 -04:00
|
|
|
})
|
2025-06-17 07:01:54 -04:00
|
|
|
|
2024-04-17 22:38:47 -04:00
|
|
|
return {
|
2025-06-17 07:01:54 -04:00
|
|
|
data: response1.data.content,
|
|
|
|
success: response1.status.success,
|
|
|
|
total: response1.data.totalElements,
|
2024-04-17 22:38:47 -04:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
editable={{
|
|
|
|
type: 'multiple',
|
|
|
|
}}
|
|
|
|
columnsState={{
|
|
|
|
persistenceKey: 'pro-table-singe-demos',
|
|
|
|
persistenceType: 'localStorage',
|
|
|
|
defaultValue: {
|
2024-04-22 02:47:08 -04:00
|
|
|
option: {fixed: 'right', disable: true},
|
2024-04-17 22:38:47 -04:00
|
|
|
},
|
2024-04-22 02:47:08 -04:00
|
|
|
// onChange(value) {
|
|
|
|
// console.log('value: ', value);
|
|
|
|
// },
|
2024-04-17 22:38:47 -04:00
|
|
|
}}
|
|
|
|
rowKey="id"
|
2024-05-28 06:54:58 -04:00
|
|
|
rowClassName={(record, i) => (i % 2 === 1 ? "even" : "odd")}
|
2024-04-17 22:38:47 -04:00
|
|
|
pagination={{
|
2025-09-09 06:54:05 -04:00
|
|
|
current: currentPage,
|
2024-04-28 22:50:41 -04:00
|
|
|
pageSize: pageSize,
|
2025-06-17 07:01:54 -04:00
|
|
|
onChange: (current, pageSize) => {
|
|
|
|
console.log('onChange', current, pageSize)
|
2025-09-09 06:54:05 -04:00
|
|
|
setCurrentPage(current)
|
2024-04-28 22:50:41 -04:00
|
|
|
setPageSize(pageSize)
|
|
|
|
}
|
2024-04-17 22:38:47 -04:00
|
|
|
}}
|
|
|
|
dateFormatter="string"
|
2025-06-23 06:49:52 -04:00
|
|
|
// scroll={{y: 580}}
|
2024-04-24 01:54:59 -04:00
|
|
|
// headerTitle="任务管理"
|
2025-06-17 07:01:54 -04:00
|
|
|
toolBarRender={() => toolBarRenderList}>
|
2024-04-25 04:36:40 -04:00
|
|
|
</ProTable>
|
2024-04-17 22:38:47 -04:00
|
|
|
);
|
|
|
|
};
|
|
|
|
export default TreeTablePro
|