Compare commits
10 Commits
e1d7446d8c
...
8243d55f11
Author | SHA1 | Date |
---|---|---|
|
8243d55f11 | |
|
b7cb308c38 | |
|
6e42e44fed | |
|
73a402c840 | |
|
6cca06d4be | |
|
f208fc593a | |
|
8fcc35d3cb | |
|
25b2ad52a1 | |
|
f76c460fd9 | |
|
97071b464b |
12
README.md
|
@ -6,12 +6,18 @@
|
|||
1. 层级展示任务
|
||||
2. 可在操作中四象线展示子任务
|
||||
|
||||

|
||||

|
||||
## 四象线
|
||||
1. 向上重要
|
||||
2. 向左紧急
|
||||
|
||||

|
||||

|
||||
## 日历
|
||||
1. 月,周,日展示
|
||||
2. 只有期望开始时间和期望结束时间都填写的时候才会在日历中展示
|
||||

|
||||

|
||||

|
||||
## 项目启动
|
||||
### 后端服务启动
|
||||
1. 后端启动应用需求:docker,redis,mysql8。
|
||||
|
@ -38,3 +44,5 @@ docker build -t task-manager-nginx .
|
|||
```shell
|
||||
docker run -d -p 3001:3001 --restart unless-stopped --name task-manager-nginx task-manager-nginx
|
||||
```
|
||||
## 查看页面
|
||||
http://taskmanagerserver.com:3001
|
||||
|
|
|
@ -2,7 +2,7 @@ FROM openjdk:8
|
|||
WORKDIR /app
|
||||
COPY task-manager-server.jar /app/task-manager-server.jar
|
||||
EXPOSE 8090
|
||||
CMD ["java", "-jar", "task-manager-server.jar"]
|
||||
CMD ["java", "-jar", "task-manager-server.jar","--spring.profiles.active=docker"]
|
||||
# 指定文件名 当前路径
|
||||
# docker build -t task-manager-server -f Dockerfile-server .
|
||||
# docker run -d -p 8090:8090 --restart unless-stopped -v ./hosts:/etc/hosts --name task-manager-server task-manager-server
|
||||
|
|
After Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 176 KiB |
After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 230 KiB |
|
@ -1,5 +1,6 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Middleware cannot be used with "output: export".
|
||||
output: 'export',
|
||||
// Optional: Change links `/me` -> `/me/` and emit `/me.html` -> `/me/index.html`
|
||||
// trailingSlash: true,
|
||||
|
@ -8,7 +9,7 @@ const nextConfig = {
|
|||
// skipTrailingSlashRedirect: true,
|
||||
|
||||
// Optional: Change the output directory `out` -> `dist`
|
||||
// distDir: 'dist',
|
||||
distDir: 'docker/out',
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
"next": "14.1.3",
|
||||
"postcss": "8.4.31",
|
||||
"react": "^18",
|
||||
"react-big-calendar": "^1.12.2",
|
||||
"react-dom": "^18",
|
||||
"sass": "^1.77.3",
|
||||
"tailwindcss": "3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-big-calendar": "^1.8.9",
|
||||
"@types/react-dom": "^18",
|
||||
"@vercel/style-guide": "^5.0.1",
|
||||
"eslint": "^8",
|
||||
|
@ -1371,6 +1374,15 @@
|
|||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rc-component/color-picker": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmmirror.com/@rc-component/color-picker/-/color-picker-1.5.3.tgz",
|
||||
|
@ -1483,6 +1495,17 @@
|
|||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@restart/hooks": {
|
||||
"version": "0.4.16",
|
||||
"resolved": "https://registry.npmmirror.com/@restart/hooks/-/hooks-0.4.16.tgz",
|
||||
"integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==",
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/eslint-patch": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz",
|
||||
|
@ -1508,6 +1531,12 @@
|
|||
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/date-arithmetic": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/@types/date-arithmetic/-/date-arithmetic-4.1.4.tgz",
|
||||
"integrity": "sha512-p9eZ2X9B80iKiTW4ukVj8B4K6q9/+xFtQ5MGYA5HWToY9nL4EkhV9+6ftT2VHpVMEZb5Tv00Iel516bVdO+yRw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
|
@ -1538,20 +1567,29 @@
|
|||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.11",
|
||||
"resolved": "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.64",
|
||||
"resolved": "https://registry.npmmirror.com/@types/react/-/react-18.2.64.tgz",
|
||||
"integrity": "sha512-MlmPvHgjj2p3vZaxbQgFUQFvD8QiZwACfGqEdDSWou5yISWxDQ4/74nCAwsUiX7UFLKZz3BbVSPj+YxeoGGCfg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-big-calendar": {
|
||||
"version": "1.8.9",
|
||||
"resolved": "https://registry.npmmirror.com/@types/react-big-calendar/-/react-big-calendar-1.8.9.tgz",
|
||||
"integrity": "sha512-HIHLUxR3PzWHrFdZ00VnCMvDjAh5uzlL0vMC2b7tL3bKaAJsqq9T8h+x0GVeDbZfMfHAd1cs5tZBhVvourNJXQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/date-arithmetic": "*",
|
||||
"@types/prop-types": "*",
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "18.2.21",
|
||||
"resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.2.21.tgz",
|
||||
|
@ -1564,8 +1602,7 @@
|
|||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.8",
|
||||
"resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz",
|
||||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.8",
|
||||
|
@ -1573,6 +1610,11 @@
|
|||
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/warning": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/@types/warning/-/warning-3.0.3.tgz",
|
||||
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q=="
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
|
||||
|
@ -2401,6 +2443,14 @@
|
|||
"resolved": "https://registry.npmmirror.com/client-only/-/client-only-0.0.1.tgz",
|
||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
|
||||
|
@ -2496,6 +2546,11 @@
|
|||
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/date-arithmetic": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/date-arithmetic/-/date-arithmetic-4.1.0.tgz",
|
||||
"integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg=="
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.10",
|
||||
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz",
|
||||
|
@ -2564,7 +2619,6 @@
|
|||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz",
|
||||
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
@ -2621,6 +2675,15 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
|
@ -3884,6 +3947,11 @@
|
|||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/globalize": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/globalize/-/globalize-0.1.1.tgz",
|
||||
"integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA=="
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "13.24.0",
|
||||
"resolved": "https://registry.npmmirror.com/globals/-/globals-13.24.0.tgz",
|
||||
|
@ -4025,6 +4093,11 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "4.3.6",
|
||||
"resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.6.tgz",
|
||||
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ=="
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -4086,6 +4159,14 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz",
|
||||
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-array-buffer": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
|
||||
|
@ -4606,6 +4687,11 @@
|
|||
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
@ -4635,6 +4721,19 @@
|
|||
"node": "14 || >=16.14"
|
||||
}
|
||||
},
|
||||
"node_modules/luxon": {
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmmirror.com/luxon/-/luxon-3.4.4.tgz",
|
||||
"integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/memoize-one": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
|
||||
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz",
|
||||
|
@ -4717,6 +4816,25 @@
|
|||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moment-timezone": {
|
||||
"version": "0.5.45",
|
||||
"resolved": "https://registry.npmmirror.com/moment-timezone/-/moment-timezone-0.5.45.tgz",
|
||||
"integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==",
|
||||
"dependencies": {
|
||||
"moment": "^2.29.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
|
||||
|
@ -5978,6 +6096,33 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-big-calendar": {
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmmirror.com/react-big-calendar/-/react-big-calendar-1.12.2.tgz",
|
||||
"integrity": "sha512-cPVcwH5V1YiC6QKaV4afvpuZ2DtP8+TocnZY98nGodqq8bfjVDiP3Ch+TewBZzj9mg7JbewHdufDZXZBqQl1lw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.7",
|
||||
"clsx": "^1.2.1",
|
||||
"date-arithmetic": "^4.1.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"dom-helpers": "^5.2.1",
|
||||
"globalize": "^0.1.1",
|
||||
"invariant": "^2.2.4",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luxon": "^3.2.1",
|
||||
"memoize-one": "^6.0.0",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.40",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-overlays": "^5.2.1",
|
||||
"uncontrollable": "^7.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.14.0 || ^17 || ^18",
|
||||
"react-dom": "^16.14.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-18.2.0.tgz",
|
||||
|
@ -6000,6 +6145,25 @@
|
|||
"resolved": "https://registry.npmmirror.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"node_modules/react-overlays": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/react-overlays/-/react-overlays-5.2.1.tgz",
|
||||
"integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.8",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@restart/hooks": "^0.4.7",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.3.0",
|
||||
"react-dom": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reactcss": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
|
||||
|
@ -6307,6 +6471,22 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.77.3",
|
||||
"resolved": "https://registry.npmmirror.com/sass/-/sass-1.77.3.tgz",
|
||||
"integrity": "sha512-WJHo+jmFp0dwRuymPmIovuxHaBntcCyja5hCB0yYY9wWrViEp4kF5Cdai98P72v6FzroPuABqu+ddLMbQWmwzA==",
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sass": "sass.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.0.tgz",
|
||||
|
@ -7064,6 +7244,20 @@
|
|||
"which-boxed-primitive": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/uncontrollable": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/uncontrollable/-/uncontrollable-7.2.1.tgz",
|
||||
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.6.3",
|
||||
"@types/react": ">=16.9.11",
|
||||
"invariant": "^2.2.4",
|
||||
"react-lifecycles-compat": "^3.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz",
|
||||
|
|
|
@ -17,12 +17,15 @@
|
|||
"next": "14.1.3",
|
||||
"postcss": "8.4.31",
|
||||
"react": "^18",
|
||||
"react-big-calendar": "^1.12.2",
|
||||
"react-dom": "^18",
|
||||
"sass": "^1.77.3",
|
||||
"tailwindcss": "3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-big-calendar": "^1.8.9",
|
||||
"@types/react-dom": "^18",
|
||||
"@vercel/style-guide": "^5.0.1",
|
||||
"eslint": "^8",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { Metadata } from "next";
|
||||
import "@/ui/globals.css";
|
||||
import Script from "next/script";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "任务管理",
|
||||
|
@ -17,7 +18,9 @@ export default function RootLayout({
|
|||
}>) {
|
||||
return (
|
||||
<html>
|
||||
<Script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"/>
|
||||
<Script src="https://cdn.jsdelivr.net/npm/dayjs@1/locale/zh-cn.js"/>
|
||||
<body style={{margin: 0}}>{children}</body>
|
||||
</html>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
'use client'
|
||||
import {usePathname, useRouter} from "next/navigation";
|
||||
import { useRouter} from "next/navigation";
|
||||
import dayjs from "dayjs";
|
||||
import {useEffect} from "react";
|
||||
|
||||
export default function Home() {
|
||||
console.log('app.usePathname()', usePathname());
|
||||
const { replace } = useRouter();
|
||||
const {replace} = useRouter();
|
||||
useEffect(()=>{
|
||||
replace("/task/four")
|
||||
},[])
|
||||
dayjs.locale('zh-cn')
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col p-6">
|
||||
</main>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
export const dynamic = 'force-dynamic' // defaults to auto
|
||||
|
||||
export async function GET(request: Request) {
|
||||
return new Response('Hello, Next.js!', {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import CalShow from "@/ui/task/calendar/CalShow";
|
||||
const Page: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<CalShow/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
|
@ -44,7 +44,7 @@ export type DataType ={
|
|||
expectedTimeRange?:(string|Dayjs|undefined)[];
|
||||
actualStartTime?:Date;
|
||||
actualEndTime?:Date;
|
||||
actualTimeRange?:(string|Dayjs)[]
|
||||
actualTimeRange?:(string|Dayjs|undefined)[]
|
||||
children: DataType[]|undefined;
|
||||
}
|
||||
export type DictType={
|
||||
|
@ -54,3 +54,8 @@ export type DictType={
|
|||
order:number;
|
||||
color:string;
|
||||
}
|
||||
export type SearchObject={
|
||||
name: string,
|
||||
value: any,
|
||||
operateType:string,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import {Event} from "react-big-calendar";
|
||||
export interface TaskEvent extends Event {
|
||||
id?: any;
|
||||
state?:any;
|
||||
priority?:any;
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import {unstable_noStore as noStore} from 'next/cache';
|
||||
import axios, {AxiosResponse} from "axios";
|
||||
import {DataType, DictType, ResponseVO, ResultPage} from "@/lib/definitions";
|
||||
import {message} from "antd";
|
||||
export async function getTaskTreeResult(requestParam:string): Promise<ResponseVO<ResultPage<DataType>>> {
|
||||
noStore();
|
||||
try {
|
||||
|
@ -217,5 +216,6 @@ export enum OPERATION_BUTTON_TYPE {
|
|||
DELETE,
|
||||
COMPLETE,
|
||||
SHOW_FOUR,
|
||||
SHOW_CALENDAR,
|
||||
ADD,
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import { GlobeAltIcon } from '@heroicons/react/24/outline';
|
||||
|
||||
export default function AcmeLogo() {
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-row items-center leading-none text-white`}
|
||||
>
|
||||
{/*<GlobeAltIcon className="h-12 w-12 rotate-[15deg]" />*/}
|
||||
<p className="text-[44px]">Acme</p>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
import {
|
||||
UserGroupIcon,
|
||||
HomeIcon,
|
||||
DocumentDuplicateIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
|
||||
// Map of links to display in the side navigation.
|
||||
// Depending on the size of the application, this would be stored in a database.
|
||||
const links = [
|
||||
{ name: 'Home', href: '/dashboard', icon: HomeIcon },
|
||||
{
|
||||
name: 'Invoices',
|
||||
href: '/dashboard/invoices',
|
||||
icon: DocumentDuplicateIcon,
|
||||
},
|
||||
{ name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon },
|
||||
];
|
||||
|
||||
export default function NavLinks() {
|
||||
return (
|
||||
<>
|
||||
{links.map((link) => {
|
||||
const LinkIcon = link.icon;
|
||||
return (
|
||||
<a
|
||||
key={link.name}
|
||||
href={link.href}
|
||||
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
|
||||
>
|
||||
{/*<LinkIcon className="w-6" />*/}
|
||||
<p className="hidden md:block">{link.name}</p>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
import Link from 'next/link';
|
||||
import NavLinks from '@/ui/dashboard/nav-links';
|
||||
import AcmeLogo from '@/ui/acme-logo';
|
||||
import { PowerIcon } from '@heroicons/react/24/outline';
|
||||
|
||||
export default function SideNav() {
|
||||
return (
|
||||
<div className="flex h-full flex-col px-3 py-4 md:px-2">
|
||||
<Link
|
||||
className="mb-2 flex h-20 items-end justify-start rounded-md bg-blue-600 p-4 md:h-40"
|
||||
href="/public"
|
||||
>
|
||||
<div className="w-32 text-white md:w-40">
|
||||
<AcmeLogo />
|
||||
</div>
|
||||
</Link>
|
||||
<div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2">
|
||||
<NavLinks />
|
||||
<div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div>
|
||||
<form>
|
||||
<button className="flex h-[48px] w-full grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3">
|
||||
<PowerIcon className="w-6" />
|
||||
<div className="hidden md:block">Sign Out</div>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
// import { Inter,Lusitana } from 'next/font/google';
|
||||
//
|
||||
// export const inter = Inter({ subsets: ['latin'] });
|
||||
// export const lusitana = Lusitana({
|
||||
// weight: ['400', '700'],
|
||||
// subsets: ['latin'],
|
||||
// });
|
|
@ -4,6 +4,7 @@ import {DownOutlined, QuestionCircleOutlined} from "@ant-design/icons";
|
|||
import {DetailForm} from "@/ui/task/four/DetailForm";
|
||||
import {commonUpdate, deleteTask, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
|
||||
import Link from "next/link";
|
||||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||
|
||||
export interface OperationButtonProps {
|
||||
itemId: number,
|
||||
|
@ -14,7 +15,7 @@ export interface OperationButtonProps {
|
|||
}
|
||||
|
||||
interface OperationModelProps {
|
||||
operationId: number | undefined,
|
||||
operationId: number,
|
||||
pPid: number,
|
||||
pid: number,
|
||||
openModal: boolean
|
||||
|
@ -27,7 +28,7 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
|||
this.state = {
|
||||
pid: props.pid,
|
||||
pPid: props.pPid,
|
||||
operationId: undefined,
|
||||
operationId: 0,
|
||||
openModal: false
|
||||
};
|
||||
}
|
||||
|
@ -89,12 +90,12 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
|||
cancelText="取消"
|
||||
onConfirm={() => {
|
||||
commonUpdate({
|
||||
updateColoumList:[{
|
||||
updateColumnList:[{
|
||||
name:'state',
|
||||
code:'state',
|
||||
value:'7'
|
||||
}],
|
||||
conditionColoumList:[{
|
||||
conditionColumnList:[{
|
||||
name:'id',
|
||||
code:'id',
|
||||
operateType:'=',
|
||||
|
@ -113,6 +114,10 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
|||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_FOUR,
|
||||
label: <Link href={"/task/four?pid=" + this.props.itemId}>四象限显示子任务</Link>,
|
||||
},
|
||||
{
|
||||
key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR,
|
||||
label: <Link href={"/task/calendar?pid=" + this.props.itemId}>日历显示子任务</Link>,
|
||||
}
|
||||
];
|
||||
return <Fragment>
|
||||
|
@ -125,42 +130,17 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
|||
</Space>
|
||||
</a>
|
||||
</Dropdown>
|
||||
<Modal
|
||||
maskClosable={false}
|
||||
destroyOnClose={true}
|
||||
open={this.state.openModal}
|
||||
title={this.state.operationId === OPERATION_BUTTON_TYPE.DETAIL ? '任务详情' :
|
||||
{this.state.openModal&&<DetailModelForm
|
||||
haveButton={false}
|
||||
itemId={this.state.operationId === OPERATION_BUTTON_TYPE.UPDATE||this.state.operationId === OPERATION_BUTTON_TYPE.DETAIL?this.props.itemId:undefined}
|
||||
pPid={this.props.pPid}
|
||||
pid={this.state.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ?this.props.itemId:undefined}
|
||||
operationId={this.state.operationId}
|
||||
description={this.state.operationId === OPERATION_BUTTON_TYPE.DETAIL ? '任务详情' :
|
||||
this.state.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? '添加支线任务' :
|
||||
this.state.operationId === OPERATION_BUTTON_TYPE.UPDATE ? '修改任务' : '未知操作'}
|
||||
// open={open}
|
||||
// onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
footer={[]}
|
||||
width={800}
|
||||
// footer={[
|
||||
// <Button key="back" onClick={handleCancel}>
|
||||
// Return
|
||||
// </Button>,
|
||||
// <Button key="submit" type="primary" loading={loading} onClick={handleOk}>
|
||||
// Submit
|
||||
// </Button>,
|
||||
// <Button
|
||||
// key="link"
|
||||
// href="https://google.com"
|
||||
// type="primary"
|
||||
// loading={loading}
|
||||
// onClick={handleOk}
|
||||
// >
|
||||
// Search on Google
|
||||
// </Button>,
|
||||
// ]}
|
||||
>
|
||||
<DetailForm itemId={this.props.itemId}
|
||||
operationId={this.state.operationId}
|
||||
handleCancel={handleCancel}
|
||||
pPid={this.props.pPid}
|
||||
/>
|
||||
</Modal>
|
||||
open={this.state.openModal}
|
||||
reloadData={handleCancel}/>}
|
||||
</Fragment>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, {useContext} from "react";
|
||||
import React, {Fragment, useContext} from "react";
|
||||
import {Button, DatePicker, Select, Space} from "antd";
|
||||
import {usePathname, useRouter} from "next/navigation";
|
||||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||
|
@ -23,25 +23,39 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
console.log('usePathname()', usePathname());
|
||||
const data = useContext(LocalContext);
|
||||
const {RangePicker} = DatePicker;
|
||||
const expectStartTimeParseResult:RequestDateType[] = data.expectedStartTime.length>0?JSON.parse(data.expectedStartTime):[undefined,undefined]
|
||||
expectStartTimeParseResult.map(item => item&&item.value ? dayjs(item.value.toString()) : undefined)
|
||||
const defaultExpectStartTime:[start: Dayjs | null | undefined, end: Dayjs | null | undefined] = [
|
||||
expectStartTimeParseResult[0]&&expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined,
|
||||
expectStartTimeParseResult[1]&&expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
|
||||
const expectStartTimeParseResult: RequestDateType[] = data.expectedStartTime.length > 0 ? JSON.parse(data.expectedStartTime) : [undefined, undefined]
|
||||
expectStartTimeParseResult.map(item => item && item.value ? dayjs(item.value.toString()) : undefined)
|
||||
const defaultExpectStartTime: [start: Dayjs | null | undefined, end: Dayjs | null | undefined] = [
|
||||
expectStartTimeParseResult[0] && expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined,
|
||||
expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
|
||||
];
|
||||
return <Space style={{marginTop: 0 ,"height": "42px", "alignContent": "center"}}>
|
||||
<DetailModelForm operationId={OPERATION_BUTTON_TYPE.ADD} description='添加主线任务' reloadData={refreshData}/>
|
||||
{usePathname().startsWith("/task/project") ?
|
||||
<>
|
||||
<Button type="primary" onClick={() => {
|
||||
replace("/task/four");
|
||||
// setCurrentPath("/task/four");
|
||||
}}>四象限显示</Button>
|
||||
</> : <>
|
||||
return <Space style={{marginTop: 0, "height": "42px", "alignContent": "center"}}>
|
||||
<DetailModelForm haveButton={true} open={false} operationId={OPERATION_BUTTON_TYPE.ADD}
|
||||
description='添加主线任务' reloadData={refreshData}/>
|
||||
{
|
||||
!usePathname().startsWith("/task/project") &&
|
||||
<Button type="primary" onClick={() => {
|
||||
replace("/task/project");
|
||||
// setCurrentPath("/task/project")
|
||||
}}>任务树</Button>
|
||||
}
|
||||
{
|
||||
!usePathname().startsWith("/task/four") &&
|
||||
<Button type="primary" onClick={() => {
|
||||
replace("/task/four");
|
||||
// setCurrentPath("/task/four");
|
||||
}}>四象限显示</Button>
|
||||
}
|
||||
{
|
||||
!usePathname().startsWith("/task/calendar") &&
|
||||
<Button type="primary" onClick={() => {
|
||||
replace("/task/calendar");
|
||||
// setCurrentPath("/task/project")
|
||||
}}>日历显示</Button>
|
||||
}
|
||||
{
|
||||
/*日历需要状态*/
|
||||
!usePathname().startsWith("/task/project") && <Fragment>
|
||||
<span style={{whiteSpace: 'nowrap'}}>任务状态:</span>
|
||||
<Select
|
||||
mode="multiple"
|
||||
|
@ -57,6 +71,11 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
return {label: item.name, value: item.code}
|
||||
})}
|
||||
/>
|
||||
</Fragment>
|
||||
}
|
||||
{
|
||||
/*四相线需要状态时间*/
|
||||
usePathname().startsWith("/task/four") && <Fragment>
|
||||
<span style={{whiteSpace: 'nowrap'}}>期望开始时间范围:</span>
|
||||
<RangePicker
|
||||
placeholder={['开始时间', '结束时间']}
|
||||
|
@ -75,7 +94,7 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
'value': dates[0],
|
||||
'operateType': ">="
|
||||
});
|
||||
}else{
|
||||
} else {
|
||||
expectStartTimeList.push(undefined)
|
||||
}
|
||||
if (dates[1]) {
|
||||
|
@ -84,13 +103,15 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
|
|||
'value': dates[1].add(1, 'day'),
|
||||
'operateType': "<"
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
expectStartTimeList.push(undefined)
|
||||
}
|
||||
setExpectedStartTime(JSON.stringify(expectStartTimeList))
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</Fragment>
|
||||
}
|
||||
|
||||
|
||||
</Space>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
'use client'
|
||||
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from "react";
|
||||
import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar'
|
||||
// https://day.js.org/docs/zh-CN/get-set/get-set
|
||||
import dayjs, {Dayjs} from 'dayjs'
|
||||
import 'react-big-calendar/lib/css/react-big-calendar.css'
|
||||
import 'react-big-calendar/lib/sass/styles.scss'
|
||||
import 'react-big-calendar/lib/addons/dragAndDrop/styles.scss'
|
||||
import '@/ui/task/calendar/index.modules.css'
|
||||
import {commonUpdate, getTaskTreeResult, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
|
||||
import {useSearchParams} from "next/dist/client/components/navigation";
|
||||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||
import {SearchObject} from "@/lib/definitions";
|
||||
import LocalContext from "@/ui/LocalContent";
|
||||
import withDragAndDrop, {EventInteractionArgs} from "react-big-calendar/lib/addons/dragAndDrop";
|
||||
import {TaskEvent} from "@/lib/task/calendar/data";
|
||||
import {number} from "prop-types";
|
||||
import {DATE_TIME} from "@/lib/constants";
|
||||
|
||||
/**
|
||||
* https://github.com/jquense/react-big-calendar?tab=readme-ov-file
|
||||
* @constructor
|
||||
*/
|
||||
const localizer = dayjsLocalizer(dayjs)
|
||||
const DragAndDropCalendar = withDragAndDrop(Calendar)
|
||||
const CalShow: React.FC = () => {
|
||||
dayjs.locale('zh-cn')
|
||||
const [view, setView] = useState<View>('week');
|
||||
const [date, setDate] = useState<Date>(new Date());
|
||||
const clickRef = useRef<number|undefined|null>(null)
|
||||
// 展示在页面的任务,默认获取当前月的信息。
|
||||
const [events, setEvents] = useState<TaskEvent[]>([]);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [description, setDescription] = useState('');
|
||||
const [operationId, setOperationId] = useState(-1);
|
||||
const [itemId, setItemId] = useState(-1);
|
||||
const [expectedStartTime, setExpectedStartTime] = useState<Dayjs>();
|
||||
const [expectedEndTime, setExpectedEndTime] = useState<Dayjs>();
|
||||
const [range, setRange] = useState<{start: Date; end: Date}>({
|
||||
start: dayjs(date).startOf('week').toDate(),
|
||||
end: dayjs(date).endOf('week').toDate()
|
||||
});
|
||||
|
||||
let state: string = useContext(LocalContext).taskState
|
||||
const handleViewChange = (newView: View) => {
|
||||
setView(newView);
|
||||
};
|
||||
var pid = useSearchParams().get('pid');
|
||||
function clearClickTimeout(){
|
||||
clickRef && typeof clickRef.current=== 'number' &&!isNaN(clickRef.current) && isFinite(clickRef.current)&&window.clearTimeout(clickRef.current)
|
||||
}
|
||||
const handleNavigate = (newDate: Date) => {
|
||||
console.log('handleNavigate', newDate)
|
||||
setDate(newDate);
|
||||
const searchList: SearchObject[] = []
|
||||
if (pid != null) {
|
||||
searchList.push({name: "pid", value: pid, operateType: "="}, {
|
||||
name: 'TREE',
|
||||
value: "false",
|
||||
operateType: "TREE"
|
||||
});
|
||||
}
|
||||
searchList.push({name: "expectedStartTime", value: range.start, operateType: ">="})
|
||||
searchList.push({name: 'expectedStartTime', value: range.end, operateType: "<="})
|
||||
loadData(searchList);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("CalShow:useEffect:range",range)
|
||||
const searchListE = []
|
||||
if (pid != null) {
|
||||
searchListE.push({name: "pid", value: pid, operateType: "="}, {
|
||||
name: 'TREE',
|
||||
value: "false",
|
||||
operateType: "TREE"
|
||||
});
|
||||
}
|
||||
searchListE.push({name: 'expectedStartTime', value: range.start, operateType: ">="})
|
||||
searchListE.push({name: 'expectedStartTime', value: range.end, operateType: "<="})
|
||||
loadData(searchListE);
|
||||
/**
|
||||
* What Is This?
|
||||
* This is to prevent a memory leak, in the off chance that you
|
||||
* teardown your interface prior to the timed method being called.
|
||||
*/
|
||||
return () => {
|
||||
clearClickTimeout()
|
||||
}
|
||||
}, [useContext(LocalContext),range]);
|
||||
const message = {
|
||||
week: '周',
|
||||
work_week: '工作周',
|
||||
day: '天',
|
||||
month: '月',
|
||||
previous: '前',
|
||||
next: '后',
|
||||
today: '当下',
|
||||
agenda: '日程'
|
||||
}
|
||||
const loadData = (searchList: SearchObject[]) => {
|
||||
if (state.length > 0) {
|
||||
searchList.push({name: 'state', value: state, operateType: "IN"})
|
||||
}
|
||||
searchList.push({name: 'expectedEndTime', value: dayjs(date).endOf('month'), operateType: "NOT NULL"})
|
||||
let request = JSON.stringify({
|
||||
pageSize: 9999,
|
||||
pageNumber: 1,
|
||||
data: searchList
|
||||
})
|
||||
getTaskTreeResult(request).then(responseD => {
|
||||
if (responseD.status.success) {
|
||||
let result:TaskEvent[] =responseD.data.content.map<TaskEvent>(taskState => {
|
||||
return {
|
||||
start: dayjs(taskState.expectedStartTime).toDate(),
|
||||
end: dayjs(taskState.expectedEndTime).toDate(),
|
||||
title: taskState.name,
|
||||
resource: taskState.id,
|
||||
id:taskState.id,
|
||||
state:taskState.state,
|
||||
priority:taskState.priority
|
||||
}
|
||||
});
|
||||
console.log('responseD.data.content:',result)
|
||||
setEvents([...result])
|
||||
}
|
||||
})
|
||||
}
|
||||
const reloadData = () => {
|
||||
setOpen(false)
|
||||
handleNavigate(expectedStartTime ? expectedStartTime.toDate() : date)
|
||||
}
|
||||
const handleSelectSlot = useCallback(
|
||||
({start, end}: SlotInfo) => {
|
||||
setExpectedEndTime(dayjs(end))
|
||||
setExpectedStartTime(dayjs(start))
|
||||
setOperationId(OPERATION_BUTTON_TYPE.ADD)
|
||||
setDescription("添加任务")
|
||||
setOpen(true);
|
||||
},
|
||||
[setEvents]
|
||||
)
|
||||
|
||||
const handleSelectEvent = useCallback(
|
||||
(event: Event, e: React.SyntheticEvent<HTMLElement>) => {
|
||||
clearClickTimeout()
|
||||
clickRef.current = window.setTimeout(()=> {
|
||||
// window.alert(event.title);
|
||||
console.log(event)
|
||||
setOperationId(OPERATION_BUTTON_TYPE.DETAIL)
|
||||
setDescription("任务详情")
|
||||
setItemId(event.resource)
|
||||
setOpen(true);
|
||||
},250)
|
||||
},
|
||||
[]
|
||||
)
|
||||
const {defaultDate, scrollToTime} = useMemo(
|
||||
() => ({
|
||||
defaultDate: new Date(2015, 3, 12),
|
||||
scrollToTime: new Date(1970, 1, 1, 6),
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const doubleClick = (event: TaskEvent, e: React.SyntheticEvent<HTMLElement>) => {
|
||||
clearClickTimeout()
|
||||
clickRef.current = window.setTimeout(()=>{
|
||||
// 数据落库
|
||||
commonUpdate({
|
||||
updateColumnList: [{
|
||||
name: '任务状态',
|
||||
code: 'state',
|
||||
value: 7
|
||||
}],
|
||||
conditionColumnList: [{
|
||||
name: 'id',
|
||||
code: 'id',
|
||||
operateType: '=',
|
||||
value: event.resource
|
||||
}]
|
||||
})
|
||||
setEvents((prev: TaskEvent[]) => {
|
||||
const existing: TaskEvent | undefined = prev.find((ev: TaskEvent) => ev.resource === event.resource);
|
||||
const filtered: TaskEvent[] | undefined = prev.filter((ev: TaskEvent) => ev.resource !== event.resource);
|
||||
let result: TaskEvent[] = [];
|
||||
if (existing !== undefined&&filtered !== undefined) {
|
||||
result= [...filtered, {...existing, state:7}];
|
||||
}
|
||||
console.log('result',result)
|
||||
return result;
|
||||
})
|
||||
},250)
|
||||
}
|
||||
|
||||
const moveEvent = useCallback(
|
||||
({event, start, end, isAllDay: droppedOnAllDaySlot = false}: EventInteractionArgs<TaskEvent>) => {
|
||||
console.log("onEventResize || onEventDrop :",start,end)
|
||||
const {allDay} = event
|
||||
if (!allDay && droppedOnAllDaySlot) {
|
||||
event.allDay = true
|
||||
}
|
||||
// 数据落库
|
||||
commonUpdate({
|
||||
updateColumnList: [{
|
||||
name: 'expectedStartTime',
|
||||
code: '',
|
||||
value: start.toLocaleString()
|
||||
}, {
|
||||
name: 'expectedEndTime',
|
||||
code: '',
|
||||
value: end.toLocaleString()
|
||||
}],
|
||||
conditionColumnList: [{
|
||||
name: 'id',
|
||||
code: 'id',
|
||||
operateType: '=',
|
||||
value: event.resource
|
||||
}]
|
||||
})
|
||||
setEvents((prev: TaskEvent[]) => {
|
||||
const existing: TaskEvent | undefined = prev.find((ev: TaskEvent) => ev.resource === event.resource);
|
||||
const filtered: TaskEvent[] | undefined = prev.filter((ev: TaskEvent) => ev.resource !== event.resource);
|
||||
if (start instanceof Date && end instanceof Date && existing !== undefined) {
|
||||
return [...filtered, {...existing, start, end, allDay}];
|
||||
}
|
||||
if (filtered !== undefined) {
|
||||
return [...filtered];
|
||||
}
|
||||
return [];
|
||||
})
|
||||
},
|
||||
[setEvents]
|
||||
)
|
||||
|
||||
const eventPropGetter = useCallback(
|
||||
(event:TaskEvent) => ({
|
||||
...(event.state===7
|
||||
? { className: 'completeTask' }
|
||||
: event.priority===3?{ className: 'importantUrgentTask' }:
|
||||
event.priority===2?{ className: 'importantNotUrgentTask' }:
|
||||
event.priority===1?{ className: 'notImportantUrgentTask' }:
|
||||
{ className: 'notImportantNotUrgentTask' }),
|
||||
}),
|
||||
[setEvents]
|
||||
)
|
||||
const rangeChange = (rangeLet: Date[]|{ start: Date; end: Date },current?:View|undefined)=>{
|
||||
console.log("rangeChange:",rangeLet,(current?current:view))
|
||||
// view 为天的时候类型为数组,index:0为当天
|
||||
if ((current?current:view)==="day"&&Array.isArray(rangeLet)) {
|
||||
if (range.start.valueOf()>rangeLet[0].valueOf()){
|
||||
setRange({...range,start:rangeLet[0]})
|
||||
}else if (range.end.valueOf()<rangeLet[0].valueOf()){
|
||||
setRange({...range,end:rangeLet[0]})
|
||||
}
|
||||
}
|
||||
// 为周的时候类型为数组,周一到周日七天
|
||||
if ((current?current:view)==="week"&&Array.isArray(rangeLet)){
|
||||
if (range.start.valueOf()>rangeLet[0].valueOf()){
|
||||
setRange({...range,start:rangeLet[0]})
|
||||
}
|
||||
if (range.end.valueOf()<rangeLet[6].valueOf()){
|
||||
setRange({...range,end:rangeLet[6]})
|
||||
}
|
||||
}
|
||||
// 为周的时候类型为对象
|
||||
if ((current?current:view)==="month"&& rangeLet && !Array.isArray(rangeLet)){
|
||||
if (range.start.valueOf()>rangeLet.start.valueOf()){
|
||||
setRange({...range,start:rangeLet.start})
|
||||
}
|
||||
if (range.end.valueOf()<rangeLet.end.valueOf()){
|
||||
setRange({...range,end:rangeLet.end})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return <div className="App" style={{height: '90vh'}}>
|
||||
{open && <DetailModelForm operationId={operationId} description={description} open={open} haveButton={false}
|
||||
itemId={itemId} pid={pid?Number(pid):0}
|
||||
reloadData={reloadData} expectedStartTime={expectedStartTime}
|
||||
expectedEndTime={expectedEndTime}/>}
|
||||
<DragAndDropCalendar
|
||||
// 本地设置
|
||||
localizer={localizer}
|
||||
messages={message}
|
||||
// 修改style
|
||||
eventPropGetter={eventPropGetter}
|
||||
events={events}
|
||||
// 界面
|
||||
view={view}
|
||||
// 界面改变
|
||||
onView={handleViewChange}
|
||||
onRangeChange={rangeChange}
|
||||
// 时间
|
||||
date={date}
|
||||
// 条目信息改变
|
||||
onNavigate={handleNavigate}
|
||||
|
||||
// 点击
|
||||
selectable
|
||||
scrollToTime={scrollToTime}
|
||||
// 双击
|
||||
onDoubleClickEvent={doubleClick}
|
||||
// 点击任务
|
||||
onSelectEvent={handleSelectEvent}
|
||||
// 点击空白处
|
||||
onSelectSlot={handleSelectSlot}
|
||||
// 改变时间长短
|
||||
resizable
|
||||
onEventResize={moveEvent}
|
||||
onEventDrop={moveEvent}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
export default CalShow;
|
|
@ -0,0 +1,20 @@
|
|||
.completeTask{
|
||||
background-color: deepskyblue !important;
|
||||
color: black !important;
|
||||
}
|
||||
.importantUrgentTask{
|
||||
background-color: red !important;
|
||||
color: black !important;
|
||||
}
|
||||
.notImportantUrgentTask{
|
||||
background-color: gray !important;
|
||||
color: black !important;
|
||||
}
|
||||
.importantNotUrgentTask{
|
||||
background-color: yellow !important;
|
||||
color: black !important;
|
||||
}
|
||||
.notImportantNotUrgentTask{
|
||||
background-color: green !important;
|
||||
color: black !important;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
'use client'
|
||||
import React, {useContext, useEffect, useState} from 'react';
|
||||
import React, {useContext} from 'react';
|
||||
import {ConfigProvider, Table} from 'antd';
|
||||
import type {TableColumnsType, TableProps} from 'antd';
|
||||
import {getTaskTreeResult, taskPriorityList, taskStateList, taskTreeResult} from "@/lib/task/project/data";
|
||||
import {DataType, ResponseVO, ResultPage} from "@/lib/definitions";
|
||||
import {taskPriorityList, taskStateList} from "@/lib/task/project/data";
|
||||
import {DataType} from "@/lib/definitions";
|
||||
import OperationButton from "@/ui/task/OperationButton";
|
||||
import "@/ui/task/four/detailForm.modules.css"
|
||||
import LocalContext from "@/ui/LocalContent";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import {PlusOutlined, QuestionCircleOutlined} from '@ant-design/icons';
|
||||
import {
|
||||
ModalForm,
|
||||
ProForm,
|
||||
|
@ -6,33 +6,72 @@ import {
|
|||
ProFormSelect,
|
||||
ProFormText, ProFormTextArea, ProFormTreeSelect,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Button, Form, message } from 'antd';
|
||||
import React, {useState} from "react";
|
||||
import {Button, Form, message, Popconfirm} from 'antd';
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {
|
||||
addTask,
|
||||
addTask, deleteTask, getTask,
|
||||
getTaskTreeResult,
|
||||
OPERATION_BUTTON_TYPE,
|
||||
taskPriorityList,
|
||||
taskStateList
|
||||
taskStateList, updateTask
|
||||
} from "@/lib/task/project/data";
|
||||
import {DataType} from "@/lib/definitions";
|
||||
import dayjs from "dayjs";
|
||||
import dayjs, {Dayjs} from "dayjs";
|
||||
|
||||
export type DetailModelFormProps={
|
||||
// 当前内容id
|
||||
itemId?: number,
|
||||
pid?:number,
|
||||
// 祖宗任务id
|
||||
pPid?:number,
|
||||
// 操作id
|
||||
operationId: number,
|
||||
// 标题描述
|
||||
description:string,
|
||||
// 是否打开界面,用于非按钮操作
|
||||
open:boolean,
|
||||
// 使用按钮操作
|
||||
haveButton:boolean,
|
||||
expectedStartTime?:Dayjs,
|
||||
expectedEndTime?:Dayjs,
|
||||
// 重新加载数据
|
||||
reloadData?: () => void
|
||||
}
|
||||
export type PidSelectTree= { label: string; value: number;pPid:number; children?: PidSelectTree[] }
|
||||
export type PidSelectTree= { label: string; value: number;pid:number; children?: PidSelectTree[] }
|
||||
|
||||
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||
console.log("DetailModelForm:props:",props)
|
||||
const [form] = Form.useForm<DataType>();
|
||||
const [pPid, setPPid] = useState<number>(0);
|
||||
const [pid, setPid] = useState<number>(props.pid?props.pid:0);
|
||||
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
||||
useEffect(() => {
|
||||
if (props.itemId!=undefined&&(
|
||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
|
||||
getTask(props.itemId).then(task => {
|
||||
console.log('DetailModelForm:getTask(props.itemId)', props.itemId, task);
|
||||
if (task.status.success) {
|
||||
// setTaskMessage(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?.()
|
||||
}
|
||||
})
|
||||
}else if(props.operationId === OPERATION_BUTTON_TYPE.ADD|| props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD){
|
||||
let data={'expectedTimeRange':[props.expectedStartTime?props.expectedStartTime:dayjs(), props.expectedEndTime],'pid':props.pid};
|
||||
form.setFieldsValue(data)
|
||||
}
|
||||
}, [props])
|
||||
function childReduce(child:DataType[]):PidSelectTree[]{
|
||||
const result:PidSelectTree[] = [];
|
||||
child.map(data=> {
|
||||
const resultData:PidSelectTree = {label:data.name,value:data.id,pPid:data.pPid};
|
||||
const resultData:PidSelectTree = {label:data.name,value:data.id,pid:data.pid};
|
||||
if (data.children){
|
||||
resultData.children=childReduce(data.children);
|
||||
}
|
||||
|
@ -40,26 +79,65 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
})
|
||||
return result;
|
||||
}
|
||||
// 如果不是添加任务需要回显
|
||||
return (
|
||||
<ModalForm<DataType>
|
||||
title={
|
||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL ? "任务详情":
|
||||
props.operationId === OPERATION_BUTTON_TYPE.ADD?"添加任务":
|
||||
props.operationId === OPERATION_BUTTON_TYPE.ADD?"修改任务":''
|
||||
}
|
||||
trigger={
|
||||
title={props.description}
|
||||
open={props.open&&!props.haveButton}
|
||||
trigger={props.haveButton?
|
||||
<Button type="primary">
|
||||
<PlusOutlined />
|
||||
{props.description}
|
||||
</Button>
|
||||
</Button>:undefined
|
||||
}
|
||||
form={form}
|
||||
autoFocusFirstInput
|
||||
modalProps={{
|
||||
destroyOnClose: true,
|
||||
onCancel: () => console.log('run'),
|
||||
onCancel: () => {
|
||||
console.log('run');
|
||||
props.reloadData?.();
|
||||
},
|
||||
}}
|
||||
// submitTimeout={2000}
|
||||
submitter={props.itemId!==undefined&&props.itemId!==-1?{
|
||||
render: (prop, defaultDoms) => {
|
||||
return [
|
||||
editFormDisable?<Button
|
||||
key="edit"
|
||||
onClick={() => {
|
||||
// props.submit();
|
||||
setEditFormDisable(false)
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>:undefined,
|
||||
props.operationId === OPERATION_BUTTON_TYPE.DETAIL||props.operationId === OPERATION_BUTTON_TYPE.UPDATE?<Popconfirm
|
||||
key ='delete'
|
||||
title="删除任务"
|
||||
description="确认要删除任务?"
|
||||
icon={<QuestionCircleOutlined style={{color: 'red'}}/>}
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
onConfirm={() => {
|
||||
if (props.itemId!==undefined) {
|
||||
deleteTask(props.itemId).then((response => {
|
||||
console.log('response', response)
|
||||
if (response.status.success) {
|
||||
message.success("删除任务成功:" + response.data)
|
||||
props.reloadData?.()
|
||||
}
|
||||
}));
|
||||
}
|
||||
}}
|
||||
><Button type="primary" danger>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>:undefined
|
||||
,
|
||||
...defaultDoms
|
||||
];
|
||||
},
|
||||
}:undefined}
|
||||
onFinish={async (values) => {
|
||||
console.log('Received values of form: ', values);
|
||||
if (values.pid===undefined){
|
||||
|
@ -77,8 +155,36 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
if (values.actualTimeRange?.[1]!=undefined) {
|
||||
values.actualEndTime=dayjs(values.actualTimeRange[1]).toDate()
|
||||
}
|
||||
values.pPid=pPid;
|
||||
values.pid=pid;
|
||||
var result:boolean=false;
|
||||
|
||||
let state = taskStateList.find(taskState => taskState.name === values.state?.toString());
|
||||
if (state) {
|
||||
values.state = state.code
|
||||
}
|
||||
let priority = taskPriorityList.find(taskPriority => taskPriority.name === values.priority?.toString())
|
||||
if (priority) {
|
||||
values.priority = priority.code
|
||||
}
|
||||
// todo 修改
|
||||
if (props.operationId === OPERATION_BUTTON_TYPE.UPDATE||(props.operationId === OPERATION_BUTTON_TYPE.DETAIL&&!editFormDisable)) {
|
||||
await updateTask(values).then(response => {
|
||||
console.log('response', response)
|
||||
if (response.status.success) {
|
||||
message.success("修改任务成功:" + response.data)
|
||||
// 树任务重新刷新
|
||||
// 四象限任务重新刷新
|
||||
// 如果可以直接更新列表而不请求。。。。。。
|
||||
console.log('props.reloadData?.()',props.reloadData)
|
||||
props.reloadData?.()
|
||||
result= true
|
||||
}else {
|
||||
message.error(response.status.message)
|
||||
result= false
|
||||
}
|
||||
}
|
||||
);
|
||||
}else {
|
||||
await addTask(values).then(response => {
|
||||
console.log('response', response)
|
||||
if (response.status.success) {
|
||||
|
@ -95,24 +201,25 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}}
|
||||
>
|
||||
<ProFormText width="sm" name="id" hidden={true} label="主键" />
|
||||
<ProFormText width="sm" name="code" 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" />
|
||||
<ProForm.Group>
|
||||
<ProFormTreeSelect
|
||||
width="md"
|
||||
request={() =>{
|
||||
return getTaskTreeResult(JSON.stringify(
|
||||
{pageSize:1000,pageNumber:1,data:[{code:'pid',value:'0',operateType:'='},{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"}]}
|
||||
)).then(result=> childReduce(result.data.content))
|
||||
}}
|
||||
name="pid"
|
||||
label="父级任务"
|
||||
fieldProps={{onSelect: (e,node) => {console.log('onSelect',e,node);setPPid(node.pPid)}}}
|
||||
disabled ={props.operationId === OPERATION_BUTTON_TYPE.DETAIL}
|
||||
fieldProps={{onSelect: (e,node) => {console.log('onSelect',e,node);setPid(e)}}}
|
||||
disabled ={editFormDisable}
|
||||
/>
|
||||
<ProFormText
|
||||
width="md"
|
||||
|
@ -120,7 +227,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
label="任务名称"
|
||||
tooltip="最长为 24 位"
|
||||
placeholder="请输入任务名称"
|
||||
disabled ={props.operationId === OPERATION_BUTTON_TYPE.DETAIL}
|
||||
disabled ={editFormDisable}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
<ProFormTextArea
|
||||
|
@ -129,7 +236,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
label="任务描述"
|
||||
// tooltip="最长为 24 位"
|
||||
placeholder="请输入任务描述"
|
||||
disabled ={props.operationId === OPERATION_BUTTON_TYPE.DETAIL}
|
||||
disabled ={editFormDisable}
|
||||
/>
|
||||
|
||||
<ProForm.Group>
|
||||
|
@ -144,7 +251,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
name="priority"
|
||||
label="任务优先级"
|
||||
initialValue='3'
|
||||
disabled ={props.operationId === OPERATION_BUTTON_TYPE.DETAIL}
|
||||
disabled ={editFormDisable}
|
||||
/>
|
||||
<ProFormSelect
|
||||
width="sm"
|
||||
|
@ -157,7 +264,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
name="state"
|
||||
label="任务状态"
|
||||
initialValue='8'
|
||||
disabled ={props.operationId === OPERATION_BUTTON_TYPE.DETAIL}
|
||||
disabled ={editFormDisable}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
|
||||
|
@ -168,14 +275,14 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
label="期望时间"
|
||||
fieldProps={{allowEmpty:[true, true],showTime:true,needConfirm:false}}
|
||||
placeholder={['开始时间','结束时间']}
|
||||
disabled ={props.operationId === OPERATION_BUTTON_TYPE.DETAIL}
|
||||
disabled ={editFormDisable}
|
||||
/>
|
||||
<ProFormDateTimeRangePicker
|
||||
name="actualTimeRange"
|
||||
label="实际时间"
|
||||
fieldProps={ {allowEmpty:[true, true],showTime:true,needConfirm:false}}
|
||||
placeholder={['开始时间','结束时间']}
|
||||
disabled ={props.operationId === OPERATION_BUTTON_TYPE.DETAIL}
|
||||
disabled ={editFormDisable}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
.odd {
|
||||
background-color: #fff;
|
||||
}
|
||||
.even {
|
||||
background-color: rgb(209, 192, 192);
|
||||
}
|
|
@ -17,6 +17,7 @@ import {
|
|||
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
|
||||
import OperationButton from "@/ui/task/OperationButton";
|
||||
import dayjs from "dayjs";
|
||||
import '@/ui/task/project/TreeTablePro.modules.css'
|
||||
|
||||
const TreeTablePro: React.FC = () => {
|
||||
const actionRef = useRef<ActionType>();
|
||||
|
@ -131,7 +132,7 @@ const TreeTablePro: React.FC = () => {
|
|||
}
|
||||
];
|
||||
let toolBarRenderList = [
|
||||
<DetailModelForm key={1} operationId={OPERATION_BUTTON_TYPE.ADD} description='添加主线任务' reloadData={()=>{
|
||||
<DetailModelForm open={false} haveButton={true} key={1} operationId={OPERATION_BUTTON_TYPE.ADD} description='添加主线任务' reloadData={()=>{
|
||||
actionRef.current?.reload( false);
|
||||
}}/>,
|
||||
<Switch key={2} checkedChildren="树" unCheckedChildren="列表" checked={switchChecked}
|
||||
|
@ -207,6 +208,7 @@ const TreeTablePro: React.FC = () => {
|
|||
// },
|
||||
}}
|
||||
rowKey="id"
|
||||
rowClassName={(record, i) => (i % 2 === 1 ? "even" : "odd")}
|
||||
pagination={{
|
||||
current: current,
|
||||
pageSize: pageSize,
|
||||
|
@ -217,7 +219,7 @@ const TreeTablePro: React.FC = () => {
|
|||
}
|
||||
}}
|
||||
dateFormatter="string"
|
||||
scroll={{y: 600}}
|
||||
scroll={{y: 580}}
|
||||
// headerTitle="任务管理"
|
||||
toolBarRender={()=>toolBarRenderList}>
|
||||
</ProTable>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
|
@ -18,9 +22,19 @@
|
|||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"docker/out/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
|