diff --git a/next.config.mjs b/next.config.mjs index 04725e4..581ff2a 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -10,6 +10,8 @@ const nextConfig = { // Optional: Change the output directory `out` -> `dist` distDir: 'docker/out', + // 严格模式下react-beautiful-dnd无法使用 + reactStrictMode:false, }; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index 2862c43..e86b2cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,11 +5,13 @@ "requires": true, "packages": { "": { + "name": "assistant-todo", "version": "0.1.0", "dependencies": { "@ant-design/pro-components": "^2.7.1", "@heroicons/react": "^2.0.18", "@tailwindcss/forms": "^0.5.7", + "@types/react-beautiful-dnd": "^13.1.8", "antd": "^5.16.1", "axios": "^1.6.8", "dayjs": "^1.11.13", @@ -34,6 +36,7 @@ "eslint-config-next": "14.1.3", "prettier": "3.0.3", "prettier-plugin-tailwindcss": "0.5.4", + "react-beautiful-dnd": "^13.1.1", "typescript": "^5" } }, @@ -1540,6 +1543,16 @@ "integrity": "sha512-p9eZ2X9B80iKiTW4ukVj8B4K6q9/+xFtQ5MGYA5HWToY9nL4EkhV9+6ftT2VHpVMEZb5Tv00Iel516bVdO+yRw==", "dev": true }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.6", + "resolved": "https://registry.npmmirror.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz", + "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==", + "dev": true, + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/js-cookie": { "version": "3.0.6", "resolved": "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-3.0.6.tgz", @@ -1588,6 +1601,14 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-beautiful-dnd": { + "version": "13.1.8", + "resolved": "https://registry.npmmirror.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz", + "integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==", + "dependencies": { + "@types/react": "*" + } + }, "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", @@ -1608,6 +1629,18 @@ "@types/react": "*" } }, + "node_modules/@types/react-redux": { + "version": "7.1.34", + "resolved": "https://registry.npmmirror.com/@types/react-redux/-/react-redux-7.1.34.tgz", + "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==", + "dev": true, + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz", @@ -2533,6 +2566,15 @@ "node": ">= 8" } }, + "node_modules/css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "dev": true, + "dependencies": { + "tiny-invariant": "^1.0.6" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", @@ -4087,6 +4129,15 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -5525,6 +5576,12 @@ "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==", + "dev": true + }, "node_modules/rc-cascader": { "version": "3.24.1", "resolved": "https://registry.npmmirror.com/rc-cascader/-/rc-cascader-3.24.1.tgz", @@ -6113,6 +6170,32 @@ "node": ">=0.10.0" } }, + "node_modules/react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmmirror.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "deprecated": "react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-beautiful-dnd/node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "dev": true + }, "node_modules/react-big-calendar": { "version": "1.12.2", "resolved": "https://registry.npmmirror.com/react-big-calendar/-/react-big-calendar-1.12.2.tgz", @@ -6193,6 +6276,37 @@ "react-dom": ">=16.3.0" } }, + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmmirror.com/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "node_modules/reactcss": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz", @@ -6316,6 +6430,15 @@ "node": ">=8.10.0" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", @@ -7078,6 +7201,12 @@ "node": ">=12.22" } }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz", @@ -7343,6 +7472,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -8666,6 +8804,16 @@ "integrity": "sha512-p9eZ2X9B80iKiTW4ukVj8B4K6q9/+xFtQ5MGYA5HWToY9nL4EkhV9+6ftT2VHpVMEZb5Tv00Iel516bVdO+yRw==", "dev": true }, + "@types/hoist-non-react-statics": { + "version": "3.3.6", + "resolved": "https://registry.npmmirror.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz", + "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==", + "dev": true, + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/js-cookie": { "version": "3.0.6", "resolved": "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-3.0.6.tgz", @@ -8714,6 +8862,14 @@ "csstype": "^3.0.2" } }, + "@types/react-beautiful-dnd": { + "version": "13.1.8", + "resolved": "https://registry.npmmirror.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz", + "integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==", + "requires": { + "@types/react": "*" + } + }, "@types/react-big-calendar": { "version": "1.8.9", "resolved": "https://registry.npmmirror.com/@types/react-big-calendar/-/react-big-calendar-1.8.9.tgz", @@ -8734,6 +8890,18 @@ "@types/react": "*" } }, + "@types/react-redux": { + "version": "7.1.34", + "resolved": "https://registry.npmmirror.com/@types/react-redux/-/react-redux-7.1.34.tgz", + "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==", + "dev": true, + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz", @@ -9464,6 +9632,15 @@ "which": "^2.0.1" } }, + "css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "dev": true, + "requires": { + "tiny-invariant": "^1.0.6" + } + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", @@ -10674,6 +10851,15 @@ "function-bind": "^1.1.2" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "requires": { + "react-is": "^16.7.0" + } + }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -11717,6 +11903,12 @@ "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, + "raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==", + "dev": true + }, "rc-cascader": { "version": "3.24.1", "resolved": "https://registry.npmmirror.com/rc-cascader/-/rc-cascader-3.24.1.tgz", @@ -12117,6 +12309,29 @@ "loose-envify": "^1.1.0" } }, + "react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmmirror.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "dependencies": { + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "dev": true + } + } + }, "react-big-calendar": { "version": "1.12.2", "resolved": "https://registry.npmmirror.com/react-big-calendar/-/react-big-calendar-1.12.2.tgz", @@ -12182,6 +12397,28 @@ "warning": "^4.0.3" } }, + "react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmmirror.com/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } + } + }, "reactcss": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz", @@ -12282,6 +12519,15 @@ "picomatch": "^2.2.1" } }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2" + } + }, "reflect.getprototypeof": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", @@ -12884,6 +13130,12 @@ "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz", "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==" }, + "tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, "tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz", @@ -13080,6 +13332,13 @@ "punycode": "^2.1.0" } }, + "use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "dev": true, + "requires": {} + }, "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", diff --git a/package.json b/package.json index d7520d8..f8cd724 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@ant-design/pro-components": "^2.7.1", "@heroicons/react": "^2.0.18", "@tailwindcss/forms": "^0.5.7", + "@types/react-beautiful-dnd": "^13.1.8", "antd": "^5.16.1", "axios": "^1.6.8", "dayjs": "^1.11.13", @@ -36,7 +37,7 @@ "eslint-config-next": "14.1.3", "prettier": "3.0.3", "prettier-plugin-tailwindcss": "0.5.4", - "typescript": "^5", - "react-beautiful-dnd": "^13.1.8" + "react-beautiful-dnd": "^13.1.1", + "typescript": "^5" } } diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..ab2574e Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index d2f8422..0000000 --- a/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/task/drag/layout.tsx b/src/app/task/drag/layout.tsx new file mode 100644 index 0000000..5745068 --- /dev/null +++ b/src/app/task/drag/layout.tsx @@ -0,0 +1,58 @@ +/** + * A layout is UI that is shared between multiple routes. On navigation, layouts preserve state, remain interactive, and do not re-render. + */ +'use client' +import React, { useState} from 'react'; +import {DragDropContext, DropResult} from 'react-beautiful-dnd'; +import {DroppableTable} from "@/ui/task/drag/DroppableTable"; +import {DataType, Request} from "@/lib/definitions"; +import {useEffect} from "react"; +import {TaskSelectVO} from "@/lib/task/drag/data"; +import {selectTaskAPI} from "@/lib/task/drag/service"; + +export default function Layout({children}: { children: React.ReactNode }) { + const [allTaskList, setAllTaskList] = useState([]); + useEffect(() => { + addData() + },[]) + + async function addData() { + const requestParam: Request = { + pageSize: 1000, + pageNumber: 1, + data: {state:'9'} + } + const res = await selectTaskAPI(requestParam) + setAllTaskList(res.data.content) + } + + // 处理拖拽结束事件 + const onDragEnd = (result: DropResult) => { + console.log('拖拽结束') + const {source, destination} = result; + console.log('Source Droppable ID:', source.droppableId); + console.log('Destination Droppable ID:', destination?.droppableId); + if (!destination || !['table1', 'table2'].includes(destination.droppableId)) return; + // 如果拖拽到无效区域,直接返回 + if (!destination) return; + // 如果拖拽到同一个表格的同一个位置,直接返回 + if (source.droppableId === destination.droppableId && source.index === destination.index) { + return; + } + }; + + return ( + +
+ {/* 不紧急不重要 */} + task.priority == '1')}/> + {/* 紧急不重要 */} + task.priority == '2')}/> + {/* 不紧急重要 */} + task.priority == '3')}/> + {/* 紧急重要 */} + task.priority == '4')}/> +
+
+ ); +} diff --git a/src/app/task/drag/page.tsx b/src/app/task/drag/page.tsx new file mode 100644 index 0000000..887a836 --- /dev/null +++ b/src/app/task/drag/page.tsx @@ -0,0 +1,11 @@ +/** + * The .js, .jsx, or .tsx file extensions can be used for Pages. + * A page is always the leaf of the route subtree. + * A page.js file is required to make a route segment publicly accessible. + * Pages are Server Components by default, but can be set to a Client Component. + * Pages can fetch data. View the Data Fetching section for more information. + * @constructor + */ +export default function Page() { + return

Dashboard Page

; +} diff --git a/src/app/task/dragtest/page.tsx b/src/app/task/dragtest/page.tsx new file mode 100644 index 0000000..b8f0fd8 --- /dev/null +++ b/src/app/task/dragtest/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return

Dashboard test

; +} diff --git a/src/lib/definitions.ts b/src/lib/definitions.ts index 16fad12..c5b29f1 100644 --- a/src/lib/definitions.ts +++ b/src/lib/definitions.ts @@ -1,15 +1,11 @@ import React from "react"; import {Dayjs} from "dayjs"; -export type Invoice = { - id: string; - customer_id: string; - amount: number; - date: string; - // In TypeScript, this is called a string union type. - // It means that the "status" property can only be one of the two strings: 'pending' or 'paid'. - status: 'pending' | 'paid'; -}; +export type Request={ + data:T, + pageSize:number, + pageNumber:number, +} type Status={ success:boolean; code:number ; @@ -19,7 +15,6 @@ export type ResultPage = { content:T[]; totalPages:number; totalElements:number; - } export type ResponseVO={ data:T; @@ -27,20 +22,26 @@ export type ResponseVO={ status:Status; } -export type DataType ={ - key: React.ReactNode; +export type TaskMessage ={ id: string; pid:string; + pName:string; pPid:string; code: string; name: string; description: string; - state: number|string|undefined; - priority: number|string|undefined; + state: string; + priority: string; +} + + +export type DataType = TaskMessage&{ + key: React.ReactNode; + type:number; action?:React.ReactNode; - expectedStartTime?:Date|string; - expectedEndTime?:Date; + expectedStartTime?:string; + expectedEndTime?:string; expectedTimeRange?:(string|Dayjs|undefined)[]; actualStartTime?:Date; actualEndTime?:Date; diff --git a/src/lib/task/drag/data.tsx b/src/lib/task/drag/data.tsx new file mode 100644 index 0000000..c8ab15a --- /dev/null +++ b/src/lib/task/drag/data.tsx @@ -0,0 +1,6 @@ +export type TaskSelectVO = { + name?: string; + state?: string; + priority?: string; + allOverdueTasks?:boolean; +} \ No newline at end of file diff --git a/src/lib/task/drag/service.tsx b/src/lib/task/drag/service.tsx new file mode 100644 index 0000000..ad5969b --- /dev/null +++ b/src/lib/task/drag/service.tsx @@ -0,0 +1,15 @@ +import {DataType, Request, ResponseVO, ResultPage} from "@/lib/definitions"; +import {unstable_noStore as noStore} from "next/dist/server/web/spec-extension/unstable-no-store"; +import {AxiosResponse} from "axios"; +import {httpReq} from "@/utils/axiosReq"; +import {TaskSelectVO} from "@/lib/task/drag/data"; + +export async function selectTaskAPI(requestParam: Request): + Promise>> { + noStore(); + // 使用 Axios 发送 PUT 请求获取数据 + const response: AxiosResponse>> = await httpReq.post( + process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/task/select', requestParam); + // 从响应中提取数据并返回 + return response.data; +} \ No newline at end of file diff --git a/src/lib/task/project/data.tsx b/src/lib/task/project/data.tsx index 587350f..c93ed91 100644 --- a/src/lib/task/project/data.tsx +++ b/src/lib/task/project/data.tsx @@ -156,7 +156,7 @@ export const taskStateList: DictType[] = [ code: '8', name: '新建', order: 8, - color: 'RED' + color: 'primary' }, { id: 9, @@ -164,6 +164,13 @@ export const taskStateList: DictType[] = [ name: '进行中', order: 9, color: 'YELLOW' + }, + { + id:10, + code:'10', + name:'已逾期', + order:10, + color: 'RED' } ] @@ -177,4 +184,5 @@ export enum OPERATION_BUTTON_TYPE { SHOW_FOUR, SHOW_CALENDAR, ADD, + UPDATE_PRIORITY } diff --git a/src/ui/task/OperationButton.tsx b/src/ui/task/OperationButton.tsx index 74f8c70..bd6c619 100644 --- a/src/ui/task/OperationButton.tsx +++ b/src/ui/task/OperationButton.tsx @@ -1,12 +1,18 @@ import React, {Fragment} from "react"; -import {Button, Dropdown, MenuProps, message, Modal, Popconfirm, Space} from "antd"; +import {Button, Dropdown, MenuProps, message, Modal, Popconfirm, Radio, Space} from "antd"; import {DownOutlined, QuestionCircleOutlined} from "@ant-design/icons"; -import {commonUpdate, deleteTask, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data"; +import { + commonUpdate, + deleteTask, + OPERATION_BUTTON_TYPE, + taskPriorityList, +} from "@/lib/task/project/data"; import Link from "next/link"; import {DetailModelForm} from "@/ui/task/project/DetailModelForm"; export interface OperationButtonProps { itemId: string, + priority?:string, pid: string, pPid: string, operationId?: string, @@ -17,7 +23,10 @@ interface OperationModelProps { operationId: number, pPid: string, pid: string, - openModal: boolean + openModal: boolean, + updatePriority:boolean, + priority?:string, + updatePriorityValue?:string, } class OperationButton extends React.Component { @@ -28,7 +37,9 @@ class OperationButton extends React.Component { console.log(key) }; + const priorityHandleOk =async ()=>{ + console.log(this.props.itemId,this.state.priority,this.state.updatePriorityValue) + if (this.state.priority==this.state.updatePriorityValue){ + return + } + // 修改任务优先级 + const res = await commonUpdate({ + updateColumnList:[{ + name:'priority', + code:'priority', + value:this.state.updatePriorityValue + }], + conditionColumnList:[{ + name:'id', + code:'id', + operateType:'=', + value:this.props.itemId + }] + }) + // 关闭弹窗 + this.setState({updatePriority:false}) + if (res.status.success) { + // 全局提示 + message.success("完成任务成功") + // 更新任务 + this.props.refreshDate?.() + }else { + message.error(res.status.message) + } + } const items: MenuProps['items'] = [ { key: OPERATION_BUTTON_TYPE.DETAIL, @@ -110,6 +151,12 @@ class OperationButton extends React.Component完成任务, }, + { + key: OPERATION_BUTTON_TYPE.UPDATE_PRIORITY, + label: { + this.setState({updatePriority: true}) + }}>修改优先级, + }, { key: OPERATION_BUTTON_TYPE.SHOW_TREE, label: 树任务显示子任务, @@ -133,6 +180,28 @@ class OperationButton extends React.Component + {this.setState({updatePriority:false})}} + destroyOnClose={true} + okText='确认' + cancelText='取消' + > + {return { + label:taskPriority.name,value:taskPriority.code + }})} + defaultValue={this.state.priority} + optionType="button" + buttonStyle="solid" + onChange={e=>{ + console.log({e}) + this.setState({updatePriorityValue:e.target.value}) + }} + /> + {this.state.openModal&& void, + setUpdatePriority?: (value: (((prevState: (string | undefined)) => (string | undefined)) | string | undefined)) => void +} + +export const DetailForm: React.FC = (props) => { + const [form] = Form.useForm(); + const [componentDisabled] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL); + const {RangePicker} = DatePicker; + const {TextArea} = Input; + // const [taskMessage,setTaskMessage]=useState({name:"useState没效果吗,是这样的"}); + let defaultPriority:string|undefined; + useEffect(() => { + if (props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE) { + getTask(props.itemId).then(task => { + console.log('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; + defaultPriority = task.data.priority + task.data.actualTimeRange = [task.data.actualStartTime ? dayjs(task.data.actualStartTime) : '', + task.data.actualEndTime ? dayjs(task.data.actualEndTime) : '']; + task.data.expectedTimeRange = [task.data.expectedStartTime ? dayjs(task.data.expectedStartTime) : '', + task.data.expectedEndTime ? dayjs(task.data.expectedEndTime) : '']; + form.setFieldsValue(task.data) + } else { + message.error(task.status.message); + props.handleCancel() + } + }) + }else if(props.operationId === OPERATION_BUTTON_TYPE.ADD|| props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD){ + let data={'expectedTimeRange':[dayjs(), undefined]}; + form.setFieldsValue(data) + } + }, []) + const range = (start: number, end: number) => { + const result = []; + for (let i = start; i < end; i++) { + result.push(i); + } + return result; + }; + const disabledDate: RangePickerProps['disabledDate'] = (current) => { + // return current && current < dayjs().endOf('day'); + console.log('current', current, current && current < dayjs().endOf('day'), current < dayjs().endOf('day')) + return current < dayjs().startOf('day'); + }; + const disabledRangeTime: RangePickerProps['disabledTime'] = (_, type) => { + console.log('current', _) + if (type === 'start') { + return { + disabledHours: () => range(0, 60).splice(4, 20), + disabledMinutes: () => range(30, 60), + disabledSeconds: () => [55, 56], + }; + } + return { + disabledHours: () => range(0, 60).splice(20, 4), + disabledMinutes: () => range(0, 31), + disabledSeconds: () => [55, 56], + }; + }; + const onFinish = (values: any) => { + console.log(values); + let request: DataType = { + key: values.id, + id: values.id, + pPid: props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? props.pPid : values.pPid, + pid: props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? props.itemId : props.operationId === OPERATION_BUTTON_TYPE.UPDATE ? values.pid : 0, + code: values.code, + name: values.name, + description: values.description, + state: values.state, + priority: values.priority, + type: values.type, + children: [] + } + if (values.expectedTimeRange) { + if (values.expectedTimeRange[0]) { + request.expectedStartTime = values.expectedTimeRange[0] + } + if (values.expectedTimeRange[1]) { + request.expectedEndTime = values.expectedTimeRange[1] + } + } + if (values.actualTimeRange) { + if (values.actualTimeRange[0]) { + request.actualStartTime = values.actualTimeRange[0] + } + if (values.actualTimeRange[1]) { + request.actualEndTime = values.actualTimeRange[1] + } + } + if (props.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD) { + addTask(request).then(response => { + console.log('response', response) + if (response.status.success) { + message.success("添加任务成功:" + response.data) + props.handleCancel() + } + } + ) + } else if (props.operationId === OPERATION_BUTTON_TYPE.UPDATE) { + var stateFind = taskStateList.find(taskState => taskState.name === request.state?.toString()); + if (stateFind) { + request.state = stateFind.code; + } + var priorityFind = taskPriorityList.find(taskPriority => taskPriority.name === request.priority?.toString()); + if (priorityFind) { + request.priority = priorityFind.code; + } + updateTask(request).then(response => { + console.log('response', response) + if (response.status.success) { + message.success("修改任务成功:" + response.data) + props.handleCancel() + }else { + message.error(response.status.message) + } + } + ) + } + + + }; + return ( + <> + {/* setComponentDisabled(e.target.checked)}*/} + {/*>*/} + {/* Form disabled*/} + {/**/} +
+ name='id' label="id" hidden={true}> + + + name='pid' label="pid" hidden={true}> + + + name='code' label="code" hidden={true}> + + + name='pPid' label="pPid" hidden={true}> + + + + name='name' label="任务名称" + rules={[{required: true, message: '任务名称不能为空'}]}> + + + name='description' label="任务描述"> +