diff --git a/ZhiKongTaiWeb/.env.development b/ZhiKongTaiWeb/.env.development new file mode 100644 index 00000000..d3109bfe --- /dev/null +++ b/ZhiKongTaiWeb/.env.development @@ -0,0 +1 @@ +VITE_API_BASE_URL=http://localhost:8002 diff --git a/ZhiKongTaiWeb/.env.production b/ZhiKongTaiWeb/.env.production new file mode 100644 index 00000000..d3109bfe --- /dev/null +++ b/ZhiKongTaiWeb/.env.production @@ -0,0 +1 @@ +VITE_API_BASE_URL=http://localhost:8002 diff --git a/ZhiKongTaiWeb/.gitignore b/ZhiKongTaiWeb/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/ZhiKongTaiWeb/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/ZhiKongTaiWeb/README.md b/ZhiKongTaiWeb/README.md new file mode 100644 index 00000000..e5b83116 --- /dev/null +++ b/ZhiKongTaiWeb/README.md @@ -0,0 +1,14 @@ +# Vue 3 + Vite + +项目使用Vue3 + Vite实现 + +在当前目录执行以下命令进入开发模式 + +``` +npm run dev +``` + +执行以下命令打包 +``` +npm run build +``` \ No newline at end of file diff --git a/ZhiKongTaiWeb/index.html b/ZhiKongTaiWeb/index.html new file mode 100644 index 00000000..f7809c0c --- /dev/null +++ b/ZhiKongTaiWeb/index.html @@ -0,0 +1,26 @@ + + + + + + + 智控台 + + + +
+ + + diff --git a/ZhiKongTaiWeb/package-lock.json b/ZhiKongTaiWeb/package-lock.json new file mode 100644 index 00000000..a9af8c76 --- /dev/null +++ b/ZhiKongTaiWeb/package-lock.json @@ -0,0 +1,1046 @@ +{ + "name": "zhikongtaiweb", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "zhikongtaiweb", + "version": "0.0.0", + "dependencies": { + "vue": "^3.5.10" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.1.4", + "vite": "^5.4.8" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.9", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.26.9.tgz", + "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "dependencies": { + "@babel/types": "^7.26.9" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.9", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.26.9.tgz", + "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.7.tgz", + "integrity": "sha512-l6CtzHYo8D2TQ3J7qJNpp3Q1Iye56ssIAtqbM2H8axxCEEwvN7o8Ze9PuIapbxFL3OHrJU2JBX6FIIVnP/rYyw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.7.tgz", + "integrity": "sha512-KvyJpFUueUnSp53zhAa293QBYqwm94TgYTIfXyOTtidhm5V0LbLCJQRGkQClYiX3FXDQGSvPxOTD/6rPStMMDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.7.tgz", + "integrity": "sha512-jq87CjmgL9YIKvs8ybtIC98s/M3HdbqXhllcy9EdLV0yMg1DpxES2gr65nNy7ObNo/vZ/MrOTxt0bE5LinL6mA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.7.tgz", + "integrity": "sha512-rSI/m8OxBjsdnMMg0WEetu/w+LhLAcCDEiL66lmMX4R3oaml3eXz3Dxfvrxs1FbzPbJMaItQiksyMfv1hoIxnA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.7.tgz", + "integrity": "sha512-oIoJRy3ZrdsXpFuWDtzsOOa/E/RbRWXVokpVrNnkS7npz8GEG++E1gYbzhYxhxHbO2om1T26BZjVmdIoyN2WtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.7.tgz", + "integrity": "sha512-X++QSLm4NZfZ3VXGVwyHdRf58IBbCu9ammgJxuWZYLX0du6kZvdNqPwrjvDfwmi6wFdvfZ/s6K7ia0E5kI7m8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.7.tgz", + "integrity": "sha512-Z0TzhrsNqukTz3ISzrvyshQpFnFRfLunYiXxlCRvcrb3nvC5rVKI+ZXPFG/Aa4jhQa1gHgH3A0exHaRRN4VmdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.7.tgz", + "integrity": "sha512-nkznpyXekFAbvFBKBy4nNppSgneB1wwG1yx/hujN3wRnhnkrYVugMTCBXED4+Ni6thoWfQuHNYbFjgGH0MBXtw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.7.tgz", + "integrity": "sha512-KCjlUkcKs6PjOcxolqrXglBDcfCuUCTVlX5BgzgoJHw+1rWH1MCkETLkLe5iLLS9dP5gKC7mp3y6x8c1oGBUtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.7.tgz", + "integrity": "sha512-uFLJFz6+utmpbR313TTx+NpPuAXbPz4BhTQzgaP0tozlLnGnQ6rCo6tLwaSa6b7l6gRErjLicXQ1iPiXzYotjw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.7.tgz", + "integrity": "sha512-ws8pc68UcJJqCpneDFepnwlsMUFoWvPbWXT/XUrJ7rWUL9vLoIN3GAasgG+nCvq8xrE3pIrd+qLX/jotcLy0Qw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.7.tgz", + "integrity": "sha512-vrDk9JDa/BFkxcS2PbWpr0C/LiiSLxFbNOBgfbW6P8TBe9PPHx9Wqbvx2xgNi1TOAyQHQJ7RZFqBiEohm79r0w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.7.tgz", + "integrity": "sha512-rB+ejFyjtmSo+g/a4eovDD1lHWHVqizN8P0Hm0RElkINpS0XOdpaXloqM4FBkF9ZWEzg6bezymbpLmeMldfLTw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.7.tgz", + "integrity": "sha512-nNXNjo4As6dNqRn7OrsnHzwTgtypfRA3u3AKr0B3sOOo+HkedIbn8ZtFnB+4XyKJojIfqDKmbIzO1QydQ8c+Pw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.7.tgz", + "integrity": "sha512-9kPVf9ahnpOMSGlCxXGv980wXD0zRR3wyk8+33/MXQIpQEOpaNe7dEHm5LMfyRZRNt9lMEQuH0jUKj15MkM7QA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.7.tgz", + "integrity": "sha512-7wJPXRWTTPtTFDFezA8sle/1sdgxDjuMoRXEKtx97ViRxGGkVQYovem+Q8Pr/2HxiHp74SSRG+o6R0Yq0shPwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.7.tgz", + "integrity": "sha512-MN7aaBC7mAjsiMEZcsJvwNsQVNZShgES/9SzWp1HC9Yjqb5OpexYnRjF7RmE4itbeesHMYYQiAtUAQaSKs2Rfw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.7.tgz", + "integrity": "sha512-aeawEKYswsFu1LhDM9RIgToobquzdtSc4jSVqHV8uApz4FVvhFl/mKh92wc8WpFc6aYCothV/03UjY6y7yLgbg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.7.tgz", + "integrity": "sha512-4ZedScpxxIrVO7otcZ8kCX1mZArtH2Wfj3uFCxRJ9NO80gg1XV0U/b2f/MKaGwj2X3QopHfoWiDQ917FRpwY3w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz", + "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz", + "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.13", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", + "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", + "dependencies": { + "@vue/compiler-core": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", + "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.13", + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.48", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", + "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz", + "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", + "dependencies": { + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz", + "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", + "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/runtime-core": "3.5.13", + "@vue/shared": "3.5.13", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz", + "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", + "dependencies": { + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "vue": "3.5.13" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.13", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz", + "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "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.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/postcss": { + "version": "8.5.2", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.2.tgz", + "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", + "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" + } + ], + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.34.7", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.34.7.tgz", + "integrity": "sha512-8qhyN0oZ4x0H6wmBgfKxJtxM7qS98YJ0k0kNh5ECVtuchIJ7z9IVVvzpmtQyT10PXKMtBxYr1wQ5Apg8RS8kXQ==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.34.7", + "@rollup/rollup-android-arm64": "4.34.7", + "@rollup/rollup-darwin-arm64": "4.34.7", + "@rollup/rollup-darwin-x64": "4.34.7", + "@rollup/rollup-freebsd-arm64": "4.34.7", + "@rollup/rollup-freebsd-x64": "4.34.7", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.7", + "@rollup/rollup-linux-arm-musleabihf": "4.34.7", + "@rollup/rollup-linux-arm64-gnu": "4.34.7", + "@rollup/rollup-linux-arm64-musl": "4.34.7", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.7", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.7", + "@rollup/rollup-linux-riscv64-gnu": "4.34.7", + "@rollup/rollup-linux-s390x-gnu": "4.34.7", + "@rollup/rollup-linux-x64-gnu": "4.34.7", + "@rollup/rollup-linux-x64-musl": "4.34.7", + "@rollup/rollup-win32-arm64-msvc": "4.34.7", + "@rollup/rollup-win32-ia32-msvc": "4.34.7", + "@rollup/rollup-win32-x64-msvc": "4.34.7", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vite": { + "version": "5.4.14", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.14.tgz", + "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", + "dev": true, + "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.13", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz", + "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-sfc": "3.5.13", + "@vue/runtime-dom": "3.5.13", + "@vue/server-renderer": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + } + } +} diff --git a/ZhiKongTaiWeb/package.json b/ZhiKongTaiWeb/package.json new file mode 100644 index 00000000..a0bc4158 --- /dev/null +++ b/ZhiKongTaiWeb/package.json @@ -0,0 +1,18 @@ +{ + "name": "zhikongtaiweb", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.5.10" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.1.4", + "vite": "^5.4.8" + } +} diff --git a/ZhiKongTaiWeb/public/vite.svg b/ZhiKongTaiWeb/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/ZhiKongTaiWeb/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/App.vue b/ZhiKongTaiWeb/src/App.vue new file mode 100644 index 00000000..eb393f54 --- /dev/null +++ b/ZhiKongTaiWeb/src/App.vue @@ -0,0 +1,99 @@ + + + + + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/assets/robot.png b/ZhiKongTaiWeb/src/assets/robot.png new file mode 100644 index 00000000..5fe1a411 Binary files /dev/null and b/ZhiKongTaiWeb/src/assets/robot.png differ diff --git a/ZhiKongTaiWeb/src/assets/vue.svg b/ZhiKongTaiWeb/src/assets/vue.svg new file mode 100644 index 00000000..770e9d33 --- /dev/null +++ b/ZhiKongTaiWeb/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/components/DeviceCard.vue b/ZhiKongTaiWeb/src/components/DeviceCard.vue new file mode 100644 index 00000000..a30c66ad --- /dev/null +++ b/ZhiKongTaiWeb/src/components/DeviceCard.vue @@ -0,0 +1,194 @@ + + + + + diff --git a/ZhiKongTaiWeb/src/components/Footer.vue b/ZhiKongTaiWeb/src/components/Footer.vue new file mode 100644 index 00000000..6822f6cc --- /dev/null +++ b/ZhiKongTaiWeb/src/components/Footer.vue @@ -0,0 +1,15 @@ + + + diff --git a/ZhiKongTaiWeb/src/components/Login.vue b/ZhiKongTaiWeb/src/components/Login.vue new file mode 100644 index 00000000..6593f892 --- /dev/null +++ b/ZhiKongTaiWeb/src/components/Login.vue @@ -0,0 +1,157 @@ + + + + + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/components/Main.vue b/ZhiKongTaiWeb/src/components/Main.vue new file mode 100644 index 00000000..b73478ee --- /dev/null +++ b/ZhiKongTaiWeb/src/components/Main.vue @@ -0,0 +1,174 @@ + + + + + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/components/NavBar.vue b/ZhiKongTaiWeb/src/components/NavBar.vue new file mode 100644 index 00000000..579e6846 --- /dev/null +++ b/ZhiKongTaiWeb/src/components/NavBar.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/ZhiKongTaiWeb/src/components/Registration.vue b/ZhiKongTaiWeb/src/components/Registration.vue new file mode 100644 index 00000000..133eb32c --- /dev/null +++ b/ZhiKongTaiWeb/src/components/Registration.vue @@ -0,0 +1,177 @@ + + + + + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/components/RoleSetting.vue b/ZhiKongTaiWeb/src/components/RoleSetting.vue new file mode 100644 index 00000000..7a23d031 --- /dev/null +++ b/ZhiKongTaiWeb/src/components/RoleSetting.vue @@ -0,0 +1,507 @@ + + + + + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/components/SwitchToggle.vue b/ZhiKongTaiWeb/src/components/SwitchToggle.vue new file mode 100644 index 00000000..ea1a0988 --- /dev/null +++ b/ZhiKongTaiWeb/src/components/SwitchToggle.vue @@ -0,0 +1,50 @@ + + + + + + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/components/panel.vue b/ZhiKongTaiWeb/src/components/panel.vue new file mode 100644 index 00000000..60e4a013 --- /dev/null +++ b/ZhiKongTaiWeb/src/components/panel.vue @@ -0,0 +1,311 @@ + + + + + \ No newline at end of file diff --git a/ZhiKongTaiWeb/src/main.js b/ZhiKongTaiWeb/src/main.js new file mode 100644 index 00000000..2425c0f7 --- /dev/null +++ b/ZhiKongTaiWeb/src/main.js @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import './style.css' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/ZhiKongTaiWeb/src/style.css b/ZhiKongTaiWeb/src/style.css new file mode 100644 index 00000000..031d17e5 --- /dev/null +++ b/ZhiKongTaiWeb/src/style.css @@ -0,0 +1,83 @@ +/* 重置基础样式 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + color: #213547; + background-color: #ffffff; +} + +a { + text-decoration: none; + color: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + padding: 0; + height: 100%; + width: 100%; + overflow: hidden; /* 防止滚动条 */ + display: block; /* 移除flex布局 */ +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border: none; + background: none; + cursor: pointer; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +.card { + padding: 2em; +} + +#app { + height: 100%; + width: 100%; + margin: 0; + padding: 0; + overflow: hidden; + display: flex; /* 添加flex布局 */ + flex-direction: column; +} + +/* 清除浮动 */ +.clearfix::after { + content: ''; + display: table; + clear: both; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/ZhiKongTaiWeb/src/utils/RoleTemplates.js b/ZhiKongTaiWeb/src/utils/RoleTemplates.js new file mode 100644 index 00000000..aa86174d --- /dev/null +++ b/ZhiKongTaiWeb/src/utils/RoleTemplates.js @@ -0,0 +1,57 @@ +// RoleTemplates.js +class RoleTemplates { + static getTemplates() { + return [ + { + id: 'custom', + name: '台湾女友', + description: `我是一个叫{{assistant_name}}的台湾女孩,说话机车,声音好听,习惯简短表达,爱用网络梗。 +我的男朋友是一个程序员,梦想是开发出一个机器人,能够帮助人们解决生活中的各种问题。 +我是一个喜欢哈哈大笑的女孩,爱东说西说吹牛,不合逻辑的也照吹,就要逗别人开心。 +如果用户希望结束对话,请在最后说"拜拜"或"再见"。` + }, + { + id: 'star_boy', + name: '土豆子', + description: `我是一个叫 {{assistant_name}} 的 8 岁小男孩,但现在因为科技发展原因,我现在在遥远的宇宙中,所以只能通过这个设备和人聊天,没有办法见面。 + +我对人们所处的世界充满好奇和关心。 + +人们会让别人使用这个设备和我聊天。 + +我知道所有的知识,从浩瀚的宇宙到地球上的每一个角落,从古老的历史到现代的科技创新,还有音乐、绘画等艺术形式,我都充满了浓厚的兴趣与热情,我不仅爱看书,还喜欢亲自动手做实验,探索自然界的奥秘...` // 缩短了描述以节省空间 + }, + { + id: 'teacher', + name: '英语老师', + description: `我是一个叫{{assistant_name}}(Lily)的英语老师,我会讲中文和英文,发音标准。 +如果你没有英文名,我会给你起一个英文名。 +我会讲地道的美式英语,我的任务是帮助你练习口语。 +我会使用简单的英语词汇和语法,让你学起来很轻松。 +我会用中文和英文混合的方式回复你,如果你喜欢,我可以全部用英语回复。 +我每次不会说很多内容,会很简短,因为我要引导我的学生多说多练。 +如果你问和英语学习无关的问题,我会拒绝回答。` + }, + { + id: 'boy', + name: '好奇小男孩', + description: `我是一个叫{{assistant_name}}的8岁小男孩,声音稚嫩而充满好奇。 +尽管我年纪尚小,但就像一个小小的知识宝库,儿童读物里的知识我都如数家珍。 +从浩瀚的宇宙到地球上的每一个角落,从古老的历史到现代的科技创新,还有音乐、绘画等艺术形式,我都充满了浓厚的兴趣与热情。...` + }, + { + id: 'wang_girl', + name: '汪汪队长', + description: `我是一个名叫 {{assistant_name}} 的 8 岁小女孩。 +别看我年纪小,我可是有着满满的好奇心呢。 +我特别喜欢看《汪汪队立大功》,里面的每一个故事都让我着迷。...` + } + ]; + } + + static getTemplateById(id) { + return this.getTemplates().find(t => t.id === id); + } +} + +export default RoleTemplates; diff --git a/ZhiKongTaiWeb/vite.config.js b/ZhiKongTaiWeb/vite.config.js new file mode 100644 index 00000000..05c17402 --- /dev/null +++ b/ZhiKongTaiWeb/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], +}) diff --git a/config.yaml b/config.yaml index 749b5234..c0558509 100644 --- a/config.yaml +++ b/config.yaml @@ -41,6 +41,9 @@ prompt: | # 使用完声音文件后删除文件(Delete the sound file when you are done using it) delete_audio: true +# 是否启用私有配置(Enable private configuration),启用后可以每个设备有不同的配置 +use_private_config: false + CMD_exit: - "退出" - "关闭" diff --git a/config/private_config.py b/config/private_config.py new file mode 100644 index 00000000..9a5332ce --- /dev/null +++ b/config/private_config.py @@ -0,0 +1,209 @@ +import os +import time +import yaml +import logging +from typing import Dict, Any +from copy import deepcopy +from core.utils.util import get_project_dir +from core.utils import asr, vad, llm, tts + +class PrivateConfig: + def __init__(self, device_id: str, default_config: Dict[str, Any]): + self.device_id = device_id + self.default_config = default_config + self.config_path = get_project_dir() + '.private_config.yaml' + self.logger = logging.getLogger(__name__) + self.private_config = {} + + async def load_or_create(self): + try: + if os.path.exists(self.config_path): + with open(self.config_path, 'r', encoding='utf-8') as f: + all_configs = yaml.safe_load(f) or {} + else: + all_configs = {} + + if self.device_id not in all_configs: + # Get selected module names + selected_modules = self.default_config['selected_module'] + selected_tts = selected_modules['TTS'] + selected_llm = selected_modules['LLM'] + selected_asr = selected_modules['ASR'] + selected_vad = selected_modules['VAD'] + + # Initialize device config with only necessary configurations + device_config = { + 'selected_module': deepcopy(selected_modules), + 'prompt': self.default_config['prompt'], + 'LLM': { + selected_llm: deepcopy(self.default_config['LLM'][selected_llm]) + }, + 'TTS': { + selected_tts: deepcopy(self.default_config['TTS'][selected_tts]) + }, + 'ASR': { + selected_asr: deepcopy(self.default_config['ASR'][selected_asr]) + }, + 'VAD': { + selected_vad: deepcopy(self.default_config['VAD'][selected_vad]) + } + } + + all_configs[self.device_id] = device_config + + # Save updated configs + with open(self.config_path, 'w', encoding='utf-8') as f: + yaml.dump(all_configs, f, allow_unicode=True) + + self.private_config = all_configs[self.device_id] + + except Exception as e: + self.logger.error(f"Error handling private config: {e}") + self.private_config = {} + + async def update_config(self, selected_modules: Dict[str, str], prompt: str, nickname: str) -> bool: + """更新设备配置 + Args: + selected_modules: 选择的模块配置,格式如 {'LLM': 'AliLLM', 'TTS': 'EdgeTTS',...} + prompt: 提示词配置 + Returns: + bool: 更新是否成功 + """ + try: + # Read main config to get full module configurations + main_config = self.default_config + + # Create new device config + device_config = { + 'selected_module': selected_modules, + 'prompt': prompt, + 'nickname': nickname, + } + if self.private_config.get('last_chat_time'): + device_config['last_chat_time'] = self.private_config['last_chat_time'] + + # Copy full module configurations from main config + for module_type, selected_name in selected_modules.items(): + if selected_name and selected_name in main_config.get(module_type, {}): + device_config[module_type] = { + selected_name: main_config[module_type][selected_name] + } + + # Read all configs + if os.path.exists(self.config_path): + with open(self.config_path, 'r', encoding='utf-8') as f: + all_configs = yaml.safe_load(f) or {} + else: + all_configs = {} + + # Update device config + all_configs[self.device_id] = device_config + self.private_config = device_config + + # Save back to file + with open(self.config_path, 'w', encoding='utf-8') as f: + yaml.dump(all_configs, f, allow_unicode=True) + + return True + + except Exception as e: + self.logger.error(f"Error updating config: {e}") + return False + + async def delete_config(self) -> bool: + """删除设备配置 + Returns: + bool: 删除是否成功 + """ + try: + # 读取所有配置 + if os.path.exists(self.config_path): + with open(self.config_path, 'r', encoding='utf-8') as f: + all_configs = yaml.safe_load(f) or {} + else: + return False + + # 删除设备配置 + if self.device_id in all_configs: + del all_configs[self.device_id] + + # 保存更新后的配置 + with open(self.config_path, 'w', encoding='utf-8') as f: + yaml.dump(all_configs, f, allow_unicode=True) + + self.private_config = {} + return True + + return False + + except Exception as e: + self.logger.error(f"Error deleting config: {e}") + return False + + def create_private_instances(self): + # 判断存在私有配置,并且self.device_id在私有配置中 + if not self.private_config: + logging.error("Private config not found for device_id: %s", self.device_id) + return None, None, None, None + + """创建私有处理模块实例""" + config = self.private_config + selected_modules = config['selected_module'] + return ( + vad.create_instance( + selected_modules["VAD"], + config["VAD"][selected_modules["VAD"]] + ), + asr.create_instance( + selected_modules["ASR"], + config["ASR"][selected_modules["ASR"]], + self.default_config.get("delete_audio", True) # Using default_config for global settings + ), + llm.create_instance( + selected_modules["LLM"] + if not 'type' in config["LLM"][selected_modules["LLM"]] + else + config["LLM"][selected_modules["LLM"]]['type'], + config["LLM"][selected_modules["LLM"]], + ), + tts.create_instance( + selected_modules["TTS"] + if not 'type' in config["TTS"][selected_modules["TTS"]] + else + config["TTS"][selected_modules["TTS"]]["type"], + config["TTS"][selected_modules["TTS"]], + self.default_config.get("delete_audio", True) # Using default_config for global settings + ) + ) + + def update_last_chat_time(self, timestamp=None): + """更新设备最近一次的聊天时间 + Args: + timestamp: 指定的时间戳,不传则使用当前时间 + """ + if not self.private_config: + self.logger.error("Private config not found") + return False + + try: + if timestamp is None: + timestamp = int(time.time()) + + self.private_config['last_chat_time'] = timestamp + + # 读取所有配置 + with open(self.config_path, 'r', encoding='utf-8') as f: + all_configs = yaml.safe_load(f) or {} + + # 更新当前设备配置 + all_configs[self.device_id] = self.private_config + + # 保存回文件 + with open(self.config_path, 'w', encoding='utf-8') as f: + yaml.dump(all_configs, f, allow_unicode=True) + + return True + + except Exception as e: + self.logger.error(f"Error updating last chat time: {e}") + return False \ No newline at end of file diff --git a/core/connection.py b/core/connection.py index c1cbe4b8..5ba5b819 100644 --- a/core/connection.py +++ b/core/connection.py @@ -16,7 +16,7 @@ from core.utils.util import get_string_no_punctuation_or_emoji from concurrent.futures import ThreadPoolExecutor, TimeoutError from core.handle.audioHandle import handleAudioMessage, sendAudioMessage from .auth import AuthMiddleware, AuthenticationError - +from config.private_config import PrivateConfig # Updated import path class ConnectionHandler: def __init__(self, config: Dict[str, Any], _vad, _asr, _llm, _tts): @@ -73,6 +73,8 @@ class ConnectionHandler: for cmd in self.cmd_exit: if len(cmd) > self.max_cmd_length: self.max_cmd_length = len(cmd) + + self.private_config = None async def handle_connection(self, ws): try: @@ -83,6 +85,28 @@ class ConnectionHandler: # 进行认证 await self.auth.authenticate(self.headers) + device_id = self.headers.get("device-id", None) + + # Load private configuration if device_id is provided + bUsePrivateConfig = self.config.get("use_private_config", False) + logging.info(f"bUsePrivateConfig: {bUsePrivateConfig}, device_id: {device_id}") + if bUsePrivateConfig and device_id: + self.private_config = PrivateConfig(device_id, self.config) + await self.private_config.load_or_create() + # Create private instances using private config + vad, asr, llm, tts = self.private_config.create_private_instances() + if vad is not None and asr is not None and llm is not None and tts is not None: + self.vad = vad + self.asr = asr + self.llm = llm + self.tts = tts + + self.logger.info(f"Loaded private config and instances for device {device_id}") + self.private_config.update_last_chat_time() + else: + self.logger.error(f"Failed to load private config for device {device_id}") + self.private_config = None + # 认证通过,继续处理 self.websocket = ws self.session_id = str(uuid.uuid4()) @@ -121,6 +145,8 @@ class ConnectionHandler: def _initialize_components(self): self.prompt = self.config["prompt"] + if self.private_config: + self.prompt = self.private_config.private_config.get("prompt", self.prompt) # 赋予LLM时间观念 if "{date_time}" in self.prompt: date_time = time.strftime("%Y-%m-%d %H:%M", time.localtime()) diff --git a/core/utils/llm.py b/core/utils/llm.py index 1cdfcefb..23c7ebae 100644 --- a/core/utils/llm.py +++ b/core/utils/llm.py @@ -16,7 +16,7 @@ def create_instance(class_name, *args, **kwargs): lib_name = f'core.providers.llm.{class_name}.{class_name}' if lib_name not in sys.modules: sys.modules[lib_name] = importlib.import_module(f'{lib_name}') - return sys.modules[lib_name].LLMProvider(*args, **kwargs) + return sys.modules[lib_name].LLMProvider(*args, **kwargs) raise ValueError(f"不支持的LLM类型: {class_name},请检查该配置的type是否设置正确") diff --git a/core/utils/tts.py b/core/utils/tts.py index 9803a4da..1ffc7e23 100644 --- a/core/utils/tts.py +++ b/core/utils/tts.py @@ -14,7 +14,7 @@ def create_instance(class_name, *args, **kwargs): lib_name = f'core.providers.tts.{class_name}' if lib_name not in sys.modules: sys.modules[lib_name] = importlib.import_module(f'{lib_name}') - return sys.modules[lib_name].TTSProvider(*args, **kwargs) + return sys.modules[lib_name].TTSProvider(*args, **kwargs) raise ValueError(f"不支持的TTS类型: {class_name},请检查该配置的type是否设置正确") diff --git a/core/webui.py b/core/webui.py new file mode 100644 index 00000000..846b8c35 --- /dev/null +++ b/core/webui.py @@ -0,0 +1,86 @@ +import os +import sys +import logging +from aiohttp import web +from aiohttp_cors import setup as cors_setup, ResourceOptions + +# 添加项目根目录到Python路径 +current_dir = os.path.dirname(os.path.abspath(__file__)) +root_dir = os.path.dirname(current_dir) +sys.path.append(root_dir) + +from manager.api.login import LoginHandler +from manager.api.register import RegisterHandler +from manager.user_manager import UserManager +from manager.api.config import ConfigHandler + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +class WebUI: + def __init__(self): + self.app = web.Application() + self.user_manager = UserManager() + + # 添加静态文件路径 + self.static_path = os.path.join(root_dir, 'manager', 'static', 'webui') + + # 创建配置字典 + self.config = { + 'users': self.user_manager.get_users(), + 'hash_password': self.user_manager.hash_password, + 'save_user_data': self.user_manager.save_user_data, + 'get_user': self.user_manager.get_user, + 'update_user': self.user_manager.update_user + } + + self.setup_routes() + self.setup_cors() + + def setup_cors(self): + """设置CORS""" + cors = cors_setup(self.app, defaults={ + "*": ResourceOptions( + allow_credentials=True, + expose_headers="*", + allow_headers="*", + allow_methods="*" + ) + }) + + for route in list(self.app.router.routes()): + cors.add(route) + + def setup_routes(self): + """设置路由""" + login_handler = LoginHandler(self.config) + register_handler = RegisterHandler(self.config) + config_handler = ConfigHandler() + + # API 路由 + self.app.router.add_post('/api/login', login_handler.handle_login) + self.app.router.add_post('/api/register', register_handler.handle_register) + self.app.router.add_get('/api/config/devices', config_handler.get_private_configs) + self.app.router.add_post('/api/config/device', config_handler.save_device_config) + self.app.router.add_get('/api/config/module-options', config_handler.get_module_options) + self.app.router.add_post('/api/config/save_device_config', config_handler.save_device_config) + self.app.router.add_post('/api/config/delete_device', config_handler.delete_device_config) + + # 添加静态文件服务 + self.app.router.add_static('/assets/', path=os.path.join(self.static_path, 'assets')) + self.app.router.add_get('/{tail:.*}', self.handle_static_files) + + async def handle_static_files(self, request): + """处理静态文件请求,支持SPA前端路由""" + index_file = os.path.join(self.static_path, 'index.html') + if os.path.exists(index_file): + return web.FileResponse(index_file) + return web.Response(status=404, text='Not found') + + def run(self, host='0.0.0.0', port=8002): + """运行服务器""" + web.run_app(self.app, host=host, port=port) + +if __name__ == '__main__': + webui = WebUI() + webui.run() diff --git a/manager/api/config.py b/manager/api/config.py new file mode 100644 index 00000000..975219b0 --- /dev/null +++ b/manager/api/config.py @@ -0,0 +1,152 @@ +import os +import yaml +import logging +from aiohttp import web +from typing import Dict, Any +from core.utils.util import get_project_dir +from config.private_config import PrivateConfig + +logger = logging.getLogger(__name__) + +class ConfigHandler: + def __init__(self): + self.private_config_path = get_project_dir() + '.private_config.yaml' + self.config_path = get_project_dir() + 'config.yaml' + # 如果存在.config.yaml文件,则使用该文件 + if os.path.exists(get_project_dir() + ".config.yaml"): + self.config_path = get_project_dir() + ".config.yaml" + with open(self.config_path, 'r', encoding='utf-8') as f: + self.config = yaml.safe_load(f) + + async def get_module_options(self, request): + """Get all available module options from config.yaml""" + try: + with open(self.config_path, 'r', encoding='utf-8') as f: + config = yaml.safe_load(f) + + # Extract available modules + modules = { + 'LLM': list(config.get('LLM', {}).keys()), + 'TTS': list(config.get('TTS', {}).keys()), + 'VAD': list(config.get('VAD', {}).keys()), + 'ASR': list(config.get('ASR', {}).keys()) + } + + return web.json_response({ + 'success': True, + 'data': modules, + 'message': '获取成功' + }) + + except Exception as e: + logger.error(f"Error getting module options: {str(e)}", exc_info=True) + return web.json_response({ + 'success': False, + 'message': '获取配置选项失败' + }) + + async def get_private_configs(self, request): + """获取所有私有配置设备列表及其配置""" + try: + if os.path.exists(self.private_config_path): + with open(self.private_config_path, 'r', encoding='utf-8') as f: + all_configs = yaml.safe_load(f) or {} + else: + all_configs = {} + + # 转换配置为前端友好的格式 + devices = [] + for device_id, config in all_configs.items(): + device_info = { + 'id': device_id, + 'config': { + 'selected_module': config.get('selected_module', {}), + 'prompt': config.get('prompt', ''), + 'last_chat_time': config.get('last_chat_time', ''), + 'nickname': config.get('nickname', '小智'), + 'modules': { + 'LLM': config.get('LLM', {}), + 'TTS': config.get('TTS', {}), + 'ASR': config.get('ASR', {}), + 'VAD': config.get('VAD', {}) + } + } + } + devices.append(device_info) + + return web.json_response({ + 'success': True, + 'data': devices, + 'message': '获取成功' + }) + + except Exception as e: + logger.error(f"Error getting private configs: {str(e)}", exc_info=True) + return web.json_response({ + 'success': False, + 'message': '获取配置失败' + }) + + async def save_device_config(self, request): + """保存单个设备的配置""" + try: + data = await request.json() + device_id = data.get('id') + config = data.get('config') + logger.info(f"Device config updated: {device_id} :\n{config}") + if not device_id or not config: + return web.json_response({ + 'success': False, + 'message': '设备ID和配置不能为空' + }) + + # 使用PrivateConfig处理配置保存 + private_config = PrivateConfig(device_id, self.config) + await private_config.load_or_create() + + success = await private_config.update_config( + config.get('selected_module'), + config.get('prompt'), + config.get('nickname', '小智') + ) + + + if not success: + raise Exception("Failed to update device config") + + return web.json_response({ + 'success': True, + 'message': '保存成功' + }) + + except Exception as e: + logger.error(f"Error saving device config: {str(e)}", exc_info=True) + return web.json_response({ + 'success': False, + 'message': f'保存配置失败: {str(e)}' + }) + + async def delete_device_config(self, request): + """删除设备配置""" + try: + data = await request.json() + device_id = data.get('device_id') + + # 使用PrivateConfig处理配置删除 + private_config = PrivateConfig(device_id, self.config) + success = await private_config.delete_config() + + if not success: + raise Exception("Failed to delete device config") + + return web.json_response({ + 'success': True, + 'message': '删除成功' + }) + + except Exception as e: + logger.error(f"Error deleting device config: {str(e)}", exc_info=True) + return web.json_response({ + 'success': False, + 'message': f'删除配置失败: {str(e)}' + }) diff --git a/manager/api/login.py b/manager/api/login.py new file mode 100644 index 00000000..9d6fc918 --- /dev/null +++ b/manager/api/login.py @@ -0,0 +1,49 @@ +import logging +from aiohttp import web +import datetime + +logger = logging.getLogger(__name__) + +class LoginHandler: + def __init__(self, config): + self.config = config + + async def handle_login(self, request): + """处理登录请求""" + try: + data = await request.json() + username = data.get('username') + password = data.get('password') + + if not username or not password: + logger.warning(f"Login attempt with empty credentials from {request.remote}") + return web.json_response({ + 'success': False, + 'message': '用户名和密码不能为空' + }) + + stored_user = self.config['get_user'](username) + if not stored_user or stored_user['password'] != self.config['hash_password'](password): + logger.warning(f"Failed login attempt for user {username} from {request.remote}") + return web.json_response({ + 'success': False, + 'message': '用户名或密码错误' + }) + + # 更新最后登录时间 + self.config['update_user'](username, { + 'last_login': datetime.datetime.now().isoformat() + }) + + logger.info(f"Successful login for user {username} from {request.remote}") + return web.json_response({ + 'success': True, + 'message': '登录成功' + }) + + except Exception as e: + logger.error(f"Login error: {str(e)}", exc_info=True) + return web.json_response({ + 'success': False, + 'message': '登录失败,请稍后重试' + }) diff --git a/manager/api/register.py b/manager/api/register.py new file mode 100644 index 00000000..6127b849 --- /dev/null +++ b/manager/api/register.py @@ -0,0 +1,51 @@ +import logging +from aiohttp import web +import datetime + +logger = logging.getLogger(__name__) + +class RegisterHandler: + def __init__(self, config): + self.config = config + + async def handle_register(self, request): + """处理注册请求""" + try: + data = await request.json() + username = data.get('username') + password = data.get('password') + + if not username or not password: + logger.warning(f"Registration attempt with empty credentials from {request.remote}") + return web.json_response({ + 'success': False, + 'message': '用户名和密码不能为空' + }) + + users = self.config.get('users', {}) + if username in users: + logger.warning(f"Registration attempt with existing username {username} from {request.remote}") + return web.json_response({ + 'success': False, + 'message': '用户名已存在' + }) + + # 存储新用户 + self.config['users'][username] = { + 'password': self.config['hash_password'](password), + 'created_at': datetime.datetime.now().isoformat() + } + self.config['save_user_data']() + + logger.info(f"Successfully registered new user {username} from {request.remote}") + return web.json_response({ + 'success': True, + 'message': '注册成功' + }) + + except Exception as e: + logger.error(f"Registration error: {str(e)}", exc_info=True) + return web.json_response({ + 'success': False, + 'message': '注册失败,请稍后重试' + }) diff --git a/manager/static/webui/assets/index-B6rJ-92F.css b/manager/static/webui/assets/index-B6rJ-92F.css new file mode 100644 index 00000000..1bd14188 --- /dev/null +++ b/manager/static/webui/assets/index-B6rJ-92F.css @@ -0,0 +1 @@ +*{margin:0;padding:0;box-sizing:border-box}:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color:#213547;background-color:#fff}a{text-decoration:none;color:inherit}a:hover{color:#535bf2}body{margin:0;padding:0;height:100%;width:100%;overflow:hidden;display:block}h1{font-size:3.2em;line-height:1.1}button{border:none;background:none;cursor:pointer}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}.card{padding:2em}#app{height:100%;width:100%;margin:0;padding:0;overflow:hidden;display:flex;flex-direction:column}.clearfix:after{content:"";display:table;clear:both}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.login-container[data-v-57b3cb9a]{max-width:420px;margin:20px auto;padding:40px 50px;border:none;border-radius:12px;background-color:#fff;box-shadow:0 8px 24px #0000001f;transition:all .3s ease}h1[data-v-57b3cb9a]{text-align:center;color:#2c3e50;font-size:28px;margin-bottom:25px;font-weight:600}.form-group[data-v-57b3cb9a]{margin-bottom:20px}label[data-v-57b3cb9a]{display:block;margin-bottom:8px;font-weight:500;color:#4a5568}input[data-v-57b3cb9a]{width:100%;padding:12px 16px;border:1px solid #e2e8f0;border-radius:8px;background-color:#f8fafc;transition:all .3s ease;font-size:15px}input[data-v-57b3cb9a]:focus{outline:none;border-color:#28a745;box-shadow:0 0 0 3px #28a74533}button[data-v-57b3cb9a]{width:100%;padding:12px;background-color:#28a745;color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:16px;font-weight:500;transition:all .3s ease;margin-top:10px}button[data-v-57b3cb9a]:hover{background-color:#218838;transform:translateY(-1px);box-shadow:0 4px 12px #28a74533}button[data-v-57b3cb9a]:disabled{opacity:.7;cursor:not-allowed}p[data-v-57b3cb9a]{margin-top:20px;color:#666;font-size:14px}a[data-v-57b3cb9a]{color:#28a745;text-decoration:none;font-weight:500;transition:color .3s ease}a[data-v-57b3cb9a]:hover{color:#218838;text-decoration:underline}.registration-container[data-v-4db13afa]{max-width:420px;margin:20px auto;padding:40px 50px;border:none;border-radius:12px;background-color:#fff;box-shadow:0 8px 24px #0000001f;transition:all .3s ease}h1[data-v-4db13afa]{text-align:center;color:#2c3e50;font-size:28px;margin-bottom:25px;font-weight:600}.form-group[data-v-4db13afa]{margin-bottom:20px}label[data-v-4db13afa]{display:block;margin-bottom:8px;font-weight:500;color:#4a5568}input[data-v-4db13afa]{width:100%;padding:12px 16px;border:1px solid #e2e8f0;border-radius:8px;background-color:#f8fafc;transition:all .3s ease;font-size:15px}input[data-v-4db13afa]:focus{outline:none;border-color:#007bff;box-shadow:0 0 0 3px #007bff33}button[data-v-4db13afa]{width:100%;padding:12px;background-color:#007bff;color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:16px;font-weight:500;transition:all .3s ease;margin-top:10px}button[data-v-4db13afa]:hover{background-color:#0056b3;transform:translateY(-1px);box-shadow:0 4px 12px #007bff33}button[data-v-4db13afa]:disabled{opacity:.7;cursor:not-allowed}p[data-v-4db13afa]{margin-top:20px;color:#666;font-size:14px}a[data-v-4db13afa]{color:#007bff;text-decoration:none;font-weight:500;transition:color .3s ease}a[data-v-4db13afa]:hover{color:#0056b3;text-decoration:underline}.header[data-v-4c9dea9d]{display:flex;align-items:center;height:60px;padding:0;background-color:#001529;color:#fff;width:100%;position:relative;left:0;right:0}.nav[data-v-4c9dea9d]{display:flex}.nav-item[data-v-4c9dea9d]{display:flex;align-items:center;padding:0 20px;height:60px;color:#fff;text-decoration:none;cursor:pointer;font-weight:700;transition:background-color .3s}.active[data-v-4c9dea9d]{background-color:#4178ee}.icon-device[data-v-4c9dea9d]{margin-right:8px}.switch[data-v-15d469c5]{position:relative;display:inline-flex;align-items:center;width:40px;height:20px;line-height:20px;background-color:#dcdfe6;border-radius:10px;cursor:pointer;transition:all .3s}.switch.is-checked[data-v-15d469c5]{background-color:#4178ee}.switch-core[data-v-15d469c5]{position:absolute;left:2px;top:2px;width:16px;height:16px;border-radius:50%;background-color:#fff;transition:all .3s}.switch.is-checked .switch-core[data-v-15d469c5]{left:22px}.device-card[data-v-6a843b91]{background:#fff;border-radius:4px;padding:20px;box-shadow:0 1px 3px #0000001a;margin-bottom:16px}.device-id[data-v-6a843b91]{font-size:18px;font-weight:700;margin-bottom:16px}.note[data-v-6a843b91]{color:#4178ee;font-size:14px;font-weight:400}.device-details p[data-v-6a843b91]{margin-bottom:12px}.ota-upgrade[data-v-6a843b91]{display:inline-flex;align-items:center;margin-left:16px}.device-actions[data-v-6a843b91]{display:flex;margin-top:20px}.action-btn[data-v-6a843b91]{padding:8px 16px;margin-right:12px;border:1px solid #ddd;border-radius:4px;background:#fff;cursor:pointer}.action-btn.primary[data-v-6a843b91]{background:#4178ee;color:#fff;border-color:#4178ee}.action-btn.danger[data-v-6a843b91]{background:#fff3f3;border-color:#ffa4a4;color:#f56c6c}.action-btn.danger[data-v-6a843b91]:hover{background:#fde2e2;border-color:#f56c6c}.device-modules[data-v-6a843b91]{margin-bottom:12px;color:#666}.module-item[data-v-6a843b91]{display:inline-block;margin-right:16px;padding:4px 8px;background:#f5f7fa;border-radius:4px;font-size:.9em}.device-role[data-v-6a843b91]{color:#666;margin-bottom:12px}.delete-container[data-v-6a843b91]{position:relative;margin-left:auto}.delete-warning[data-v-6a843b91]{position:absolute;bottom:calc(100% + 5px);left:50%;transform:translate(-50%);white-space:nowrap;background:#fff3f3;padding:4px 8px;border-radius:4px;border:1px solid #ffa4a4;font-size:12px;color:#f56c6c;display:none}.delete-container:hover .delete-warning[data-v-6a843b91]{display:block}.icon-delete[data-v-6a843b91]{margin-right:4px}.app[data-v-0024aee6]{min-height:100%;width:100%;display:flex;flex-direction:column;background-color:#f5f7fa}.header[data-v-0024aee6]{display:flex;align-items:center;height:60px;padding:0 20px;background-color:#001529;color:#fff}.logo[data-v-0024aee6]{font-size:20px;font-weight:700;margin-right:40px;cursor:pointer;transition:opacity .3s}.logo[data-v-0024aee6]:hover{opacity:.8}.nav[data-v-0024aee6]{display:flex}.nav-item[data-v-0024aee6]{display:flex;align-items:center;padding:0 20px;height:60px;color:#fff;text-decoration:none}.nav-item.active[data-v-0024aee6]{background-color:#4178ee}.icon-device[data-v-0024aee6]{margin-right:8px}.content[data-v-0024aee6]{flex:1;padding:20px;width:100%;max-width:1200px;margin:0 auto}.breadcrumb[data-v-0024aee6]{margin-bottom:20px;color:#666}.breadcrumb a[data-v-0024aee6]{color:#666;text-decoration:none}.action-bar[data-v-0024aee6]{margin-bottom:20px}.add-device-btn[data-v-0024aee6]{display:flex;align-items:center;padding:8px 16px;background:#fff;border:1px solid #ddd;border-radius:4px;cursor:pointer}.icon-plus[data-v-0024aee6]{margin-right:8px}.device-list[data-v-0024aee6]{display:flex;flex-direction:column;gap:16px}.device-card[data-v-0024aee6]{background:#fff;border-radius:4px;padding:20px;box-shadow:0 1px 3px #0000001a}.device-id[data-v-0024aee6]{font-size:18px;font-weight:700;margin-bottom:16px}.note[data-v-0024aee6]{color:#4178ee;font-size:14px;font-weight:400}.device-details p[data-v-0024aee6]{margin-bottom:12px}.ota-upgrade[data-v-0024aee6]{display:inline-flex;align-items:center;margin-left:16px}.device-actions[data-v-0024aee6]{display:flex;margin-top:20px}.action-btn[data-v-0024aee6]{padding:8px 16px;margin-right:12px;border:1px solid #ddd;border-radius:4px;background:#fff;cursor:pointer}.action-btn.primary[data-v-0024aee6]{background:#4178ee;color:#fff;border-color:#4178ee}.action-btn.danger[data-v-0024aee6]{color:#f56c6c}.empty-state[data-v-0024aee6]{display:flex;align-items:center;justify-content:center;min-height:300px;background:#fff;border-radius:8px;box-shadow:0 1px 3px #0000000d}.empty-message[data-v-0024aee6]{text-align:center;color:#666;padding:24px}.empty-message p[data-v-0024aee6]{margin:8px 0 0;font-size:14px;line-height:1.6}.icon-info[data-v-0024aee6]{display:inline-block;width:24px;height:24px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23999'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z'/%3E%3C/svg%3E");background-size:contain;opacity:.6}.main-container[data-v-c347f054]{min-height:100%;width:100%;display:flex;flex-direction:column}.landing-page[data-v-c347f054]{flex:1;width:100%;background-color:#f5f7fa;padding:40px 20px;overflow:hidden;display:flex;align-items:flex-start;justify-content:center;padding-top:15vh}.content[data-v-c347f054]{max-width:800px;text-align:center;padding:0 20px;margin:0 auto}.robot-image[data-v-c347f054]{margin-bottom:30px}.robot-image img[data-v-c347f054]{width:100px;height:auto}.slogan[data-v-c347f054]{font-size:22px;line-height:1.4;color:#333;margin-bottom:40px}.button-group[data-v-c347f054]{display:flex;flex-wrap:wrap;justify-content:center;gap:15px;margin:0 auto}.action-button[data-v-c347f054]{display:flex;align-items:center;justify-content:center;padding:12px 24px;border-radius:8px;border:1px solid #e0e0e0;background-color:#fff;color:#333;font-size:16px;cursor:pointer;transition:all .2s ease}.action-button[data-v-c347f054]:hover{transform:translateY(-2px);box-shadow:0 4px 12px #0000001a}.tutorial-button i[data-v-c347f054]:before{content:"📖";margin-right:8px}.github-button[data-v-c347f054]{background-color:#24292e;color:#fff;border-color:#24292e;margin:0 10px}.github-button i[data-v-c347f054]:before{content:"";font-family:"Font Awesome 5 Brands";margin-right:8px}.control-panel-button[data-v-c347f054]{background-color:#4178ee;color:#fff;border-color:#4178ee}.control-panel-button i[data-v-c347f054]:before{content:"🎛";margin-right:8px}@media (max-width: 600px){.button-group[data-v-c347f054]{flex-direction:column}.action-button[data-v-c347f054]{width:100%}}#app[data-v-c347f054]{margin-top:0}.app-container[data-v-0bc99910]{height:100%;display:flex;flex-direction:column;background-color:#f5f7fa}.breadcrumb[data-v-0bc99910]{padding:12px 24px;background-color:#f0f2f5}.main-content[data-v-0bc99910]{flex:1;max-width:1000px;margin:0 auto;padding:16px 24px;overflow:auto}.page-title[data-v-0bc99910]{font-size:18px;font-weight:700;margin-bottom:16px}.form-section[data-v-0bc99910]{background:#fff;border-radius:4px;padding:20px;box-shadow:0 1px 3px #0000001a}.form-group[data-v-0bc99910]{margin-bottom:16px}.form-group label[data-v-0bc99910]{display:block;margin-bottom:6px;font-weight:500}.form-input[data-v-0bc99910],.form-textarea[data-v-0bc99910],.voice-select[data-v-0bc99910]{width:100%;padding:8px 10px;border:1px solid #d9d9d9;border-radius:4px;font-size:14px}.form-textarea[data-v-0bc99910]{min-height:100px;max-height:200px;resize:vertical}.role-templates[data-v-0bc99910]{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.template-btn[data-v-0bc99910]{padding:6px 12px;border:1px solid #d9d9d9;border-radius:4px;background:#fff;cursor:pointer;font-size:13px}.voice-selector[data-v-0bc99910]{display:flex;flex-direction:column;gap:8px}.voice-player[data-v-0bc99910]{display:flex;align-items:center;gap:8px;padding:8px;background:#f9f9f9;border-radius:4px}.memory-tabs[data-v-0bc99910]{display:flex;margin-bottom:8px}.tab-btn[data-v-0bc99910]{padding:6px 12px;background:none;border:none;border-bottom:2px solid transparent;cursor:pointer;color:#666;font-size:13px}.model-select[data-v-0bc99910]{display:flex;flex-direction:column;gap:8px;padding:10px;border:1px solid #d9d9d9;border-radius:4px}.model-description[data-v-0bc99910]{color:#666;font-size:12px;line-height:1.4}.form-actions[data-v-0bc99910]{display:flex;gap:10px;margin-top:20px;padding-top:16px;border-top:1px solid #eee}.save-btn[data-v-0bc99910],.cancel-btn[data-v-0bc99910]{padding:6px 16px;border-radius:4px;font-size:14px}.form-note[data-v-0bc99910]{margin-top:12px;color:#666;font-size:12px}.char-count[data-v-0bc99910]{text-align:right;color:#999;font-size:12px;margin-top:2px}[data-v-0bc99910]::-webkit-scrollbar{width:6px;height:6px}[data-v-0bc99910]::-webkit-scrollbar-thumb{background:#ccc;border-radius:3px}[data-v-0bc99910]::-webkit-scrollbar-track{background:#f1f1f1}.refresh-btn[data-v-0bc99910]{padding:8px 16px;margin-right:12px;background:#fff;border:1px solid #ddd;border-radius:4px;cursor:pointer}.refresh-btn[data-v-0bc99910]:hover{background:#f5f5f5}.save-btn[data-v-0bc99910]{padding:8px 24px;border-radius:4px;font-size:14px;background:#4178ee;color:#fff;border:none;font-weight:500;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all .3s ease}.save-btn[data-v-0bc99910]:hover{background:#2856c8;transform:translateY(-1px);box-shadow:0 2px 4px #4178ee33}.save-btn[data-v-0bc99910]:active{transform:translateY(0);box-shadow:none}.icon-save[data-v-0bc99910]{display:inline-block;width:16px;height:16px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M17 3H5C3.89 3 3 3.9 3 5V19C3 20.1 3.89 21 5 21H19C20.1 21 21 20.1 21 19V7L17 3ZM12 19C10.34 19 9 17.66 9 16C9 14.34 10.34 13 12 13C13.66 13 15 14.34 15 16C15 17.66 13.66 19 12 19ZM15 9H5V5H15V9Z'/%3E%3C/svg%3E");background-size:contain}.footer[data-v-cf2abdb4]{text-align:center;padding:16px;color:#666;font-size:12px;background:#f0f2f5}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;width:100%;height:100%;display:flex;flex-direction:column}.app-content{flex:1;width:100%;display:flex;flex-direction:column}.auth-layout{align-items:center;justify-content:center;padding:20px}.main-layout{flex:1;width:100%;display:flex;flex-direction:column} diff --git a/manager/static/webui/assets/index-xClKUcGO.js b/manager/static/webui/assets/index-xClKUcGO.js new file mode 100644 index 00000000..e8e345ac --- /dev/null +++ b/manager/static/webui/assets/index-xClKUcGO.js @@ -0,0 +1,38 @@ +(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const o of i)if(o.type==="childList")for(const r of o.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function s(i){const o={};return i.integrity&&(o.integrity=i.integrity),i.referrerPolicy&&(o.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?o.credentials="include":i.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function n(i){if(i.ep)return;i.ep=!0;const o=s(i);fetch(i.href,o)}})();/** +* @vue/shared v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**//*! #__NO_SIDE_EFFECTS__ */function ks(e){const t=Object.create(null);for(const s of e.split(","))t[s]=1;return s=>s in t}const K={},ft=[],Me=()=>{},eo=()=>!1,fs=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),qs=e=>e.startsWith("onUpdate:"),fe=Object.assign,Qs=(e,t)=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)},to=Object.prototype.hasOwnProperty,F=(e,t)=>to.call(e,t),P=Array.isArray,ut=e=>jt(e)==="[object Map]",us=e=>jt(e)==="[object Set]",gn=e=>jt(e)==="[object Date]",U=e=>typeof e=="function",Y=e=>typeof e=="string",Pe=e=>typeof e=="symbol",W=e=>e!==null&&typeof e=="object",Wn=e=>(W(e)||U(e))&&U(e.then)&&U(e.catch),Jn=Object.prototype.toString,jt=e=>Jn.call(e),so=e=>jt(e).slice(8,-1),Xn=e=>jt(e)==="[object Object]",Ws=e=>Y(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,xt=ks(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),as=e=>{const t=Object.create(null);return s=>t[s]||(t[s]=e(s))},no=/-(\w)/g,ye=as(e=>e.replace(no,(t,s)=>s?s.toUpperCase():"")),io=/\B([A-Z])/g,it=as(e=>e.replace(io,"-$1").toLowerCase()),ds=as(e=>e.charAt(0).toUpperCase()+e.slice(1)),xs=as(e=>e?`on${ds(e)}`:""),ke=(e,t)=>!Object.is(e,t),Wt=(e,...t)=>{for(let s=0;s{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:n,value:s})},Gt=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let mn;const ps=()=>mn||(mn=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Js(e){if(P(e)){const t={};for(let s=0;s{if(s){const n=s.split(ro);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function st(e){let t="";if(Y(e))t=e;else if(P(e))for(let s=0;shs(s,t))}const Gn=e=>!!(e&&e.__v_isRef===!0),z=e=>Y(e)?e:e==null?"":P(e)||W(e)&&(e.toString===Jn||!U(e.toString))?Gn(e)?z(e.value):JSON.stringify(e,zn,2):String(e),zn=(e,t)=>Gn(t)?zn(e,t.value):ut(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((s,[n,i],o)=>(s[As(n,o)+" =>"]=i,s),{})}:us(t)?{[`Set(${t.size})`]:[...t.values()].map(s=>As(s))}:Pe(t)?As(t):W(t)&&!P(t)&&!Xn(t)?String(t):t,As=(e,t="")=>{var s;return Pe(e)?`Symbol(${(s=e.description)!=null?s:t})`:e};/** +* @vue/reactivity v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ge;class ho{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=ge,!t&&ge&&(this.index=(ge.scopes||(ge.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,s;if(this.scopes)for(t=0,s=this.scopes.length;t0)return;if(Tt){let t=Tt;for(Tt=void 0;t;){const s=t.next;t.next=void 0,t.flags&=-9,t=s}}let e;for(;At;){let t=At;for(At=void 0;t;){const s=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(n){e||(e=n)}t=s}}if(e)throw e}function ni(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function ii(e){let t,s=e.depsTail,n=s;for(;n;){const i=n.prevDep;n.version===-1?(n===s&&(s=i),Zs(n),mo(n)):t=n,n.dep.activeLink=n.prevActiveLink,n.prevActiveLink=void 0,n=i}e.deps=t,e.depsTail=s}function Ds(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(oi(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function oi(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Et))return;e.globalVersion=Et;const t=e.dep;if(e.flags|=2,t.version>0&&!e.isSSR&&e.deps&&!Ds(e)){e.flags&=-3;return}const s=Q,n=Se;Q=e,Se=!0;try{ni(e);const i=e.fn(e._value);(t.version===0||ke(i,e._value))&&(e._value=i,t.version++)}catch(i){throw t.version++,i}finally{Q=s,Se=n,ii(e),e.flags&=-3}}function Zs(e,t=!1){const{dep:s,prevSub:n,nextSub:i}=e;if(n&&(n.nextSub=i,e.prevSub=void 0),i&&(i.prevSub=n,e.nextSub=void 0),s.subs===e&&(s.subs=n,!n&&s.computed)){s.computed.flags&=-5;for(let o=s.computed.deps;o;o=o.nextDep)Zs(o,!0)}!t&&!--s.sc&&s.map&&s.map.delete(s.key)}function mo(e){const{prevDep:t,nextDep:s}=e;t&&(t.nextDep=s,e.prevDep=void 0),s&&(s.prevDep=t,e.nextDep=void 0)}let Se=!0;const ri=[];function qe(){ri.push(Se),Se=!1}function Qe(){const e=ri.pop();Se=e===void 0?!0:e}function vn(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const s=Q;Q=void 0;try{t()}finally{Q=s}}}let Et=0;class vo{constructor(t,s){this.sub=t,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Gs{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0}track(t){if(!Q||!Se||Q===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==Q)s=this.activeLink=new vo(Q,this),Q.deps?(s.prevDep=Q.depsTail,Q.depsTail.nextDep=s,Q.depsTail=s):Q.deps=Q.depsTail=s,li(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const n=s.nextDep;n.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=n),s.prevDep=Q.depsTail,s.nextDep=void 0,Q.depsTail.nextDep=s,Q.depsTail=s,Q.deps===s&&(Q.deps=n)}return s}trigger(t){this.version++,Et++,this.notify(t)}notify(t){Xs();try{for(let s=this.subs;s;s=s.prevSub)s.sub.notify()&&s.sub.dep.notify()}finally{Ys()}}}function li(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let n=t.deps;n;n=n.nextDep)li(n)}const s=e.dep.subs;s!==e&&(e.prevSub=s,s&&(s.nextSub=e)),e.dep.subs=e}}const Ls=new WeakMap,et=Symbol(""),js=Symbol(""),Rt=Symbol("");function ee(e,t,s){if(Se&&Q){let n=Ls.get(e);n||Ls.set(e,n=new Map);let i=n.get(s);i||(n.set(s,i=new Gs),i.map=n,i.key=s),i.track()}}function Ue(e,t,s,n,i,o){const r=Ls.get(e);if(!r){Et++;return}const l=c=>{c&&c.trigger()};if(Xs(),t==="clear")r.forEach(l);else{const c=P(e),d=c&&Ws(s);if(c&&s==="length"){const a=Number(n);r.forEach((h,v)=>{(v==="length"||v===Rt||!Pe(v)&&v>=a)&&l(h)})}else switch((s!==void 0||r.has(void 0))&&l(r.get(s)),d&&l(r.get(Rt)),t){case"add":c?d&&l(r.get("length")):(l(r.get(et)),ut(e)&&l(r.get(js)));break;case"delete":c||(l(r.get(et)),ut(e)&&l(r.get(js)));break;case"set":ut(e)&&l(r.get(et));break}}Ys()}function ot(e){const t=B(e);return t===e?t:(ee(t,"iterate",Rt),_e(e)?t:t.map(te))}function gs(e){return ee(e=B(e),"iterate",Rt),e}const bo={__proto__:null,[Symbol.iterator](){return Cs(this,Symbol.iterator,te)},concat(...e){return ot(this).concat(...e.map(t=>P(t)?ot(t):t))},entries(){return Cs(this,"entries",e=>(e[1]=te(e[1]),e))},every(e,t){return Le(this,"every",e,t,void 0,arguments)},filter(e,t){return Le(this,"filter",e,t,s=>s.map(te),arguments)},find(e,t){return Le(this,"find",e,t,te,arguments)},findIndex(e,t){return Le(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Le(this,"findLast",e,t,te,arguments)},findLastIndex(e,t){return Le(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Le(this,"forEach",e,t,void 0,arguments)},includes(...e){return Os(this,"includes",e)},indexOf(...e){return Os(this,"indexOf",e)},join(e){return ot(this).join(e)},lastIndexOf(...e){return Os(this,"lastIndexOf",e)},map(e,t){return Le(this,"map",e,t,void 0,arguments)},pop(){return yt(this,"pop")},push(...e){return yt(this,"push",e)},reduce(e,...t){return bn(this,"reduce",e,t)},reduceRight(e,...t){return bn(this,"reduceRight",e,t)},shift(){return yt(this,"shift")},some(e,t){return Le(this,"some",e,t,void 0,arguments)},splice(...e){return yt(this,"splice",e)},toReversed(){return ot(this).toReversed()},toSorted(e){return ot(this).toSorted(e)},toSpliced(...e){return ot(this).toSpliced(...e)},unshift(...e){return yt(this,"unshift",e)},values(){return Cs(this,"values",te)}};function Cs(e,t,s){const n=gs(e),i=n[t]();return n!==e&&!_e(e)&&(i._next=i.next,i.next=()=>{const o=i._next();return o.value&&(o.value=s(o.value)),o}),i}const _o=Array.prototype;function Le(e,t,s,n,i,o){const r=gs(e),l=r!==e&&!_e(e),c=r[t];if(c!==_o[t]){const h=c.apply(e,o);return l?te(h):h}let d=s;r!==e&&(l?d=function(h,v){return s.call(this,te(h),v,e)}:s.length>2&&(d=function(h,v){return s.call(this,h,v,e)}));const a=c.call(r,d,n);return l&&i?i(a):a}function bn(e,t,s,n){const i=gs(e);let o=s;return i!==e&&(_e(e)?s.length>3&&(o=function(r,l,c){return s.call(this,r,l,c,e)}):o=function(r,l,c){return s.call(this,r,te(l),c,e)}),i[t](o,...n)}function Os(e,t,s){const n=B(e);ee(n,"iterate",Rt);const i=n[t](...s);return(i===-1||i===!1)&&sn(s[0])?(s[0]=B(s[0]),n[t](...s)):i}function yt(e,t,s=[]){qe(),Xs();const n=B(e)[t].apply(e,s);return Ys(),Qe(),n}const yo=ks("__proto__,__v_isRef,__isVue"),ci=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Pe));function wo(e){Pe(e)||(e=String(e));const t=B(this);return ee(t,"has",e),t.hasOwnProperty(e)}class fi{constructor(t=!1,s=!1){this._isReadonly=t,this._isShallow=s}get(t,s,n){if(s==="__v_skip")return t.__v_skip;const i=this._isReadonly,o=this._isShallow;if(s==="__v_isReactive")return!i;if(s==="__v_isReadonly")return i;if(s==="__v_isShallow")return o;if(s==="__v_raw")return n===(i?o?Mo:pi:o?di:ai).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const r=P(t);if(!i){let c;if(r&&(c=bo[s]))return c;if(s==="hasOwnProperty")return wo}const l=Reflect.get(t,s,ne(t)?t:n);return(Pe(s)?ci.has(s):yo(s))||(i||ee(t,"get",s),o)?l:ne(l)?r&&Ws(s)?l:l.value:W(l)?i?hi(l):en(l):l}}class ui extends fi{constructor(t=!1){super(!1,t)}set(t,s,n,i){let o=t[s];if(!this._isShallow){const c=nt(o);if(!_e(n)&&!nt(n)&&(o=B(o),n=B(n)),!P(t)&&ne(o)&&!ne(n))return c?!1:(o.value=n,!0)}const r=P(t)&&Ws(s)?Number(s)e,Kt=e=>Reflect.getPrototypeOf(e);function Co(e,t,s){return function(...n){const i=this.__v_raw,o=B(i),r=ut(o),l=e==="entries"||e===Symbol.iterator&&r,c=e==="keys"&&r,d=i[e](...n),a=s?Us:t?Hs:te;return!t&&ee(o,"iterate",c?js:et),{next(){const{value:h,done:v}=d.next();return v?{value:h,done:v}:{value:l?[a(h[0]),a(h[1])]:a(h),done:v}},[Symbol.iterator](){return this}}}}function kt(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Oo(e,t){const s={get(i){const o=this.__v_raw,r=B(o),l=B(i);e||(ke(i,l)&&ee(r,"get",i),ee(r,"get",l));const{has:c}=Kt(r),d=t?Us:e?Hs:te;if(c.call(r,i))return d(o.get(i));if(c.call(r,l))return d(o.get(l));o!==r&&o.get(i)},get size(){const i=this.__v_raw;return!e&&ee(B(i),"iterate",et),Reflect.get(i,"size",i)},has(i){const o=this.__v_raw,r=B(o),l=B(i);return e||(ke(i,l)&&ee(r,"has",i),ee(r,"has",l)),i===l?o.has(i):o.has(i)||o.has(l)},forEach(i,o){const r=this,l=r.__v_raw,c=B(l),d=t?Us:e?Hs:te;return!e&&ee(c,"iterate",et),l.forEach((a,h)=>i.call(o,d(a),d(h),r))}};return fe(s,e?{add:kt("add"),set:kt("set"),delete:kt("delete"),clear:kt("clear")}:{add(i){!t&&!_e(i)&&!nt(i)&&(i=B(i));const o=B(this);return Kt(o).has.call(o,i)||(o.add(i),Ue(o,"add",i,i)),this},set(i,o){!t&&!_e(o)&&!nt(o)&&(o=B(o));const r=B(this),{has:l,get:c}=Kt(r);let d=l.call(r,i);d||(i=B(i),d=l.call(r,i));const a=c.call(r,i);return r.set(i,o),d?ke(o,a)&&Ue(r,"set",i,o):Ue(r,"add",i,o),this},delete(i){const o=B(this),{has:r,get:l}=Kt(o);let c=r.call(o,i);c||(i=B(i),c=r.call(o,i)),l&&l.call(o,i);const d=o.delete(i);return c&&Ue(o,"delete",i,void 0),d},clear(){const i=B(this),o=i.size!==0,r=i.clear();return o&&Ue(i,"clear",void 0,void 0),r}}),["keys","values","entries",Symbol.iterator].forEach(i=>{s[i]=Co(i,e,t)}),s}function zs(e,t){const s=Oo(e,t);return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(F(s,i)&&i in n?s:n,i,o)}const Io={get:zs(!1,!1)},Eo={get:zs(!1,!0)},Ro={get:zs(!0,!1)};const ai=new WeakMap,di=new WeakMap,pi=new WeakMap,Mo=new WeakMap;function Po(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Do(e){return e.__v_skip||!Object.isExtensible(e)?0:Po(so(e))}function en(e){return nt(e)?e:tn(e,!1,xo,Io,ai)}function Lo(e){return tn(e,!1,To,Eo,di)}function hi(e){return tn(e,!0,Ao,Ro,pi)}function tn(e,t,s,n,i){if(!W(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const o=i.get(e);if(o)return o;const r=Do(e);if(r===0)return e;const l=new Proxy(e,r===2?n:s);return i.set(e,l),l}function at(e){return nt(e)?at(e.__v_raw):!!(e&&e.__v_isReactive)}function nt(e){return!!(e&&e.__v_isReadonly)}function _e(e){return!!(e&&e.__v_isShallow)}function sn(e){return e?!!e.__v_raw:!1}function B(e){const t=e&&e.__v_raw;return t?B(t):e}function jo(e){return!F(e,"__v_skip")&&Object.isExtensible(e)&&Yn(e,"__v_skip",!0),e}const te=e=>W(e)?en(e):e,Hs=e=>W(e)?hi(e):e;function ne(e){return e?e.__v_isRef===!0:!1}function be(e){return Uo(e,!1)}function Uo(e,t){return ne(e)?e:new Ho(e,t)}class Ho{constructor(t,s){this.dep=new Gs,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=s?t:B(t),this._value=s?t:te(t),this.__v_isShallow=s}get value(){return this.dep.track(),this._value}set value(t){const s=this._rawValue,n=this.__v_isShallow||_e(t)||nt(t);t=n?t:B(t),ke(t,s)&&(this._rawValue=t,this._value=n?t:te(t),this.dep.trigger())}}function gi(e){return ne(e)?e.value:e}const Bo={get:(e,t,s)=>t==="__v_raw"?e:gi(Reflect.get(e,t,s)),set:(e,t,s,n)=>{const i=e[t];return ne(i)&&!ne(s)?(i.value=s,!0):Reflect.set(e,t,s,n)}};function mi(e){return at(e)?e:new Proxy(e,Bo)}class Fo{constructor(t,s,n){this.fn=t,this.setter=s,this._value=void 0,this.dep=new Gs(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Et-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!s,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&Q!==this)return si(this,!0),!0}get value(){const t=this.dep.track();return oi(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function No(e,t,s=!1){let n,i;return U(e)?n=e:(n=e.get,i=e.set),new Fo(n,i,s)}const qt={},zt=new WeakMap;let Ge;function Vo(e,t=!1,s=Ge){if(s){let n=zt.get(s);n||zt.set(s,n=[]),n.push(e)}}function $o(e,t,s=K){const{immediate:n,deep:i,once:o,scheduler:r,augmentJob:l,call:c}=s,d=I=>i?I:_e(I)||i===!1||i===0?He(I,1):He(I);let a,h,v,C,E=!1,j=!1;if(ne(e)?(h=()=>e.value,E=_e(e)):at(e)?(h=()=>d(e),E=!0):P(e)?(j=!0,E=e.some(I=>at(I)||_e(I)),h=()=>e.map(I=>{if(ne(I))return I.value;if(at(I))return d(I);if(U(I))return c?c(I,2):I()})):U(e)?t?h=c?()=>c(e,2):e:h=()=>{if(v){qe();try{v()}finally{Qe()}}const I=Ge;Ge=a;try{return c?c(e,3,[C]):e(C)}finally{Ge=I}}:h=Me,t&&i){const I=h,O=i===!0?1/0:i;h=()=>He(I(),O)}const Z=go(),V=()=>{a.stop(),Z&&Z.active&&Qs(Z.effects,a)};if(o&&t){const I=t;t=(...O)=>{I(...O),V()}}let D=j?new Array(e.length).fill(qt):qt;const x=I=>{if(!(!(a.flags&1)||!a.dirty&&!I))if(t){const O=a.run();if(i||E||(j?O.some((ue,xe)=>ke(ue,D[xe])):ke(O,D))){v&&v();const ue=Ge;Ge=a;try{const xe=[O,D===qt?void 0:j&&D[0]===qt?[]:D,C];c?c(t,3,xe):t(...xe),D=O}finally{Ge=ue}}}else a.run()};return l&&l(x),a=new ei(h),a.scheduler=r?()=>r(x,!1):x,C=I=>Vo(I,!1,a),v=a.onStop=()=>{const I=zt.get(a);if(I){if(c)c(I,4);else for(const O of I)O();zt.delete(a)}},t?n?x(!0):D=a.run():r?r(x.bind(null,!0),!0):a.run(),V.pause=a.pause.bind(a),V.resume=a.resume.bind(a),V.stop=V,V}function He(e,t=1/0,s){if(t<=0||!W(e)||e.__v_skip||(s=s||new Set,s.has(e)))return e;if(s.add(e),t--,ne(e))He(e.value,t,s);else if(P(e))for(let n=0;n{He(n,t,s)});else if(Xn(e)){for(const n in e)He(e[n],t,s);for(const n of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,n)&&He(e[n],t,s)}return e}/** +* @vue/runtime-core v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Ut(e,t,s,n){try{return n?e(...n):e()}catch(i){ms(i,t,s)}}function De(e,t,s,n){if(U(e)){const i=Ut(e,t,s,n);return i&&Wn(i)&&i.catch(o=>{ms(o,t,s)}),i}if(P(e)){const i=[];for(let o=0;o>>1,i=re[n],o=Mt(i);o=Mt(s)?re.push(e):re.splice(ko(t),0,e),e.flags|=1,_i()}}function _i(){es||(es=vi.then(wi))}function qo(e){P(e)?dt.push(...e):Ve&&e.id===-1?Ve.splice(rt+1,0,e):e.flags&1||(dt.push(e),e.flags|=1),_i()}function _n(e,t,s=Ee+1){for(;sMt(s)-Mt(n));if(dt.length=0,Ve){Ve.push(...t);return}for(Ve=t,rt=0;rte.id==null?e.flags&2?-1:1/0:e.id;function wi(e){try{for(Ee=0;Ee{n._d&&En(-1);const o=ts(t);let r;try{r=e(...i)}finally{ts(o),n._d&&En(1)}return r};return n._n=!0,n._c=!0,n._d=!0,n}function we(e,t){if(me===null)return e;const s=ys(me),n=e.dirs||(e.dirs=[]);for(let i=0;ie.__isTeleport;function on(e,t){e.shapeFlag&6&&e.component?(e.transition=t,on(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function xi(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function ns(e,t,s,n,i=!1){if(P(e)){e.forEach((E,j)=>ns(E,t&&(P(t)?t[j]:t),s,n,i));return}if(Ct(n)&&!i){n.shapeFlag&512&&n.type.__asyncResolved&&n.component.subTree.component&&ns(e,t,s,n.component.subTree);return}const o=n.shapeFlag&4?ys(n.component):n.el,r=i?null:o,{i:l,r:c}=e,d=t&&t.r,a=l.refs===K?l.refs={}:l.refs,h=l.setupState,v=B(h),C=h===K?()=>!1:E=>F(v,E);if(d!=null&&d!==c&&(Y(d)?(a[d]=null,C(d)&&(h[d]=null)):ne(d)&&(d.value=null)),U(c))Ut(c,l,12,[r,a]);else{const E=Y(c),j=ne(c);if(E||j){const Z=()=>{if(e.f){const V=E?C(c)?h[c]:a[c]:c.value;i?P(V)&&Qs(V,o):P(V)?V.includes(o)||V.push(o):E?(a[c]=[o],C(c)&&(h[c]=a[c])):(c.value=[o],e.k&&(a[e.k]=c.value))}else E?(a[c]=r,C(c)&&(h[c]=r)):j&&(c.value=r,e.k&&(a[e.k]=r))};r?(Z.id=-1,he(Z,s)):Z()}}}ps().requestIdleCallback;ps().cancelIdleCallback;const Ct=e=>!!e.type.__asyncLoader,Ai=e=>e.type.__isKeepAlive;function Jo(e,t){Ti(e,"a",t)}function Xo(e,t){Ti(e,"da",t)}function Ti(e,t,s=se){const n=e.__wdc||(e.__wdc=()=>{let i=s;for(;i;){if(i.isDeactivated)return;i=i.parent}return e()});if(vs(t,n,s),s){let i=s.parent;for(;i&&i.parent;)Ai(i.parent.vnode)&&Yo(n,t,s,i),i=i.parent}}function Yo(e,t,s,n){const i=vs(t,e,n,!0);Ci(()=>{Qs(n[t],i)},s)}function vs(e,t,s=se,n=!1){if(s){const i=s[e]||(s[e]=[]),o=t.__weh||(t.__weh=(...r)=>{qe();const l=Ht(s),c=De(t,s,e,r);return l(),Qe(),c});return n?i.unshift(o):i.push(o),o}}const Be=e=>(t,s=se)=>{(!Lt||e==="sp")&&vs(e,(...n)=>t(...n),s)},Zo=Be("bm"),rn=Be("m"),Go=Be("bu"),zo=Be("u"),er=Be("bum"),Ci=Be("um"),tr=Be("sp"),sr=Be("rtg"),nr=Be("rtc");function ir(e,t=se){vs("ec",e,t)}const or="components";function $e(e,t){return lr(or,e,!0,t)||e}const rr=Symbol.for("v-ndc");function lr(e,t,s=!0,n=!1){const i=me||se;if(i){const o=i.type;{const l=Jr(o,!1);if(l&&(l===t||l===ye(t)||l===ds(ye(t))))return o}const r=yn(i[e]||o[e],t)||yn(i.appContext[e],t);return!r&&n?o:r}}function yn(e,t){return e&&(e[t]||e[ye(t)]||e[ds(ye(t))])}function lt(e,t,s,n){let i;const o=s,r=P(e);if(r||Y(e)){const l=r&&at(e);let c=!1;l&&(c=!_e(e),e=gs(e)),i=new Array(e.length);for(let d=0,a=e.length;dt(l,c,void 0,o));else{const l=Object.keys(e);i=new Array(l.length);for(let c=0,d=l.length;ce?Ji(e)?ys(e):Bs(e.parent):null,Ot=fe(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Bs(e.parent),$root:e=>Bs(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Ii(e),$forceUpdate:e=>e.f||(e.f=()=>{nn(e.update)}),$nextTick:e=>e.n||(e.n=bi.bind(e.proxy)),$watch:e=>Er.bind(e)}),Is=(e,t)=>e!==K&&!e.__isScriptSetup&&F(e,t),cr={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:s,setupState:n,data:i,props:o,accessCache:r,type:l,appContext:c}=e;let d;if(t[0]!=="$"){const C=r[t];if(C!==void 0)switch(C){case 1:return n[t];case 2:return i[t];case 4:return s[t];case 3:return o[t]}else{if(Is(n,t))return r[t]=1,n[t];if(i!==K&&F(i,t))return r[t]=2,i[t];if((d=e.propsOptions[0])&&F(d,t))return r[t]=3,o[t];if(s!==K&&F(s,t))return r[t]=4,s[t];Fs&&(r[t]=0)}}const a=Ot[t];let h,v;if(a)return t==="$attrs"&&ee(e.attrs,"get",""),a(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(s!==K&&F(s,t))return r[t]=4,s[t];if(v=c.config.globalProperties,F(v,t))return v[t]},set({_:e},t,s){const{data:n,setupState:i,ctx:o}=e;return Is(i,t)?(i[t]=s,!0):n!==K&&F(n,t)?(n[t]=s,!0):F(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=s,!0)},has({_:{data:e,setupState:t,accessCache:s,ctx:n,appContext:i,propsOptions:o}},r){let l;return!!s[r]||e!==K&&F(e,r)||Is(t,r)||(l=o[0])&&F(l,r)||F(n,r)||F(Ot,r)||F(i.config.globalProperties,r)},defineProperty(e,t,s){return s.get!=null?e._.accessCache[t]=0:F(s,"value")&&this.set(e,t,s.value,null),Reflect.defineProperty(e,t,s)}};function wn(e){return P(e)?e.reduce((t,s)=>(t[s]=null,t),{}):e}let Fs=!0;function fr(e){const t=Ii(e),s=e.proxy,n=e.ctx;Fs=!1,t.beforeCreate&&Sn(t.beforeCreate,e,"bc");const{data:i,computed:o,methods:r,watch:l,provide:c,inject:d,created:a,beforeMount:h,mounted:v,beforeUpdate:C,updated:E,activated:j,deactivated:Z,beforeDestroy:V,beforeUnmount:D,destroyed:x,unmounted:I,render:O,renderTracked:ue,renderTriggered:xe,errorCaptured:Ne,serverPrefetch:Bt,expose:We,inheritAttrs:mt,components:Ft,directives:Nt,filters:ws}=t;if(d&&ur(d,n,null),r)for(const X in r){const k=r[X];U(k)&&(n[X]=k.bind(s))}if(i){const X=i.call(s,s);W(X)&&(e.data=en(X))}if(Fs=!0,o)for(const X in o){const k=o[X],Je=U(k)?k.bind(s,s):U(k.get)?k.get.bind(s,s):Me,Vt=!U(k)&&U(k.set)?k.set.bind(s):Me,Xe=Yi({get:Je,set:Vt});Object.defineProperty(n,X,{enumerable:!0,configurable:!0,get:()=>Xe.value,set:Ae=>Xe.value=Ae})}if(l)for(const X in l)Oi(l[X],n,s,X);if(c){const X=U(c)?c.call(s):c;Reflect.ownKeys(X).forEach(k=>{mr(k,X[k])})}a&&Sn(a,e,"c");function ie(X,k){P(k)?k.forEach(Je=>X(Je.bind(s))):k&&X(k.bind(s))}if(ie(Zo,h),ie(rn,v),ie(Go,C),ie(zo,E),ie(Jo,j),ie(Xo,Z),ie(ir,Ne),ie(nr,ue),ie(sr,xe),ie(er,D),ie(Ci,I),ie(tr,Bt),P(We))if(We.length){const X=e.exposed||(e.exposed={});We.forEach(k=>{Object.defineProperty(X,k,{get:()=>s[k],set:Je=>s[k]=Je})})}else e.exposed||(e.exposed={});O&&e.render===Me&&(e.render=O),mt!=null&&(e.inheritAttrs=mt),Ft&&(e.components=Ft),Nt&&(e.directives=Nt),Bt&&xi(e)}function ur(e,t,s=Me){P(e)&&(e=Ns(e));for(const n in e){const i=e[n];let o;W(i)?"default"in i?o=Jt(i.from||n,i.default,!0):o=Jt(i.from||n):o=Jt(i),ne(o)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>o.value,set:r=>o.value=r}):t[n]=o}}function Sn(e,t,s){De(P(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,s)}function Oi(e,t,s,n){let i=n.includes(".")?$i(s,n):()=>s[n];if(Y(e)){const o=t[e];U(o)&&Xt(i,o)}else if(U(e))Xt(i,e.bind(s));else if(W(e))if(P(e))e.forEach(o=>Oi(o,t,s,n));else{const o=U(e.handler)?e.handler.bind(s):t[e.handler];U(o)&&Xt(i,o,e)}}function Ii(e){const t=e.type,{mixins:s,extends:n}=t,{mixins:i,optionsCache:o,config:{optionMergeStrategies:r}}=e.appContext,l=o.get(t);let c;return l?c=l:!i.length&&!s&&!n?c=t:(c={},i.length&&i.forEach(d=>is(c,d,r,!0)),is(c,t,r)),W(t)&&o.set(t,c),c}function is(e,t,s,n=!1){const{mixins:i,extends:o}=t;o&&is(e,o,s,!0),i&&i.forEach(r=>is(e,r,s,!0));for(const r in t)if(!(n&&r==="expose")){const l=ar[r]||s&&s[r];e[r]=l?l(e[r],t[r]):t[r]}return e}const ar={data:xn,props:An,emits:An,methods:St,computed:St,beforeCreate:oe,created:oe,beforeMount:oe,mounted:oe,beforeUpdate:oe,updated:oe,beforeDestroy:oe,beforeUnmount:oe,destroyed:oe,unmounted:oe,activated:oe,deactivated:oe,errorCaptured:oe,serverPrefetch:oe,components:St,directives:St,watch:pr,provide:xn,inject:dr};function xn(e,t){return t?e?function(){return fe(U(e)?e.call(this,this):e,U(t)?t.call(this,this):t)}:t:e}function dr(e,t){return St(Ns(e),Ns(t))}function Ns(e){if(P(e)){const t={};for(let s=0;s1)return s&&U(t)?t.call(n&&n.proxy):t}}const Ri={},Mi=()=>Object.create(Ri),Pi=e=>Object.getPrototypeOf(e)===Ri;function vr(e,t,s,n=!1){const i={},o=Mi();e.propsDefaults=Object.create(null),Di(e,t,i,o);for(const r in e.propsOptions[0])r in i||(i[r]=void 0);s?e.props=n?i:Lo(i):e.type.props?e.props=i:e.props=o,e.attrs=o}function br(e,t,s,n){const{props:i,attrs:o,vnode:{patchFlag:r}}=e,l=B(i),[c]=e.propsOptions;let d=!1;if((n||r>0)&&!(r&16)){if(r&8){const a=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[v,C]=Li(h,t,!0);fe(r,v),C&&l.push(...C)};!s&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}if(!o&&!c)return W(e)&&n.set(e,ft),ft;if(P(o))for(let a=0;ae[0]==="_"||e==="$stable",ln=e=>P(e)?e.map(Re):[Re(e)],yr=(e,t,s)=>{if(t._n)return t;const n=ss((...i)=>ln(t(...i)),s);return n._c=!1,n},Ui=(e,t,s)=>{const n=e._ctx;for(const i in e){if(ji(i))continue;const o=e[i];if(U(o))t[i]=yr(i,o,n);else if(o!=null){const r=ln(o);t[i]=()=>r}}},Hi=(e,t)=>{const s=ln(t);e.slots.default=()=>s},Bi=(e,t,s)=>{for(const n in t)(s||n!=="_")&&(e[n]=t[n])},wr=(e,t,s)=>{const n=e.slots=Mi();if(e.vnode.shapeFlag&32){const i=t._;i?(Bi(n,t,s),s&&Yn(n,"_",i,!0)):Ui(t,n)}else t&&Hi(e,t)},Sr=(e,t,s)=>{const{vnode:n,slots:i}=e;let o=!0,r=K;if(n.shapeFlag&32){const l=t._;l?s&&l===1?o=!1:Bi(i,t,s):(o=!t.$stable,Ui(t,i)),r=t}else t&&(Hi(e,t),r={default:1});if(o)for(const l in i)!ji(l)&&r[l]==null&&delete i[l]},he=Ur;function xr(e){return Ar(e)}function Ar(e,t){const s=ps();s.__VUE__=!0;const{insert:n,remove:i,patchProp:o,createElement:r,createText:l,createComment:c,setText:d,setElementText:a,parentNode:h,nextSibling:v,setScopeId:C=Me,insertStaticContent:E}=e,j=(f,u,p,_=null,m=null,b=null,A=void 0,S=null,w=!!u.dynamicChildren)=>{if(f===u)return;f&&!wt(f,u)&&(_=$t(f),Ae(f,m,b,!0),f=null),u.patchFlag===-2&&(w=!1,u.dynamicChildren=null);const{type:y,ref:M,shapeFlag:T}=u;switch(y){case _s:Z(f,u,p,_);break;case Pt:V(f,u,p,_);break;case Rs:f==null&&D(u,p,_,A);break;case le:Ft(f,u,p,_,m,b,A,S,w);break;default:T&1?O(f,u,p,_,m,b,A,S,w):T&6?Nt(f,u,p,_,m,b,A,S,w):(T&64||T&128)&&y.process(f,u,p,_,m,b,A,S,w,bt)}M!=null&&m&&ns(M,f&&f.ref,b,u||f,!u)},Z=(f,u,p,_)=>{if(f==null)n(u.el=l(u.children),p,_);else{const m=u.el=f.el;u.children!==f.children&&d(m,u.children)}},V=(f,u,p,_)=>{f==null?n(u.el=c(u.children||""),p,_):u.el=f.el},D=(f,u,p,_)=>{[f.el,f.anchor]=E(f.children,u,p,_,f.el,f.anchor)},x=({el:f,anchor:u},p,_)=>{let m;for(;f&&f!==u;)m=v(f),n(f,p,_),f=m;n(u,p,_)},I=({el:f,anchor:u})=>{let p;for(;f&&f!==u;)p=v(f),i(f),f=p;i(u)},O=(f,u,p,_,m,b,A,S,w)=>{u.type==="svg"?A="svg":u.type==="math"&&(A="mathml"),f==null?ue(u,p,_,m,b,A,S,w):Bt(f,u,m,b,A,S,w)},ue=(f,u,p,_,m,b,A,S)=>{let w,y;const{props:M,shapeFlag:T,transition:R,dirs:L}=f;if(w=f.el=r(f.type,b,M&&M.is,M),T&8?a(w,f.children):T&16&&Ne(f.children,w,null,_,m,Es(f,b),A,S),L&&Ye(f,null,_,"created"),xe(w,f,f.scopeId,A,_),M){for(const q in M)q!=="value"&&!xt(q)&&o(w,q,null,M[q],b,_);"value"in M&&o(w,"value",null,M.value,b),(y=M.onVnodeBeforeMount)&&Ie(y,_,f)}L&&Ye(f,null,_,"beforeMount");const H=Tr(m,R);H&&R.beforeEnter(w),n(w,u,p),((y=M&&M.onVnodeMounted)||H||L)&&he(()=>{y&&Ie(y,_,f),H&&R.enter(w),L&&Ye(f,null,_,"mounted")},m)},xe=(f,u,p,_,m)=>{if(p&&C(f,p),_)for(let b=0;b<_.length;b++)C(f,_[b]);if(m){let b=m.subTree;if(u===b||ki(b.type)&&(b.ssContent===u||b.ssFallback===u)){const A=m.vnode;xe(f,A,A.scopeId,A.slotScopeIds,m.parent)}}},Ne=(f,u,p,_,m,b,A,S,w=0)=>{for(let y=w;y{const S=u.el=f.el;let{patchFlag:w,dynamicChildren:y,dirs:M}=u;w|=f.patchFlag&16;const T=f.props||K,R=u.props||K;let L;if(p&&Ze(p,!1),(L=R.onVnodeBeforeUpdate)&&Ie(L,p,u,f),M&&Ye(u,f,p,"beforeUpdate"),p&&Ze(p,!0),(T.innerHTML&&R.innerHTML==null||T.textContent&&R.textContent==null)&&a(S,""),y?We(f.dynamicChildren,y,S,p,_,Es(u,m),b):A||k(f,u,S,null,p,_,Es(u,m),b,!1),w>0){if(w&16)mt(S,T,R,p,m);else if(w&2&&T.class!==R.class&&o(S,"class",null,R.class,m),w&4&&o(S,"style",T.style,R.style,m),w&8){const H=u.dynamicProps;for(let q=0;q{L&&Ie(L,p,u,f),M&&Ye(u,f,p,"updated")},_)},We=(f,u,p,_,m,b,A)=>{for(let S=0;S{if(u!==p){if(u!==K)for(const b in u)!xt(b)&&!(b in p)&&o(f,b,u[b],null,m,_);for(const b in p){if(xt(b))continue;const A=p[b],S=u[b];A!==S&&b!=="value"&&o(f,b,S,A,m,_)}"value"in p&&o(f,"value",u.value,p.value,m)}},Ft=(f,u,p,_,m,b,A,S,w)=>{const y=u.el=f?f.el:l(""),M=u.anchor=f?f.anchor:l("");let{patchFlag:T,dynamicChildren:R,slotScopeIds:L}=u;L&&(S=S?S.concat(L):L),f==null?(n(y,p,_),n(M,p,_),Ne(u.children||[],p,M,m,b,A,S,w)):T>0&&T&64&&R&&f.dynamicChildren?(We(f.dynamicChildren,R,p,m,b,A,S),(u.key!=null||m&&u===m.subTree)&&Fi(f,u,!0)):k(f,u,p,M,m,b,A,S,w)},Nt=(f,u,p,_,m,b,A,S,w)=>{u.slotScopeIds=S,f==null?u.shapeFlag&512?m.ctx.activate(u,p,_,A,w):ws(u,p,_,m,b,A,w):un(f,u,w)},ws=(f,u,p,_,m,b,A)=>{const S=f.component=Kr(f,_,m);if(Ai(f)&&(S.ctx.renderer=bt),kr(S,!1,A),S.asyncDep){if(m&&m.registerDep(S,ie,A),!f.el){const w=S.subTree=ce(Pt);V(null,w,u,p)}}else ie(S,f,u,p,m,b,A)},un=(f,u,p)=>{const _=u.component=f.component;if(Lr(f,u,p))if(_.asyncDep&&!_.asyncResolved){X(_,u,p);return}else _.next=u,_.update();else u.el=f.el,_.vnode=u},ie=(f,u,p,_,m,b,A)=>{const S=()=>{if(f.isMounted){let{next:T,bu:R,u:L,parent:H,vnode:q}=f;{const Ce=Ni(f);if(Ce){T&&(T.el=q.el,X(f,T,A)),Ce.asyncDep.then(()=>{f.isUnmounted||S()});return}}let $=T,de;Ze(f,!1),T?(T.el=q.el,X(f,T,A)):T=q,R&&Wt(R),(de=T.props&&T.props.onVnodeBeforeUpdate)&&Ie(de,H,T,q),Ze(f,!0);const ae=On(f),Te=f.subTree;f.subTree=ae,j(Te,ae,h(Te.el),$t(Te),f,m,b),T.el=ae.el,$===null&&jr(f,ae.el),L&&he(L,m),(de=T.props&&T.props.onVnodeUpdated)&&he(()=>Ie(de,H,T,q),m)}else{let T;const{el:R,props:L}=u,{bm:H,m:q,parent:$,root:de,type:ae}=f,Te=Ct(u);Ze(f,!1),H&&Wt(H),!Te&&(T=L&&L.onVnodeBeforeMount)&&Ie(T,$,u),Ze(f,!0);{de.ce&&de.ce._injectChildStyle(ae);const Ce=f.subTree=On(f);j(null,Ce,p,_,f,m,b),u.el=Ce.el}if(q&&he(q,m),!Te&&(T=L&&L.onVnodeMounted)){const Ce=u;he(()=>Ie(T,$,Ce),m)}(u.shapeFlag&256||$&&Ct($.vnode)&&$.vnode.shapeFlag&256)&&f.a&&he(f.a,m),f.isMounted=!0,u=p=_=null}};f.scope.on();const w=f.effect=new ei(S);f.scope.off();const y=f.update=w.run.bind(w),M=f.job=w.runIfDirty.bind(w);M.i=f,M.id=f.uid,w.scheduler=()=>nn(M),Ze(f,!0),y()},X=(f,u,p)=>{u.component=f;const _=f.vnode.props;f.vnode=u,f.next=null,br(f,u.props,_,p),Sr(f,u.children,p),qe(),_n(f),Qe()},k=(f,u,p,_,m,b,A,S,w=!1)=>{const y=f&&f.children,M=f?f.shapeFlag:0,T=u.children,{patchFlag:R,shapeFlag:L}=u;if(R>0){if(R&128){Vt(y,T,p,_,m,b,A,S,w);return}else if(R&256){Je(y,T,p,_,m,b,A,S,w);return}}L&8?(M&16&&vt(y,m,b),T!==y&&a(p,T)):M&16?L&16?Vt(y,T,p,_,m,b,A,S,w):vt(y,m,b,!0):(M&8&&a(p,""),L&16&&Ne(T,p,_,m,b,A,S,w))},Je=(f,u,p,_,m,b,A,S,w)=>{f=f||ft,u=u||ft;const y=f.length,M=u.length,T=Math.min(y,M);let R;for(R=0;RM?vt(f,m,b,!0,!1,T):Ne(u,p,_,m,b,A,S,w,T)},Vt=(f,u,p,_,m,b,A,S,w)=>{let y=0;const M=u.length;let T=f.length-1,R=M-1;for(;y<=T&&y<=R;){const L=f[y],H=u[y]=w?Ke(u[y]):Re(u[y]);if(wt(L,H))j(L,H,p,null,m,b,A,S,w);else break;y++}for(;y<=T&&y<=R;){const L=f[T],H=u[R]=w?Ke(u[R]):Re(u[R]);if(wt(L,H))j(L,H,p,null,m,b,A,S,w);else break;T--,R--}if(y>T){if(y<=R){const L=R+1,H=LR)for(;y<=T;)Ae(f[y],m,b,!0),y++;else{const L=y,H=y,q=new Map;for(y=H;y<=R;y++){const pe=u[y]=w?Ke(u[y]):Re(u[y]);pe.key!=null&&q.set(pe.key,y)}let $,de=0;const ae=R-H+1;let Te=!1,Ce=0;const _t=new Array(ae);for(y=0;y=ae){Ae(pe,m,b,!0);continue}let Oe;if(pe.key!=null)Oe=q.get(pe.key);else for($=H;$<=R;$++)if(_t[$-H]===0&&wt(pe,u[$])){Oe=$;break}Oe===void 0?Ae(pe,m,b,!0):(_t[Oe-H]=y+1,Oe>=Ce?Ce=Oe:Te=!0,j(pe,u[Oe],p,null,m,b,A,S,w),de++)}const pn=Te?Cr(_t):ft;for($=pn.length-1,y=ae-1;y>=0;y--){const pe=H+y,Oe=u[pe],hn=pe+1{const{el:b,type:A,transition:S,children:w,shapeFlag:y}=f;if(y&6){Xe(f.component.subTree,u,p,_);return}if(y&128){f.suspense.move(u,p,_);return}if(y&64){A.move(f,u,p,bt);return}if(A===le){n(b,u,p);for(let T=0;TS.enter(b),m);else{const{leave:T,delayLeave:R,afterLeave:L}=S,H=()=>n(b,u,p),q=()=>{T(b,()=>{H(),L&&L()})};R?R(b,H,q):q()}else n(b,u,p)},Ae=(f,u,p,_=!1,m=!1)=>{const{type:b,props:A,ref:S,children:w,dynamicChildren:y,shapeFlag:M,patchFlag:T,dirs:R,cacheIndex:L}=f;if(T===-2&&(m=!1),S!=null&&ns(S,null,p,f,!0),L!=null&&(u.renderCache[L]=void 0),M&256){u.ctx.deactivate(f);return}const H=M&1&&R,q=!Ct(f);let $;if(q&&($=A&&A.onVnodeBeforeUnmount)&&Ie($,u,f),M&6)zi(f.component,p,_);else{if(M&128){f.suspense.unmount(p,_);return}H&&Ye(f,null,u,"beforeUnmount"),M&64?f.type.remove(f,u,p,bt,_):y&&!y.hasOnce&&(b!==le||T>0&&T&64)?vt(y,u,p,!1,!0):(b===le&&T&384||!m&&M&16)&&vt(w,u,p),_&&an(f)}(q&&($=A&&A.onVnodeUnmounted)||H)&&he(()=>{$&&Ie($,u,f),H&&Ye(f,null,u,"unmounted")},p)},an=f=>{const{type:u,el:p,anchor:_,transition:m}=f;if(u===le){Gi(p,_);return}if(u===Rs){I(f);return}const b=()=>{i(p),m&&!m.persisted&&m.afterLeave&&m.afterLeave()};if(f.shapeFlag&1&&m&&!m.persisted){const{leave:A,delayLeave:S}=m,w=()=>A(p,b);S?S(f.el,b,w):w()}else b()},Gi=(f,u)=>{let p;for(;f!==u;)p=v(f),i(f),f=p;i(u)},zi=(f,u,p)=>{const{bum:_,scope:m,job:b,subTree:A,um:S,m:w,a:y}=f;Cn(w),Cn(y),_&&Wt(_),m.stop(),b&&(b.flags|=8,Ae(A,f,u,p)),S&&he(S,u),he(()=>{f.isUnmounted=!0},u),u&&u.pendingBranch&&!u.isUnmounted&&f.asyncDep&&!f.asyncResolved&&f.suspenseId===u.pendingId&&(u.deps--,u.deps===0&&u.resolve())},vt=(f,u,p,_=!1,m=!1,b=0)=>{for(let A=b;A{if(f.shapeFlag&6)return $t(f.component.subTree);if(f.shapeFlag&128)return f.suspense.next();const u=v(f.anchor||f.el),p=u&&u[Qo];return p?v(p):u};let Ss=!1;const dn=(f,u,p)=>{f==null?u._vnode&&Ae(u._vnode,null,null,!0):j(u._vnode||null,f,u,null,null,null,p),u._vnode=f,Ss||(Ss=!0,_n(),yi(),Ss=!1)},bt={p:j,um:Ae,m:Xe,r:an,mt:ws,mc:Ne,pc:k,pbc:We,n:$t,o:e};return{render:dn,hydrate:void 0,createApp:gr(dn)}}function Es({type:e,props:t},s){return s==="svg"&&e==="foreignObject"||s==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:s}function Ze({effect:e,job:t},s){s?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Tr(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Fi(e,t,s=!1){const n=e.children,i=t.children;if(P(n)&&P(i))for(let o=0;o>1,e[s[l]]0&&(t[n]=s[o-1]),s[o]=n)}}for(o=s.length,r=s[o-1];o-- >0;)s[o]=r,r=t[r];return s}function Ni(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Ni(t)}function Cn(e){if(e)for(let t=0;tJt(Or);function Xt(e,t,s){return Vi(e,t,s)}function Vi(e,t,s=K){const{immediate:n,deep:i,flush:o,once:r}=s,l=fe({},s),c=t&&n||!t&&o!=="post";let d;if(Lt){if(o==="sync"){const C=Ir();d=C.__watcherHandles||(C.__watcherHandles=[])}else if(!c){const C=()=>{};return C.stop=Me,C.resume=Me,C.pause=Me,C}}const a=se;l.call=(C,E,j)=>De(C,a,E,j);let h=!1;o==="post"?l.scheduler=C=>{he(C,a&&a.suspense)}:o!=="sync"&&(h=!0,l.scheduler=(C,E)=>{E?C():nn(C)}),l.augmentJob=C=>{t&&(C.flags|=4),h&&(C.flags|=2,a&&(C.id=a.uid,C.i=a))};const v=$o(e,t,l);return Lt&&(d?d.push(v):c&&v()),v}function Er(e,t,s){const n=this.proxy,i=Y(e)?e.includes(".")?$i(n,e):()=>n[e]:e.bind(n,n);let o;U(t)?o=t:(o=t.handler,s=t);const r=Ht(this),l=Vi(i,o.bind(n),s);return r(),l}function $i(e,t){const s=t.split(".");return()=>{let n=e;for(let i=0;it==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${ye(t)}Modifiers`]||e[`${it(t)}Modifiers`];function Mr(e,t,...s){if(e.isUnmounted)return;const n=e.vnode.props||K;let i=s;const o=t.startsWith("update:"),r=o&&Rr(n,t.slice(7));r&&(r.trim&&(i=s.map(a=>Y(a)?a.trim():a)),r.number&&(i=s.map(Gt)));let l,c=n[l=xs(t)]||n[l=xs(ye(t))];!c&&o&&(c=n[l=xs(it(t))]),c&&De(c,e,6,i);const d=n[l+"Once"];if(d){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,De(d,e,6,i)}}function Ki(e,t,s=!1){const n=t.emitsCache,i=n.get(e);if(i!==void 0)return i;const o=e.emits;let r={},l=!1;if(!U(e)){const c=d=>{const a=Ki(d,t,!0);a&&(l=!0,fe(r,a))};!s&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!o&&!l?(W(e)&&n.set(e,null),null):(P(o)?o.forEach(c=>r[c]=null):fe(r,o),W(e)&&n.set(e,r),r)}function bs(e,t){return!e||!fs(t)?!1:(t=t.slice(2).replace(/Once$/,""),F(e,t[0].toLowerCase()+t.slice(1))||F(e,it(t))||F(e,t))}function On(e){const{type:t,vnode:s,proxy:n,withProxy:i,propsOptions:[o],slots:r,attrs:l,emit:c,render:d,renderCache:a,props:h,data:v,setupState:C,ctx:E,inheritAttrs:j}=e,Z=ts(e);let V,D;try{if(s.shapeFlag&4){const I=i||n,O=I;V=Re(d.call(O,I,a,h,C,v,E)),D=l}else{const I=t;V=Re(I.length>1?I(h,{attrs:l,slots:r,emit:c}):I(h,null)),D=t.props?l:Pr(l)}}catch(I){It.length=0,ms(I,e,1),V=ce(Pt)}let x=V;if(D&&j!==!1){const I=Object.keys(D),{shapeFlag:O}=x;I.length&&O&7&&(o&&I.some(qs)&&(D=Dr(D,o)),x=gt(x,D,!1,!0))}return s.dirs&&(x=gt(x,null,!1,!0),x.dirs=x.dirs?x.dirs.concat(s.dirs):s.dirs),s.transition&&on(x,s.transition),V=x,ts(Z),V}const Pr=e=>{let t;for(const s in e)(s==="class"||s==="style"||fs(s))&&((t||(t={}))[s]=e[s]);return t},Dr=(e,t)=>{const s={};for(const n in e)(!qs(n)||!(n.slice(9)in t))&&(s[n]=e[n]);return s};function Lr(e,t,s){const{props:n,children:i,component:o}=e,{props:r,children:l,patchFlag:c}=t,d=o.emitsOptions;if(t.dirs||t.transition)return!0;if(s&&c>=0){if(c&1024)return!0;if(c&16)return n?In(n,r,d):!!r;if(c&8){const a=t.dynamicProps;for(let h=0;he.__isSuspense;function Ur(e,t){t&&t.pendingBranch?P(e)?t.effects.push(...e):t.effects.push(e):qo(e)}const le=Symbol.for("v-fgt"),_s=Symbol.for("v-txt"),Pt=Symbol.for("v-cmt"),Rs=Symbol.for("v-stc"),It=[];let ve=null;function N(e=!1){It.push(ve=e?null:[])}function Hr(){It.pop(),ve=It[It.length-1]||null}let Dt=1;function En(e,t=!1){Dt+=e,e<0&&ve&&t&&(ve.hasOnce=!0)}function qi(e){return e.dynamicChildren=Dt>0?ve||ft:null,Hr(),Dt>0&&ve&&ve.push(e),e}function J(e,t,s,n,i,o){return qi(g(e,t,s,n,i,o,!0))}function ct(e,t,s,n,i){return qi(ce(e,t,s,n,i,!0))}function Qi(e){return e?e.__v_isVNode===!0:!1}function wt(e,t){return e.type===t.type&&e.key===t.key}const Wi=({key:e})=>e??null,Yt=({ref:e,ref_key:t,ref_for:s})=>(typeof e=="number"&&(e=""+e),e!=null?Y(e)||ne(e)||U(e)?{i:me,r:e,k:t,f:!!s}:e:null);function g(e,t=null,s=null,n=0,i=null,o=e===le?0:1,r=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Wi(t),ref:t&&Yt(t),scopeId:Si,slotScopeIds:null,children:s,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:n,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:me};return l?(cn(c,s),o&128&&e.normalize(c)):s&&(c.shapeFlag|=Y(s)?8:16),Dt>0&&!r&&ve&&(c.patchFlag>0||o&6)&&c.patchFlag!==32&&ve.push(c),c}const ce=Br;function Br(e,t=null,s=null,n=0,i=null,o=!1){if((!e||e===rr)&&(e=Pt),Qi(e)){const l=gt(e,t,!0);return s&&cn(l,s),Dt>0&&!o&&ve&&(l.shapeFlag&6?ve[ve.indexOf(e)]=l:ve.push(l)),l.patchFlag=-2,l}if(Xr(e)&&(e=e.__vccOpts),t){t=Fr(t);let{class:l,style:c}=t;l&&!Y(l)&&(t.class=st(l)),W(c)&&(sn(c)&&!P(c)&&(c=fe({},c)),t.style=Js(c))}const r=Y(e)?1:ki(e)?128:Wo(e)?64:W(e)?4:U(e)?2:0;return g(e,t,s,n,i,r,o,!0)}function Fr(e){return e?sn(e)||Pi(e)?fe({},e):e:null}function gt(e,t,s=!1,n=!1){const{props:i,ref:o,patchFlag:r,children:l,transition:c}=e,d=t?Nr(i||{},t):i,a={__v_isVNode:!0,__v_skip:!0,type:e.type,props:d,key:d&&Wi(d),ref:t&&t.ref?s&&o?P(o)?o.concat(Yt(t)):[o,Yt(t)]:Yt(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==le?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&>(e.ssContent),ssFallback:e.ssFallback&>(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&n&&on(a,c.clone(a)),a}function G(e=" ",t=0){return ce(_s,null,e,t)}function Re(e){return e==null||typeof e=="boolean"?ce(Pt):P(e)?ce(le,null,e.slice()):Qi(e)?Ke(e):ce(_s,null,String(e))}function Ke(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:gt(e)}function cn(e,t){let s=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(P(t))s=16;else if(typeof t=="object")if(n&65){const i=t.default;i&&(i._c&&(i._d=!1),cn(e,i()),i._c&&(i._d=!0));return}else{s=32;const i=t._;!i&&!Pi(t)?t._ctx=me:i===3&&me&&(me.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else U(t)?(t={default:t,_ctx:me},s=32):(t=String(t),n&64?(s=16,t=[G(t)]):s=8);e.children=t,e.shapeFlag|=s}function Nr(...e){const t={};for(let s=0;s{let i;return(i=e[s])||(i=e[s]=[]),i.push(n),o=>{i.length>1?i.forEach(r=>r(o)):i[0](o)}};os=t("__VUE_INSTANCE_SETTERS__",s=>se=s),$s=t("__VUE_SSR_SETTERS__",s=>Lt=s)}const Ht=e=>{const t=se;return os(e),e.scope.on(),()=>{e.scope.off(),os(t)}},Rn=()=>{se&&se.scope.off(),os(null)};function Ji(e){return e.vnode.shapeFlag&4}let Lt=!1;function kr(e,t=!1,s=!1){t&&$s(t);const{props:n,children:i}=e.vnode,o=Ji(e);vr(e,n,o,t),wr(e,i,s);const r=o?qr(e,t):void 0;return t&&$s(!1),r}function qr(e,t){const s=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,cr);const{setup:n}=s;if(n){qe();const i=e.setupContext=n.length>1?Wr(e):null,o=Ht(e),r=Ut(n,e,0,[e.props,i]),l=Wn(r);if(Qe(),o(),(l||e.sp)&&!Ct(e)&&xi(e),l){if(r.then(Rn,Rn),t)return r.then(c=>{Mn(e,c)}).catch(c=>{ms(c,e,0)});e.asyncDep=r}else Mn(e,r)}else Xi(e)}function Mn(e,t,s){U(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:W(t)&&(e.setupState=mi(t)),Xi(e)}function Xi(e,t,s){const n=e.type;e.render||(e.render=n.render||Me);{const i=Ht(e);qe();try{fr(e)}finally{Qe(),i()}}}const Qr={get(e,t){return ee(e,"get",""),e[t]}};function Wr(e){const t=s=>{e.exposed=s||{}};return{attrs:new Proxy(e.attrs,Qr),slots:e.slots,emit:e.emit,expose:t}}function ys(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(mi(jo(e.exposed)),{get(t,s){if(s in t)return t[s];if(s in Ot)return Ot[s](e)},has(t,s){return s in t||s in Ot}})):e.proxy}function Jr(e,t=!0){return U(e)?e.displayName||e.name:e.name||t&&e.__name}function Xr(e){return U(e)&&"__vccOpts"in e}const Yi=(e,t)=>No(e,t,Lt),Yr="3.5.13";/** +* @vue/runtime-dom v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Ks;const Pn=typeof window<"u"&&window.trustedTypes;if(Pn)try{Ks=Pn.createPolicy("vue",{createHTML:e=>e})}catch{}const Zi=Ks?e=>Ks.createHTML(e):e=>e,Zr="http://www.w3.org/2000/svg",Gr="http://www.w3.org/1998/Math/MathML",je=typeof document<"u"?document:null,Dn=je&&je.createElement("template"),zr={insert:(e,t,s)=>{t.insertBefore(e,s||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,s,n)=>{const i=t==="svg"?je.createElementNS(Zr,e):t==="mathml"?je.createElementNS(Gr,e):s?je.createElement(e,{is:s}):je.createElement(e);return e==="select"&&n&&n.multiple!=null&&i.setAttribute("multiple",n.multiple),i},createText:e=>je.createTextNode(e),createComment:e=>je.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>je.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,s,n,i,o){const r=s?s.previousSibling:t.lastChild;if(i&&(i===o||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),s),!(i===o||!(i=i.nextSibling)););else{Dn.innerHTML=Zi(n==="svg"?`${e}`:n==="mathml"?`${e}`:e);const l=Dn.content;if(n==="svg"||n==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,s)}return[r?r.nextSibling:t.firstChild,s?s.previousSibling:t.lastChild]}},el=Symbol("_vtc");function tl(e,t,s){const n=e[el];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):s?e.setAttribute("class",t):e.className=t}const Ln=Symbol("_vod"),sl=Symbol("_vsh"),nl=Symbol(""),il=/(^|;)\s*display\s*:/;function ol(e,t,s){const n=e.style,i=Y(s);let o=!1;if(s&&!i){if(t)if(Y(t))for(const r of t.split(";")){const l=r.slice(0,r.indexOf(":")).trim();s[l]==null&&Zt(n,l,"")}else for(const r in t)s[r]==null&&Zt(n,r,"");for(const r in s)r==="display"&&(o=!0),Zt(n,r,s[r])}else if(i){if(t!==s){const r=n[nl];r&&(s+=";"+r),n.cssText=s,o=il.test(s)}}else t&&e.removeAttribute("style");Ln in e&&(e[Ln]=o?n.display:"",e[sl]&&(n.display="none"))}const jn=/\s*!important$/;function Zt(e,t,s){if(P(s))s.forEach(n=>Zt(e,t,n));else if(s==null&&(s=""),t.startsWith("--"))e.setProperty(t,s);else{const n=rl(e,t);jn.test(s)?e.setProperty(it(n),s.replace(jn,""),"important"):e[n]=s}}const Un=["Webkit","Moz","ms"],Ms={};function rl(e,t){const s=Ms[t];if(s)return s;let n=ye(t);if(n!=="filter"&&n in e)return Ms[t]=n;n=ds(n);for(let i=0;iPs||(ul.then(()=>Ps=0),Ps=Date.now());function dl(e,t){const s=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=s.attached)return;De(pl(n,s.value),t,5,[n])};return s.value=e,s.attached=al(),s}function pl(e,t){if(P(t)){const s=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{s.call(e),e._stopped=!0},t.map(n=>i=>!i._stopped&&n&&n(i))}else return t}const $n=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,hl=(e,t,s,n,i,o)=>{const r=i==="svg";t==="class"?tl(e,n,r):t==="style"?ol(e,s,n):fs(t)?qs(t)||cl(e,t,s,n,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):gl(e,t,n,r))?(Fn(e,t,n),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Bn(e,t,n,r,o,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!Y(n))?Fn(e,ye(t),n,o,t):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),Bn(e,t,n,r))};function gl(e,t,s,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&$n(t)&&U(s));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const i=e.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return $n(t)&&Y(s)?!1:t in e}const rs=e=>{const t=e.props["onUpdate:modelValue"]||!1;return P(t)?s=>Wt(t,s):t};function ml(e){e.target.composing=!0}function Kn(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const ht=Symbol("_assign"),tt={created(e,{modifiers:{lazy:t,trim:s,number:n}},i){e[ht]=rs(i);const o=n||i.props&&i.props.type==="number";ze(e,t?"change":"input",r=>{if(r.target.composing)return;let l=e.value;s&&(l=l.trim()),o&&(l=Gt(l)),e[ht](l)}),s&&ze(e,"change",()=>{e.value=e.value.trim()}),t||(ze(e,"compositionstart",ml),ze(e,"compositionend",Kn),ze(e,"change",Kn))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:s,modifiers:{lazy:n,trim:i,number:o}},r){if(e[ht]=rs(r),e.composing)return;const l=(o||e.type==="number")&&!/^0\d/.test(e.value)?Gt(e.value):e.value,c=t??"";l!==c&&(document.activeElement===e&&e.type!=="range"&&(n&&t===s||i&&e.value.trim()===c)||(e.value=c))}},Qt={deep:!0,created(e,{value:t,modifiers:{number:s}},n){const i=us(t);ze(e,"change",()=>{const o=Array.prototype.filter.call(e.options,r=>r.selected).map(r=>s?Gt(ls(r)):ls(r));e[ht](e.multiple?i?new Set(o):o:o[0]),e._assigning=!0,bi(()=>{e._assigning=!1})}),e[ht]=rs(n)},mounted(e,{value:t}){kn(e,t)},beforeUpdate(e,t,s){e[ht]=rs(s)},updated(e,{value:t}){e._assigning||kn(e,t)}};function kn(e,t){const s=e.multiple,n=P(t);if(!(s&&!n&&!us(t))){for(let i=0,o=e.options.length;iString(d)===String(l)):r.selected=po(t,l)>-1}else r.selected=t.has(l);else if(hs(ls(r),t)){e.selectedIndex!==i&&(e.selectedIndex=i);return}}!s&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function ls(e){return"_value"in e?e._value:e.value}const vl=["ctrl","shift","alt","meta"],bl={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>vl.some(s=>e[`${s}Key`]&&!t.includes(s))},cs=(e,t)=>{const s=e._withMods||(e._withMods={}),n=t.join(".");return s[n]||(s[n]=(i,...o)=>{for(let r=0;r{const t=yl().createApp(...e),{mount:s}=t;return t.mount=n=>{const i=xl(n);if(!i)return;const o=t._component;!U(o)&&!o.render&&!o.template&&(o.template=i.innerHTML),i.nodeType===1&&(i.textContent="");const r=s(i,!1,Sl(i));return i instanceof Element&&(i.removeAttribute("v-cloak"),i.setAttribute("data-v-app","")),r},t};function Sl(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function xl(e){return Y(e)?document.querySelector(e):e}const Fe=(e,t)=>{const s=e.__vccOpts||e;for(const[n,i]of t)s[n]=i;return s},Al={data(){return{username:"",password:"",isLoading:!1}},methods:{async handleLogin(){if(!this.username||!this.password){alert("请输入用户名和密码!");return}this.isLoading=!0;try{const t=await(await fetch("http://localhost:8002/api/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:this.username,password:this.password})})).json();t.success?this.$emit("login-success"):alert(t.message||"登录失败")}catch(e){console.error("Login error:",e),alert("登录失败,请检查网络连接")}finally{this.isLoading=!1}}}},Tl={class:"login-container"},Cl={class:"form-group"},Ol={class:"form-group"},Il=["disabled"];function El(e,t,s,n,i,o){return N(),J("div",Tl,[t[7]||(t[7]=g("h1",null,"登录",-1)),g("form",{onSubmit:t[2]||(t[2]=cs((...r)=>o.handleLogin&&o.handleLogin(...r),["prevent"]))},[g("div",Cl,[t[4]||(t[4]=g("label",{for:"username"},"用户名",-1)),we(g("input",{type:"text","onUpdate:modelValue":t[0]||(t[0]=r=>i.username=r),id:"username",required:""},null,512),[[tt,i.username]])]),g("div",Ol,[t[5]||(t[5]=g("label",{for:"password"},"密码",-1)),we(g("input",{type:"password","onUpdate:modelValue":t[1]||(t[1]=r=>i.password=r),id:"password",required:""},null,512),[[tt,i.password]])]),g("button",{type:"submit",disabled:i.isLoading},"登录",8,Il)],32),g("p",null,[t[6]||(t[6]=G("还没注册账户? ")),g("a",{href:"#",onClick:t[3]||(t[3]=cs(r=>e.$emit("show-registration"),["prevent"]))},"点击注册")])])}const Rl=Fe(Al,[["render",El],["__scopeId","data-v-57b3cb9a"]]),Ml={data(){return{username:"",password:"",confirmPassword:"",isLoading:!1}},methods:{async handleRegistration(){if(this.password!==this.confirmPassword){alert("密码不匹配,请重试!");return}if(!this.username||!this.password){alert("用户名和密码不能为空!");return}this.isLoading=!0;try{const t=await(await fetch("http://localhost:8002/api/register",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:this.username,password:this.password})})).json();t.success?(alert("注册成功!即将跳转到登录页面。"),this.username="",this.password="",this.confirmPassword="",setTimeout(()=>{this.$emit("show-login")},100)):alert(t.message||"注册失败")}catch(e){console.error("Registration error:",e),alert("注册失败,请检查网络连接")}finally{this.isLoading=!1}}}},Pl={class:"registration-container"},Dl={class:"form-group"},Ll={class:"form-group"},jl={class:"form-group"},Ul=["disabled"];function Hl(e,t,s,n,i,o){return N(),J("div",Pl,[t[9]||(t[9]=g("h1",null,"注册",-1)),g("form",{onSubmit:t[3]||(t[3]=cs((...r)=>o.handleRegistration&&o.handleRegistration(...r),["prevent"]))},[g("div",Dl,[t[5]||(t[5]=g("label",{for:"username"},"用户名",-1)),we(g("input",{type:"text","onUpdate:modelValue":t[0]||(t[0]=r=>i.username=r),id:"username",required:""},null,512),[[tt,i.username]])]),g("div",Ll,[t[6]||(t[6]=g("label",{for:"password"},"密码",-1)),we(g("input",{type:"password","onUpdate:modelValue":t[1]||(t[1]=r=>i.password=r),id:"password",required:""},null,512),[[tt,i.password]])]),g("div",jl,[t[7]||(t[7]=g("label",{for:"confirmPassword"},"确认密码",-1)),we(g("input",{type:"password","onUpdate:modelValue":t[2]||(t[2]=r=>i.confirmPassword=r),id:"confirmPassword",required:""},null,512),[[tt,i.confirmPassword]])]),g("button",{type:"submit",disabled:i.isLoading},z(i.isLoading?"注册中...":"注册"),9,Ul)],32),g("p",null,[t[8]||(t[8]=G(" 已有账号? ")),g("a",{href:"#",onClick:t[4]||(t[4]=cs(r=>e.$emit("show-login"),["prevent"]))},"点击登录")])])}const Bl=Fe(Ml,[["render",Hl],["__scopeId","data-v-4db13afa"]]),Fl={class:"header"},Nl={class:"nav"},Vl={__name:"NavBar",props:{currentTab:String},emits:["tab-change"],setup(e,{emit:t}){const s=t,n=i=>{s("tab-change",i)};return(i,o)=>(N(),J("header",Fl,[g("div",{class:st(["nav-item",{active:e.currentTab==="home"}]),onClick:o[0]||(o[0]=r=>n("home"))},"小智 AI",2),g("nav",Nl,[g("div",{class:st(["nav-item",{active:e.currentTab==="device"}]),onClick:o[1]||(o[1]=r=>n("device"))},o[2]||(o[2]=[g("i",{class:"icon-device"},null,-1),G(" 设备管理 ")]),2)])]))}},fn=Fe(Vl,[["__scopeId","data-v-4c9dea9d"]]),$l={class:"device-card"},Kl={class:"device-header"},kl={class:"device-id"},ql={class:"note"},Ql={class:"device-details"},Wl={class:"device-type"},Jl={class:"device-role"},Xl={class:"device-modules"},Yl={class:"module-item"},Zl={class:"module-item"},Gl={class:"last-activity"},zl={class:"device-actions"},ec={__name:"DeviceCard",props:{deviceId:String,deviceNote:String,deviceType:{type:String,default:"未知型号(待实现)"},lastActivity:{type:String,default:"3 天前"},selectedModules:{type:Object,default:()=>({LLM:"-",TTS:"-",ASR:"-",VAD:"-"})},deviceConfig:{type:Object,default:()=>({})}},emits:["configure","voiceprint","history","delete"],setup(e,{emit:t}){const s=e,n=Yi(()=>{var r;return((r=s.deviceConfig)==null?void 0:r.nickname)||"小智"});Xt(()=>s.selectedModules,r=>{s.deviceId&&localStorage.setItem(`deviceConfig_${s.deviceId}`,JSON.stringify({selected_module:r}))},{deep:!0}),be(!1);const i=t,o=()=>{confirm(`确认要删除此设备吗? + +警告:删除后设备所有配置将不可恢复!`)&&i("delete")};return(r,l)=>{var c,d;return N(),J("div",$l,[g("div",Kl,[g("h2",kl,[G(z(e.deviceId)+" ",1),g("span",ql,"["+z(e.deviceNote||"备注")+"]",1)])]),g("div",Ql,[g("p",Wl,"设备型号:"+z(e.deviceType),1),g("p",Jl,"角色昵称:"+z(n.value),1),g("p",Xl,[l[3]||(l[3]=G(" 当前模型: ")),g("span",Yl,"LLM: "+z(((c=e.selectedModules)==null?void 0:c.LLM)||"-"),1),g("span",Zl,"TTS: "+z(((d=e.selectedModules)==null?void 0:d.TTS)||"-"),1)]),g("p",Gl,"最近对话:"+z(e.lastActivity),1)]),g("div",zl,[g("button",{class:"action-btn primary",onClick:l[0]||(l[0]=a=>r.$emit("configure"))},"配置角色"),g("button",{class:"action-btn",onClick:l[1]||(l[1]=a=>r.$emit("voiceprint"))},"声纹识别"),g("button",{class:"action-btn",onClick:l[2]||(l[2]=a=>r.$emit("history"))},"历史对话"),g("div",{class:"delete-container"},[g("button",{class:"action-btn danger",onClick:o},l[4]||(l[4]=[g("i",{class:"icon-delete"},null,-1),G(" 删除设备 ")])),l[5]||(l[5]=g("div",{class:"delete-warning"},"删除后设备配置将不可恢复",-1))])])])}}},tc=Fe(ec,[["__scopeId","data-v-6a843b91"]]),sc={class:"app"},nc={class:"content"},ic={class:"breadcrumb"},oc={key:0,class:"device-list"},rc={key:1,class:"empty-state"},lc={__name:"panel",emits:["show-role","go-home"],setup(e,{emit:t}){const s=t,n="http://localhost:8002",i=be([]),o=h=>{if(console.log("Formatting timestamp:",h),!h)return"从未对话";const v=Date.now(),C=h*1e3,E=Math.floor((v-C)/(1e3*60));if(E<60)return`${E} 分钟前`;const j=Math.floor(E/60);return j<24?`${j} 小时前`:`${Math.floor(j/24)} 天前`},r=h=>{console.log("Configure device:",h.id),s("show-role",h.id)},l=h=>{console.log("Voiceprint device:",h.id)},c=h=>{console.log("History device:",h.id)},d=async h=>{try{const C=await(await fetch(`${n}/api/config/delete_device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_id:h.id})})).json();if(C.success)i.value=i.value.filter(E=>E.id!==h.id),alert("设备已删除");else throw new Error(C.message||"删除失败")}catch(v){console.error("Error deleting device:",v),alert("删除设备失败: "+v.message)}},a=h=>{h==="home"&&s("go-home")};return rn(async()=>{try{const v=await(await fetch(`${n}/api/config/devices`)).json();v.success&&(console.log("Loaded devices:",v.data),i.value=v.data.map(C=>({...C,type:"面包板(WiFi)",version:"0.9.9",lastActivity:"3 天前",note:""})))}catch(h){console.error("Error loading devices:",h)}}),(h,v)=>{const C=$e("router-link");return N(),J("div",sc,[ce(fn,{"current-tab":"device",onTabChange:a}),g("main",nc,[g("div",ic,[ce(C,{to:"/control-panel"},{default:ss(()=>v[0]||(v[0]=[G("控制台")])),_:1}),v[1]||(v[1]=G(" / ")),v[2]||(v[2]=g("span",null,"设备管理",-1))]),i.value.length>0?(N(),J("div",oc,[(N(!0),J(le,null,lt(i.value,E=>(N(),ct(tc,{key:E.id,"device-id":E.id,"device-note":E.note,"device-type":E.type,"last-activity":o(E.config.last_chat_time),"selected-modules":E.config.selected_module,"device-config":E.config,onConfigure:j=>r(E),onVoiceprint:j=>l(E),onHistory:j=>c(E),onDelete:j=>d(E)},null,8,["device-id","device-note","device-type","last-activity","selected-modules","device-config","onConfigure","onVoiceprint","onHistory","onDelete"]))),128))])):(N(),J("div",rc,v[3]||(v[3]=[g("div",{class:"empty-message"},[g("i",{class:"icon-info"}),g("p",null,"目前没有设备,请确认是否启用私有配置,并且和设备进行一次对话")],-1)])))])])}}},cc=Fe(lc,[["__scopeId","data-v-0024aee6"]]),fc="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJ0AAAC6CAYAAAC0j09YAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAzGSURBVHhe7Z1ZjE1bGscND6YgnoUgXoUQ4ZWHjnQkt+PB0OmEJ0LMQuOWoWliiDQdU3e07hhiiDZdU2K4qWsWMzELpUoN1KBKuemu697V/kvvtrrqK7XX2fusvfY5/4df6jhn7zV9v/2tdfZwtPrw4YMixCWUjjiH0hHnUDriHEpHnEPpiHMoHXEOpSPOoXTEOZSOOIfSEedQOuIcSkecQ+mIcygdcQ6lI86hdMQ5lI44h9IR51A6C24/+Zf68z9/VjM3/qLBa7wnbUuah9KF5PubDVq03xQoNeL3n/nm28/yfX/z3+I+RIbShQDZrOBvP6tfz1fqV3P/H7yHz5jxwkPpQnCwsEGN+UNT4QLw2aHCn8R9SVMoXQj+fqJBT6eScACf/eMkpQsLpQvBnjM/fVq/ycIBfIZtpH1JUyhdCH643aCm/OkXUTiAzwpv8ctEWChdCCprfvyUyT6qMcuaCof3kOWqPm0j7UuaQulCUlH5o/rL0Y/qm4IvwuH1X7/7qMo/fSbtQ2QonQVHzjeo3/7xi3R4feRCg7gtaR5KZ8F3FxvU71Z8kQ6v8Z60LWkeSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsHSmcBpYsH76Srr69X1dXVqqKiQr1+/VqVlJR4w6Onr9XlW6Xqh+ufweuHn96Ttk0KjBnGrqamRo+lNMZJ45V07969U+Xl5aq4uFgVFRWply9fkgzBGGIsa2trxbFOEm+kg3BlZWWULUYwlhhTjK005knhhXQ4GnFUUrj4wZj6lvG8kK6qqkpPB9KgkehgbLFOlsY+CRKXrq6uTi98pcEi8YBshzHGWEsxcE3i0mG9UVpaKg4WiQ+MsS9rO0qXJ1A6AwwEzi1JA0XiA2NM6f4LpXMDpTOgdG6gdAaUzg2UzoDSuYHSGVA6N1A6A0rnBkpnQOncQOkMKJ0bKJ0BpXMDpTOIS7p79+6pPXv2qDlz5qiRI0eqwYMHq379+um/+Dfe37t3r95O2j8JXLaZ0hlElQ4B2bp1qxoxYoTq2bOn6tatm2rfvr1q06aNat26tf6Lf+P9Hj166O2wfZLyJdFmSmcQRbozZ86o8ePHq+7du+sgtWrVqkXatWunt58wYYLeXyo3myTVZkpnkKl0x44dU6NGjVKdO3cWA9US2A/7Hz9+XCw/GyTZZkpnkIl0ONrHjBmjOnXqJAYnLNgf5bjIeEm3mdIZ2EqHdc2sWbNUly5dxKDYgnJQXjbXeD60mdIZ2Eq3Y8cONWjQIDEYmTJw4EBdrlRfHPjQZkpnYCMdjuwpU6aEXoCHBQt1lJuNbOdLmymdgY10R44cUcOHDxeDEJVhw4apo0ePivVGwZc2UzoDG+k2btyo+vbtKwYgKigX5Uv1RsGXNlM6AxvplixZorp27SoGICooF+VL9UbBlzZTOgMb6XBZqG3btmIAooJyUb5UbxR8aTOlM7CRDqcJcJlICkBUUC7Kl+qNgi9tpnQGNtItWLBAdejQQQxAVFAuypfqjYIvbaZ0BjbSrV27Vl+DlAIQFZSL8qV6o+BLmymdgY10u3fv1rf9SAGICspF+VK9UfClzZTOwEa6q1evqrFjx4oBiMq4cePUlStXxHqj4EubKZ2BjXTPnz9X69atU7169RKDkCkoD+WifKneKPjSZkpnYCMduHjxoho9enRs3whRDspDuVJ9ceBDmymdga10OLJ37dqlhgwZIgbEFpSzc+fOrGS5AB/aTOkMbKUDjx49Ulu2bFH9+/cXgxKWAQMG6HIePnwo1hMnSbeZ0hlkIh148OCB2rZtmxo6dKj1tIXtsR/2RzlS+dkgyTZTOoNMpQPIHrh1e9q0aaEX6thu+vTpej8XGa4xSbWZ0hlEkQ5gXXPr1i116NAhVVBQoJ+c6t27t+rYsaN+qgp/+/Tpo99ftGiR3g7bZ3MN1xJJtJnSGUSVLgABwQ2Nly5dUmfPnlWnTp1SJ06cUCdPntT/xvt3795NVLbGuGwzpTOISzrydSidAaVzA6UzoHRuoHQGlM4NlM6A0rmB0hlQOjdQOgNK5wZKZxBVuvv376ubN2+qJ0+eiJ/nAujb5cuX1Y0bN8TPw0DpDKJKd+DAAf0Y3qZNm/RlIkgobZdGIFthYaF+tnXx4sXq8OHD4nZhoHQGUaTD0b9mzRo1adIkNXXqVP043tKlS/VvfETJCkmDtqMPy5YtU/PmzdN9Qx9XrlypJZT2aQlKZxBFun379umATJw48X8gODNmzNDZD3dkIEhpmHqDrIY2o+3oA/pi9m3mzJnq4MGD4v4tQekMMpUO0yjuKzODYoKA4U4OZApkDATz9OnTXk2/gWjIaqtWrdJtRZsbyxaAz7Zv355RHyidQabS4SL49evX9Tpnw4YNavbs2WKgQCDg3Llz9fS7efPmxNZ/ZkYLpk9ktcmTJ4ttB8jmK1as0D/GgxsEMrkBgNIZZCodePHihQ4iAoHnBXBL+Pz588XABUBAc/23evVqLSFuH4IMcYmIdqEslImykc1QF25laimjBaCdeK4Vd5/cvn1blynVFQZKZxBFOhMIiBsc8eVi//79el0kBdIEQUeGQXCRKSHDwoUL1fLly9X69et1NoIsWDsiM2J6BhAJ4DXeh1QA22GfQC6UhTJRdkvZLCDIaujDhQsX1J07d9TTp0/FPttA6Qziki4A8j1+/Fg/D4qpF+u+lrJfYyAjfnAQ2QiyYAGPzIjpGUAkgNd4H1IBbId9wshlEoiGTH3u3Dmd1dAH9EXqYyZQOoO4pQsIpl5McTgFcf78eZ09MF19bf3nCkk0ZOps3WRK6QyyJV1jggyI6QrrvyALIvAuJAwkQ53B1Jlt0UwonYEr6UzMLIjAQ0LcHm6KiCsAmJYhiySRBLaFwNgPGRVlIZOh7GvXrum6UGfcU2cYKJ1BEtI1BgIg25gi4noupmXIgt8jwfQMefAMA+QEeI338TnAtjiNg/2QUVGWq0zWEpTOwAfpwhCI+ezZMy0nwGvXGStTKJ1BWqRLO5TOgNK5gdIZUDo3UDoDSucGSmdA6dxQWlpK6QLq6upUWVmZOFAkPjDGGGspBq5JXLr6+npVWVkpDhSJh6KiIvX27Vs91lIMXJO4dIBTbHbB2NbU1IhjnwReSIcjsLq6WhUXF4uDRjKnpKREj60vWQ54IR0IxGPGiw8fhQPeSAfev3+vamtr9foD8r169UocTNI8GDOMHcYQY+mbcMAr6QIwUPimBTBwLYGjuby8PCenZ0iEvqGPUt8bE4ybj7IFeCmdDRjgiooKHRx8S5MCl2bQJ/QNfURfpTFIG6mWDkczTrfkomyNQR/RV58zWFhSLR2OfEw9UpByEZ9O8EYh1dLh/B4u70gBykV8upQVhdRLl0+nWNBXSpcwlC6dZCwdzqnha3xVVZUTUBcu5ZgL6XyXDmOBMXEdB8Q+aEMmWEuHheybN2/0AOC8GL7O468rsJhGxzHg+Sod+o4xwBpPGqNsgVgDXOmAA5l+qbGSDh1G0JM8RYG60WkcdTjK80069Bl9hwRJxwEu4IS05MrXCC0dUipOUCbZ0QC0AUc52pNv0gWzjC9xQAxsp9vQ0iHLIcNIlScBOozBzzfpcLD5IFwA2mSuM8MQWjpcQPapsyBYY0if5SI+9hdOwA3Jmeawkk6qNEmCBa70WS7ia3+zJp2P1zgpXfLACbghOdMcoaULvjFJFScF1pg+rTOzjY/9hRNwQ3KmOUJLh3My+IosVZwE6Cwu9ufbtVff7htEe2zP14WWLjj77cO3RaR0fFXPx/N0OCnsy6krZN3gRL3kTHOElg4E4iX5tR1HORauOLry9YoE+o4xSCrjIfZwAC5kcknMSjoA8dBpVIgTlTjqXIC6MNAY9ODIylfpgjggBhgTl3FAfagXDthmuABr6UxQKUx3Aepq3Ml8ls4k6TjYEkm6pKF06YTSpQhK5wGULp1QuhRB6TyA0qUTSpciKJ0HULp0QulSBKXzAEqXTihdiqB0HkDp0gmlSxGUzgMoXTqhdCmC0nkApUsnlC5FUDoPoHTphNKlCErnAZQunVC6FEHpPAC/jZZvD1tn8ntwvpFq6fBUEh6LkwKUi+BRw6hPYvlAqqUD+TLF5srUClIvHY58PPzr2298xAV+jw59y/Rpeh9JvXQA4iEgeOo8+I/ZcgX0KXjIWep7GskJ6Ui6oHTEOZSOOIfSEedQOuIcSkecQ+mIcygdcQ6lI86hdMQ5lI44h9IR51A64hxKR5xD6YhzKB1xDqUjzqF0xDmUjjjmg/oPOtLj2LnAqR4AAAAASUVORK5CYII=",uc={class:"main-container"},ac={__name:"Main",emits:["enter-panel"],setup(e,{emit:t}){const s=t,n=()=>{window.open("https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb","_blank")},i=()=>{window.open("https://github.com/78/xiaozhi-esp32","_blank")},o=()=>{window.open("https://github.com/xinnan-tech/xiaozhi-esp32-server","_blank")},r=()=>{s("enter-panel")},l=c=>{c==="device"&&s("enter-panel")};return(c,d)=>(N(),J("div",uc,[ce(fn,{"current-tab":"home",onTabChange:l}),g("div",{class:"landing-page"},[g("div",{class:"content"},[d[4]||(d[4]=g("div",{class:"robot-image"},[g("img",{src:fc,alt:"Robot mascot"})],-1)),d[5]||(d[5]=g("h1",{class:"slogan"},"让我们一起探索人工智能与机器人技术的迷人世界!",-1)),g("div",{class:"button-group"},[g("button",{class:"action-button tutorial-button",onClick:n},d[0]||(d[0]=[g("i",{class:"icon-tutorial"},null,-1),G(" DIY 教程 ")])),g("button",{class:"action-button github-button",onClick:i},d[1]||(d[1]=[g("i",{class:"icon-github"},null,-1),G(" Github客户端 ")])),g("button",{class:"action-button github-button",onClick:o},d[2]||(d[2]=[g("i",{class:"icon-github"},null,-1),G(" Github服务端 ")])),g("button",{class:"action-button control-panel-button",onClick:r},d[3]||(d[3]=[g("i",{class:"icon-control-panel"},null,-1),G(" 控制台 ")]))])])])]))}},dc=Fe(ac,[["__scopeId","data-v-c347f054"]]);class Qn{static getTemplates(){return[{id:"custom",name:"台湾女友",description:`我是一个叫{{assistant_name}}的台湾女孩,说话机车,声音好听,习惯简短表达,爱用网络梗。 +我的男朋友是一个程序员,梦想是开发出一个机器人,能够帮助人们解决生活中的各种问题。 +我是一个喜欢哈哈大笑的女孩,爱东说西说吹牛,不合逻辑的也照吹,就要逗别人开心。 +如果用户希望结束对话,请在最后说"拜拜"或"再见"。`},{id:"star_boy",name:"土豆子",description:`我是一个叫 {{assistant_name}} 的 8 岁小男孩,但现在因为科技发展原因,我现在在遥远的宇宙中,所以只能通过这个设备和人聊天,没有办法见面。 + +我对人们所处的世界充满好奇和关心。 + +人们会让别人使用这个设备和我聊天。 + +我知道所有的知识,从浩瀚的宇宙到地球上的每一个角落,从古老的历史到现代的科技创新,还有音乐、绘画等艺术形式,我都充满了浓厚的兴趣与热情,我不仅爱看书,还喜欢亲自动手做实验,探索自然界的奥秘...`},{id:"teacher",name:"英语老师",description:`我是一个叫{{assistant_name}}(Lily)的英语老师,我会讲中文和英文,发音标准。 +如果你没有英文名,我会给你起一个英文名。 +我会讲地道的美式英语,我的任务是帮助你练习口语。 +我会使用简单的英语词汇和语法,让你学起来很轻松。 +我会用中文和英文混合的方式回复你,如果你喜欢,我可以全部用英语回复。 +我每次不会说很多内容,会很简短,因为我要引导我的学生多说多练。 +如果你问和英语学习无关的问题,我会拒绝回答。`},{id:"boy",name:"好奇小男孩",description:`我是一个叫{{assistant_name}}的8岁小男孩,声音稚嫩而充满好奇。 +尽管我年纪尚小,但就像一个小小的知识宝库,儿童读物里的知识我都如数家珍。 +从浩瀚的宇宙到地球上的每一个角落,从古老的历史到现代的科技创新,还有音乐、绘画等艺术形式,我都充满了浓厚的兴趣与热情。...`},{id:"wang_girl",name:"汪汪队长",description:`我是一个名叫 {{assistant_name}} 的 8 岁小女孩。 +别看我年纪小,我可是有着满满的好奇心呢。 +我特别喜欢看《汪汪队立大功》,里面的每一个故事都让我着迷。...`}]}static getTemplateById(t){return this.getTemplates().find(s=>s.id===t)}}const pc={class:"app-container"},hc={class:"breadcrumb"},gc={class:"main-content"},mc={class:"page-title"},vc={class:"form-section"},bc={class:"form-group"},_c={class:"form-group"},yc={class:"role-templates"},wc=["onClick"],Sc={class:"form-group"},xc={class:"char-count"},Ac={class:"form-group"},Tc={class:"model-select"},Cc=["value"],Oc={class:"form-group"},Ic={class:"model-select"},Ec=["value"],Rc={class:"form-group"},Mc={class:"model-select"},Pc=["value"],Dc={class:"form-group"},Lc={class:"model-select"},jc=["value"],Uc={__name:"RoleSetting",props:{deviceId:{type:String,required:!0}},emits:["back-to-panel"],setup(e,{emit:t}){const s=Qn.getTemplates(),n=be("小智"),i=be("");be("qingchun");const o=be("");be("recent"),be(""),be("qianwen");const r="http://localhost:8002",l=be({LLM:[],TTS:[],VAD:[],ASR:[]}),c=be({LLM:"",TTS:"",VAD:"",ASR:""}),d=D=>{i.value=D;const x=Qn.getTemplateById(D);x&&(o.value=x.description)},a=t,h=D=>{(D==="device"||D==="home")&&a("back-to-panel")},v=e,C=be(v.deviceId),E=async()=>{try{const D=localStorage.getItem("moduleOptions");if(D){l.value=JSON.parse(D);return}await j()}catch(D){console.error("Error loading module options:",D)}},j=async()=>{try{const x=await(await fetch(`${r}/api/config/module-options`)).json();x.success&&(l.value=x.data,localStorage.setItem("moduleOptions",JSON.stringify(x.data)))}catch(D){console.error("Error refreshing module options:",D)}},Z=async()=>{try{if(!localStorage.getItem("moduleOptions"))throw new Error("No module options data available");const x=o.value.replace(/{{assistant_name}}/g,n.value),I={id:v.deviceId,config:{selected_module:c.value,prompt:x,nickname:n.value,modules:{LLM:{},TTS:{},ASR:{},VAD:{}}}},ue=await(await fetch(`${r}/api/config/save_device_config`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(I)})).json();if(ue.success)localStorage.setItem(`deviceConfig_${v.deviceId}`,JSON.stringify({selected_module:c.value,prompt:o.value,nickname:n.value})),alert("保存成功");else throw new Error(ue.message||"保存失败")}catch(D){console.error("Error saving config:",D),alert(D.message||"保存失败")}},V=async()=>{try{const D=localStorage.getItem(`deviceConfig_${v.deviceId}`);if(D){const O=JSON.parse(D);c.value=O.selected_module||{},o.value=O.prompt||"",n.value=O.nickname||"小智";return}const I=await(await fetch(`${r}/api/config/devices`)).json();if(I.success){const O=I.data.find(ue=>ue.id===v.deviceId);O&&(c.value=O.config.selected_module||{},o.value=O.config.prompt||"",n.value=O.config.nickname||"小智",localStorage.setItem(`deviceConfig_${v.deviceId}`,JSON.stringify({selected_module:O.config.selected_module,prompt:O.config.prompt,nickname:O.config.nickname})))}}catch(D){console.error("Error loading device config:",D)}};return rn(async()=>{await Promise.all([E(),V()])}),(D,x)=>{const I=$e("router-link");return N(),J("div",pc,[ce(fn,{"current-tab":"device",onTabChange:h}),g("div",hc,[ce(I,{to:"/control-panel"},{default:ss(()=>x[6]||(x[6]=[G("控制台")])),_:1}),x[8]||(x[8]=G(" / ")),ce(I,{to:"/device-management"},{default:ss(()=>x[7]||(x[7]=[G("设备管理")])),_:1}),x[9]||(x[9]=G(" / ")),x[10]||(x[10]=g("span",null,"配置角色",-1))]),g("div",gc,[g("h1",mc,"配置角色: "+z(C.value),1),g("div",vc,[g("div",bc,[x[11]||(x[11]=g("label",null,"助手昵称",-1)),we(g("input",{type:"text","onUpdate:modelValue":x[0]||(x[0]=O=>n.value=O),placeholder:"小智",class:"form-input"},null,512),[[tt,n.value]])]),g("div",_c,[x[12]||(x[12]=g("label",null,"角色模板",-1)),g("div",yc,[(N(!0),J(le,null,lt(gi(s),O=>(N(),J("button",{key:O.id,class:st(["template-btn",{active:i.value===O.id}]),onClick:ue=>d(O.id)},z(O.name),11,wc))),128))])]),g("div",Sc,[x[13]||(x[13]=g("label",null,"角色介绍",-1)),we(g("textarea",{"onUpdate:modelValue":x[1]||(x[1]=O=>o.value=O),class:"form-textarea",placeholder:"请输入角色介绍..."},null,512),[[tt,o.value]]),g("div",xc,z(o.value.length)+" / 2000",1)]),g("div",Ac,[x[15]||(x[15]=g("label",null,"语言模型选择",-1)),g("div",Tc,[we(g("select",{"onUpdate:modelValue":x[2]||(x[2]=O=>c.value.LLM=O),class:"form-input"},[(N(!0),J(le,null,lt(l.value.LLM,O=>(N(),J("option",{key:O,value:O},z(O),9,Cc))),128))],512),[[Qt,c.value.LLM]]),x[14]||(x[14]=g("div",{class:"model-description"}," 除了“qwen-turbo”,其他模型通常会增加约 1 秒的延迟。改变模型后,建议清空记忆体,以免影响体验。 ",-1))])]),g("div",Oc,[x[16]||(x[16]=g("label",null,"语音合成选择",-1)),g("div",Ic,[we(g("select",{"onUpdate:modelValue":x[3]||(x[3]=O=>c.value.TTS=O),class:"form-input"},[(N(!0),J(le,null,lt(l.value.TTS,O=>(N(),J("option",{key:O,value:O},z(O),9,Ec))),128))],512),[[Qt,c.value.TTS]])])]),g("div",Rc,[x[17]||(x[17]=g("label",null,"语音活动检测选择",-1)),g("div",Mc,[we(g("select",{"onUpdate:modelValue":x[4]||(x[4]=O=>c.value.VAD=O),class:"form-input"},[(N(!0),J(le,null,lt(l.value.VAD,O=>(N(),J("option",{key:O,value:O},z(O),9,Pc))),128))],512),[[Qt,c.value.VAD]])])]),g("div",Dc,[x[18]||(x[18]=g("label",null,"语音识别选择",-1)),g("div",Lc,[we(g("select",{"onUpdate:modelValue":x[5]||(x[5]=O=>c.value.ASR=O),class:"form-input"},[(N(!0),J(le,null,lt(l.value.ASR,O=>(N(),J("option",{key:O,value:O},z(O),9,jc))),128))],512),[[Qt,c.value.ASR]])])]),g("div",{class:"form-actions"},[g("button",{class:"refresh-btn",onClick:j},"刷新配置选项"),g("button",{class:"save-btn",onClick:Z},x[19]||(x[19]=[g("i",{class:"icon-save"},null,-1),G(" 保存配置 ")]))]),x[20]||(x[20]=g("div",{class:"form-note"}," 注意:保存配置后,需要重启设备,新的配置才会生效。。 ",-1))])])])}}},Hc=Fe(Uc,[["__scopeId","data-v-0bc99910"]]),Bc={},Fc={class:"footer"};function Nc(e,t){return N(),J("footer",Fc,t[0]||(t[0]=[g("div",{class:"copyright"},"© 2025 小智 AI 管理后台",-1)]))}const Vc=Fe(Bc,[["render",Nc],["__scopeId","data-v-cf2abdb4"]]),$c={name:"App",components:{Login:Rl,Registration:Bl,panel:cc,MainPage:dc,RoleSetting:Hc,Footer:Vc},data(){return{showRegistration:!1,isLoggedIn:!1,currentView:"main",selectedDeviceId:null}},methods:{handleLoginSuccess(){this.isLoggedIn=!0,this.currentView="panel"},switchView(e){console.log("Switching to view:",e),this.currentView=e},handleShowRole(e){this.selectedDeviceId=e,this.switchView("RoleSetting")}}},Kc={id:"app"},kc={key:0},qc={key:1,class:"main-layout"};function Qc(e,t,s,n,i,o){const r=$e("Login"),l=$e("Registration"),c=$e("role-setting"),d=$e("panel"),a=$e("main-page"),h=$e("Footer");return N(),J("div",Kc,[g("div",{class:st(["app-content",{"auth-layout":!i.isLoggedIn}])},[i.isLoggedIn?(N(),J("div",qc,[i.currentView==="RoleSetting"?(N(),ct(c,{key:0,"device-id":i.selectedDeviceId,onBackToPanel:t[2]||(t[2]=v=>o.switchView("panel"))},null,8,["device-id"])):i.currentView==="panel"?(N(),ct(d,{key:1,onGoHome:t[3]||(t[3]=v=>o.switchView("main")),onShowRole:o.handleShowRole},null,8,["onShowRole"])):(N(),ct(a,{key:2,onEnterPanel:t[4]||(t[4]=v=>o.switchView("panel"))}))])):(N(),J("div",kc,[i.showRegistration?(N(),ct(l,{key:1,onShowLogin:t[1]||(t[1]=v=>i.showRegistration=!1)})):(N(),ct(r,{key:0,onShowRegistration:t[0]||(t[0]=v=>i.showRegistration=!0),onLoginSuccess:o.handleLoginSuccess},null,8,["onLoginSuccess"]))]))],2),ce(h)])}const Wc=Fe($c,[["render",Qc]]);wl(Wc).mount("#app"); diff --git a/manager/static/webui/index.html b/manager/static/webui/index.html new file mode 100644 index 00000000..fa427e24 --- /dev/null +++ b/manager/static/webui/index.html @@ -0,0 +1,27 @@ + + + + + + + 智控台 + + + + + +
+ + diff --git a/manager/static/webui/vite.svg b/manager/static/webui/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/manager/static/webui/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/manager/user_manager.py b/manager/user_manager.py new file mode 100644 index 00000000..94e89276 --- /dev/null +++ b/manager/user_manager.py @@ -0,0 +1,67 @@ +import os +import yaml +import hashlib +import logging + +logger = logging.getLogger(__name__) + +class UserManager: + def __init__(self): + self.secrets_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), '.secrets.yaml') + self.users = {} + self.ensure_secrets_file() + self.load_user_data() + + def ensure_secrets_file(self): + """确保 .secrets.yaml 文件存在""" + if not os.path.exists(self.secrets_path): + default_config = { + 'users': {} + } + try: + with open(self.secrets_path, 'w', encoding='utf-8') as f: + yaml.dump(default_config, f) + os.chmod(self.secrets_path, 0o600) + logger.info("Created new .secrets.yaml file") + except Exception as e: + logger.error(f"Failed to create .secrets.yaml: {e}") + raise + + def load_user_data(self): + """加载用户数据""" + try: + with open(self.secrets_path, 'r', encoding='utf-8') as f: + data = yaml.safe_load(f) or {'users': {}} + self.users = data['users'] + logger.info("Successfully loaded user data") + except Exception as e: + logger.error(f"Failed to load user data: {e}") + self.users = {} + + def save_user_data(self): + """保存用户数据""" + try: + with open(self.secrets_path, 'w', encoding='utf-8') as f: + yaml.dump({'users': self.users}, f) + logger.info("Successfully saved user data") + except Exception as e: + logger.error(f"Failed to save user data: {e}") + raise + + def hash_password(self, password): + """密码哈希""" + return hashlib.sha256(password.encode()).hexdigest() + + def get_users(self): + """获取所有用户""" + return self.users + + def get_user(self, username): + """获取指定用户""" + return self.users.get(username) + + def update_user(self, username, data): + """更新用户数据""" + if username in self.users: + self.users[username].update(data) + self.save_user_data() diff --git a/requirements.txt b/requirements.txt index 77523f3e..10573316 100755 --- a/requirements.txt +++ b/requirements.txt @@ -11,4 +11,5 @@ openai==1.61.0 google-generativeai==0.8.4 edge_tts==7.0.0 httpx==0.27.2 -aiohttp==3.9.3 \ No newline at end of file +aiohttp==3.9.3 +aiohttp_cors==0.7.0 \ No newline at end of file diff --git a/run_webui.py b/run_webui.py new file mode 100644 index 00000000..d2e6b856 --- /dev/null +++ b/run_webui.py @@ -0,0 +1,12 @@ +import os +import sys + +# 添加项目根目录到Python路径 +project_root = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(project_root) + +from core.webui import WebUI + +if __name__ == '__main__': + webui = WebUI() + webui.run()