diff --git a/.gitignore b/.gitignore index fc3d87bf..12ab2e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -199,4 +199,4 @@ cython_debug/ # PyPI configuration file .pypirc - +江西城市生命线-可交互原型/frontend/node_modules/* \ No newline at end of file diff --git a/江西城市生命线-可交互原型/frontend/index.html b/江西城市生命线-可交互原型/frontend/index.html new file mode 100644 index 00000000..ea8e8246 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + AI数智化平台 + + +
+ + + diff --git a/江西城市生命线-可交互原型/frontend/package-lock.json b/江西城市生命线-可交互原型/frontend/package-lock.json new file mode 100644 index 00000000..ff0ee6bb --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/package-lock.json @@ -0,0 +1,2196 @@ +{ + "name": "urbanmind-frontend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "urbanmind-frontend", + "version": "1.0.0", + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "axios": "^1.6.2", + "element-plus": "^2.4.4", + "pinia": "^2.1.7", + "vue": "^3.3.11", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.5.2", + "sass": "^1.69.5", + "vite": "^5.0.10" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", + "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", + "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.25", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz", + "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz", + "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.25", + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz", + "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.25.tgz", + "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.25.tgz", + "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.25.tgz", + "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.25", + "@vue/runtime-core": "3.5.25", + "@vue/shared": "3.5.25", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.25.tgz", + "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25" + }, + "peerDependencies": { + "vue": "3.5.25" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", + "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "license": "MIT", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/element-plus": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.12.0.tgz", + "integrity": "sha512-M9YLSn2np9OnqrSKWsiXvGe3qnF8pd94+TScsHj1aTMCD+nSEvucXermf807qNt6hOP040le0e5Aft7E9ZfHmA==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.2", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.17.20", + "@types/lodash-es": "^4.17.12", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.19", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.3", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz", + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "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/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/sass": { + "version": "1.94.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", + "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.25.tgz", + "integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-sfc": "3.5.25", + "@vue/runtime-dom": "3.5.25", + "@vue/server-renderer": "3.5.25", + "@vue/shared": "3.5.25" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", + "integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + } + } +} diff --git a/江西城市生命线-可交互原型/frontend/package.json b/江西城市生命线-可交互原型/frontend/package.json new file mode 100644 index 00000000..05a740a1 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/package.json @@ -0,0 +1,24 @@ +{ + "name": "urbanmind-frontend", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.6.2", + "vue": "^3.3.11", + "vue-router": "^4.2.5", + "pinia": "^2.1.7", + "@element-plus/icons-vue": "^2.3.1", + "element-plus": "^2.4.4" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.5.2", + "sass": "^1.69.5", + "vite": "^5.0.10" + } +} diff --git a/江西城市生命线-可交互原型/frontend/public/avatar.svg b/江西城市生命线-可交互原型/frontend/public/avatar.svg new file mode 100644 index 00000000..b537ce1d --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/public/avatar.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/江西城市生命线-可交互原型/frontend/public/favicon.svg b/江西城市生命线-可交互原型/frontend/public/favicon.svg new file mode 100644 index 00000000..0064d6fc --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/public/favicon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/public/logo.jpg b/江西城市生命线-可交互原型/frontend/public/logo.jpg new file mode 100644 index 00000000..18b5da66 Binary files /dev/null and b/江西城市生命线-可交互原型/frontend/public/logo.jpg differ diff --git a/江西城市生命线-可交互原型/frontend/src/App.vue b/江西城市生命线-可交互原型/frontend/src/App.vue new file mode 100644 index 00000000..05e892fd --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/App.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/api/project.js b/江西城市生命线-可交互原型/frontend/src/api/project.js new file mode 100644 index 00000000..033ee110 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/api/project.js @@ -0,0 +1,221 @@ +/** + * 项目管理 API 服务 + */ + +import axios from 'axios' + +const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api' + +// 创建 axios 实例 +const apiClient = axios.create({ + baseURL: API_BASE_URL, + timeout: 10000, + headers: { + 'Content-Type': 'application/json' + } +}) + +// 请求拦截器 +apiClient.interceptors.request.use( + config => { + // 可以在这里添加 token + const token = localStorage.getItem('token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + error => { + return Promise.reject(error) + } +) + +// 响应拦截器 +apiClient.interceptors.response.use( + response => { + return response.data + }, + error => { + console.error('API Error:', error) + return Promise.reject(error) + } +) + +/** + * 项目管理 API + */ +export const projectApi = { + /** + * 获取项目列表 + * @param {Object} params - 查询参数 + * @returns {Promise} + */ + getProjects(params = {}) { + return apiClient.get('/projects', { params }) + }, + + /** + * 获取项目详情 + * @param {Number} projectId - 项目ID + * @returns {Promise} + */ + getProjectDetail(projectId) { + return apiClient.get(`/projects/${projectId}`) + }, + + /** + * 创建项目 + * @param {Object} data - 项目数据 + * @returns {Promise} + */ + createProject(data) { + return apiClient.post('/projects', data) + }, + + /** + * 更新项目 + * @param {Number} projectId - 项目ID + * @param {Object} data - 项目数据 + * @returns {Promise} + */ + updateProject(projectId, data) { + return apiClient.put(`/projects/${projectId}`, data) + }, + + /** + * 删除项目 + * @param {Number} projectId - 项目ID + * @returns {Promise} + */ + deleteProject(projectId) { + return apiClient.delete(`/projects/${projectId}`) + }, + + /** + * 更新文件提交信息 + * @param {Number} projectId - 项目ID + * @param {Object} data - 提交信息 + * @returns {Promise} + */ + updateSubmission(projectId, data) { + return apiClient.put(`/projects/${projectId}/submission`, data) + }, + + /** + * 标记为已提交 + * @param {Number} projectId - 项目ID + * @param {Object} data - 提交确认信息 + * @returns {Promise} + */ + markAsSubmitted(projectId, data) { + return apiClient.post(`/projects/${projectId}/submit`, data) + }, + + /** + * 更新开标信息 + * @param {Number} projectId - 项目ID + * @param {Object} data - 开标信息 + * @returns {Promise} + */ + updateBiddingInfo(projectId, data) { + return apiClient.put(`/projects/${projectId}/bidding`, data) + }, + + /** + * 上传开标媒体文件 + * @param {Number} projectId - 项目ID + * @param {FormData} formData - 文件数据 + * @returns {Promise} + */ + uploadBiddingMedia(projectId, formData) { + return apiClient.post(`/projects/${projectId}/bidding/media`, formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + }, + + /** + * 更新结果公示 + * @param {Number} projectId - 项目ID + * @param {Object} data - 结果信息 + * @returns {Promise} + */ + updateResult(projectId, data) { + return apiClient.put(`/projects/${projectId}/result`, data) + }, + + /** + * 添加经验总结 + * @param {Number} projectId - 项目ID + * @param {Object} data - 经验总结 + * @returns {Promise} + */ + addExperience(projectId, data) { + return apiClient.post(`/projects/${projectId}/experience`, data) + }, + + /** + * 归档项目 + * @param {Number} projectId - 项目ID + * @param {Object} data - 归档信息 + * @returns {Promise} + */ + archiveProject(projectId, data) { + return apiClient.post(`/projects/${projectId}/archive`, data) + }, + + /** + * 导出项目信息 + * @param {Number} projectId - 项目ID + * @returns {Promise} + */ + exportProject(projectId) { + return apiClient.get(`/projects/${projectId}/export`, { + responseType: 'blob' + }) + }, + + /** + * 下载文件 + * @param {Number} projectId - 项目ID + * @param {String} fileType - 文件类型 + * @returns {Promise} + */ + downloadFile(projectId, fileType) { + return apiClient.get(`/projects/${projectId}/files/${fileType}`, { + responseType: 'blob' + }) + } +} + +/** + * 文件上传辅助函数 + * @param {File} file - 文件对象 + * @param {String} type - 文件类型 + * @returns {FormData} + */ +export function createFileFormData(file, type) { + const formData = new FormData() + formData.append('file', file) + formData.append('type', type) + return formData +} + +/** + * 下载文件辅助函数 + * @param {Blob} blob - 文件数据 + * @param {String} filename - 文件名 + */ +export function downloadBlob(blob, filename) { + const url = window.URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = filename + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + window.URL.revokeObjectURL(url) +} + +export default projectApi diff --git a/江西城市生命线-可交互原型/frontend/src/components/Sidebar.vue b/江西城市生命线-可交互原型/frontend/src/components/Sidebar.vue new file mode 100644 index 00000000..13a68e26 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/Sidebar.vue @@ -0,0 +1,269 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/components/UserPanel.vue b/江西城市生命线-可交互原型/frontend/src/components/UserPanel.vue new file mode 100644 index 00000000..a048b6ba --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/UserPanel.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/BiddingInfo.vue b/江西城市生命线-可交互原型/frontend/src/components/project/BiddingInfo.vue new file mode 100644 index 00000000..beba0c18 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/BiddingInfo.vue @@ -0,0 +1,804 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/FileSubmission.vue b/江西城市生命线-可交互原型/frontend/src/components/project/FileSubmission.vue new file mode 100644 index 00000000..e2382eff --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/FileSubmission.vue @@ -0,0 +1,599 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/ProjectDetail.vue b/江西城市生命线-可交互原型/frontend/src/components/project/ProjectDetail.vue new file mode 100644 index 00000000..05c863d8 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/ProjectDetail.vue @@ -0,0 +1,277 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/README.md b/江西城市生命线-可交互原型/frontend/src/components/project/README.md new file mode 100644 index 00000000..cdfee349 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/README.md @@ -0,0 +1,227 @@ +# 项目管理组件使用说明 + +## 组件概述 + +本目录包含招标助手系统的项目管理功能组件,实现了进行中项目的三个核心功能模块: + +1. **文件提交模块** (`FileSubmission.vue`) +2. **开标信息模块** (`BiddingInfo.vue`) +3. **结果公示模块** (`ResultAnnouncement.vue`) +4. **项目详情主组件** (`ProjectDetail.vue`) + +## 组件结构 + +``` +components/project/ +├── ProjectDetail.vue # 项目详情主组件 +├── FileSubmission.vue # 文件提交模块 +├── BiddingInfo.vue # 开标信息模块 +├── ResultAnnouncement.vue # 结果公示模块 +└── README.md # 本文件 +``` + +## 使用方法 + +### 1. 在 BiddingView.vue 中集成 + +在 `BiddingView.vue` 的项目详情部分引入 `ProjectDetail` 组件: + +```vue + + + +``` + +### 2. 单独使用各个子组件 + +如果需要单独使用某个功能模块: + +```vue + + + +``` + +## 组件 Props + +### ProjectDetail + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| project | Object | 是 | 项目对象 | + +### FileSubmission / BiddingInfo / ResultAnnouncement + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| project | Object | 是 | 项目对象 | + +## 组件 Events + +### ProjectDetail + +| 事件名 | 参数 | 说明 | +|--------|------|------| +| back | - | 返回项目列表 | +| update | - | 项目信息已更新 | + +### FileSubmission / BiddingInfo / ResultAnnouncement + +| 事件名 | 参数 | 说明 | +|--------|------|------| +| update | - | 模块信息已更新 | + +## 数据结构 + +### 项目对象 (Project) + +```javascript +{ + id: Number, // 项目ID + name: String, // 项目名称 + client: String, // 招标单位 + status: String, // 项目状态: ongoing/pending/won/lost/failed + progress: String, // 当前进度: 信息提取/文件准备/文件提交/开标/评标/结果公示 + createTime: String, // 创建时间 + // ... 其他字段 +} +``` + +## API 接口 + +项目管理相关的 API 接口已在 `src/api/project.js` 中定义: + +```javascript +import { projectApi } from '@/api/project' + +// 获取项目详情 +const project = await projectApi.getProjectDetail(projectId) + +// 更新文件提交信息 +await projectApi.updateSubmission(projectId, data) + +// 更新开标信息 +await projectApi.updateBiddingInfo(projectId, data) + +// 更新结果公示 +await projectApi.updateResult(projectId, data) +``` + +## 功能特性 + +### 文件提交模块 + +- ✅ 展示商务标、技术标、报价文件详细信息 +- ✅ 文件预览、下载、重新生成 +- ✅ 关键时间节点时间轴展示 +- ✅ 提交前检查清单(7项) +- ✅ 完成度进度条 +- ✅ 标记为已提交功能 + +### 开标信息模块 + +- ✅ 开标时间倒计时提醒 +- ✅ 开标地点地图导航 +- ✅ 参会人员信息管理 +- ✅ 开标流程时间轴 +- ✅ 开标记录详细展示 +- ✅ 所有投标单位报价对比表 +- ✅ 现场照片/视频上传 + +### 结果公示模块 + +- ✅ 三种结果类型切换(中标/未中标/流标) +- ✅ **中标情况**: + - 公示信息、中标详情 + - 综合得分展示 + - 合同签订信息 + - 项目执行进度跟踪 +- ✅ **未中标情况**: + - 得分差距分析 + - 失败原因总结 + - 改进建议列表 +- ✅ **流标情况**: + - 流标原因分析 + - 后续处理方案 + - 保证金退还状态 + +## 样式定制 + +所有组件都使用 SCSS 编写样式,支持自定义主题色: + +```scss +// 主色调 +$primary-color: #7c3aed; +$success-color: #10b981; +$warning-color: #f59e0b; +$danger-color: #ef4444; + +// 可以在组件中覆盖这些变量 +``` + +## 注意事项 + +1. **Element Plus 依赖**: 组件依赖 Element Plus UI 库,确保已正确安装 +2. **图标组件**: 使用 Element Plus Icons,需要单独引入 +3. **响应式设计**: 组件已适配不同屏幕尺寸 +4. **数据模拟**: 当前使用模拟数据,实际使用时需连接后端 API +5. **权限控制**: 某些操作可能需要权限验证 + +## 开发计划 + +- [ ] 添加文件上传进度显示 +- [ ] 实现实时倒计时功能 +- [ ] 添加数据导出为 Excel 功能 +- [ ] 实现地图导航集成 +- [ ] 添加消息通知提醒 +- [ ] 优化移动端显示 + +## 更新日志 + +### v1.0.0 (2024-12-08) +- ✅ 完成文件提交模块 +- ✅ 完成开标信息模块 +- ✅ 完成结果公示模块 +- ✅ 完成项目详情主组件 +- ✅ 创建 API 服务文件 + +## 技术支持 + +如有问题,请联系开发团队或查看项目文档。 diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/ResultAnnouncement.vue b/江西城市生命线-可交互原型/frontend/src/components/project/ResultAnnouncement.vue new file mode 100644 index 00000000..047896fa --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/ResultAnnouncement.vue @@ -0,0 +1,1028 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/开标信息编辑功能说明.md b/江西城市生命线-可交互原型/frontend/src/components/project/开标信息编辑功能说明.md new file mode 100644 index 00000000..10fe0c9a --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/开标信息编辑功能说明.md @@ -0,0 +1,405 @@ +# 开标信息编辑功能说明 + +## 📝 功能概述 + +开标会议信息现已支持完整的编辑功能,用户可以自定义开标时间、地点、参会人员等信息。 + +## ✨ 新增功能 + +### 1. **编辑开标时间** 📅 + +**日期选择**: +- 使用日期选择器选择开标日期 +- 格式:YYYY-MM-DD +- 宽度:200px + +**时间选择**: +- 使用时间选择器选择开标时间 +- 格式:HH:mm:ss +- 宽度:150px + +### 2. **编辑开标地点** 📍 + +**可编辑字段**: +- **地址**: 文本输入框(300px) +- **联系电话**: 文本输入框(200px) +- **备注**: 多行文本框(2行,300px) + +**删除的功能**: +- ❌ 查看地图按钮 +- ❌ 一键导航按钮 + +### 3. **编辑参会人员** 👥 + +**编辑功能**: +- 每个参会人员可编辑姓名和电话 +- 姓名输入框:120px +- 电话输入框:150px + +**删除功能**: +- 每个参会人员旁边有"删除"按钮 +- 点击删除会弹出确认对话框 +- 确认后删除该参会人员 + +**添加功能**: +- 底部有"添加参会人员"按钮 +- 点击后添加新的空白参会人员 +- 默认角色为"参会人员" + +## 🎨 界面布局 + +### 开标时间区域 +``` +📅 开标时间 +├─ 日期: [日期选择器: 2024-12-15] +├─ 时间: [时间选择器: 09:30:00] +├─ 倒计时: [还剩6天2小时15分钟] +└─ 状态: [🟡 待开标] +``` + +### 开标地点区域 +``` +📍 开标地点 +├─ 地址: [输入框: XX市公共资源交易中心3楼开标室A] +├─ 联系电话: [输入框: 0791-88888888] +└─ 备注: [文本框: 需携带法人授权委托书原件及身份证] +``` + +### 参会人员区域 +``` +👥 参会人员 +├─ 投标代表: [姓名: 张三] [电话: 13800138000] [删除] +├─ 技术负责人: [姓名: 李四] [电话: 13900139000] [删除] +├─ 备选人员: [姓名: 王五] [电话: 13700137000] [删除] +└─ [+ 添加参会人员] +``` + +## 💻 代码实现 + +### 模板结构 + +```vue + +
+ 日期: + +
+ +
+ 时间: + +
+ + +
+ 地址: + +
+ + +
+ {{ person.role }}: +
+ + + 删除 +
+
+ + + 添加参会人员 + +``` + +### 数据结构 + +```javascript +const biddingInfo = ref({ + dateValue: '2024-12-15', // 日期选择器绑定值 + timeValue: '09:30:00', // 时间选择器绑定值 + countdown: '还剩6天2小时15分钟', + statusText: '待开标', + + location: { + address: 'XX市公共资源交易中心3楼开标室A', + phone: '0791-88888888', + note: '需携带法人授权委托书原件及身份证' + }, + + attendees: [ + { role: '投标代表', name: '张三', phone: '13800138000' }, + { role: '技术负责人', name: '李四', phone: '13900139000' }, + { role: '备选人员', name: '王五', phone: '13700137000' } + ] +}) +``` + +### 核心方法 + +#### 1. 添加参会人员 +```javascript +const addPerson = () => { + biddingInfo.value.attendees.push({ + role: '参会人员', + name: '', + phone: '' + }) + ElMessage.success('已添加参会人员,请填写信息') +} +``` + +#### 2. 删除参会人员 +```javascript +const removePerson = (index) => { + ElMessageBox.confirm('确定要删除这个参会人员吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + biddingInfo.value.attendees.splice(index, 1) + ElMessage.success('删除成功') + }).catch(() => { + ElMessage.info('已取消删除') + }) +} +``` + +## 🎨 样式实现 + +```scss +.info-item { + &.editable-person { + .person-inputs { + display: flex; + align-items: center; + gap: 12px; + flex: 1; + } + } +} +``` + +## 🔄 已删除的功能 + +### 地图导航功能 +```javascript +// ❌ 已删除 +const viewMap = () => { + ElMessage.info('打开地图查看开标地点') +} + +const navigate = () => { + ElMessage.info('启动导航到开标地点') +} +``` + +**删除原因**: +- 简化界面,减少不必要的功能 +- 用户可以直接复制地址使用第三方地图应用 + +## 📊 组件导入变更 + +### 新增导入 +```javascript +import { ElMessageBox } from 'element-plus' +import { Delete, Plus } from '@element-plus/icons-vue' +``` + +### 删除导入 +```javascript +// ❌ 已删除 +import { Location, Position } from '@element-plus/icons-vue' +``` + +## 🎯 使用场景 + +### 场景 1: 修改开标时间 +项目经理收到通知,开标时间延期。 + +**操作步骤**: +1. 点击日期选择器,选择新的日期 +2. 点击时间选择器,选择新的时间 +3. 系统自动更新倒计时 + +### 场景 2: 更新开标地点 +开标地点临时变更。 + +**操作步骤**: +1. 在地址输入框中修改新地址 +2. 更新联系电话 +3. 在备注中添加变更说明 + +### 场景 3: 调整参会人员 +技术负责人临时有事,需要更换。 + +**操作步骤**: +1. 找到"技术负责人"行 +2. 修改姓名和电话 +3. 或点击"删除"按钮移除 +4. 点击"添加参会人员"添加新人员 + +### 场景 4: 增加参会人员 +需要增加一名备用人员。 + +**操作步骤**: +1. 点击"添加参会人员"按钮 +2. 填写新人员的姓名 +3. 填写新人员的电话 + +## ⚠️ 注意事项 + +### 1. 数据验证 +建议添加数据验证: + +```javascript +const addPerson = () => { + // 检查是否有未填写完整的人员 + const hasEmpty = biddingInfo.value.attendees.some( + p => !p.name || !p.phone + ) + + if (hasEmpty) { + ElMessage.warning('请先完成当前人员信息的填写') + return + } + + biddingInfo.value.attendees.push({ + role: '参会人员', + name: '', + phone: '' + }) +} +``` + +### 2. 电话号码格式 +建议添加电话号码格式验证: + +```javascript +const validatePhone = (phone) => { + const phoneReg = /^1[3-9]\d{9}$/ + return phoneReg.test(phone) +} +``` + +### 3. 最少参会人员 +建议至少保留一名参会人员: + +```javascript +const removePerson = (index) => { + if (biddingInfo.value.attendees.length <= 1) { + ElMessage.warning('至少需要保留一名参会人员') + return + } + // ... 删除逻辑 +} +``` + +### 4. 保存提示 +修改后建议添加保存按钮: + +```vue + + 保存修改 + +``` + +## 🚀 后续优化建议 + +### 1. 角色选择 +为参会人员添加角色下拉选择: + +```vue + + + + + + +``` + +### 2. 批量导入 +支持从 Excel 批量导入参会人员: + +```vue + + 批量导入 + +``` + +### 3. 历史记录 +记录开标信息的修改历史: + +```javascript +const history = ref([]) + +const saveBiddingInfo = () => { + history.value.push({ + time: new Date(), + data: JSON.parse(JSON.stringify(biddingInfo.value)) + }) +} +``` + +### 4. 自动提醒 +根据开标时间自动设置提醒: + +```javascript +watch(() => biddingInfo.value.dateValue, (newDate) => { + // 自动设置提前1天、3小时、30分钟的提醒 + setReminders(newDate) +}) +``` + +## 📸 效果对比 + +### 修改前 +``` +📍 开标地点 +地址: XX市公共资源交易中心3楼开标室A +联系电话: 0791-88888888 +导航: [查看地图] [一键导航] ← 删除 +备注: 需携带法人授权委托书原件及身份证 + +👥 参会人员 +投标代表: 张三 (13800138000) ← 不可编辑 +技术负责人: 李四 (13900139000) +备选人员: 王五 (13700137000) +``` + +### 修改后 +``` +📍 开标地点 +地址: [输入框] ← 可编辑 +联系电话: [输入框] +备注: [文本框] + +👥 参会人员 +投标代表: [姓名] [电话] [删除] ← 可编辑、可删除 +技术负责人: [姓名] [电话] [删除] +备选人员: [姓名] [电话] [删除] +[+ 添加参会人员] ← 可添加 +``` + +--- + +**版本**: v1.4.0 +**更新时间**: 2024-12-08 +**功能状态**: ✅ 已实现 +**适用模块**: BiddingInfo.vue diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/投标单位报价编辑功能说明.md b/江西城市生命线-可交互原型/frontend/src/components/project/投标单位报价编辑功能说明.md new file mode 100644 index 00000000..49962fe6 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/投标单位报价编辑功能说明.md @@ -0,0 +1,428 @@ +# 投标单位报价编辑功能说明 + +## 📝 功能概述 + +开标记录中的"所有投标单位报价"表格现已支持完整的编辑功能,用户可以添加、编辑、删除投标单位信息,并标记我方单位。 + +## ✨ 新增功能 + +### 1. **编辑投标单位信息** ✏️ + +**可编辑字段**: +- **排名**: 数字输入框(1-99) +- **投标单位**: 文本输入框 +- **报价金额**: 数字输入框(精度2位小数,步长1000) +- **工期(天)**: 数字输入框(1-999) + +### 2. **添加投标单位** ➕ + +**操作方式**: +- 点击表格右上角的"添加投标单位"按钮 +- 自动添加新行,排名自动递增 +- 填写单位名称、报价金额、工期 + +**默认值**: +```javascript +{ + rank: 自动递增, + company: '', + price: 0, + workDays: 60, + isOur: false +} +``` + +### 3. **删除投标单位** 🗑️ + +**操作方式**: +- 点击每行的"删除"按钮 +- 弹出确认对话框 +- 确认后删除该投标单位 +- 自动重新排序(rank 重新计算) + +### 4. **标记为我方** 🏷️ + +**操作方式**: +- 点击"标记为我方"按钮 +- 自动清除其他单位的我方标记 +- 标记当前单位为我方 +- 我方单位名称和报价高亮显示 + +**视觉效果**: +- 单位名称:紫色加粗(#7c3aed) +- 报价金额:红色加粗(#ef4444) +- 按钮文字:显示"我方"并禁用 + +### 5. **保存开标记录** 💾 + +**操作方式**: +- 点击"保存开标记录"按钮 +- 验证所有单位信息是否完整 +- 保存成功后触发更新事件 + +**验证规则**: +- 单位名称不能为空 +- 报价金额必须大于0 + +## 🎨 界面布局 + +### 表格头部 +``` +所有投标单位报价 [+ 添加投标单位] +``` + +### 表格内容 +``` +┌────┬──────────────┬────────┬────────┬──────────────┐ +│排名│ 投标单位 │报价金额│工期(天)│ 操作 │ +├────┼──────────────┼────────┼────────┼──────────────┤ +│ 1 │[输入框] │[数字] │[数字] │[标记][删除] │ +│ 2 │[输入框] │[数字] │[数字] │[标记][删除] │ +│ 3 │[输入框]★ │[数字]★ │[数字] │[我方][删除] │ +└────┴──────────────┴────────┴────────┴──────────────┘ +★ = 我方单位高亮显示 +``` + +### 操作按钮 +``` +[✓ 保存开标记录] [📥 下载开标记录表] +``` + +## 💻 代码实现 + +### 模板结构 + +```vue +
+ +
+

所有投标单位报价

+ 添加投标单位 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + 保存开标记录 + + + 下载开标记录表 + +
+``` + +### 核心方法 + +#### 1. 添加投标单位 +```javascript +const addBidder = () => { + const newRank = biddingInfo.value.record.allBidders.length + 1 + biddingInfo.value.record.allBidders.push({ + rank: newRank, + company: '', + price: 0, + workDays: 60, + isOur: false + }) + ElMessage.success('已添加投标单位,请填写信息') +} +``` + +#### 2. 删除投标单位 +```javascript +const removeBidder = (index) => { + ElMessageBox.confirm('确定要删除这个投标单位吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + biddingInfo.value.record.allBidders.splice(index, 1) + // 重新排序 + biddingInfo.value.record.allBidders.forEach((bidder, idx) => { + bidder.rank = idx + 1 + }) + ElMessage.success('删除成功') + }) +} +``` + +#### 3. 标记为我方 +```javascript +const markAsOur = (index) => { + // 先清除所有的我方标记 + biddingInfo.value.record.allBidders.forEach(bidder => { + bidder.isOur = false + }) + // 标记当前为我方 + biddingInfo.value.record.allBidders[index].isOur = true + ElMessage.success('已标记为我方') +} +``` + +#### 4. 保存开标记录 +```javascript +const saveBiddingRecord = () => { + // 验证数据 + const hasEmpty = biddingInfo.value.record.allBidders.some( + b => !b.company || b.price <= 0 + ) + + if (hasEmpty) { + ElMessage.warning('请完整填写所有投标单位信息') + return + } + + ElMessage.success('开标记录已保存') + emit('update') +} +``` + +## 🎨 样式实现 + +### 表头样式 +```scss +.table-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; +} +``` + +### 我方单位高亮 +```scss +// 单位名称高亮 +:deep(.our-company-input) { + .el-input__inner { + color: #7c3aed; // 紫色 + font-weight: 600; + } +} + +// 报价金额高亮 +:deep(.our-price-input) { + input { + color: #ef4444; // 红色 + font-weight: 600; + } +} +``` + +### 数字输入框 +```scss +:deep(.el-input-number) { + width: 100%; // 填满单元格 +} +``` + +## 🎯 使用场景 + +### 场景 1: 录入开标结果 +开标会议结束后,需要录入所有投标单位的报价信息。 + +**操作步骤**: +1. 点击"添加投标单位"按钮8次(假设8家单位) +2. 依次填写每家单位的名称、报价、工期 +3. 找到我方单位,点击"标记为我方" +4. 点击"保存开标记录" + +### 场景 2: 修正错误信息 +发现某家单位的报价录入错误。 + +**操作步骤**: +1. 找到对应的单位行 +2. 修改报价金额 +3. 点击"保存开标记录" + +### 场景 3: 删除无效单位 +某家单位临时弃标,需要删除。 + +**操作步骤**: +1. 找到对应的单位行 +2. 点击"删除"按钮 +3. 确认删除 +4. 系统自动重新排序 +5. 点击"保存开标记录" + +### 场景 4: 调整排名 +根据最终评分调整排名顺序。 + +**操作步骤**: +1. 修改各单位的排名数字 +2. 点击"保存开标记录" + +## ⚠️ 注意事项 + +### 1. 数据验证 +保存时会验证: +- 单位名称不能为空 +- 报价金额必须大于0 + +### 2. 自动排序 +删除单位后会自动重新排序,确保排名连续。 + +### 3. 唯一我方 +同时只能有一个单位被标记为"我方",标记新的会自动清除旧的。 + +### 4. 报价格式 +报价金额支持两位小数,步长为1000元。 + +## 🚀 后续优化建议 + +### 1. 批量导入 +支持从 Excel 批量导入投标单位信息: + +```vue + + 批量导入 + +``` + +### 2. 自动排序 +根据报价金额自动排序: + +```javascript +const autoSort = () => { + biddingInfo.value.record.allBidders.sort((a, b) => a.price - b.price) + biddingInfo.value.record.allBidders.forEach((bidder, idx) => { + bidder.rank = idx + 1 + }) +} +``` + +### 3. 数据导出 +导出为 Excel 格式: + +```javascript +const exportToExcel = () => { + // 使用 xlsx 库导出 + const data = biddingInfo.value.record.allBidders.map(b => ({ + '排名': b.rank, + '投标单位': b.company, + '报价金额': b.price, + '工期': b.workDays + })) + // ... 导出逻辑 +} +``` + +### 4. 历史对比 +对比上次开标记录: + +```javascript +const compareWithHistory = () => { + // 显示与历史记录的差异 +} +``` + +### 5. 价格区间验证 +验证报价是否在合理区间: + +```javascript +const validatePrice = (price) => { + const controlPrice = biddingInfo.value.record.controlPrice + if (price > controlPrice) { + ElMessage.warning('报价超过控制价') + } +} +``` + +## 📸 效果对比 + +### 修改前 +``` +所有投标单位报价 + +排名 | 投标单位 | 报价金额 | 工期 +-----|----------|----------|------ + 1 | XX公司 | ¥2,650,000 | 55 + 2 | XX公司 | ¥2,750,000 | 60 + 3 | 我方 | ¥2,850,000 | 60 ← 只读显示 +``` + +### 修改后 +``` +所有投标单位报价 [+ 添加投标单位] + +排名 | 投标单位 | 报价金额 | 工期 | 操作 +-----|----------|----------|------|------------- + [1] | [输入框] | [数字] | [60] | [标记][删除] + [2] | [输入框] | [数字] | [60] | [标记][删除] + [3] | [输入框]★| [数字]★ | [60] | [我方][删除] ← 可编辑 + +[✓ 保存开标记录] [📥 下载开标记录表] +``` + +## 🔄 按钮变更 + +### 删除的按钮 +- ❌ "查看详细记录" + +### 新增的按钮 +- ✅ "添加投标单位" +- ✅ "保存开标记录" +- ✅ "标记为我方" +- ✅ "删除"(每行) + +--- + +**版本**: v1.5.0 +**更新时间**: 2024-12-08 +**功能状态**: ✅ 已实现 +**适用模块**: BiddingInfo.vue diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/更新日志.md b/江西城市生命线-可交互原型/frontend/src/components/project/更新日志.md new file mode 100644 index 00000000..1364c8a1 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/更新日志.md @@ -0,0 +1,185 @@ +# 项目管理组件更新日志 + +## v1.1.0 (2024-12-08) + +### 🎨 界面优化 + +#### FileSubmission.vue - 文件提交模块 + +**变更内容**: + +1. **删除报价文件部分** + - 移除了报价文件的展示区域 + - 删除了相关的数据定义 (`priceDoc`) + - 删除了"修改报价"功能 (`modifyPrice`) + +2. **调整状态显示布局** + - 将状态标签从详情列表中移到标题旁边 + - 状态标签尺寸从 `small` 改为 `large` + - 添加了 `doc-header` 容器,使标题和状态在同一行 + - 在标题和详情之间添加了分隔线 + +**视觉效果**: +``` +之前: +┌─────────────────────────────┐ +│ 📑 商务标书 │ +│ │ +│ 文件名称: xxx.pdf │ +│ 生成时间: 2024-12-08 │ +│ 文件大小: 15.6 MB │ +│ 页数: 85页 │ +│ 状态: [已完成] │ +│ │ +│ [预览] [下载] [重新生成] │ +└─────────────────────────────┘ + +现在: +┌─────────────────────────────┐ +│ 📑 商务标书 [已完成] │ +│ ─────────────────────────── │ +│ 文件名称: xxx.pdf │ +│ 生成时间: 2024-12-08 │ +│ 文件大小: 15.6 MB │ +│ 页数: 85页 │ +│ │ +│ [预览] [下载] [重新生成] │ +└─────────────────────────────┘ +``` + +**样式变更**: +- 新增 `.doc-header` 样式 + - `display: flex` - 横向布局 + - `justify-content: space-between` - 两端对齐 + - `border-bottom: 2px solid #e5e7eb` - 底部分隔线 + - `padding-bottom: 12px` - 底部内边距 + +**数据结构变更**: +```javascript +// 删除 +const priceDoc = ref({ + fileName: '某数据中心发电机组采购-报价表.xlsx', + generateTime: '2024-12-09 10:20:15', + fileSize: '2.1 MB', + amount: '¥2,850,000.00', + status: '已完成' +}) + +// 删除 +const modifyPrice = () => { + ElMessage.info('打开报价修改对话框') +} +``` + +### 📊 影响范围 + +**受影响的功能**: +- ✅ 文件提交模块 - 界面优化 +- ⚠️ 报价文件相关功能 - 已移除 + +**不受影响的功能**: +- ✅ 商务标书展示和操作 +- ✅ 技术标书展示和操作 +- ✅ 时间节点展示 +- ✅ 检查清单功能 +- ✅ 提交功能 + +### 🔄 迁移指南 + +如果您的代码中引用了报价文件相关功能,请进行以下调整: + +1. **移除报价文件引用** +```javascript +// 删除这些引用 +priceDoc.value +modifyPrice() +``` + +2. **更新文档数量** +```javascript +// 之前: 3个文件(商务标、技术标、报价文件) +// 现在: 2个文件(商务标、技术标) +``` + +3. **更新检查清单** +```javascript +// 如果检查清单中包含"报价文件核对",建议移除或调整 +``` + +### 🎯 优化效果 + +**优点**: +1. ✅ 界面更简洁,状态一目了然 +2. ✅ 减少了冗余信息 +3. ✅ 状态标签更突出 +4. ✅ 视觉层次更清晰 + +**注意事项**: +1. ⚠️ 如果业务需要报价文件,需要在其他地方展示 +2. ⚠️ 确保后端API不再返回报价文件数据 +3. ⚠️ 更新相关文档和测试用例 + +### 📝 文件变更清单 + +**修改的文件**: +- `FileSubmission.vue` (模板、脚本、样式) + +**修改的行数**: +- 删除: ~50 行 +- 新增: ~15 行 +- 修改: ~10 行 + +**代码差异**: +```diff +- 报价文件展示区域 (HTML) +- priceDoc 数据定义 (JavaScript) +- modifyPrice 函数 (JavaScript) ++ doc-header 容器 (HTML) ++ doc-header 样式 (CSS) +``` + +### 🧪 测试建议 + +1. **视觉测试** + - 检查状态标签是否正确显示在标题旁边 + - 确认分隔线是否正常显示 + - 验证标签尺寸是否合适 + +2. **功能测试** + - 测试预览、下载、重新生成按钮 + - 确认没有报价相关的错误 + - 验证其他功能正常工作 + +3. **响应式测试** + - 测试不同屏幕尺寸下的显示效果 + - 确保移动端显示正常 + +### 📸 截图对比 + +**优化前**: +- 状态标签在详情列表中 +- 报价文件占用额外空间 +- 信息密集度高 + +**优化后**: +- 状态标签在标题旁边,更醒目 +- 移除报价文件,界面更简洁 +- 信息层次更清晰 + +--- + +## v1.0.0 (2024-12-08) + +### 🎉 初始版本 + +- ✅ 实现文件提交模块 +- ✅ 实现开标信息模块 +- ✅ 实现结果公示模块 +- ✅ 集成到 BiddingView 页面 +- ✅ 完成文档编写 + +--- + +**维护者**: Cascade AI Assistant +**更新时间**: 2024-12-08 +**版本**: v1.1.0 diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/检查清单编辑功能说明.md b/江西城市生命线-可交互原型/frontend/src/components/project/检查清单编辑功能说明.md new file mode 100644 index 00000000..cc02bd39 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/检查清单编辑功能说明.md @@ -0,0 +1,332 @@ +# 检查清单编辑功能说明 + +## 📝 功能概述 + +文件提交模块的"提交前检查清单"现已支持完整的编辑功能,用户可以自定义检查项内容。 + +## ✨ 新增功能 + +### 1. **编辑检查项** ✏️ + +**操作方式**: +- 鼠标悬停在检查项上,显示"编辑"按钮 +- 点击"编辑"按钮 +- 检查项文本变为可编辑的输入框 +- 修改内容后按 `Enter` 或点击外部区域保存 + +**特点**: +- ✅ 即时编辑,无需额外对话框 +- ✅ 支持键盘快捷键(Enter 保存) +- ✅ 自动失焦保存 + +### 2. **删除检查项** 🗑️ + +**操作方式**: +- 鼠标悬停在检查项上,显示"删除"按钮 +- 点击"删除"按钮 +- 弹出确认对话框 +- 确认后删除该检查项 + +**特点**: +- ✅ 二次确认,防止误删 +- ✅ 自动更新完成度进度 +- ✅ 同步移除已勾选状态 + +**安全机制**: +```javascript +// 删除时会同时: +1. 从检查清单中移除 +2. 从已勾选项中移除 +3. 重新计算完成度 +``` + +### 3. **添加检查项** ➕ + +**操作方式**: +- 点击检查清单底部的"添加检查项"按钮 +- 在弹出的对话框中输入检查项内容 +- 设置是否为必须项(开关) +- 点击"确定"添加 + +**特点**: +- ✅ 支持自定义检查项内容 +- ✅ 可设置必须/非必须 +- ✅ 字数限制(最多50字) +- ✅ 实时显示字数统计 + +**对话框字段**: +| 字段 | 类型 | 说明 | +|------|------|------| +| 检查项 | 文本输入 | 最多50字,显示字数统计 | +| 是否必须 | 开关 | 开启后显示"必须"标签 | + +## 🎨 界面设计 + +### 检查项布局 + +``` +┌─────────────────────────────────────────────────┐ +│ ☑ 商务标完整性检查 [必须] [编辑] [删除] │ +│ ☑ 技术标完整性检查 [必须] [编辑] [删除] │ +│ ☑ 保证金缴纳凭证 [必须] [编辑] [删除] │ +│ ☐ 授权委托书签字盖章 [编辑] [删除] │ +│ │ +│ [+ 添加检查项] │ +└─────────────────────────────────────────────────┘ +``` + +### 交互效果 + +**默认状态**: +- 编辑/删除按钮半透明(opacity: 0.6) + +**鼠标悬停**: +- 背景色变浅 +- 编辑/删除按钮完全显示(opacity: 1) + +**编辑状态**: +- 文本变为输入框 +- 输入框宽度 300px +- 自动聚焦 + +## 🔧 技术实现 + +### 数据结构 + +```javascript +const checklistItems = ref([ + { + id: 1, + label: '商务标完整性检查', + required: true, // 是否必须 + editing: false // 是否正在编辑 + }, + // ... +]) +``` + +### 核心方法 + +#### 1. 编辑检查项 +```javascript +const editItem = (item) => { + item.editing = true // 切换为编辑状态 +} +``` + +#### 2. 删除检查项 +```javascript +const deleteItem = (id) => { + ElMessageBox.confirm('确定要删除这个检查项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + // 从列表中删除 + const index = checklistItems.value.findIndex(item => item.id === id) + checklistItems.value.splice(index, 1) + + // 从已选中项中移除 + const checkedIndex = checkedItems.value.indexOf(id) + checkedItems.value.splice(checkedIndex, 1) + + ElMessage.success('删除成功') + }) +} +``` + +#### 3. 添加检查项 +```javascript +const addNewItem = () => { + if (!newItemForm.value.label.trim()) { + ElMessage.warning('请输入检查项内容') + return + } + + checklistItems.value.push({ + id: nextItemId++, + label: newItemForm.value.label, + required: newItemForm.value.required, + editing: false + }) + + ElMessage.success('添加成功') + showAddItemDialog.value = false +} +``` + +## 📊 完成度计算 + +完成度会根据检查项的增删自动更新: + +```javascript +const checklistProgress = computed(() => { + return Math.round( + (checkedItems.value.length / checklistItems.value.length) * 100 + ) +}) +``` + +**示例**: +- 总共 7 项检查项 +- 已勾选 5 项 +- 完成度 = 5 / 7 × 100% ≈ 71% + +## 🎯 使用场景 + +### 场景 1: 自定义检查项 +项目经理可以根据不同项目的特点,添加特定的检查项。 + +**示例**: +``` +原有检查项: +- 商务标完整性检查 +- 技术标完整性检查 + +新增检查项: +- 环保资质证明 +- 安全生产许可证 +- 项目经理证书 +``` + +### 场景 2: 修改检查项描述 +根据实际情况,调整检查项的描述更加准确。 + +**示例**: +``` +修改前: 授权委托书签字盖章 +修改后: 法人授权委托书签字并加盖公章 +``` + +### 场景 3: 删除不适用的检查项 +某些检查项可能不适用于当前项目,可以删除。 + +**示例**: +``` +删除: 纸质文件打印装订 +原因: 本项目仅需电子投标 +``` + +## ⚠️ 注意事项 + +### 1. 数据持久化 +当前实现使用前端状态管理,刷新页面后修改会丢失。 + +**建议**: +- 集成后端 API,保存到数据库 +- 或使用 localStorage 本地存储 + +### 2. 必须项限制 +标记为"必须"的检查项建议不允许删除,或删除时给予警告。 + +**改进方案**: +```javascript +const deleteItem = (id) => { + const item = checklistItems.value.find(i => i.id === id) + + if (item.required) { + ElMessageBox.confirm( + '这是必须项,删除可能影响提交,确定要删除吗?', + '警告', + { type: 'warning' } + ).then(() => { + // 执行删除 + }) + } else { + // 正常删除 + } +} +``` + +### 3. 字数限制 +检查项内容限制在 50 字以内,确保界面美观。 + +### 4. ID 管理 +新增检查项使用递增 ID,确保唯一性。 + +```javascript +let nextItemId = 8 // 从现有最大 ID + 1 开始 +``` + +## 🎨 样式特点 + +### 1. 悬停效果 +```scss +.checklist-item { + &:hover { + background: #f3f4f6; // 背景变浅 + + .item-actions { + opacity: 1; // 按钮完全显示 + } + } +} +``` + +### 2. 添加按钮 +```scss +.add-item-btn { + width: 100%; + border-style: dashed; // 虚线边框 + + &:hover { + border-color: #7c3aed; // 紫色边框 + color: #7c3aed; // 紫色文字 + } +} +``` + +### 3. 操作按钮 +```scss +.item-actions { + opacity: 0.6; // 默认半透明 + transition: opacity 0.2s; // 平滑过渡 +} +``` + +## 📸 效果展示 + +### 默认状态 +- 检查项正常显示 +- 操作按钮半透明 + +### 悬停状态 +- 背景色变浅 +- 操作按钮完全显示 + +### 编辑状态 +- 文本变为输入框 +- 可直接修改内容 + +### 添加对话框 +- 简洁的表单界面 +- 字数统计提示 +- 必须项开关 + +## 🚀 后续优化建议 + +1. **拖拽排序** + - 支持拖拽调整检查项顺序 + - 使用 `vue-draggable` 库 + +2. **批量操作** + - 批量删除 + - 批量设置必须项 + +3. **模板功能** + - 保存常用检查清单为模板 + - 快速应用模板 + +4. **历史记录** + - 记录修改历史 + - 支持撤销/重做 + +5. **权限控制** + - 不同角色有不同编辑权限 + - 普通用户只能查看,管理员可编辑 + +--- + +**版本**: v1.2.0 +**更新时间**: 2024-12-08 +**功能状态**: ✅ 已实现 diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/流程步骤条说明.md b/江西城市生命线-可交互原型/frontend/src/components/project/流程步骤条说明.md new file mode 100644 index 00000000..6aa215a0 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/流程步骤条说明.md @@ -0,0 +1,353 @@ +# 项目流程步骤条说明 + +## 📍 功能概述 + +在文件提交模块顶部添加了项目信息头部和流程步骤条,清晰展示当前项目所处的阶段。 + +## 🎨 界面布局 + +### 1. 项目信息头部 + +``` +┌─────────────────────────────────────────────┐ +│ 某数据中心发电机组采购项目 │ +│ 创建时间:2024-11-20 09:30:00 [进行中] │ +└─────────────────────────────────────────────┘ +``` + +**特点**: +- 🎨 渐变紫色背景(#667eea → #764ba2) +- 📝 显示项目名称 +- 📅 显示创建时间 +- 🏷️ 显示项目状态标签 + +### 2. 流程步骤条 + +``` +招标信息提取 → 撰写投标文件 → 文件提交 → 开标 → 结果公示 + (完成) (完成) (进行中) (待进行) (待进行) + ✓ ✓ ⟳ 4 5 +``` + +**5个步骤**: +1. **招标信息提取** - 已完成 ✓ +2. **撰写投标文件** - 已完成 ✓ +3. **文件提交** - 进行中 ⟳ (当前) +4. **开标** - 待进行 +5. **结果公示** - 待进行 + +## 🎯 步骤状态 + +### 已完成步骤 +- **图标**: 绿色对勾 ✓ +- **颜色**: #10b981 (绿色) +- **描述**: "已完成" + +### 进行中步骤 (当前) +- **图标**: 紫色旋转加载图标 ⟳ +- **颜色**: #7c3aed (紫色) +- **描述**: "进行中" +- **动画**: 持续旋转 + +### 待进行步骤 +- **图标**: 数字序号 +- **颜色**: 默认灰色 +- **描述**: "待进行" + +## 💻 代码实现 + +### 模板结构 + +```vue + +``` + +### 样式实现 + +```scss +// 项目信息头部 +.project-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + padding: 24px 32px; + border-radius: 12px; + margin-bottom: 24px; + color: white; + + h2 { + font-size: 24px; + font-weight: 600; + margin: 0 0 12px 0; + } + + .project-meta { + display: flex; + align-items: center; + gap: 16px; + font-size: 14px; + opacity: 0.95; + } +} + +// 流程步骤卡片 +.timeline-card { + margin-bottom: 24px; + + .project-timeline-header { + margin-bottom: 20px; + + h3 { + font-size: 18px; + font-weight: 600; + color: #1f2937; + margin: 0; + } + } + + :deep(.el-steps) { + .el-step__title { + font-size: 14px; + font-weight: 500; + } + + .el-step__description { + font-size: 12px; + } + + .el-step.is-process { + .el-step__title { + color: #7c3aed; + font-weight: 600; + } + } + + .rotating { + animation: rotate 2s linear infinite; + } + } +} + +// 旋转动画 +@keyframes rotate { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} +``` + +## 🎨 视觉效果 + +### 项目头部 +- **背景**: 渐变紫色(从 #667eea 到 #764ba2) +- **文字**: 白色 +- **圆角**: 12px +- **内边距**: 24px 32px + +### 步骤条 +- **对齐**: 居中对齐 +- **当前步骤**: 紫色高亮 +- **完成步骤**: 绿色对勾 +- **待进行**: 灰色数字 + +### 动画效果 +- **旋转图标**: 2秒一圈,无限循环 +- **平滑过渡**: 所有状态变化都有过渡效果 + +## 📊 步骤索引说明 + +```javascript +:active="2" // 当前激活的步骤索引(从0开始) +``` + +**索引对应**: +- 0 = 招标信息提取 +- 1 = 撰写投标文件 +- 2 = 文件提交 ← 当前 +- 3 = 开标 +- 4 = 结果公示 + +## 🔄 其他模块适配 + +### BiddingInfo.vue (开标信息) +```vue + + + + + + +``` + +### ResultAnnouncement.vue (结果公示) +```vue + + + + + + +``` + +## 💡 使用建议 + +### 1. 动态步骤索引 +根据项目实际进度动态设置 `active` 值: + +```javascript +const currentStepIndex = computed(() => { + const stepMap = { + '招标信息提取': 0, + '撰写投标文件': 1, + '文件提交': 2, + '开标': 3, + '结果公示': 4 + } + return stepMap[project.value.progress] || 0 +}) +``` + +### 2. 步骤点击跳转 +可以为步骤添加点击事件,实现快速跳转: + +```vue + + +``` + +### 3. 响应式设计 +在移动端可以使用垂直步骤条: + +```vue + + +``` + +## 🎯 优化建议 + +### 1. 步骤时间显示 +在描述中显示完成时间: + +```vue + + +``` + +### 2. 进度百分比 +在头部显示整体进度: + +```vue +
+ 创建时间:{{ project.createTime }} + 整体进度:60% + +
+``` + +### 3. 步骤详情提示 +鼠标悬停显示步骤详情: + +```vue + + + +``` + +## 📸 效果预览 + +### 完整界面 +``` +┌─────────────────────────────────────────────────┐ +│ 某数据中心发电机组采购项目 │ +│ 创建时间:2024-11-20 09:30:00 [进行中] │ +└─────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────┐ +│ 项目流程 │ +│ │ +│ ✓ ✓ ⟳ 4 5 │ +│ 招标信息 撰写投标 文件提交 开标 结果公示 │ +│ 提取 文件 │ +│ 已完成 已完成 进行中 待进行 待进行 │ +└─────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────┐ +│ 已生成标书文件 │ +│ ... │ +└─────────────────────────────────────────────────┘ +``` + +--- + +**版本**: v1.3.0 +**更新时间**: 2024-12-08 +**功能状态**: ✅ 已实现 +**适用模块**: FileSubmission.vue diff --git a/江西城市生命线-可交互原型/frontend/src/components/project/集成示例.md b/江西城市生命线-可交互原型/frontend/src/components/project/集成示例.md new file mode 100644 index 00000000..2cbafb3c --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/project/集成示例.md @@ -0,0 +1,335 @@ +# 项目管理模块集成示例 + +## 在 BiddingView.vue 中集成项目详情组件 + +### 步骤 1: 导入组件 + +在 `BiddingView.vue` 的 ` +``` + +## 测试步骤 + +1. **启动开发服务器** + ```bash + cd frontend + npm run dev + ``` + +2. **访问页面** + - 打开浏览器访问 `http://localhost:5173` + - 进入招标助手系统 + - 点击左侧导航"项目管理" → "进行中项目" + +3. **测试功能** + - 点击任意项目卡片进入详情 + - 切换不同 Tab 查看各个模块 + - 测试文件提交模块的检查清单 + - 测试开标信息模块的报价对比表 + - 测试结果公示模块的三种结果类型切换 + +## 注意事项 + +1. **确保依赖已安装** + ```bash + npm install element-plus @element-plus/icons-vue + ``` + +2. **检查路径** + - 确保组件路径正确: `@/components/project/ProjectDetail.vue` + - 如果使用相对路径,根据实际情况调整 + +3. **样式冲突** + - 新组件的样式使用了 `scoped`,不会影响现有样式 + - 如有冲突,可以调整组件内的样式 + +4. **数据对接** + - 当前使用模拟数据 + - 实际使用时需要对接后端 API + - 参考 `src/api/project.js` 中的接口定义 + +## 后续优化建议 + +1. **性能优化** + - 使用虚拟滚动处理大量项目列表 + - 懒加载项目详情数据 + +2. **用户体验** + - 添加加载状态提示 + - 添加错误处理和重试机制 + - 实现数据缓存 + +3. **功能扩展** + - 添加项目搜索和筛选 + - 实现项目排序功能 + - 添加批量操作功能 + +4. **移动端适配** + - 优化移动端布局 + - 添加触摸手势支持 diff --git a/江西城市生命线-可交互原型/frontend/src/components/workflow/WorkflowEditor.vue b/江西城市生命线-可交互原型/frontend/src/components/workflow/WorkflowEditor.vue new file mode 100644 index 00000000..072cebce --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/components/workflow/WorkflowEditor.vue @@ -0,0 +1,618 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/main.js b/江西城市生命线-可交互原型/frontend/src/main.js new file mode 100644 index 00000000..5d8c9791 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/main.js @@ -0,0 +1,20 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' +import App from './App.vue' +import router from './router' +import './styles/main.scss' + +const app = createApp(App) + +// Register all Element Plus icons +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} + +app.use(createPinia()) +app.use(router) +app.use(ElementPlus) +app.mount('#app') diff --git a/江西城市生命线-可交互原型/frontend/src/router/index.js b/江西城市生命线-可交互原型/frontend/src/router/index.js new file mode 100644 index 00000000..4de0ba0b --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/router/index.js @@ -0,0 +1,62 @@ +import { createRouter, createWebHistory } from 'vue-router' +import ChatView from '@/views/ChatView.vue' + +const routes = [ + { + path: '/', + name: 'chat', + component: ChatView + }, + { + path: '/knowledge', + name: 'knowledge', + component: () => import('@/views/KnowledgeView.vue') + }, + { + path: '/apps', + name: 'apps', + component: () => import('@/views/AppsView.vue') + }, + { + path: '/workflow', + name: 'workflow', + component: () => import('@/views/WorkflowView.vue') + }, + { + path: '/service', + name: 'service', + component: () => import('@/views/ServiceView.vue') + }, + { + path: '/bidding', + name: 'bidding', + component: () => import('@/views/BiddingView.vue') + }, + { + path: '/hazard', + name: 'hazard', + component: () => import('@/views/HazardView.vue') + }, + { + path: '/emergency', + name: 'emergency', + component: () => import('@/views/EmergencyView.vue') + }, + { + path: '/profile', + name: 'profile', + component: () => import('@/views/ProfileView.vue') + }, + { + path: '/admin', + name: 'admin', + component: () => import('@/views/AdminView.vue') + } +] + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +export default router diff --git a/江西城市生命线-可交互原型/frontend/src/stores/agent.js b/江西城市生命线-可交互原型/frontend/src/stores/agent.js new file mode 100644 index 00000000..39640050 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/stores/agent.js @@ -0,0 +1,91 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' + +export const useAgentStore = defineStore('agent', () => { + // 智能体列表 + const agents = ref([ + { + id: 'default', + name: '泰豪AI助手', + description: '通用AI智能助手,可以回答各类问题', + icon: '🤖', + color: '#7c3aed', + category: 'office', + usage: 25000 + }, + { + id: 'xiaohongshu', + name: '小红书文案生成', + description: '一键生成爆款小红书文案,支持多种风格,自动添加热门话题标签', + icon: '📕', + color: '#ff2442', + category: 'content', + usage: 12580 + }, + { + id: 'contract', + name: '泰豪合同助手', + description: '智能合同审核、条款分析、风险提示,提高合同处理效率', + icon: '📄', + color: '#7c3aed', + category: 'business', + usage: 8320 + }, + { + id: 'video', + name: '泰豪短视频助手', + description: '短视频脚本创作、文案优化、热门话题推荐', + icon: '🎬', + color: '#10b981', + category: 'content', + usage: 5640 + }, + { + id: 'email', + name: '邮件写作助手', + description: '商务邮件、会议邀请、工作汇报等各类邮件智能生成', + icon: '✉️', + color: '#6366f1', + category: 'office', + usage: 7230 + }, + { + id: 'translate', + name: '多语言翻译', + description: '支持中英日韩等多语言互译,专业术语精准翻译', + icon: '🌐', + color: '#14b8a6', + category: 'office', + usage: 11200 + } + ]) + + // 当前选中的智能体ID + const currentAgentId = ref('default') + + // 当前智能体 + const currentAgent = computed(() => { + return agents.value.find(a => a.id === currentAgentId.value) || agents.value[0] + }) + + // 设置当前智能体 + const setCurrentAgent = (agentId) => { + const agent = agents.value.find(a => a.id === agentId) + if (agent) { + currentAgentId.value = agentId + } + } + + // 添加新智能体 + const addAgent = (agent) => { + agents.value.push(agent) + } + + return { + agents, + currentAgentId, + currentAgent, + setCurrentAgent, + addAgent + } +}) diff --git a/江西城市生命线-可交互原型/frontend/src/stores/chat.js b/江西城市生命线-可交互原型/frontend/src/stores/chat.js new file mode 100644 index 00000000..75653635 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/stores/chat.js @@ -0,0 +1,99 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import axios from 'axios' + +const api = axios.create({ + baseURL: '/api', + timeout: 30000 +}) + +export const useChatStore = defineStore('chat', () => { + const messages = ref([]) + const isLoading = ref(false) + const currentSession = ref(null) + + // Mock responses for when backend is not available + const mockResponses = { + '城市生命线': '城市生命线是指城市中维持城市正常运转的关键基础设施系统,包括供水、供电、供气、通信、交通等系统。这些系统如同城市的"生命线",一旦发生故障,将对城市运行和居民生活产生重大影响。', + '关键设施': '城市生命线关键设施包括:\n1. 供水系统:水厂、管网、加压站\n2. 供电系统:变电站、配电网\n3. 供气系统:门站、调压站、管网\n4. 通信系统:基站、光纤网络\n5. 交通系统:道路、桥梁、隧道', + '消防安全': '消防安全隐患常见问题及处理措施:\n1. 消防通道堵塞 - 立即清理,保持畅通\n2. 灭火器过期 - 及时更换检修\n3. 电气线路老化 - 专业检测更换\n4. 易燃物品堆放 - 规范存储管理\n5. 消防设施损坏 - 定期检查维护', + '排水': '如何平衡排水能力和生态环境保护:\n1. 采用海绵城市理念,增加透水面积\n2. 建设生态调蓄池,减缓雨水径流\n3. 推广透水铺装,促进雨水下渗\n4. 保护自然水系,维护生态平衡\n5. 雨污分流改造,提高污水处理效率' + } + + const getMockResponse = (input) => { + for (const [key, value] of Object.entries(mockResponses)) { + if (input.includes(key)) { + return value + } + } + return `您好!关于"${input}"的问题,我正在为您查询相关资料。作为城市生命线智能助手,我可以帮助您:\n\n1. 查询城市生命线相关知识\n2. 识别潜在安全隐患\n3. 编制应急预案\n4. 撰写公文报告\n\n请问还有什么可以帮助您的?` + } + + const sendMessage = async (content) => { + isLoading.value = true + try { + const response = await api.post('/chat/send', { + content, + role: 'user', + sessionId: currentSession.value + }) + return response.data + } catch (error) { + console.log('Backend not available, using mock response') + // Return mock response when backend is not available + return { + id: Date.now().toString(), + content: getMockResponse(content), + role: 'assistant', + timestamp: new Date().toISOString() + } + } finally { + isLoading.value = false + } + } + + const getHistory = async () => { + try { + const response = await api.get('/chat/history') + messages.value = response.data + return response.data + } catch (error) { + console.log('Backend not available') + return [] + } + } + + const getSuggestions = async () => { + try { + const response = await api.get('/chat/suggestions') + return response.data + } catch (error) { + return [ + '城市生命线关键设施有哪些?', + '消防安全隐患常见问题以及处理措施有哪些?', + '如何平衡排水能力和生态环境保护?' + ] + } + } + + const newChat = async () => { + try { + await api.post('/chat/new') + messages.value = [] + currentSession.value = Date.now().toString() + } catch (error) { + messages.value = [] + currentSession.value = Date.now().toString() + } + } + + return { + messages, + isLoading, + currentSession, + sendMessage, + getHistory, + getSuggestions, + newChat + } +}) diff --git a/江西城市生命线-可交互原型/frontend/src/stores/workflow.js b/江西城市生命线-可交互原型/frontend/src/stores/workflow.js new file mode 100644 index 00000000..002abb27 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/stores/workflow.js @@ -0,0 +1,140 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' + +export const useWorkflowStore = defineStore('workflow', () => { + // 节点列表 + const nodes = ref([]) + + // 连接线列表 + const connections = ref([]) + + // 选中的节点ID + const selectedNodeId = ref(null) + + // 节点ID计数器 + let nodeIdCounter = 1 + + // 节点类型定义 + const nodeTypes = [ + { type: 'start', label: '开始', icon: '▶', color: '#10b981', category: 'control' }, + { type: 'end', label: '结束', icon: '⏹', color: '#ef4444', category: 'control' }, + { type: 'llm', label: 'LLM 模型', icon: '🤖', color: '#7c3aed', category: 'ai' }, + { type: 'knowledge', label: '知识库', icon: '📚', color: '#3b82f6', category: 'ai' }, + { type: 'condition', label: '条件判断', icon: '⋔', color: '#f59e0b', category: 'logic' }, + { type: 'code', label: '代码执行', icon: '{ }', color: '#6366f1', category: 'logic' }, + { type: 'http', label: 'HTTP 请求', icon: '🌐', color: '#14b8a6', category: 'integration' }, + { type: 'variable', label: '变量赋值', icon: '𝑥=', color: '#8b5cf6', category: 'logic' }, + { type: 'template', label: '模板转换', icon: '📝', color: '#ec4899', category: 'transform' }, + { type: 'loop', label: '循环', icon: '↻', color: '#f97316', category: 'logic' } + ] + + // 添加节点 + const addNode = (type, position) => { + const nodeType = nodeTypes.find(n => n.type === type) + if (!nodeType) return null + + const newNode = { + id: `node_${nodeIdCounter++}`, + type: type, + label: nodeType.label, + icon: nodeType.icon, + color: nodeType.color, + x: position.x, + y: position.y, + width: 180, + height: 60, + inputs: type !== 'start' ? [{ id: 'in_1', label: '输入' }] : [], + outputs: type !== 'end' ? [{ id: 'out_1', label: '输出' }] : [] + } + + nodes.value.push(newNode) + return newNode + } + + // 更新节点位置 + const updateNodePosition = (nodeId, x, y) => { + const node = nodes.value.find(n => n.id === nodeId) + if (node) { + node.x = x + node.y = y + } + } + + // 删除节点 + const deleteNode = (nodeId) => { + const index = nodes.value.findIndex(n => n.id === nodeId) + if (index > -1) { + nodes.value.splice(index, 1) + // 删除相关连接 + connections.value = connections.value.filter( + c => c.sourceNodeId !== nodeId && c.targetNodeId !== nodeId + ) + } + if (selectedNodeId.value === nodeId) { + selectedNodeId.value = null + } + } + + // 添加连接 + const addConnection = (sourceNodeId, sourcePortId, targetNodeId, targetPortId) => { + // 检查是否已存在相同连接 + const exists = connections.value.some( + c => c.sourceNodeId === sourceNodeId && + c.sourcePortId === sourcePortId && + c.targetNodeId === targetNodeId && + c.targetPortId === targetPortId + ) + if (exists) return null + + const newConnection = { + id: `conn_${Date.now()}`, + sourceNodeId, + sourcePortId, + targetNodeId, + targetPortId + } + connections.value.push(newConnection) + return newConnection + } + + // 删除连接 + const deleteConnection = (connectionId) => { + const index = connections.value.findIndex(c => c.id === connectionId) + if (index > -1) { + connections.value.splice(index, 1) + } + } + + // 选中节点 + const selectNode = (nodeId) => { + selectedNodeId.value = nodeId + } + + // 清空画布 + const clearCanvas = () => { + nodes.value = [] + connections.value = [] + selectedNodeId.value = null + nodeIdCounter = 1 + } + + // 获取节点 + const getNode = (nodeId) => { + return nodes.value.find(n => n.id === nodeId) + } + + return { + nodes, + connections, + selectedNodeId, + nodeTypes, + addNode, + updateNodePosition, + deleteNode, + addConnection, + deleteConnection, + selectNode, + clearCanvas, + getNode + } +}) diff --git a/江西城市生命线-可交互原型/frontend/src/styles/main.scss b/江西城市生命线-可交互原型/frontend/src/styles/main.scss new file mode 100644 index 00000000..752bc42e --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/styles/main.scss @@ -0,0 +1,72 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html, body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + font-size: 14px; + line-height: 1.5; + color: #333; + background-color: #f5f5f5; +} + +:root { + --primary-color: #7c3aed; + --primary-light: #a78bfa; + --primary-dark: #5b21b6; + --sidebar-bg: #4a1d7e; + --sidebar-hover: rgba(255, 255, 255, 0.1); + --sidebar-active: rgba(255, 255, 255, 0.2); + --text-white: #ffffff; + --text-gray: #9ca3af; + --border-color: #e5e7eb; + --card-bg: #ffffff; + --shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +// Scrollbar styles +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: #d1d5db; + border-radius: 3px; + + &:hover { + background: #9ca3af; + } +} + +// Input styles +input, textarea { + font-family: inherit; + font-size: inherit; +} + +// Button reset +button { + border: none; + background: none; + cursor: pointer; + font-family: inherit; + font-size: inherit; +} + +// Link reset +a { + text-decoration: none; + color: inherit; +} + +// List reset +ul, ol { + list-style: none; +} diff --git a/江西城市生命线-可交互原型/frontend/src/views/AdminView.vue b/江西城市生命线-可交互原型/frontend/src/views/AdminView.vue new file mode 100644 index 00000000..3b1669b2 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/AdminView.vue @@ -0,0 +1,4051 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/AgentChatView.vue b/江西城市生命线-可交互原型/frontend/src/views/AgentChatView.vue new file mode 100644 index 00000000..94fb5305 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/AgentChatView.vue @@ -0,0 +1,453 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/AppsView.vue b/江西城市生命线-可交互原型/frontend/src/views/AppsView.vue new file mode 100644 index 00000000..a4b4225c --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/AppsView.vue @@ -0,0 +1,473 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/BiddingView.vue b/江西城市生命线-可交互原型/frontend/src/views/BiddingView.vue new file mode 100644 index 00000000..da51dbff --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/BiddingView.vue @@ -0,0 +1,18847 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/ChatView.vue b/江西城市生命线-可交互原型/frontend/src/views/ChatView.vue new file mode 100644 index 00000000..b3dc4596 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/ChatView.vue @@ -0,0 +1,899 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/EmergencyView.vue b/江西城市生命线-可交互原型/frontend/src/views/EmergencyView.vue new file mode 100644 index 00000000..28392b0c --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/EmergencyView.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/HazardView.vue b/江西城市生命线-可交互原型/frontend/src/views/HazardView.vue new file mode 100644 index 00000000..fe7acb85 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/HazardView.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/KnowledgeView.vue b/江西城市生命线-可交互原型/frontend/src/views/KnowledgeView.vue new file mode 100644 index 00000000..d96e2fd3 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/KnowledgeView.vue @@ -0,0 +1,202 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/ProfileView.vue b/江西城市生命线-可交互原型/frontend/src/views/ProfileView.vue new file mode 100644 index 00000000..eccafce0 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/ProfileView.vue @@ -0,0 +1,276 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/ServiceView.vue b/江西城市生命线-可交互原型/frontend/src/views/ServiceView.vue new file mode 100644 index 00000000..373d743b --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/ServiceView.vue @@ -0,0 +1,2017 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/src/views/WorkflowView.vue b/江西城市生命线-可交互原型/frontend/src/views/WorkflowView.vue new file mode 100644 index 00000000..715654e0 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/src/views/WorkflowView.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/江西城市生命线-可交互原型/frontend/vite.config.js b/江西城市生命线-可交互原型/frontend/vite.config.js new file mode 100644 index 00000000..0b474e44 --- /dev/null +++ b/江西城市生命线-可交互原型/frontend/vite.config.js @@ -0,0 +1,22 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import { resolve } from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': resolve(__dirname, 'src') + } + }, + server: { + port: 5173, + allowedHosts:['.trycloudflare.com','.ngrok-free.app','.cpolar.top','.cpolar.cn'], + proxy: { + '/api': { + target: 'http://localhost:8080', + changeOrigin: true + } + } + } +})