feat:去除四象限滚动条
This commit is contained in:
parent
47aeb7c228
commit
135bf4ff41
|
@ -12,7 +12,7 @@
|
||||||
# next.js
|
# next.js
|
||||||
/.next/
|
/.next/
|
||||||
/out/
|
/out/
|
||||||
|
/docker/out/
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"react-big-calendar": "^1.12.2",
|
"react-big-calendar": "^1.12.2",
|
||||||
"react-device-detect": "^2.2.3",
|
"react-device-detect": "^2.2.3",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
"react-virtualized": "^9.22.6",
|
||||||
"sass": "^1.77.3",
|
"sass": "^1.77.3",
|
||||||
"tailwindcss": "3.3.3"
|
"tailwindcss": "3.3.3"
|
||||||
},
|
},
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-big-calendar": "^1.8.9",
|
"@types/react-big-calendar": "^1.8.9",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
|
"@types/react-virtualized": "^9.22.2",
|
||||||
"@vercel/style-guide": "^5.0.1",
|
"@vercel/style-guide": "^5.0.1",
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "14.2.29",
|
"eslint-config-next": "14.2.29",
|
||||||
|
@ -1647,6 +1649,16 @@
|
||||||
"redux": "^4.0.0"
|
"redux": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-virtualized": {
|
||||||
|
"version": "9.22.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/react-virtualized/-/react-virtualized-9.22.2.tgz",
|
||||||
|
"integrity": "sha512-0Eg/ME3OHYWGxs+/n4VelfYrhXssireZaa1Uqj5SEkTpSaBu5ctFGOCVxcOqpGXRiEdrk/7uho9tlZaryCIjHA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/prop-types": "*",
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/scheduler": {
|
"node_modules/@types/scheduler": {
|
||||||
"version": "0.16.8",
|
"version": "0.16.8",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz",
|
||||||
|
@ -6318,6 +6330,23 @@
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/react-virtualized": {
|
||||||
|
"version": "9.22.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/react-virtualized/-/react-virtualized-9.22.6.tgz",
|
||||||
|
"integrity": "sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.7.2",
|
||||||
|
"clsx": "^1.0.4",
|
||||||
|
"dom-helpers": "^5.1.3",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/reactcss": {
|
"node_modules/reactcss": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
|
"resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
|
||||||
|
@ -8919,6 +8948,16 @@
|
||||||
"redux": "^4.0.0"
|
"redux": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-virtualized": {
|
||||||
|
"version": "9.22.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/react-virtualized/-/react-virtualized-9.22.2.tgz",
|
||||||
|
"integrity": "sha512-0Eg/ME3OHYWGxs+/n4VelfYrhXssireZaa1Uqj5SEkTpSaBu5ctFGOCVxcOqpGXRiEdrk/7uho9tlZaryCIjHA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/prop-types": "*",
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/scheduler": {
|
"@types/scheduler": {
|
||||||
"version": "0.16.8",
|
"version": "0.16.8",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz",
|
||||||
|
@ -12437,6 +12476,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-virtualized": {
|
||||||
|
"version": "9.22.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/react-virtualized/-/react-virtualized-9.22.6.tgz",
|
||||||
|
"integrity": "sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.7.2",
|
||||||
|
"clsx": "^1.0.4",
|
||||||
|
"dom-helpers": "^5.1.3",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"reactcss": {
|
"reactcss": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
|
"resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
"react-big-calendar": "^1.12.2",
|
"react-big-calendar": "^1.12.2",
|
||||||
"react-device-detect": "^2.2.3",
|
"react-device-detect": "^2.2.3",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
"react-virtualized": "^9.22.6",
|
||||||
"sass": "^1.77.3",
|
"sass": "^1.77.3",
|
||||||
"tailwindcss": "3.3.3"
|
"tailwindcss": "3.3.3"
|
||||||
},
|
},
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-big-calendar": "^1.8.9",
|
"@types/react-big-calendar": "^1.8.9",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
|
"@types/react-virtualized": "^9.22.2",
|
||||||
"@vercel/style-guide": "^5.0.1",
|
"@vercel/style-guide": "^5.0.1",
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "14.2.29",
|
"eslint-config-next": "14.2.29",
|
||||||
|
|
|
@ -21,8 +21,11 @@ export default function RootLayout({
|
||||||
<title>任务管理</title>
|
<title>任务管理</title>
|
||||||
<link rel="icon" href="/favicon.ico"/>
|
<link rel="icon" href="/favicon.ico"/>
|
||||||
<script src="/static/iconfont.js"></script>
|
<script src="/static/iconfont.js"></script>
|
||||||
|
{/*FOUC,Flash of Unstyled Content*/}
|
||||||
|
{/*<link rel="preload" href="https://cdn.jsdelivr.net/npm/antd/dist/antd.min.css" as="style"/>*/}
|
||||||
|
{/*<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/antd/dist/antd.min.css"/>*/}
|
||||||
</head>
|
</head>
|
||||||
<body style={{margin: 0,padding:0,maxHeight:"100vh",overflow:"hidden"}}>{children}</body>
|
<body style={{margin: 0, padding: 0, maxHeight: "100vh", overflow: "hidden"}}>{children}</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
* A layout is UI that is shared between multiple routes. On navigation, layouts preserve state, remain interactive, and do not re-render.
|
* A layout is UI that is shared between multiple routes. On navigation, layouts preserve state, remain interactive, and do not re-render.
|
||||||
*/
|
*/
|
||||||
'use client'
|
'use client'
|
||||||
import React, { useState} from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import {DragDropContext, DropResult} from 'react-beautiful-dnd';
|
import {DragDropContext, DropResult} from 'react-beautiful-dnd';
|
||||||
import {DroppableTable} from "@/ui/task/drag/DroppableTable";
|
import {DroppableTable} from "@/ui/task/drag/DroppableTable";
|
||||||
import {DataType, Request} from "@/lib/definitions";
|
import {DataType, Request} from "@/lib/definitions";
|
||||||
import {useEffect} from "react";
|
|
||||||
import {TaskSelectVO} from "@/lib/task/drag/data";
|
import {TaskSelectVO} from "@/lib/task/drag/data";
|
||||||
import {selectTaskAPI} from "@/lib/task/drag/service";
|
import {selectTaskAPI} from "@/lib/task/drag/service";
|
||||||
|
|
||||||
|
@ -14,13 +13,13 @@ export default function Layout({children}: { children: React.ReactNode }) {
|
||||||
const [allTaskList, setAllTaskList] = useState<DataType[]>([]);
|
const [allTaskList, setAllTaskList] = useState<DataType[]>([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
addData()
|
addData()
|
||||||
},[])
|
}, [])
|
||||||
|
|
||||||
async function addData() {
|
async function addData() {
|
||||||
const requestParam: Request<TaskSelectVO> = {
|
const requestParam: Request<TaskSelectVO> = {
|
||||||
pageSize: 1000,
|
pageSize: 1000,
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
data: {state:'9'}
|
data: {state: '9'}
|
||||||
}
|
}
|
||||||
const res = await selectTaskAPI(requestParam)
|
const res = await selectTaskAPI(requestParam)
|
||||||
setAllTaskList(res.data.content)
|
setAllTaskList(res.data.content)
|
||||||
|
@ -41,9 +40,8 @@ export default function Layout({children}: { children: React.ReactNode }) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (<div style={{display: 'flex', flexWrap: 'wrap', boxSizing: 'border-box', width: '100vw'}}>
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<div style={{display: 'flex',flexWrap: 'wrap',boxSizing: 'border-box',width:'100vw'}}>
|
|
||||||
{/* 紧急重要 */}
|
{/* 紧急重要 */}
|
||||||
<DroppableTable tableCode='3' taskList={allTaskList.filter(task => task.priority == '3')}/>
|
<DroppableTable tableCode='3' taskList={allTaskList.filter(task => task.priority == '3')}/>
|
||||||
{/* 不紧急重要 */}
|
{/* 不紧急重要 */}
|
||||||
|
@ -52,7 +50,7 @@ export default function Layout({children}: { children: React.ReactNode }) {
|
||||||
<DroppableTable tableCode="1" taskList={allTaskList.filter(task => task.priority == '1')}/>
|
<DroppableTable tableCode="1" taskList={allTaskList.filter(task => task.priority == '1')}/>
|
||||||
{/* 不紧急不重要 */}
|
{/* 不紧急不重要 */}
|
||||||
<DroppableTable tableCode='0' taskList={allTaskList.filter(task => task.priority == '0')}/>
|
<DroppableTable tableCode='0' taskList={allTaskList.filter(task => task.priority == '0')}/>
|
||||||
</div>
|
</DragDropContext></div>
|
||||||
</DragDropContext>
|
)
|
||||||
);
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export default function Page() {
|
|
||||||
return <p>Dashboard test</p>;
|
|
||||||
}
|
|
|
@ -88,6 +88,15 @@ export async function deleteTaskAPI(id: string): Promise<ResponseVO<string>> {
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTaskState(code:string){
|
||||||
|
return taskStateList.filter(taskState => code==taskState.code)[0];
|
||||||
|
}
|
||||||
|
export const TASK_TYPE:{label:string,value:string}[]=[
|
||||||
|
{label:"常规",value:"0"},
|
||||||
|
{label:"团队",value:"1"},
|
||||||
|
{label:"顺序",value:"2"},
|
||||||
|
{label:"周期",value:"3"}
|
||||||
|
]
|
||||||
//0,重要紧急红色,1,重要不紧急黄色,2,不重要紧急灰色,3不重要,不紧急绿色
|
//0,重要紧急红色,1,重要不紧急黄色,2,不重要紧急灰色,3不重要,不紧急绿色
|
||||||
export const taskPriorityList: DictType[] = [
|
export const taskPriorityList: DictType[] = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,4 +30,24 @@ html {
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-right: 0.5em;
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
.displayFlexRow{
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start; /* 水平居中 */
|
||||||
|
align-items: center; /* 垂直居中 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.displayFlexColumn{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start; /* 水平居中 */
|
||||||
|
align-items: center; /* 垂直居中 */
|
||||||
|
}
|
||||||
|
.scrollHidden{
|
||||||
|
overflow: auto;
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
-ms-overflow-style: none; /* IE和Edge */
|
||||||
|
}
|
||||||
|
.scrollHidden::-webkit-scrollbar {
|
||||||
|
display: none; /* Chrome, Safari, Opera */
|
||||||
}
|
}
|
|
@ -163,7 +163,7 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: OPERATION_BUTTON_TYPE.SHOW_FOUR,
|
key: OPERATION_BUTTON_TYPE.SHOW_FOUR,
|
||||||
label: <Link href={"/task/four?pid=" + this.props.itemId}>四象限显示子任务</Link>,
|
label: <Link href={"/task/drag?pid=" + this.props.itemId}>四象限显示子任务</Link>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR,
|
key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR,
|
||||||
|
|
|
@ -43,9 +43,9 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
}}>任务树</Button>
|
}}>任务树</Button>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
!usePathname().startsWith("/task/four") &&
|
!usePathname().startsWith("/task/drag") &&
|
||||||
<Button type="primary" onClick={() => {
|
<Button type="primary" onClick={() => {
|
||||||
replace("/task/four");
|
replace("/task/drag");
|
||||||
// setCurrentPath("/task/four");
|
// setCurrentPath("/task/four");
|
||||||
}}>四象限显示</Button>
|
}}>四象限显示</Button>
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/*四相线需要状态时间*/
|
/*四相线需要状态时间*/
|
||||||
usePathname().startsWith("/task/four") && <Fragment>
|
usePathname().startsWith("/task/drag") && <Fragment>
|
||||||
<span style={{whiteSpace: 'nowrap'}}>期望开始时间范围:</span>
|
<span style={{whiteSpace: 'nowrap'}}>期望开始时间范围:</span>
|
||||||
<RangePicker
|
<RangePicker
|
||||||
placeholder={['开始时间', '结束时间']}
|
placeholder={['开始时间', '结束时间']}
|
||||||
|
@ -114,6 +114,12 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
/*日历需要状态*/
|
||||||
|
!usePathname().startsWith("/task/project") && <Fragment>
|
||||||
|
<Button>搜索</Button>
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
</Space>
|
</Space>
|
||||||
<svg style={{height: "32px", width: "32px", alignItems: "center"}} className="icon" aria-hidden="true">
|
<svg style={{height: "32px", width: "32px", alignItems: "center"}} className="icon" aria-hidden="true">
|
||||||
<use xlinkHref="#icon-user__easyico"></use>
|
<use xlinkHref="#icon-user__easyico"></use>
|
||||||
|
|
|
@ -1,176 +1,145 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, {CSSProperties, useEffect} from "react";
|
import React, {CSSProperties} from "react";
|
||||||
import {Draggable, Droppable} from "react-beautiful-dnd";
|
import {Draggable, Droppable} from "react-beautiful-dnd";
|
||||||
import {ConfigProvider, Table, TableProps, Tooltip} from "antd";
|
import {ConfigProvider, Tooltip} from "antd";
|
||||||
import {DataType} from "@/lib/definitions";
|
import {DataType} from "@/lib/definitions";
|
||||||
import './index.modules.css'
|
import './index.modules.css'
|
||||||
import dayjs, {Dayjs} from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {taskPriorityList} from "@/lib/task/project/data";
|
import {getTaskState, taskPriorityList} from "@/lib/task/project/data";
|
||||||
|
import {List as VirtualizedList, AutoSizer} from "react-virtualized";
|
||||||
|
import 'react-virtualized/styles.css';
|
||||||
|
import OperationButton from "@/ui/task/OperationButton";
|
||||||
|
|
||||||
interface DroppableTableProps // extends DragDropContextProps
|
interface DroppableTableProps {
|
||||||
{
|
tableCode: string,
|
||||||
tableCode:string,
|
taskList: DataType[]
|
||||||
taskList:DataType[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DroppableTable: React.FC<DroppableTableProps> = (props) => {
|
export const DroppableTable = React.memo((props: DroppableTableProps) => {
|
||||||
|
const stateName = React.useMemo(() => {
|
||||||
const [stateName, setStateName] = React.useState("");
|
switch (props.tableCode) {
|
||||||
useEffect(() => {
|
case '0':
|
||||||
if(props.tableCode=='0'){
|
return '不紧急不重要';
|
||||||
setStateName('不紧急不重要');
|
case '1':
|
||||||
}else if (props.tableCode=='1'){
|
return '紧急不重要';
|
||||||
setStateName('紧急不重要');
|
case '2':
|
||||||
}else if (props.tableCode=='2'){
|
return '不紧急重要';
|
||||||
setStateName('不紧急重要');
|
case '3':
|
||||||
}else if (props.tableCode=='3'){
|
return '紧急重要';
|
||||||
setStateName('紧急重要');
|
default:
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
}, [props]);
|
}, [props.tableCode]);
|
||||||
const getItemStyle = (isDragging:any, draggableStyle:any):CSSProperties => {
|
|
||||||
console.log({draggableStyle})
|
const getItemStyle = React.useCallback((isDragging: boolean, draggableStyle: any): CSSProperties => ({
|
||||||
return {
|
|
||||||
// some basic styles to make the items look a bit nicer
|
|
||||||
userSelect: "none",
|
userSelect: "none",
|
||||||
// change background colour if dragging
|
background: isDragging ? "lightgreen" : "white",
|
||||||
background: isDragging ? "lightgreen" : "grey",
|
position: 'relative', // 确保 zIndex 生效
|
||||||
// styles we need to apply on draggables
|
zIndex: isDragging ? 2147483647 : 'auto', // 使用 'auto' 代替 0 可能更好
|
||||||
...draggableStyle,
|
...draggableStyle,
|
||||||
height:80
|
borderBottom: '1px solid #f0f0f0',
|
||||||
}};
|
boxSizing: 'border-box',
|
||||||
|
// verticalAlign: 'middle',
|
||||||
|
// textAlign: 'center',
|
||||||
|
}), []);
|
||||||
|
|
||||||
const getListStyle = (isDraggingOver:boolean) => ({
|
const getListStyle = React.useCallback((isDraggingOver: boolean) => ({
|
||||||
background: isDraggingOver ? "lightblue" : "lightgrey",
|
background: isDraggingOver ? "lightblue" : "white",
|
||||||
overflow:'hidden'
|
height: 'calc((100vh - 42px)/2)',
|
||||||
});
|
width: '50vw'
|
||||||
|
}), []);
|
||||||
|
|
||||||
function isDayjs(obj: unknown): obj is Dayjs {
|
const rowRenderer = React.useCallback(({index, key, style}: {
|
||||||
return obj != null && typeof (obj as Dayjs).format === 'function';
|
index: number;
|
||||||
}
|
key: string;
|
||||||
|
style: React.CSSProperties
|
||||||
|
}) => {
|
||||||
|
const record = props.taskList[index];
|
||||||
|
if (!record) return null;
|
||||||
|
|
||||||
// 渲染表格行
|
return (
|
||||||
// @ts-ignore
|
<Draggable key={record.id} draggableId={record.id} index={index}>
|
||||||
const renderTableRow = (data: DataType[], droppableId: string): TableProps<Item>['components']['body']['row'] =>
|
{(provided, snapshot) => (
|
||||||
(props:any) => {
|
<div
|
||||||
// console.log({props, droppableId});
|
ref={provided.innerRef}
|
||||||
const { children, ...restProps } = props;
|
{...provided.draggableProps}
|
||||||
const record = data.find((item) => item.id === restProps['data-row-key']);
|
{...provided.dragHandleProps}
|
||||||
const index = data.findIndex((item) => item.id === restProps['data-row-key']);
|
style={getItemStyle(snapshot.isDragging, {...provided.draggableProps.style, ...style})}
|
||||||
if (!record) {
|
className="virtualized-row displayFlexRow"
|
||||||
// console.error('Invalid record at index:', index);
|
>
|
||||||
return null; // 或者返回一个占位符
|
<div style={{width: '15%'}} className='displayFlexRow'>
|
||||||
}
|
<Tooltip placement="topLeft" title={record.name} className='displayFlexRow'>
|
||||||
return (
|
<div className='displayFlexRow'>{record.name}</div>
|
||||||
<Draggable key={record.id} draggableId={record.id} index={index}>
|
</Tooltip>
|
||||||
{(provided,snapshot) => (
|
</div>
|
||||||
<tr
|
<div style={{width: '40%' , boxSizing: 'border-box', minWidth: 0}} className='displayFlexRow'>
|
||||||
ref={provided.innerRef}
|
<Tooltip placement="topLeft" title={record.description}>
|
||||||
{...provided.draggableProps}
|
<div className='displayFlexRow'>{record.description}</div>
|
||||||
{...provided.dragHandleProps}
|
</Tooltip>
|
||||||
style={getItemStyle(
|
</div>
|
||||||
snapshot.isDragging,
|
<div style={{
|
||||||
provided.draggableProps.style
|
width: '10%',
|
||||||
)}
|
}} className='displayFlexRow'>{getTaskState(record.state) ? getTaskState(record.state).name : ""}</div>
|
||||||
>
|
<div style={{width: '25%'}} className='displayFlexColumn'>
|
||||||
{/*<td>{record.code}</td>*/}
|
<div>起: {record.expectedStartTime ? dayjs(record.expectedStartTime).format("YYYY-MM-DD HH:mm") : ""}</div>
|
||||||
<td>{record.name}</td>
|
<div>止: {record.expectedStartTime ? dayjs(record.expectedStartTime).format("YYYY-MM-DD HH:mm") : ""}</div>
|
||||||
<td>{record?.description}</td>
|
</div>
|
||||||
<td>{record.state}</td>
|
<div style={{width: '10%'}} className='displayFlexRow'>
|
||||||
<td>起:{record.expectedStartTime? dayjs(record.expectedStartTime).format("YYYY-MM-DD HH:mm") :""}<br/>
|
<OperationButton itemId={record.id} priority={record.priority} pid={record.pid}
|
||||||
止:{record.expectedStartTime? dayjs(record.expectedStartTime).format("YYYY-MM-DD HH:mm") : ""}</td>
|
pPid={record.pPid}/>
|
||||||
</tr>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</Draggable>
|
)}
|
||||||
);
|
</Draggable>
|
||||||
};
|
);
|
||||||
const calculateScrollHeight = () => {
|
}, [props.taskList, getItemStyle]);
|
||||||
// 计算50%视窗高度减去21px
|
|
||||||
const height = `calc(50vh - 80px)`;
|
const headerStyle = React.useMemo(() => ({
|
||||||
return { y: height };
|
backgroundColor: taskPriorityList.find((item) => item.code === props.tableCode)?.color,
|
||||||
};
|
height: '55px',
|
||||||
|
borderBottom: '1px solid #f0f0f0',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}), [props.tableCode]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Droppable droppableId={props.tableCode} key={props.tableCode} >
|
<Droppable droppableId={props.tableCode} key={props.tableCode}>
|
||||||
{(provided,snapshot) => (
|
{(provided, snapshot) => (
|
||||||
<div ref={provided.innerRef}
|
<div
|
||||||
{...provided.droppableProps}
|
ref={provided.innerRef}
|
||||||
style={getListStyle(snapshot.isDraggingOver)}
|
{...provided.droppableProps}
|
||||||
className="droppable-table"
|
style={getListStyle(snapshot.isDraggingOver)}
|
||||||
|
className="droppable-table"
|
||||||
>
|
>
|
||||||
<ConfigProvider
|
<ConfigProvider>
|
||||||
theme={{
|
{/* 表头 */}
|
||||||
components: {
|
<div style={headerStyle} className='displayFlexRow'>
|
||||||
Table: {
|
<div style={{width: '15%'}} className='displayFlexRow'>{stateName}</div>
|
||||||
headerBg: taskPriorityList.find((item) => item.code === props.tableCode)?.color
|
<div style={{width: '40%'}} className='displayFlexRow'>任务描述</div>
|
||||||
/* 这里是你的组件 token */
|
<div style={{width: '15%'}} className='displayFlexRow'>任务状态</div>
|
||||||
},
|
<div style={{width: '20%'}} className='displayFlexRow'>期望时间</div>
|
||||||
},
|
<div style={{width: '10%'}} className='displayFlexRow'>操作</div>
|
||||||
}}
|
</div>
|
||||||
>
|
{/* 虚拟列表主体 */}
|
||||||
<Table<DataType>
|
<div style={{height: 'calc(50vh - 76px)'}}>
|
||||||
dataSource={props.taskList}
|
<AutoSizer>
|
||||||
scroll={calculateScrollHeight()}
|
{({height, width}) => (
|
||||||
columns={[
|
<VirtualizedList
|
||||||
// {
|
className={"scrollHidden"}
|
||||||
// title: '任务编码',
|
height={height}
|
||||||
// dataIndex: 'code',
|
width={width}
|
||||||
// key: 'code',
|
rowCount={props.taskList.length}
|
||||||
// width: '10%',
|
rowHeight={80} // 与你的行高匹配
|
||||||
// },
|
rowRenderer={rowRenderer}
|
||||||
{
|
overscanRowCount={8} // 预渲染的行数
|
||||||
title: stateName,
|
/>
|
||||||
dataIndex: 'name',
|
)}
|
||||||
key: 'name',
|
</AutoSizer>
|
||||||
width: '10%',
|
</div>
|
||||||
ellipsis: {
|
|
||||||
showTitle: false,
|
|
||||||
},
|
|
||||||
render: (address) => (
|
|
||||||
<Tooltip placement="topLeft" title={address}>
|
|
||||||
{address}
|
|
||||||
</Tooltip>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '任务描述',
|
|
||||||
dataIndex: 'description',
|
|
||||||
key: 'description',
|
|
||||||
width: '20%',
|
|
||||||
ellipsis: {
|
|
||||||
showTitle: false,
|
|
||||||
},
|
|
||||||
render: (description) => (
|
|
||||||
<Tooltip placement="topLeft" title={description}>
|
|
||||||
{description}
|
|
||||||
</Tooltip>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '任务状态',
|
|
||||||
dataIndex: 'state',
|
|
||||||
width: '5%',
|
|
||||||
key: 'state',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '期望时间',
|
|
||||||
dataIndex: 'expectedStartTime',
|
|
||||||
width: '10%',
|
|
||||||
key: 'expectedStartTime',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
rowKey="id"
|
|
||||||
components={{
|
|
||||||
body: {
|
|
||||||
row: renderTableRow(props.taskList, props.tableCode),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
pagination={false}
|
|
||||||
/>
|
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
)
|
)
|
||||||
}
|
});
|
|
@ -1,5 +1,36 @@
|
||||||
.droppable-table{
|
.droppable-table {
|
||||||
width: 50vw;
|
box-sizing: border-box;
|
||||||
height: calc(50vh - 21px);
|
border: 1px solid #f0f0f0;
|
||||||
overflow-y: auto;
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.virtualized-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-ellipsis {
|
||||||
|
/* 单行省略 */
|
||||||
|
/*width: 100%;*/
|
||||||
|
/*box-sizing: border-box;*/
|
||||||
|
/*white-space: nowrap;*/
|
||||||
|
/*overflow: hidden;*/
|
||||||
|
/*text-overflow: ellipsis;*/
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
line-height: 1.5em; /* 根据实际字体大小调整 */
|
||||||
|
max-height: 3em; /* 2行 x 1.5em */
|
||||||
|
word-break: break-word; /* 允许长单词换行 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 拖拽时的样式增强 */
|
||||||
|
.ReactVirtualized__List {
|
||||||
|
outline: none;
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@ import React, {useEffect, useState} from "react";
|
||||||
import {
|
import {
|
||||||
addTask, deleteTask, getTask,
|
addTask, deleteTask, getTask,
|
||||||
getTaskTreeResult,
|
getTaskTreeResult,
|
||||||
OPERATION_BUTTON_TYPE,
|
OPERATION_BUTTON_TYPE, TASK_TYPE,
|
||||||
taskPriorityList,
|
taskPriorityList,
|
||||||
taskStateList, updateTask
|
taskStateList, updateTask
|
||||||
} from "@/lib/task/project/data";
|
} from "@/lib/task/project/data";
|
||||||
|
@ -44,6 +44,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
const [form] = Form.useForm<DataType>();
|
const [form] = Form.useForm<DataType>();
|
||||||
const [pid, setPid] = useState<string>(props.pid?props.pid:'0');
|
const [pid, setPid] = useState<string>(props.pid?props.pid:'0');
|
||||||
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
||||||
|
// 团队第一层 pid必须为0
|
||||||
|
const [taskType, setTaskType] = useState('0')
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.itemId!=undefined&&(
|
if (props.itemId!=undefined&&(
|
||||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
||||||
|
@ -209,8 +211,31 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
<ProFormText width="sm" name="code" initialValue={props.itemId} hidden={true} label="任务编码" />
|
<ProFormText width="sm" name="code" initialValue={props.itemId} hidden={true} label="任务编码" />
|
||||||
<ProFormText width="sm" name="pPid" initialValue={props.pPid} hidden={true} label="祖宗id" />
|
<ProFormText width="sm" name="pPid" initialValue={props.pPid} hidden={true} label="祖宗id" />
|
||||||
<ProForm.Group>
|
<ProForm.Group>
|
||||||
|
<ProFormSelect
|
||||||
|
required={true}
|
||||||
|
options={TASK_TYPE}
|
||||||
|
width="sm"
|
||||||
|
name="taskType"
|
||||||
|
label="任务类型"
|
||||||
|
initialValue='0'
|
||||||
|
disabled ={editFormDisable}
|
||||||
|
onChange={(value:string, option)=>{
|
||||||
|
setTaskType(value)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProFormText
|
||||||
|
required={true}
|
||||||
|
hidden={taskType!='1'}
|
||||||
|
width="sm"
|
||||||
|
name="fName"
|
||||||
|
label="团队名称"
|
||||||
|
tooltip="最长为 10 位"
|
||||||
|
placeholder="请输入团队名称"
|
||||||
|
disabled ={editFormDisable}
|
||||||
|
/>
|
||||||
<ProFormTreeSelect
|
<ProFormTreeSelect
|
||||||
width="md"
|
hidden={taskType=='1'}
|
||||||
|
width="sm"
|
||||||
request={() =>{
|
request={() =>{
|
||||||
return getTaskTreeResult(JSON.stringify(
|
return getTaskTreeResult(JSON.stringify(
|
||||||
{pageSize:1000,pageNumber:1,data:[{code:'pid',value:'0',operateType:'='},{code:'state',value:'8,9',operateType:'IN'},{code:'',value:true,operateType: "TREE"}]}
|
{pageSize:1000,pageNumber:1,data:[{code:'pid',value:'0',operateType:'='},{code:'state',value:'8,9',operateType:'IN'},{code:'',value:true,operateType: "TREE"}]}
|
||||||
|
@ -222,10 +247,11 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
disabled ={editFormDisable}
|
disabled ={editFormDisable}
|
||||||
/>
|
/>
|
||||||
<ProFormText
|
<ProFormText
|
||||||
width="md"
|
required={true}
|
||||||
|
width="sm"
|
||||||
name="name"
|
name="name"
|
||||||
label="任务名称"
|
label="任务名称"
|
||||||
tooltip="最长为 24 位"
|
tooltip="最长为 10 位"
|
||||||
placeholder="请输入任务名称"
|
placeholder="请输入任务名称"
|
||||||
disabled ={editFormDisable}
|
disabled ={editFormDisable}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Reference in New Issue