diff --git a/package-lock.json b/package-lock.json index 788ec70..64fcbb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^13.5.0", + "antd": "^5.25.4", + "axios": "^1.9.0", "react": "^19.1.0", "react-dom": "^19.1.0", "react-scripts": "5.0.1", @@ -49,6 +51,103 @@ "node": ">=6.0.0" } }, + "node_modules/@ant-design/colors": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.23.0.tgz", + "integrity": "sha512-7GAg9bD/iC9ikWatU9ym+P9ugJhi/WbsTWzcKN6T4gU0aehsprtke1UAaaSxxkjjmkJb3llet/rbUSLPgwlY4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz", + "integrity": "sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==", + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -2351,6 +2450,18 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "license": "MIT" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", @@ -3087,6 +3198,155 @@ } } }, + "node_modules/@rc-component/async-validator": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", + "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6", + "@babel/runtime": "^7.23.6", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz", + "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz", + "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.6.tgz", + "integrity": "sha512-/9zuTnWwhQ3S3WT1T8BubuFTT46kvnXgaERR9f4BTKyn61/wpf/BvbImzYBubzJibU707FxwbKszLlHjcLiv1Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.44.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -4561,6 +4821,71 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/antd": { + "version": "5.25.4", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.25.4.tgz", + "integrity": "sha512-yXdWqq1NJSZnD1HoPZWnWuQJGVYYnB3h0Ufsz4sbt3T0N9SdJ4G9GPpLMk8Gn9zWtwBekfR4THPVZ9uzAyhBHQ==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.2.1", + "@ant-design/cssinjs": "^1.23.0", + "@ant-design/cssinjs-utils": "^1.1.3", + "@ant-design/fast-color": "^2.0.6", + "@ant-design/icons": "^5.6.1", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.26.0", + "@rc-component/color-picker": "~2.0.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/qrcode": "~1.0.0", + "@rc-component/tour": "~1.15.1", + "@rc-component/trigger": "^2.2.6", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.11", + "rc-cascader": "~3.34.0", + "rc-checkbox": "~3.5.0", + "rc-collapse": "~3.9.0", + "rc-dialog": "~9.6.0", + "rc-drawer": "~7.3.0", + "rc-dropdown": "~4.2.1", + "rc-field-form": "~2.7.0", + "rc-image": "~7.12.0", + "rc-input": "~1.8.0", + "rc-input-number": "~9.5.0", + "rc-mentions": "~2.20.0", + "rc-menu": "~9.16.1", + "rc-motion": "^2.9.5", + "rc-notification": "~5.6.4", + "rc-pagination": "~5.1.0", + "rc-picker": "~4.11.3", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.1", + "rc-resize-observer": "^1.4.3", + "rc-segmented": "~2.7.0", + "rc-select": "~14.16.8", + "rc-slider": "~11.1.8", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.50.5", + "rc-tabs": "~15.6.1", + "rc-textarea": "~1.10.0", + "rc-tooltip": "~6.4.0", + "rc-tree": "~5.13.1", + "rc-tree-select": "~5.27.0", + "rc-upload": "~4.9.2", + "rc-util": "^5.44.4", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -4896,6 +5221,32 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -5602,6 +5953,12 @@ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "license": "MIT" }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -5846,6 +6203,12 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5909,6 +6272,15 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js": { "version": "3.42.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", @@ -6364,6 +6736,12 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "license": "MIT" }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -6435,6 +6813,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -10961,6 +11345,15 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "license": "MIT" }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -13643,6 +14036,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/psl": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", @@ -13770,6 +14169,618 @@ "node": ">=0.10.0" } }, + "node_modules/rc-cascader": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.34.0.tgz", + "integrity": "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "^2.3.1", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.5.0.tgz", + "integrity": "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.9.0.tgz", + "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz", + "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.3.0.tgz", + "integrity": "sha512-DX6CIgiBWNpJIMGFO8BAISFkxiuKitoizooj4BDyee8/SnBn0zwO2FHrNDpqqepj0E/TFTDpmEBCyFuTgC7MOg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.1.tgz", + "integrity": "sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.44.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.7.0.tgz", + "integrity": "sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.12.0.tgz", + "integrity": "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.8.0.tgz", + "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.5.0.tgz", + "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.8.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.20.0.tgz", + "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.8.0", + "rc-menu": "~9.16.0", + "rc-textarea": "~1.10.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.1.tgz", + "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.4.tgz", + "integrity": "sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.4.1.tgz", + "integrity": "sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.1.0.tgz", + "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.11.3.tgz", + "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.43.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", + "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.44.1", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.7.0.tgz", + "integrity": "sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.16.8", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.16.8.tgz", + "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.8.tgz", + "integrity": "sha512-2gg/72YFSpKP+Ja5AjC5DPL1YnV8DEITDQrcc1eASrUYjl0esptaBVJBh5nLTXCCp15eD8EuGjwezVGSHhs9tQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.50.5", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.50.5.tgz", + "integrity": "sha512-FDZu8aolhSYd3v9KOc3lZOVAU77wmRRu44R0Wfb8Oj1dXRUsloFaXMSl6f7yuWZUxArJTli7k8TEOX2mvhDl4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.44.3", + "rc-virtual-list": "^3.14.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.6.1.tgz", + "integrity": "sha512-/HzDV1VqOsUWyuC0c6AkxVYFjvx9+rFPKZ32ejxX0Uc7QCzcEjTA9/xMgv4HemPKwzBNX8KhGVbbumDjnj92aA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.10.0.tgz", + "integrity": "sha512-ai9IkanNuyBS4x6sOL8qu/Ld40e6cEs6pgk93R+XLYg0mDSjNBGey6/ZpDs5+gNLD7urQ14po3V6Ck2dJLt9SA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.8.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.4.0.tgz", + "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1", + "rc-util": "^5.44.3" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz", + "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.27.0.tgz", + "integrity": "sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "2.x", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.9.2.tgz", + "integrity": "sha512-nHx+9rbd1FKMiMRYsqQ3NkXUv7COHPBo3X1Obwq9SWS6/diF/A0aJ5OHubvwUAIDs+4RMleljV0pcrNUc823GQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/rc-virtual-list": { + "version": "3.18.6", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.18.6.tgz", + "integrity": "sha512-TQ5SsutL3McvWmmxqQtMIbfeoE3dGjJrRSfKekgby7WQMpPIFvv4ghytp5Z0s3D8Nik9i9YNOCqHBfk86AwgAA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", @@ -14232,6 +15243,12 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -14659,6 +15676,15 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -15301,6 +16327,12 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "license": "MIT" + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -15590,6 +16622,12 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -16090,6 +17128,15 @@ "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", "license": "MIT" }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -16114,6 +17161,12 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", diff --git a/package.json b/package.json index 2c46698..0a5e4c2 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^13.5.0", + "antd": "^5.25.4", + "axios": "^1.9.0", "react": "^19.1.0", "react-dom": "^19.1.0", "react-scripts": "5.0.1", diff --git a/public/pictures/R-C.jpg b/public/pictures/R-C.jpg new file mode 100644 index 0000000..6d3ac8c Binary files /dev/null and b/public/pictures/R-C.jpg differ diff --git a/src/App.css b/src/App.css index 74b5e05..08f123f 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +1,702 @@ -.App { +/* App.css */ +.app { + font-family: Arial, sans-serif; + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +.app-header { + margin-bottom: 30px; + padding-bottom: 20px; + border-bottom: 1px solid #eee; +} + +.app-header h1 { + margin: 0 0 15px 0; + color: #333; text-align: center; } -.App-logo { - height: 40vmin; +.stats { + display: flex; + justify-content: center; + gap: 20px; + margin-bottom: 20px; + font-size: 16px; + color: #666; +} + +.stats span { + padding: 5px 15px; + background-color: #f0f0f0; + border-radius: 4px; +} + +.controls { + display: flex; + flex-direction: column; + gap: 15px; +} + +.filter-controls { + display: flex; + flex-wrap: wrap; + gap: 20px; +} + +.token-input, .user-filter { + flex: 1; + min-width: 250px; +} + +.token-input label, .user-filter label { + display: block; + font-weight: bold; + margin-bottom: 5px; + color: #555; +} + +.token-input input, .user-filter select { + width: 100%; + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 14px; +} + +.refresh-btn { + padding: 10px 20px; + background-color: #1890ff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + transition: background-color 0.3s; + align-self: flex-end; +} + +.refresh-btn:hover { + background-color: #40a9ff; +} + +.refresh-btn:disabled { + background-color: #d9d9d9; + cursor: not-allowed; +} + +.status-message { + padding: 30px; + text-align: center; + font-size: 18px; + border-radius: 4px; + margin: 20px 0; +} + +.loading { + color: #1890ff; + background-color: #e6f7ff; +} + +.error { + color: #f5222d; + background-color: #fff1f0; +} + +.no-data { + color: #faad14; + background-color: #fffbe6; +} + +.image-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 20px; + margin-top: 20px; +} + +.image-card { + border: 1px solid #eee; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); + transition: all 0.3s ease; + cursor: pointer; + background-color: white; +} + +.image-card:hover { + transform: translateY(-5px); + box-shadow: 0 5px 15px rgba(0,0,0,0.1); +} + +.image-preview { + height: 200px; + background-color: #fafafa; + display: flex; + align-items: center; + justify-content: center; + border-bottom: 1px solid #eee; +} + +.image-preview img { + max-width: 100%; + max-height: 100%; + object-fit: contain; +} + +.image-placeholder { + color: #bfbfbf; + font-size: 16px; +} + +.image-details { + padding: 15px; +} + +.image-details h3 { + margin: 0 0 10px; + font-size: 16px; + color: #333; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.image-details p { + margin: 6px 0; + font-size: 14px; + color: #666; +} + +.image-details p strong { + color: #444; +} + +/* 模态框样式 */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +.modal-content { + background-color: white; + border-radius: 8px; + width: 90%; + max-width: 900px; + max-height: 90vh; + overflow-y: auto; + padding: 25px; + position: relative; + box-shadow: 0 5px 20px rgba(0,0,0,0.2); +} + +.close-btn { + position: absolute; + top: 15px; + right: 15px; + font-size: 24px; + background: none; + border: none; + cursor: pointer; + color: #999; + padding: 5px; +} + +.close-btn:hover { + color: #666; +} + +.modal-content h2 { + margin-top: 0; + color: #333; + border-bottom: 1px solid #eee; + padding-bottom: 10px; +} + +.modal-body { + display: flex; + flex-direction: column; + gap: 20px; + margin-top: 20px; +} + +@media (min-width: 768px) { + .modal-body { + flex-direction: row; + } +} + +.modal-image-preview { + flex: 1; + min-height: 300px; + background-color: #fafafa; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #eee; + border-radius: 4px; + padding: 15px; +} + +.modal-image-preview img { + max-width: 100%; + max-height: 400px; + object-fit: contain; +} + +.image-metadata { + flex: 1; + min-width: 300px; +} + +.image-metadata h3 { + margin-top: 0; + color: #333; + font-size: 18px; + border-bottom: 1px solid #eee; + padding-bottom: 10px; +} + +.metadata-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 15px; + margin-top: 15px; +} + +.metadata-item { + display: flex; + flex-direction: column; +} + +.metadata-item label { + font-size: 13px; + color: #888; + margin-bottom: 3px; +} + +.metadata-item span { + font-size: 14px; + color: #333; + word-break: break-word; +} + +/* 图片悬停信息 */ +.image-hover-info { + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: rgba(0, 0, 0, 0.7); + color: white; + padding: 5px; + font-size: 12px; + opacity: 0; + transition: opacity 0.3s; pointer-events: none; } -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } +.image-wrapper:hover .image-hover-info { + opacity: 1; } -.App-header { - background-color: #282c34; - min-height: 100vh; +.image-wrapper { + position: relative; +} + +/* 放大图片样式 */ +.enlarged-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.9); display: flex; - flex-direction: column; - align-items: center; justify-content: center; - font-size: calc(10px + 2vmin); + align-items: center; + z-index: 1000; +} + +.enlarged-content { + position: relative; + max-width: 90%; + max-height: 90%; +} + +.enlarged-image { + max-width: 100%; + max-height: 80vh; + object-fit: contain; +} + +.enlarged-content .close-btn { + position: absolute; + top: -40px; + right: 0; + background: transparent; + border: none; + color: white; + font-size: 30px; + cursor: pointer; +} + +/* 模态框中的图片预览 */ +.modal-preview .image-preview { + cursor: zoom-in; + max-height: 300px; +} + +/* 已选择图片样式 */ +.image-card.selected { + border: 2px solid #1890ff; + background-color: #f0f7ff; +} + +.image-checkbox { + position: absolute; + top: 5px; + right: 5px; + z-index: 1; +} + +/* 关联按钮样式 */ +.action-buttons { + display: flex; + gap: 10px; +} + +.link-btn { + background-color: #52c41a; color: white; } -.App-link { - color: #61dafb; +.link-btn:hover { + background-color: #73d13d; } -@keyframes App-logo-spin { - from { - transform: rotate(0deg); +.selected-count { + margin-left: 15px; + color: #1890ff; + font-weight: bold; +} + +/* 关联模态框样式 */ +.link-modal { + max-width: 800px; +} + +.link-form { + margin-top: 20px; +} + +.selected-images-preview { + margin-bottom: 20px; +} + +.preview-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); + gap: 10px; + max-height: 200px; + overflow-y: auto; +} + +.small-preview .image-preview { + max-height: 80px; + width: auto; +} + +.small-preview .image-wrapper { + height: 80px; + display: flex; + align-items: center; + justify-content: center; +} + +.small-preview .image-hover-info { + display: none; +} + +/* 数字输入框样式 */ +input[type="number"] { + width: 100%; + padding: 8px; + border: 1px solid #d9d9d9; + border-radius: 4px; +} + +select { + width: 100%; + padding: 8px; + border: 1px solid #d9d9d9; + border-radius: 4px; + background-color: white; +} + +/* 关联模式下的图片卡片样式 */ +.image-card.linking-mode { + cursor: pointer; +} + +.image-card.linking-mode:hover { + box-shadow: 0 0 0 2px #1890ff; +} + +/* 取消按钮样式 */ +.cancel-btn { + background-color: #ff4d4f; + color: white; +} + +.cancel-btn:hover { + background-color: #ff7875; +} + +/* 详情模态框中的部件ID字段 */ +.image-metadata .metadata-item { + margin-bottom: 10px; +} + +/* 关联模式下隐藏的悬停信息 */ +.linking-mode .image-hover-info { + display: none; +} + +/* 图片选择复选框样式 */ +.image-checkbox { + position: absolute; + top: 5px; + right: 5px; + z-index: 1; +} + +.image-checkbox input { + width: 16px; + height: 16px; +} + +.adaptive-link-form { + display: flex; + flex-direction: column; + width: 100%; +} + +.image-container { + width: 100%; + margin-bottom: 16px; + display: flex; + justify-content: center; +} + +.adaptive-image { + max-width: 100%; + max-height: 40vh; /* 图片最大高度 */ + object-fit: contain; + border-radius: 8px; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 20px; + overflow-y: auto; /* 仅表单区域可滚动 */ + flex-grow: 1; + padding: 8px; +} + +.form-group { + background: #f8f9fa; + padding: 16px; + border-radius: 8px; + display: flex; + flex-direction: column; + gap: 12px; +} + +.form-group h4 { + margin: 0 0 12px 0; + color: #333; + font-size: 16px; +} + +.form-item { + display: flex; + flex-direction: column; + gap: 4px; +} + +.form-item label { + font-size: 12px; + color: #666; +} + +.form-item .value { + padding: 8px; + background: white; + border-radius: 4px; + border: 1px solid #eee; +} + +.inline-fields { + display: flex; + gap: 12px; +} + +.form-actions { + position: sticky; + bottom: 0; + background: white; + padding: 16px 0; + display: flex; + justify-content: flex-end; +} + +/* 响应式调整 */ +@media (max-width: 768px) { + .form-grid { + grid-template-columns: 1fr; } - to { - transform: rotate(360deg); +} + +/* 主容器 (与modal-body配合) */ +.modal-body { + display: flex; + height: 80vh; + gap: 24px; +} + +.modal-image-preview { + flex: 0 0 45%; + overflow: hidden; +} + +.link-form-container { + flex: 1; + display: flex; + flex-direction: column; + overflow-y: auto; + padding-right: 8px; +} + +/* 表单标题区 */ +.form-header { + margin-bottom: 20px; + padding-bottom: 12px; + border-bottom: 1px solid #eee; +} + +.form-header h3 { + margin: 0 0 8px 0; + font-size: 18px; +} + +.image-meta { + display: flex; + justify-content: space-between; + color: #666; + font-size: 13px; +} + +/* 表单网格布局 */ +.form-grid { + display: flex; + flex-direction: column; + gap: 20px; + flex-grow: 1; +} + +.form-group { + background: white; + padding: 16px; + border-radius: 8px; + box-shadow: 0 1px 3px rgba(0,0,0,0.08); +} + +.form-row { + display: flex; + gap: 16px; + margin-bottom: 12px; +} + +.form-row:last-child { + margin-bottom: 0; +} + +.form-item { + flex: 1; + display: flex; + flex-direction: column; + gap: 6px; +} + +.form-item label { + font-size: 13px; + color: #666; +} + +.form-item select { + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 4px; + background: white; +} + +/* 操作按钮 */ +.form-actions { + position: sticky; + bottom: 0; + background: white; + padding: 16px 0; + margin-top: auto; +} + +.submit-button { + padding: 10px 24px; + background: #1890ff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + width: 100%; +} + +.submit-button:hover { + background: #40a9ff; +} + +.submit-button:disabled { + background: #d9d9d9; + cursor: not-allowed; +} + +/* 响应式调整 */ +@media (max-width: 992px) { + .modal-body { + flex-direction: column; + height: auto; + max-height: 90vh; + } + + .modal-image-preview { + flex: auto; + max-height: 40vh; } } + +@media (max-width: 576px) { + .form-row { + flex-direction: column; + gap: 12px; + } +} \ No newline at end of file diff --git a/src/App.js b/src/App.js index 3784575..d235f4b 100644 --- a/src/App.js +++ b/src/App.js @@ -1,25 +1,261 @@ -import logo from './logo.svg'; +/** + * 主应用组件 + * 图片管理系统入口,整合所有子组件 + * 主要功能: + * - 显示图片列表 + * - 提供筛选功能 + * - 显示图片详情和关联表单 + */ +import React, { useState, useEffect } from 'react'; import './App.css'; +import { fetchImages, linkImagesToPart } from './components/ImageAPI.js'; +import ImagePreview from './components/ImagePreview'; +import LinkForm from './components/LinkForm'; +import UserFilter from './components/UserFilter'; function App() { + const [images, setImages] = useState([]); + const [filteredImages, setFilteredImages] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [token, setToken] = useState(''); + const [selectedImage, setSelectedImage] = useState(null); + const [showModal, setShowModal] = useState(false); + const [uploadUsers, setUploadUsers] = useState(['all']); + const [selectedUser, setSelectedUser] = useState('all'); + const [enlargedImage, setEnlargedImage] = useState(null); + const [linkFormData, setLinkFormData] = useState({ + collectorId: '', + collectorName: '', + humidness: '', + imagePaths: [], + partId: '', + shootingDistance: '', + shootingMethod: '', + shootingTimeBegin: '', + shootingTimeEnd: '', + temperatureMax: '', + temperatureMin: '', + weather: '', + windLevel: '' + }); + + // 获取图片数据 + const fetchImageData = async () => { + try { + setLoading(true); + setError(null); + + const imagesData = await fetchImages(token); + setImages(imagesData); + + // 提取所有不重复的上传用户 + const users = [...new Set(imagesData.map(img => img.uploadUser || '未知'))]; + setUploadUsers(['all', ...users]); + + // 设置默认用户筛选 + if (users.length > 0) { + setSelectedUser(users[0]); + setFilteredImages(imagesData.filter(img => img.uploadUser === users[0])); + } else { + setFilteredImages(imagesData); + } + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + // 初始化加载 + useEffect(() => { + fetchImageData(); + }, []); + + // 用户筛选处理 + useEffect(() => { + if (selectedUser === 'all') { + setFilteredImages(images); + } else { + setFilteredImages(images.filter(img => img.uploadUser === selectedUser)); + } + }, [selectedUser, images]); + + const handleTokenChange = (e) => { + setToken(e.target.value); + }; + + const handleRefresh = () => { + fetchImageData(); + }; + + const handleImageClick = (image) => { + setSelectedImage(image); + setShowModal(true); + + // 初始化关联表单数据 + setLinkFormData({ + collectorId: image.collectorId || '', + collectorName: image.collectorName || '', + humidness: image.humidness || '', + imagePaths: [image.imagePath], + partId: image.partId || '', + shootingDistance: image.shootingDistance || '', + shootingMethod: image.shootingMethod || '', + shootingTimeBegin: image.shootingTimeBegin || '', + shootingTimeEnd: image.shootingTimeEnd || '', + temperatureMax: image.temperatureMax || '', + temperatureMin: image.temperatureMin || '', + weather: image.weather || '', + windLevel: image.windLevel || '' + }); + }; + + const closeModal = () => { + setShowModal(false); + setSelectedImage(null); + setEnlargedImage(null); + }; + + const handleUserFilterChange = (e) => { + setSelectedUser(e.target.value); + }; + + // 处理关联表单字段变化 + const handleLinkFormChange = (fieldName, value) => { + setLinkFormData(prev => ({ + ...prev, + [fieldName]: value + })); + }; + + // 提交关联图片到机组 + const handleLinkImages = async () => { + if (!linkFormData.partId) { + alert('请填写部件ID'); + return; + } + + try { + setLoading(true); + await linkImagesToPart(token, linkFormData); + alert('图片关联成功'); + closeModal(); + fetchImageData(); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - +
+
+

上传图片管理系统

+
+ 总图片数: {images.length} + 当前显示: {filteredImages.length} +
+
+
+
+ + +
+ +
+
+ +
+
+ +
+ {loading && images.length === 0 ? ( +
加载中...
+ ) : error ? ( +
{error}
+ ) : filteredImages.length === 0 ? ( +
+ {selectedUser === 'all' ? '没有找到图片数据' : '该用户没有上传图片'} +
+ ) : ( +
+ {filteredImages.map((image) => ( +
handleImageClick(image)} + > + +
+

{image.imageName || '未命名图片'}

+

上传用户: {image.uploadUser || '未知'}

+

拍摄时间: {image.shootingTime || '未知'}

+ {image.partId &&

关联部件: {image.partId}

} +
+
+ ))} +
+ )} +
+ + {/* 图片详情模态框 */} + {showModal && selectedImage && ( +
+
e.stopPropagation()}> + +

图片关联信息

+ +
+
+ +
+ +
+
+
+ )} + + {/* 放大图片的模态框 */} + {enlargedImage && ( +
setEnlargedImage(null)}> +
e.stopPropagation()}> + + 放大图片 +
+
+ )}
); } -export default App; +export default App; \ No newline at end of file diff --git a/src/components/DEFINE.js b/src/components/DEFINE.js new file mode 100644 index 0000000..8dcaca8 --- /dev/null +++ b/src/components/DEFINE.js @@ -0,0 +1,3 @@ +const DTAI_SITE = 'http://pms.dtyx.net:9158'; + +export default DTAI_SITE; \ No newline at end of file diff --git a/src/components/EditableField.js b/src/components/EditableField.js new file mode 100644 index 0000000..1d41bbe --- /dev/null +++ b/src/components/EditableField.js @@ -0,0 +1,44 @@ +/** + * 可编辑字段组件 + * 提供一个带有标签的可编辑输入字段,支持多种输入类型 + * + * 用法: + * + * + * @param {string} label - 字段标签文本 + * @param {string|number} value - 字段当前值 + * @param {string} fieldName - 字段名称,用于标识字段 + * @param {function} onChange - 字段值变化时的回调函数 (fieldName, newValue) => void + * @param {string} [type="text"] - 输入类型,支持text/number/datetime-local等 + */ +import React, { useState } from 'react'; + +const EditableField = ({ label, value, fieldName, onChange, type = "text" }) => { + const [fieldValue, setFieldValue] = useState(value || ''); + + const handleChange = (e) => { + const newValue = e.target.value; + setFieldValue(newValue); + onChange(fieldName, newValue); + }; + + return ( +
+ + +
+ ); +}; + +export default EditableField; \ No newline at end of file diff --git a/src/components/ImageAPI.js b/src/components/ImageAPI.js new file mode 100644 index 0000000..36fe022 --- /dev/null +++ b/src/components/ImageAPI.js @@ -0,0 +1,73 @@ +/** + * 图片数据API模块 + * 封装所有与图片数据相关的API调用 + * + * 主要函数: + * - fetchImages(token): 获取图片列表 + * - linkImagesToPart(token, formData): 关联图片到部件 + * + * 依赖: + * - axios: HTTP请求库 + * - DTAI_SITE: API基础URL + */ +import axios from 'axios'; +import DTAI_SITE from './DEFINE.js'; + +/** + * 获取图片列表 + * @param {string} token - 授权token(可选) + * @returns {Promise} 图片数据数组 + */ +export const fetchImages = async (token) => { + try { + const headers = {}; + if (token) { + headers.Authorization = token; + } + + const response = await axios.get(`${DTAI_SITE}/image/list/app-upload-images`, { + headers + }); + + if (response.data && response.data.success) { + return response.data.data || []; + } + throw new Error('获取图片失败'); + } catch (err) { + throw new Error(err.message || '获取图片时发生错误'); + } +}; + +/** + * 关联图片到部件 + * @param {string} token - 授权token(可选) + * @param {Object} formData - 关联表单数据 + * @returns {Promise} 响应数据 + */ +export const linkImagesToPart = async (token, formData) => { + const headers = {}; + if (token) { + headers.Authorization = token; + } + + // 转换数值类型字段 + const payload = { + ...formData, + humidness: formData.humidness ? parseInt(formData.humidness) : undefined, + shootingDistance: formData.shootingDistance ? parseInt(formData.shootingDistance) : undefined, + temperatureMax: formData.temperatureMax ? parseFloat(formData.temperatureMax) : undefined, + temperatureMin: formData.temperatureMin ? parseFloat(formData.temperatureMin) : undefined, + windLevel: formData.windLevel ? parseInt(formData.windLevel) : undefined + }; + + const response = await axios.post( + DTAI_SITE + '/image/linkAppImagesToPart', + payload, + { headers } + ); + + if (response.data && response.data.success) { + return response.data; + } + throw new Error('图片关联失败'); +}; \ No newline at end of file diff --git a/src/components/ImagePreview.js b/src/components/ImagePreview.js new file mode 100644 index 0000000..cd26569 --- /dev/null +++ b/src/components/ImagePreview.js @@ -0,0 +1,63 @@ +/** + * 图片预览组件 + * 显示图片预览及基本信息,支持错误处理和点击放大 + * + * 用法: + * + * + * @param {Object} image - 图片数据对象 + * @param {boolean} [isInModal=false] - 是否在模态框中显示 + * @param {function} [onEnlarge] - 点击放大回调函数 + */ +import React from 'react'; +import DTAI_SITE from './DEFINE.js'; + +const ImagePreview = ({ image, isInModal = false, onEnlarge }) => { + /** + * 获取图片预览URL + * @param {string} imagePath - 图片路径 + * @returns {string} 完整图片URL + */ + const getImagePreviewUrl = (imagePath) => { + if (!imagePath) return ''; + return `${DTAI_SITE}${imagePath}`; + }; + + const previewUrl = getImagePreviewUrl(image.imagePath); + const imageSizeInfo = image.imageSize ? `大小: ${image.imageSize}` : '大小: 未知'; + const resolutionInfo = image.imageWidth && image.imageHeight + ? `分辨率: ${image.imageResolution}` + : '分辨率: 未知'; + + return ( +
+ {previewUrl ? ( +
+ {image.imageName { + e.target.onerror = null; + e.target.src = './pictures/R-C.jpg'; + }} + title={`${imageSizeInfo}\n${resolutionInfo}`} + onClick={isInModal && onEnlarge ? () => onEnlarge(previewUrl) : undefined} + /> +
+
{imageSizeInfo}
+
{resolutionInfo}
+
+
+ ) : ( +
无预览图
+ )} +
+ ); +}; + +export default ImagePreview; \ No newline at end of file diff --git a/src/components/LinkForm.js b/src/components/LinkForm.js new file mode 100644 index 0000000..7506844 --- /dev/null +++ b/src/components/LinkForm.js @@ -0,0 +1,165 @@ +/** + * 图片关联表单组件 - 与预览组件配合的布局 + * 自适应右侧表单区域,确保与左侧预览协调 + */ +import React from 'react'; +import EditableField from './EditableField'; +import WeatherSelect from './weatherselect.js'; + +const SHOOTING_METHOD_OPTIONS = [ + 'MANUAL', 'AUTO', 'TRIPOD', 'DRONE', 'ROBOT' +]; + +const LinkForm = ({ formData, image, onChange, onSubmit, loading }) => { + return ( +
+ {/* 表单标题 */} +
+

图片关联信息

+
+ {image.imageName} + {image.imageWidth}×{image.imageHeight} +
+
+ + {/* 自适应表单网格 */} +
+ {/* 第一组:核心信息 */} +
+
+ +
+
+ + +
+
+ + {/* 第二组:拍摄信息 */} +
+
+ onChange('weather', value)} + /> +
+ + +
+
+
+ +
+
+ + {/* 第三组:环境信息 */} +
+
+ + +
+
+ + +
+
+ + {/* 第四组:时间信息 */} +
+
+ +
+
+ +
+
+
+ + {/* 操作按钮 */} +
+ +
+
+ ); +}; + +export default LinkForm; \ No newline at end of file diff --git a/src/components/UserFilter.js b/src/components/UserFilter.js new file mode 100644 index 0000000..fe9b1d3 --- /dev/null +++ b/src/components/UserFilter.js @@ -0,0 +1,40 @@ +/** + * 用户筛选组件 + * 提供按用户筛选图片的功能 + * + * 用法: + * + * + * @param {Array} users - 用户列表,包含'all'选项 + * @param {string} selectedUser - 当前选中的用户 + * @param {function} onChange - 用户选择变化回调 + * @param {boolean} disabled - 是否禁用选择框 + */ +import React from 'react'; + +const UserFilter = ({ users, selectedUser, onChange, disabled }) => { + return ( +
+ + +
+ ); +}; + +export default UserFilter; \ No newline at end of file diff --git a/src/components/weatherselect.js b/src/components/weatherselect.js new file mode 100644 index 0000000..8b2e46c --- /dev/null +++ b/src/components/weatherselect.js @@ -0,0 +1,76 @@ +import React, { useState, useEffect } from 'react'; +import DTAI_SITE from './DEFINE'; + +const WeatherSelect = ({ value, onChange }) => { + const [weatherOptions, setWeatherOptions] = useState([]); + const [loading, setLoading] = useState(true); + + // 默认天气选项 + const defaultWeatherOptions = [ + { value: 'sunny', label: '晴天' }, + { value: 'cloudy', label: '多云' }, + { value: 'light-rain', label: '小雨' }, + { value: 'moderate-rain', label: '中雨' }, + { value: 'heavy-rain', label: '大雨' }, + { value: 'storm', label: '暴雨' } + ]; + + useEffect(() => { + const fetchWeatherOptions = async () => { + try { + const response = await fetch(DTAI_SITE + '/weather-type/list'); + const data = await response.json(); + if (data.code === 0) { + // 转换API数据格式 + const options = data.rows.map(item => ({ + value: item.weatherCode, + label: item.chineseName + })); + // 如果API返回的列表不为空则使用API数据,否则使用默认选项 + setWeatherOptions(options.length > 0 ? options : defaultWeatherOptions); + } else { + // API返回错误时使用默认选项 + setWeatherOptions(defaultWeatherOptions); + } + } catch (error) { + console.error('获取天气选项失败:', error); + // 请求失败时使用默认选项 + setWeatherOptions(defaultWeatherOptions); + } finally { + setLoading(false); + } + }; + + fetchWeatherOptions(); + }, []); + + if (loading) { + return ( +
+ + +
+ ); + } + + return ( +
+ + +
+ ); +}; + +export default WeatherSelect; \ No newline at end of file diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..8dc6ee5 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,3 @@ +export const SHOOTING_METHOD_OPTIONS = [ + 'MANUAL', 'AUTO', 'TRIPOD', 'DRONE', 'ROBOT' +]; \ No newline at end of file