diff --git a/frontend_admin/.env.development b/frontend_admin/.env.development new file mode 100644 index 0000000..71af20f --- /dev/null +++ b/frontend_admin/.env.development @@ -0,0 +1,2 @@ +VITE_APP_TITLE=Easycard 管理后台 +VITE_API_BASE_URL= diff --git a/frontend_admin/.env.production b/frontend_admin/.env.production new file mode 100644 index 0000000..71af20f --- /dev/null +++ b/frontend_admin/.env.production @@ -0,0 +1,2 @@ +VITE_APP_TITLE=Easycard 管理后台 +VITE_API_BASE_URL= diff --git a/frontend_admin/index.html b/frontend_admin/index.html new file mode 100644 index 0000000..2604da0 --- /dev/null +++ b/frontend_admin/index.html @@ -0,0 +1,13 @@ + + + + + + + Easycard 管理后台 + + +
+ + + diff --git a/frontend_admin/package-lock.json b/frontend_admin/package-lock.json new file mode 100644 index 0000000..ace9fab --- /dev/null +++ b/frontend_admin/package-lock.json @@ -0,0 +1,2597 @@ +{ + "name": "easycard-admin", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "easycard-admin", + "version": "0.1.0", + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "axios": "^1.9.0", + "element-plus": "^2.9.11", + "pinia": "^3.0.3", + "sortablejs": "^1.15.7", + "vue": "^3.5.13", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.2", + "@types/node": "^24.0.3", + "@types/sortablejs": "^1.15.9", + "@vitejs/plugin-vue": "^5.2.4", + "@vue/tsconfig": "^0.7.0", + "sass": "^1.89.2", + "typescript": "~5.8.3", + "vite": "^6.3.5", + "vue-tsc": "^2.2.10" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", + "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.8", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz", + "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tsconfig/node22": { + "version": "22.0.5", + "resolved": "https://registry.npmmirror.com/@tsconfig/node22/-/node22-22.0.5.tgz", + "integrity": "sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "24.12.0", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/sortablejs": { + "version": "1.15.9", + "resolved": "https://registry.npmmirror.com/@types/sortablejs/-/sortablejs-1.15.9.tgz", + "integrity": "sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.15" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.29.tgz", + "integrity": "sha512-cuzPhD8fwRHk8IGfmYaR4eEe4cAyJEL66Ove/WZL7yWNL134nqLddSLwNRIsFlnnW1kK+p8Ck3viFnC0chXCXw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/shared": "3.5.29", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.29.tgz", + "integrity": "sha512-n0G5o7R3uBVmVxjTIYcz7ovr8sy7QObFG8OQJ3xGCDNhbG60biP/P5KnyY8NLd81OuT1WJflG7N4KWYHaeeaIg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.29", + "@vue/shared": "3.5.29" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.29.tgz", + "integrity": "sha512-oJZhN5XJs35Gzr50E82jg2cYdZQ78wEwvRO6Y63TvLVTc+6xICzJHP1UIecdSPPYIbkautNBanDiWYa64QSFIA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/compiler-core": "3.5.29", + "@vue/compiler-dom": "3.5.29", + "@vue/compiler-ssr": "3.5.29", + "@vue/shared": "3.5.29", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.29.tgz", + "integrity": "sha512-Y/ARJZE6fpjzL5GH/phJmsFwx3g6t2KmHKHx5q+MLl2kencADKIrhH5MLF6HHpRMmlRAYBRSvv347Mepf1zVNw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.29", + "@vue/shared": "3.5.29" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/language-core": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.29.tgz", + "integrity": "sha512-zcrANcrRdcLtmGZETBxWqIkoQei8HaFpZWx/GHKxx79JZsiZ8j1du0VUJtu4eJjgFvU/iKL5lRXFXksVmI+5DA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.29" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.29.tgz", + "integrity": "sha512-8DpW2QfdwIWOLqtsNcds4s+QgwSaHSJY/SUe04LptianUQ/0xi6KVsu/pYVh+HO3NTVvVJjIPL2t6GdeKbS4Lg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.29", + "@vue/shared": "3.5.29" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.29.tgz", + "integrity": "sha512-AHvvJEtcY9tw/uk+s/YRLSlxxQnqnAkjqvK25ZiM4CllCZWzElRAoQnCM42m9AHRLNJ6oe2kC5DCgD4AUdlvXg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.29", + "@vue/runtime-core": "3.5.29", + "@vue/shared": "3.5.29", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.29.tgz", + "integrity": "sha512-G/1k6WK5MusLlbxSE2YTcqAAezS+VuwHhOvLx2KnQU7G2zCH6KIb+5Wyt6UjMq7a3qPzNEjJXs1hvAxDclQH+g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.29", + "@vue/shared": "3.5.29" + }, + "peerDependencies": { + "vue": "3.5.29" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.29.tgz", + "integrity": "sha512-w7SR0A5zyRByL9XUkCfdLs7t9XOHUyJ67qPGQjOou3p6GvBeBW+AVjUUmlxtZ4PIYaRvE+1LmK44O4uajlZwcg==", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.7.0", + "resolved": "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.7.0.tgz", + "integrity": "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": "5.x", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core": { + "version": "12.0.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-12.0.0.tgz", + "integrity": "sha512-C12RukhXiJCbx4MGhjmd/gH52TjJsc3G0E0kQj/kb19H3Nt6n1CA4DRWuTdWWcaFRdlTe0npWDS942mvacvNBw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "12.0.0", + "@vueuse/shared": "12.0.0", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.0.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-12.0.0.tgz", + "integrity": "sha512-Yzimd1D3sjxTDOlF05HekU5aSGdKjxhuhRFHA7gDWLn57PRbBIh+SF5NmjhJ0WRgF3my7T8LBucyxdFJjIfRJQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.0.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-12.0.0.tgz", + "integrity": "sha512-3i6qtcq2PIio5i/vVYidkkcgvmTjCqrf26u+Fd4LhnbBmIT6FN8y6q/GJERp8lfcB9zVEfjdV0Br0443qZuJpw==", + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.6", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/element-plus": { + "version": "2.13.5", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.13.5.tgz", + "integrity": "sha512-dmY24fhSREfZN/PuUt0YZigMso7wWzl+B5o+YKNN15kQIn/0hzamsPU+ebj9SES0IbUqsLX1wkrzYmzU8VrVOQ==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^4.2.0", + "@element-plus/icons-vue": "^2.3.2", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.17.20", + "@types/lodash-es": "^4.17.12", + "@vueuse/core": "12.0.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.19", + "lodash": "^4.17.23", + "lodash-es": "^4.17.23", + "lodash-unified": "^1.0.3", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.3.0" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/immutable": { + "version": "5.1.5", + "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "license": "MIT" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/sass": { + "version": "1.97.3", + "resolved": "https://registry.npmmirror.com/sass/-/sass-1.97.3.tgz", + "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sortablejs": { + "version": "1.15.7", + "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.7.tgz", + "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", + "license": "MIT" + }, + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.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 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.29", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.29.tgz", + "integrity": "sha512-BZqN4Ze6mDQVNAni0IHeMJ5mwr8VAJ3MQC9FmprRhcBYENw+wOAAjRj8jfmN6FLl0j96OXbR+CjWhmAmM+QGnA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.29", + "@vue/compiler-sfc": "3.5.29", + "@vue/runtime-dom": "3.5.29", + "@vue/server-renderer": "3.5.29", + "@vue/shared": "3.5.29" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + } + } +} diff --git a/frontend_admin/package.json b/frontend_admin/package.json new file mode 100644 index 0000000..ca3fcf3 --- /dev/null +++ b/frontend_admin/package.json @@ -0,0 +1,31 @@ +{ + "name": "easycard-admin", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc -b && vite build && rm -f dist.zip && cd dist && zip -rq ../dist.zip .", + "preview": "vite preview" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "axios": "^1.9.0", + "element-plus": "^2.9.11", + "pinia": "^3.0.3", + "sortablejs": "^1.15.7", + "vue": "^3.5.13", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.2", + "@types/node": "^24.0.3", + "@types/sortablejs": "^1.15.9", + "@vitejs/plugin-vue": "^5.2.4", + "@vue/tsconfig": "^0.7.0", + "sass": "^1.89.2", + "typescript": "~5.8.3", + "vite": "^6.3.5", + "vue-tsc": "^2.2.10" + } +} diff --git a/frontend_admin/public/favicon.svg b/frontend_admin/public/favicon.svg new file mode 100644 index 0000000..80fdadf --- /dev/null +++ b/frontend_admin/public/favicon.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend_admin/src/App.vue b/frontend_admin/src/App.vue new file mode 100644 index 0000000..98240ae --- /dev/null +++ b/frontend_admin/src/App.vue @@ -0,0 +1,3 @@ + diff --git a/frontend_admin/src/api/auth.ts b/frontend_admin/src/api/auth.ts new file mode 100644 index 0000000..5962dd8 --- /dev/null +++ b/frontend_admin/src/api/auth.ts @@ -0,0 +1,18 @@ +import { http } from '@/utils/http' +import type { CurrentUser, LoginResult } from '@/types/auth' + +export function login(data: { username: string; password: string }) { + return http.post('/api/v1/auth/login', data) +} + +export function logout() { + return http.post('/api/v1/auth/logout') +} + +export function getCurrentUser() { + return http.get('/api/v1/auth/me') +} + +export function changePassword(data: { oldPassword: string; newPassword: string }) { + return http.post('/api/v1/auth/change-password', data) +} diff --git a/frontend_admin/src/api/file.ts b/frontend_admin/src/api/file.ts new file mode 100644 index 0000000..589b795 --- /dev/null +++ b/frontend_admin/src/api/file.ts @@ -0,0 +1,12 @@ +import { http } from '@/utils/http' +import type { FileAsset } from '@/types/file' + +export function uploadFile(file: File) { + const formData = new FormData() + formData.append('file', file) + return http.post('/api/v1/files/upload', formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }) +} diff --git a/frontend_admin/src/api/platform.ts b/frontend_admin/src/api/platform.ts new file mode 100644 index 0000000..61ffed5 --- /dev/null +++ b/frontend_admin/src/api/platform.ts @@ -0,0 +1,26 @@ +import { http } from '@/utils/http' +import type { MiniappConfig, TenantCreatePayload, TenantDetail, TenantFormPayload } from '@/types/platform' + +export function listTenants() { + return http.get('/api/v1/platform/tenants') +} + +export function createTenant(data: TenantCreatePayload) { + return http.post('/api/v1/platform/tenants', data) +} + +export function updateTenant(tenantId: number, data: TenantFormPayload) { + return http.put(`/api/v1/platform/tenants/${tenantId}`, data) +} + +export function deleteTenant(tenantId: number) { + return http.delete(`/api/v1/platform/tenants/${tenantId}`) +} + +export function listMiniapps() { + return http.get('/api/v1/platform/miniapps') +} + +export function updateMiniapp(tenantId: number, data: Omit & { miniappAppSecret?: string; remark?: string }) { + return http.put(`/api/v1/platform/miniapps/${tenantId}`, data) +} diff --git a/frontend_admin/src/api/tenant.ts b/frontend_admin/src/api/tenant.ts new file mode 100644 index 0000000..f60e9da --- /dev/null +++ b/frontend_admin/src/api/tenant.ts @@ -0,0 +1,124 @@ +import { http } from '@/utils/http' +import type { + CardDetail, + CardTrendItem, + DashboardStats, + Department, + FirmProfile, + LawyerListItem, + PracticeArea, + TenantMiniappConfig, + TenantMiniappConfigPayload, + TenantUser, + TenantUserUpsertPayload, +} from '@/types/tenant' + +export function getDashboardStats() { + return http.get('/api/v1/tenant/stats/overview') +} + +export function getDashboardTrend(days = 7) { + return http.get('/api/v1/tenant/stats/trend', { + params: { days }, + }) +} + +export function getFirmProfile() { + return http.get('/api/v1/tenant/firm-profile') +} + +export function saveFirmProfile(data: FirmProfile) { + return http.put('/api/v1/tenant/firm-profile', data) +} + +export function getTenantMiniappConfig() { + return http.get('/api/v1/tenant/miniapp-config') +} + +export function saveTenantMiniappConfig(data: TenantMiniappConfigPayload) { + return http.put('/api/v1/tenant/miniapp-config', data) +} + +export function listPracticeAreas() { + return http.get('/api/v1/tenant/practice-areas') +} + +export function createPracticeArea(data: Omit) { + return http.post('/api/v1/tenant/practice-areas', data) +} + +export function updatePracticeArea(areaId: number, data: Omit) { + return http.put(`/api/v1/tenant/practice-areas/${areaId}`, data) +} + +export function listDepartments() { + return http.get('/api/v1/tenant/departments') +} + +export function createDepartment(data: Omit) { + return http.post('/api/v1/tenant/departments', data) +} + +export function updateDepartment(deptId: number, data: Omit) { + return http.put(`/api/v1/tenant/departments/${deptId}`, data) +} + +export function listUsers(keyword = '') { + return http.get('/api/v1/tenant/users', { + params: { keyword: keyword || undefined }, + }) +} + +export function createUser(data: TenantUserUpsertPayload) { + return http.post('/api/v1/tenant/users', data) +} + +export function updateUser(userId: number, data: TenantUserUpsertPayload) { + return http.put(`/api/v1/tenant/users/${userId}`, data) +} + +export function resetUserPassword(userId: number) { + return http.post(`/api/v1/tenant/users/${userId}/reset-password`) +} + +export function updateUserStatus(userId: number, userStatus: TenantUser['userStatus']) { + return http.patch(`/api/v1/tenant/users/${userId}/status`, { userStatus }) +} + +export function sortUsers(userIds: number[]) { + return http.put('/api/v1/tenant/users/sort', { userIds }) +} + +export function listLawyers(keyword = '') { + return http.get('/api/v1/tenant/cards', { + params: { keyword: keyword || undefined }, + }) +} + +export function createLawyer(data: CardDetail) { + return http.post('/api/v1/tenant/cards', data) +} + +export function getCard(cardId: number) { + return http.get(`/api/v1/tenant/cards/${cardId}`) +} + +export function updateCard(cardId: number, data: CardDetail) { + return http.put(`/api/v1/tenant/cards/${cardId}`, data) +} + +export function deleteCard(cardId: number) { + return http.delete(`/api/v1/tenant/cards/${cardId}`) +} + +export function sortCards(cardIds: number[]) { + return http.put('/api/v1/tenant/cards/sort', { cardIds }) +} + +export function getMyCard() { + return http.get('/api/v1/tenant/cards/me') +} + +export function saveMyCard(data: CardDetail) { + return http.put('/api/v1/tenant/cards/me', data) +} diff --git a/frontend_admin/src/assets/styles/index.scss b/frontend_admin/src/assets/styles/index.scss new file mode 100644 index 0000000..2274638 --- /dev/null +++ b/frontend_admin/src/assets/styles/index.scss @@ -0,0 +1,608 @@ +:root { + --ec-bg: #fbfbfd; + --ec-bg-accent: #f5f5f7; + --ec-surface: rgba(255, 255, 255, 0.82); + --ec-surface-strong: #ffffff; + --ec-surface-soft: rgba(255, 255, 255, 0.5); + --ec-border: rgba(34, 45, 37, 0.08); + --ec-border-strong: rgba(34, 45, 37, 0.14); + --ec-text: #1d1d1f; + --ec-text-secondary: #86868b; + --ec-accent: #223b31; + --ec-accent-strong: #16271f; + --ec-accent-soft: rgba(34, 59, 49, 0.08); + --ec-accent-muted: #8e9c95; + --ec-warning-soft: rgba(210, 156, 58, 0.1); + --ec-danger: #d93025; + --ec-shadow: 0 12px 36px rgba(0, 0, 0, 0.04); + --ec-shadow-soft: 0 6px 16px rgba(0, 0, 0, 0.03); + --ec-shadow-hover: 0 16px 48px rgba(0, 0, 0, 0.08); + --ec-radius-xl: 28px; + --ec-radius-lg: 20px; + --ec-radius-md: 16px; + --ec-radius-sm: 12px; + --ec-transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); +} + +* { + box-sizing: border-box; +} + +html, +body, +#app { + min-height: 100%; + margin: 0; +} + +body { + background: + radial-gradient(circle at 0 0, rgba(34, 59, 49, 0.12), transparent 22%), + radial-gradient(circle at 100% 20%, rgba(211, 200, 180, 0.24), transparent 20%), + linear-gradient(180deg, #f7f5f0 0%, var(--ec-bg) 44%, var(--ec-bg-accent) 100%); + color: var(--ec-text); + font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +button, +input, +textarea { + font: inherit; +} + +.page-shell { + padding: 24px; +} + +.page-card { + background: var(--ec-surface); + border: 1px solid var(--ec-border); + border-radius: var(--ec-radius-lg); + box-shadow: var(--ec-shadow); + backdrop-filter: blur(20px); + transition: var(--ec-transition); +} + +.page-card:hover { + box-shadow: var(--ec-shadow-hover); + transform: translateY(-2px); +} + +.page-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + margin-bottom: 20px; +} + +.page-title { + margin: 0; + font-size: 26px; + line-height: 1.2; + font-weight: 700; + letter-spacing: -0.02em; +} + +.page-subtitle { + margin: 8px 0 0; + color: var(--ec-text-secondary); + font-size: 13px; + line-height: 1.5; +} + +.page-section-title { + margin: 0 0 14px; + font-size: 16px; + font-weight: 700; +} + +.eyebrow { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 12px; + border: 1px solid var(--ec-border); + border-radius: 999px; + background: rgba(255, 255, 255, 0.7); + color: var(--ec-text-secondary); + font-size: 11px; + letter-spacing: 0.1em; +} + +.section-grid { + display: grid; + grid-template-columns: repeat(12, minmax(0, 1fr)); + gap: 16px; +} + +.section-span-4 { + grid-column: span 4; +} + +.section-span-6 { + grid-column: span 6; +} + +.section-span-8 { + grid-column: span 8; +} + +.section-span-12 { + grid-column: span 12; +} + +.stat-card { + padding: 20px; +} + +.stat-card__label { + color: var(--ec-text-secondary); + font-size: 13px; +} + +.stat-card__value { + margin-top: 12px; + font-size: 32px; + font-weight: 700; +} + +.stat-card__helper { + margin-top: 10px; + color: var(--ec-text-secondary); + font-size: 13px; +} + +.metric-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 16px; +} + +.metric-tile { + padding: 18px 18px 16px; + border: 1px solid var(--ec-border); + border-radius: var(--ec-radius-md); + background: rgba(255, 255, 255, 0.58); + box-shadow: var(--ec-shadow-soft); + transition: var(--ec-transition); +} + +.metric-tile:hover { + box-shadow: var(--ec-shadow-hover); + transform: translateY(-2px); + background: rgba(255, 255, 255, 0.82); +} + +.metric-tile__label { + color: var(--ec-text-secondary); + font-size: 12px; +} + +.metric-tile__value { + margin-top: 12px; + font-size: 30px; + font-weight: 700; + letter-spacing: -0.03em; +} + +.metric-tile__footnote { + margin-top: 10px; + color: var(--ec-text-secondary); + font-size: 12px; + line-height: 1.4; +} + +.filter-bar { + display: flex; + flex-wrap: wrap; + gap: 12px; + align-items: center; +} + +.filter-bar__grow { + flex: 1 1 260px; +} + +.split-panel { + display: grid; + grid-template-columns: 1.2fr 0.8fr; + gap: 20px; +} + +.info-list { + display: grid; + gap: 12px; +} + +.info-item { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + padding: 14px 0; + border-bottom: 1px solid rgba(34, 45, 37, 0.08); +} + +.info-item:last-child { + border-bottom: 0; +} + +.info-item__label { + color: var(--ec-text-secondary); + font-size: 13px; +} + +.info-item__value { + text-align: right; + font-size: 14px; + font-weight: 600; +} + +.law-chip { + display: inline-flex; + align-items: center; + padding: 6px 10px; + border-radius: 999px; + background: var(--ec-accent-soft); + color: var(--ec-accent-strong); + font-size: 12px; + font-weight: 600; +} + +.law-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--ec-accent); + box-shadow: 0 0 0 5px rgba(34, 59, 49, 0.08); +} + +.shell-stack { + display: grid; + gap: 16px; +} + +.hero-panel { + position: relative; + overflow: hidden; + padding: 24px; + border-radius: var(--ec-radius-xl); + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.72), rgba(255, 255, 255, 0.56)), + linear-gradient(120deg, rgba(34, 59, 49, 0.06), transparent 48%); +} + +.hero-panel::after { + content: ''; + position: absolute; + right: -40px; + top: -40px; + width: 180px; + height: 180px; + border-radius: 50%; + background: radial-gradient(circle, rgba(34, 59, 49, 0.1), transparent 68%); +} + +.hero-grid { + position: relative; + z-index: 1; + display: grid; + grid-template-columns: minmax(0, 1.1fr) minmax(320px, 0.9fr); + gap: 20px; +} + +.hero-main { + display: grid; + gap: 18px; +} + +.hero-kicker { + display: flex; + align-items: center; + gap: 10px; + color: var(--ec-text-secondary); + font-size: 12px; + letter-spacing: 0.12em; +} + +.hero-main h1, +.hero-main h2 { + margin: 0; + font-size: 34px; + line-height: 1.06; + letter-spacing: -0.04em; +} + +.hero-main p { + max-width: 560px; + margin: 0; + color: var(--ec-text-secondary); + font-size: 14px; + line-height: 1.6; +} + +.hero-side { + display: grid; + gap: 12px; + align-content: start; +} + +.quick-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; +} + +.quick-card { + padding: 16px; + border: 1px solid var(--ec-border); + border-radius: var(--ec-radius-md); + background: rgba(255, 255, 255, 0.56); + transition: var(--ec-transition); +} + +.quick-card:hover { + background: rgba(255, 255, 255, 0.88); + transform: translateY(-1px); + box-shadow: var(--ec-shadow-soft); +} + +.quick-card strong { + display: block; + font-size: 24px; + letter-spacing: -0.03em; +} + +.quick-card span { + display: block; + margin-top: 6px; + color: var(--ec-text-secondary); + font-size: 12px; +} + +.compact-list { + display: grid; + gap: 10px; +} + +.compact-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 14px; + padding: 12px 14px; + border: 1px solid var(--ec-border); + border-radius: 16px; + background: rgba(255, 255, 255, 0.5); + transition: var(--ec-transition); +} + +.compact-row:hover { + background: rgba(255, 255, 255, 0.85); + box-shadow: var(--ec-shadow-soft); +} + +.compact-row__main { + display: grid; + gap: 4px; +} + +.compact-row__title { + font-size: 14px; + font-weight: 600; +} + +.compact-row__meta { + color: var(--ec-text-secondary); + font-size: 12px; +} + +.status-pill { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 999px; + font-size: 12px; + font-weight: 600; +} + +.status-pill--success { + background: rgba(64, 132, 91, 0.12); + color: #2f6d4b; +} + +.status-pill--warning { + background: rgba(210, 156, 58, 0.14); + color: #8a6824; +} + +.status-pill--danger { + background: rgba(159, 75, 66, 0.12); + color: #8e4138; +} + +.toolbar-actions { + display: flex; + align-items: center; + gap: 10px; +} + +.subtle-panel { + padding: 18px; + border: 1px solid var(--ec-border); + border-radius: var(--ec-radius-md); + background: rgba(255, 255, 255, 0.5); +} + +.table-meta { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--ec-text-secondary); + font-size: 12px; +} + +.muted { + color: var(--ec-text-secondary); +} + +:deep(.el-button--primary) { + --el-button-bg-color: var(--ec-accent); + --el-button-border-color: var(--ec-accent); + --el-button-hover-bg-color: var(--ec-accent-strong); + --el-button-hover-border-color: var(--ec-accent-strong); + --el-button-active-bg-color: var(--ec-accent-strong); + --el-button-active-border-color: var(--ec-accent-strong); +} + +:deep(.el-input__wrapper), +:deep(.el-select__wrapper), +:deep(.el-textarea__inner) { + border-radius: 14px; + background: rgba(255, 255, 255, 0.82); + box-shadow: none; +} + +:deep(.el-table) { + --el-table-header-bg-color: rgba(242, 238, 231, 0.88); + --el-table-border-color: rgba(34, 45, 37, 0.08); + --el-table-row-hover-bg-color: rgba(228, 235, 231, 0.48); + --el-table-bg-color: transparent; + --el-fill-color-blank: transparent; +} + +:deep(.el-table th.el-table__cell) { + color: var(--ec-text-secondary); + font-weight: 600; + font-size: 12px; +} + +:deep(.el-table tr) { + background: transparent; +} + +:deep(.el-table .cell) { + padding-top: 4px; + padding-bottom: 4px; +} + +:deep(.el-menu) { + --el-menu-bg-color: transparent; + --el-menu-hover-bg-color: rgba(255, 255, 255, 0.7); + --el-menu-active-color: var(--ec-accent-strong); +} + +:deep(.el-button) { + border-radius: 14px; +} + +@media (max-width: 1200px) { + .section-span-4, + .section-span-6, + .section-span-8 { + grid-column: span 12; + } + + .metric-grid, + .split-panel, + .hero-grid, + .quick-grid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 768px) { + .page-shell { + padding: 16px; + } + + .page-title { + font-size: 24px; + } + + .metric-grid { + grid-template-columns: 1fr; + } + + .hero-main h1, + .hero-main h2 { + font-size: 28px; + } +} + +.section-panel { + padding: 24px; +} + +.table-stack { + display: grid; + gap: 6px; +} + +.page-form :deep(.el-form-item) { + margin-bottom: 18px; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0 16px; +} + +.form-grid__full { + grid-column: 1 / -1; +} + +.panel-title { + margin: 12px 0 18px; + font-size: 14px; + font-weight: 700; +} + +.summary-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; +} + +.summary-card { + display: grid; + gap: 8px; + padding: 16px; + border: 1px solid var(--ec-border); + border-radius: var(--ec-radius-md); + background: rgba(255, 255, 255, 0.58); + transition: var(--ec-transition); +} + +.summary-card:hover { + background: rgba(255, 255, 255, 0.88); + transform: translateY(-2px); + box-shadow: var(--ec-shadow-soft); +} + +.summary-card__label, +.summary-card__meta { + color: var(--ec-text-secondary); + font-size: 12px; +} + +.summary-card__value { + font-size: 28px; + font-weight: 700; + letter-spacing: -0.03em; +} + +@media (max-width: 768px) { + .form-grid, + .summary-grid { + grid-template-columns: 1fr; + } +} diff --git a/frontend_admin/src/env.d.ts b/frontend_admin/src/env.d.ts new file mode 100644 index 0000000..7c188e2 --- /dev/null +++ b/frontend_admin/src/env.d.ts @@ -0,0 +1,10 @@ +/// + +interface ImportMetaEnv { + readonly VITE_APP_TITLE: string + readonly VITE_API_BASE_URL: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/frontend_admin/src/layouts/AdminLayout.vue b/frontend_admin/src/layouts/AdminLayout.vue new file mode 100644 index 0000000..ce48b1c --- /dev/null +++ b/frontend_admin/src/layouts/AdminLayout.vue @@ -0,0 +1,376 @@ + + + + + diff --git a/frontend_admin/src/main.ts b/frontend_admin/src/main.ts new file mode 100644 index 0000000..57a89d8 --- /dev/null +++ b/frontend_admin/src/main.ts @@ -0,0 +1,19 @@ +import ElementPlus from 'element-plus' +import zhCn from 'element-plus/es/locale/lang/zh-cn' +import { createApp } from 'vue' + +import App from './App.vue' +import { router } from './router' +import { pinia } from './stores' +import './assets/styles/index.scss' +import 'element-plus/dist/index.css' + +const app = createApp(App) + +app.use(pinia) +app.use(router) +app.use(ElementPlus, { + locale: zhCn, +}) + +app.mount('#app') diff --git a/frontend_admin/src/mock/tenant.ts b/frontend_admin/src/mock/tenant.ts new file mode 100644 index 0000000..38adcb8 --- /dev/null +++ b/frontend_admin/src/mock/tenant.ts @@ -0,0 +1,55 @@ +export interface TenantItem { + id: number + tenantName: string + tenantCode: string + contactName: string + contactPhone: string + adminName: string + userLimit: number + activeUsers: number + miniappAppId: string + storageUsage: string + city: string +} + +export const tenantList: TenantItem[] = [ + { + id: 1, + tenantName: '衡知律师事务所', + tenantCode: 'hengzhi-law', + contactName: '李主任', + contactPhone: '13800138000', + adminName: '王律师', + userLimit: 20, + activeUsers: 12, + miniappAppId: 'wx8b1c6d1f0a1e0001', + storageUsage: '1.6 GB / 10 GB', + city: '南京', + }, + { + id: 2, + tenantName: '明理律师事务所', + tenantCode: 'mingli-law', + contactName: '周主任', + contactPhone: '13800138008', + adminName: '周律师', + userLimit: 50, + activeUsers: 34, + miniappAppId: 'wx8b1c6d1f0a1e0002', + storageUsage: '3.8 GB / 20 GB', + city: '上海', + }, + { + id: 3, + tenantName: '启衡律师事务所', + tenantCode: 'qiheng-law', + contactName: '陈律师', + contactPhone: '13800138018', + adminName: '陈律师', + userLimit: 30, + activeUsers: 18, + miniappAppId: 'wx8b1c6d1f0a1e0003', + storageUsage: '4.2 GB / 10 GB', + city: '杭州', + }, +] diff --git a/frontend_admin/src/router/index.ts b/frontend_admin/src/router/index.ts new file mode 100644 index 0000000..834bafb --- /dev/null +++ b/frontend_admin/src/router/index.ts @@ -0,0 +1,38 @@ +import { createRouter, createWebHistory } from 'vue-router' + +import { useAuthStore } from '@/stores/auth' +import { pinia } from '@/stores' + +import { routes } from './routes' + +export const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes, + scrollBehavior() { + return { top: 0 } + }, +}) + +router.beforeEach((to) => { + const authStore = useAuthStore(pinia) + return authStore.bootstrap().then(() => { + if (to.meta.requiresAuth && !authStore.isAuthenticated) { + return { + path: '/login', + query: { + redirect: to.fullPath, + }, + } + } + + if (to.meta.guestOnly && authStore.isAuthenticated) { + return '/dashboard' + } + + if (to.meta.roles && !authStore.hasAnyRole(to.meta.roles)) { + return '/dashboard' + } + + return true + }) +}) diff --git a/frontend_admin/src/router/routes.ts b/frontend_admin/src/router/routes.ts new file mode 100644 index 0000000..89c15bc --- /dev/null +++ b/frontend_admin/src/router/routes.ts @@ -0,0 +1,190 @@ +import type { RouteRecordRaw } from 'vue-router' +import type { RoleCode } from '@/types/common' + +import { + HomeFilled, + Lock, + Notebook, + OfficeBuilding, + Postcard, + Setting, + User, + UserFilled, +} from '@element-plus/icons-vue' + +export interface AppRouteMeta { + title: string + icon?: unknown + hidden?: boolean + activeMenu?: string + requiresAuth?: boolean + guestOnly?: boolean + subtitle?: string + roles?: RoleCode[] +} + +declare module 'vue-router' { + interface RouteMeta extends AppRouteMeta {} +} + +export const routes: RouteRecordRaw[] = [ + { + path: '/login', + name: 'login', + component: () => import('@/views/system/LoginView.vue'), + meta: { + title: '登录', + icon: Lock, + hidden: true, + guestOnly: true, + }, + }, + { + path: '/', + component: () => import('@/layouts/AdminLayout.vue'), + redirect: '/dashboard', + meta: { + requiresAuth: true, + title: '控制台', + }, + children: [ + { + path: 'dashboard', + name: 'dashboard', + component: () => import('@/views/dashboard/DashboardView.vue'), + meta: { + title: '首页', + icon: HomeFilled, + subtitle: '概览核心数字与主链路状态。', + requiresAuth: true, + roles: ['PLATFORM_SUPER_ADMIN', 'TENANT_ADMIN', 'TENANT_USER'], + }, + }, + { + path: 'tenants', + name: 'tenants', + component: () => import('@/views/tenant/TenantListView.vue'), + meta: { + title: '租户管理', + icon: OfficeBuilding, + subtitle: '查看租户状态、席位与续期节点。', + requiresAuth: true, + roles: ['PLATFORM_SUPER_ADMIN'], + }, + }, + { + path: 'firm-profile', + name: 'firm-profile', + component: () => import('@/views/tenant/FirmProfileView.vue'), + meta: { + title: '事务所资料', + icon: Notebook, + subtitle: '维护主页信息、专业领域与组织架构。', + requiresAuth: true, + roles: ['TENANT_ADMIN'], + }, + }, + { + path: 'lawyers', + name: 'lawyers', + component: () => import('@/views/tenant/LawyerListView.vue'), + meta: { + title: '律师管理', + icon: UserFilled, + subtitle: '统一维护律师名片、展示顺序与对外资料。', + requiresAuth: true, + roles: ['TENANT_ADMIN'], + }, + }, + { + path: 'lawyers/create', + name: 'lawyer-create', + component: () => import('@/views/card/MyCardView.vue'), + meta: { + title: '新增律师', + subtitle: '创建律师名片并补充对外展示资料。', + activeMenu: '/lawyers', + hidden: true, + requiresAuth: true, + roles: ['TENANT_ADMIN'], + }, + }, + { + path: 'lawyers/:cardId/edit', + name: 'lawyer-edit', + component: () => import('@/views/card/MyCardView.vue'), + meta: { + title: '编辑律师', + subtitle: '修改律师名片、图片素材与展示信息。', + activeMenu: '/lawyers', + hidden: true, + requiresAuth: true, + roles: ['TENANT_ADMIN'], + }, + }, + { + path: 'tenant-users', + name: 'tenant-users', + component: () => import('@/views/tenant/UserListView.vue'), + meta: { + title: '用户管理', + icon: UserFilled, + subtitle: '管理当前租户成员账号与角色。', + hidden: true, + requiresAuth: true, + roles: ['TENANT_ADMIN'], + }, + }, + { + path: 'tenant-miniapp', + name: 'tenant-miniapp', + component: () => import('@/views/tenant/TenantMiniappBindingView.vue'), + meta: { + title: '小程序管理', + icon: Setting, + subtitle: '绑定当前租户站点与小程序 AppID。', + requiresAuth: true, + roles: ['TENANT_ADMIN'], + }, + }, + { + path: 'my-card', + name: 'my-card', + component: () => import('@/views/card/MyCardView.vue'), + meta: { + title: '我的名片', + icon: Postcard, + subtitle: '编辑并发布个人电子名片。', + hidden: true, + requiresAuth: true, + roles: ['TENANT_ADMIN', 'TENANT_USER'], + }, + }, + { + path: 'profile', + name: 'profile', + component: () => import('@/views/system/ProfileView.vue'), + meta: { + title: '个人中心', + icon: User, + subtitle: '查看登录信息并修改密码。', + requiresAuth: true, + roles: ['PLATFORM_SUPER_ADMIN', 'TENANT_ADMIN', 'TENANT_USER'], + }, + }, + { + path: 'settings', + name: 'settings', + component: () => import('@/views/system/SystemSettingsView.vue'), + meta: { + title: '系统配置', + icon: Setting, + subtitle: '维护平台参数与基础配置。', + requiresAuth: true, + hidden: true, + roles: ['PLATFORM_SUPER_ADMIN'], + }, + }, + ], + }, +] diff --git a/frontend_admin/src/stores/app.ts b/frontend_admin/src/stores/app.ts new file mode 100644 index 0000000..7eecd29 --- /dev/null +++ b/frontend_admin/src/stores/app.ts @@ -0,0 +1,22 @@ +import { computed, ref } from 'vue' +import { defineStore } from 'pinia' + +export const useAppStore = defineStore('app', () => { + const appTitle = ref(import.meta.env.VITE_APP_TITLE || 'Easycard 管理后台') + const appTagline = ref('律所电子名片后台') + const asideCollapsed = ref(false) + + const asideWidth = computed(() => (asideCollapsed.value ? '84px' : '240px')) + + function toggleAside() { + asideCollapsed.value = !asideCollapsed.value + } + + return { + appTitle, + appTagline, + asideCollapsed, + asideWidth, + toggleAside, + } +}) diff --git a/frontend_admin/src/stores/auth.ts b/frontend_admin/src/stores/auth.ts new file mode 100644 index 0000000..55264e4 --- /dev/null +++ b/frontend_admin/src/stores/auth.ts @@ -0,0 +1,109 @@ +import { computed, ref } from 'vue' +import { defineStore } from 'pinia' + +import * as authApi from '@/api/auth' +import type { CurrentUser } from '@/types/auth' +import type { RoleCode } from '@/types/common' +import { clearAccessToken, getAccessToken, setAccessToken } from '@/utils/auth' + +export const useAuthStore = defineStore('auth', () => { + const accessToken = ref(getAccessToken()) + const currentUser = ref(null) + const initialized = ref(false) + const bootstrapping = ref(false) + let bootstrapPromise: Promise | null = null + + const isAuthenticated = computed(() => Boolean(accessToken.value && currentUser.value)) + + function clearSession() { + accessToken.value = '' + currentUser.value = null + clearAccessToken() + } + + function hasAnyRole(roles?: RoleCode[]) { + if (!roles || roles.length === 0) { + return true + } + const codes = currentUser.value?.roleCodes ?? [] + return roles.some(role => codes.includes(role)) + } + + async function bootstrap() { + if (initialized.value) { + return Promise.resolve() + } + if (!accessToken.value) { + initialized.value = true + return Promise.resolve() + } + if (bootstrapPromise) { + return bootstrapPromise + } + + bootstrapping.value = true + bootstrapPromise = authApi.getCurrentUser() + .then((user) => { + currentUser.value = user + }) + .catch(() => { + clearSession() + }) + .finally(() => { + initialized.value = true + bootstrapping.value = false + bootstrapPromise = null + }) + + return bootstrapPromise + } + + async function login(payload: { username: string; password: string }) { + const result = await authApi.login(payload) + accessToken.value = result.accessToken + currentUser.value = result.currentUser + initialized.value = true + setAccessToken(result.accessToken) + } + + async function logout() { + try { + if (accessToken.value) { + await authApi.logout() + } + } finally { + clearSession() + initialized.value = true + } + } + + async function refreshCurrentUser() { + if (!accessToken.value) { + clearSession() + return null + } + const user = await authApi.getCurrentUser() + currentUser.value = user + return user + } + + async function changePassword(payload: { oldPassword: string; newPassword: string }) { + await authApi.changePassword(payload) + await refreshCurrentUser() + } + + return { + accessToken, + currentUser, + initialized, + bootstrapping, + isAuthenticated, + bootstrap, + login, + logout, + refreshCurrentUser, + changePassword, + hasAnyRole, + clearSession, + } +}) diff --git a/frontend_admin/src/stores/index.ts b/frontend_admin/src/stores/index.ts new file mode 100644 index 0000000..c569ef7 --- /dev/null +++ b/frontend_admin/src/stores/index.ts @@ -0,0 +1,3 @@ +import { createPinia } from 'pinia' + +export const pinia = createPinia() diff --git a/frontend_admin/src/types/auth.ts b/frontend_admin/src/types/auth.ts new file mode 100644 index 0000000..979bc72 --- /dev/null +++ b/frontend_admin/src/types/auth.ts @@ -0,0 +1,20 @@ +import type { RoleCode } from './common' + +export interface CurrentUser { + id: number + tenantId: number + username: string + realName: string + userType: string + tenantName: string + roleName: string + roleCodes: RoleCode[] + deptName: string + jobTitle: string + mustUpdatePassword: boolean +} + +export interface LoginResult { + accessToken: string + currentUser: CurrentUser +} diff --git a/frontend_admin/src/types/common.ts b/frontend_admin/src/types/common.ts new file mode 100644 index 0000000..ccbf783 --- /dev/null +++ b/frontend_admin/src/types/common.ts @@ -0,0 +1,13 @@ +export interface ApiResponse { + code: string + message: string + data: T +} + +export interface ApiErrorPayload { + code: string + message: string + status?: number +} + +export type RoleCode = 'PLATFORM_SUPER_ADMIN' | 'TENANT_ADMIN' | 'TENANT_USER' diff --git a/frontend_admin/src/types/file.ts b/frontend_admin/src/types/file.ts new file mode 100644 index 0000000..11ff086 --- /dev/null +++ b/frontend_admin/src/types/file.ts @@ -0,0 +1,8 @@ +export interface FileAsset { + id: number + originalName: string + mimeType: string + fileSize: number + accessUrl: string + createdTime: string +} diff --git a/frontend_admin/src/types/platform.ts b/frontend_admin/src/types/platform.ts new file mode 100644 index 0000000..9dad0fc --- /dev/null +++ b/frontend_admin/src/types/platform.ts @@ -0,0 +1,40 @@ +export interface TenantDetail { + id: number + tenantCode: string + tenantName: string + tenantShortName: string + userLimit: number + storageLimitMb: number + contactName: string + contactPhone: string + miniappAppId: string + miniappName: string + miniappOriginalId: string +} + +export interface MiniappConfig { + tenantId: number + tenantCode: string + tenantName: string + envCode: 'DEV' | 'TEST' | 'PROD' + miniappAppId: string + miniappName: string + miniappOriginalId: string + requestDomain: string + uploadDomain: string + downloadDomain: string + versionTag: string + publishStatus: 'UNCONFIGURED' | 'DRAFT' | 'PUBLISHED' | 'DISABLED' +} + +export interface TenantFormPayload { + tenantName: string + miniappAppId: string +} + +export interface TenantCreatePayload { + tenantName: string + adminUsername: string + adminPassword: string + miniappAppId: string +} diff --git a/frontend_admin/src/types/tenant.ts b/frontend_admin/src/types/tenant.ts new file mode 100644 index 0000000..8652e31 --- /dev/null +++ b/frontend_admin/src/types/tenant.ts @@ -0,0 +1,137 @@ +export interface DashboardStats { + totalCards: number + publishedCards: number + totalViews: number + totalShares: number + todayViews: number +} + +export interface CardTrendItem { + statDate: string + viewCount: number + shareCount: number +} + +export interface FirmProfile { + id: number | null + firmName: string + firmShortName: string + englishName: string + logoAssetId: number | null + heroAssetId: number | null + logoUrl?: string + heroUrl?: string + intro: string + hotlinePhone: string + websiteUrl: string + wechatOfficialAccount?: string + hqAddress: string + hqLatitude: string | null + hqLongitude: string | null +} + +export interface TenantMiniappConfig { + tenantId: number + tenantCode: string + tenantName: string + envCode: 'DEV' | 'TEST' | 'PROD' + miniappAppId: string + miniappName: string + miniappOriginalId: string + requestDomain: string + uploadDomain: string + downloadDomain: string + versionTag: string + publishStatus: 'UNCONFIGURED' | 'DRAFT' | 'PUBLISHED' | 'DISABLED' +} + +export interface TenantMiniappConfigPayload { + miniappAppId: string +} + +export interface PracticeArea { + id: number + areaCode: string + areaName: string + displayOrder: number + areaStatus: string +} + +export interface Department { + id: number + parentId: number + deptCode: string + deptName: string + deptType: string + contactPhone: string + address: string + displayOrder: number + deptStatus: string +} + +export interface TenantUser { + id: number + username: string + realName: string + mobile: string + email: string + jobTitle: string + userStatus: 'ENABLED' | 'DISABLED' + memberSort: number + deptId: number | null + deptName: string + roleCode: 'TENANT_ADMIN' | 'TENANT_USER' +} + +export interface TenantUserUpsertPayload { + username: string + realName: string + mobile: string + email: string + jobTitle: string + userStatus: 'ENABLED' | 'DISABLED' + deptId: number | null + roleCode: 'TENANT_ADMIN' | 'TENANT_USER' +} + +export interface LawyerListItem { + id: number + userId: number | null + cardName: string + cardTitle: string + mobile: string + email: string + publishStatus: 'DRAFT' | 'PUBLISHED' | 'OFFLINE' | string + displayOrder: number + createdTime: string + updatedTime: string +} + +export interface CardDetail { + id: number | null + userId: number | null + username: string + deptId: number | null + deptName: string + cardName: string + cardTitle: string + mobile: string + telephone: string + email: string + officeAddress: string + avatarAssetId: number | null + coverAssetId: number | null + wechatQrAssetId: number | null + avatarUrl: string + coverUrl: string + wechatQrUrl: string + bio: string + certificateNo: string + educationInfo: string + honorInfo: string + isPublic: number + isRecommended: number + publishStatus: string + displayOrder: number + specialties: string[] +} diff --git a/frontend_admin/src/utils/auth.ts b/frontend_admin/src/utils/auth.ts new file mode 100644 index 0000000..ef185a2 --- /dev/null +++ b/frontend_admin/src/utils/auth.ts @@ -0,0 +1,13 @@ +const ACCESS_TOKEN_KEY = 'easycard-admin-access-token' + +export function getAccessToken() { + return window.localStorage.getItem(ACCESS_TOKEN_KEY) || '' +} + +export function setAccessToken(token: string) { + window.localStorage.setItem(ACCESS_TOKEN_KEY, token) +} + +export function clearAccessToken() { + window.localStorage.removeItem(ACCESS_TOKEN_KEY) +} diff --git a/frontend_admin/src/utils/file-upload.ts b/frontend_admin/src/utils/file-upload.ts new file mode 100644 index 0000000..3e08086 --- /dev/null +++ b/frontend_admin/src/utils/file-upload.ts @@ -0,0 +1,40 @@ +import { ElMessage } from 'element-plus' + +const MAX_IMAGE_SIZE = 5 * 1024 * 1024 + +export function validateImageFile(file: File, label: string) { + if (!file.type.startsWith('image/')) { + ElMessage.error(`${label}仅支持图片格式`) + return false + } + + if (file.size > MAX_IMAGE_SIZE) { + ElMessage.error(`${label}大小不能超过 5MB`) + return false + } + + return true +} + +export function resolveUploadErrorMessage(error: unknown, fallback: string) { + if (error instanceof Error && error.message) { + return error.message + } + + if (typeof error === 'object' && error && 'message' in error) { + const message = Reflect.get(error, 'message') + if (typeof message === 'string' && message) { + return message + } + } + + return fallback +} + +export function createUploadAjaxError(message: string) { + return Object.assign(new Error(message), { + status: 0, + method: 'post', + url: '', + }) +} diff --git a/frontend_admin/src/utils/format.ts b/frontend_admin/src/utils/format.ts new file mode 100644 index 0000000..626badf --- /dev/null +++ b/frontend_admin/src/utils/format.ts @@ -0,0 +1,23 @@ +export function formatDateTime(value?: string | null, fallback = '-') { + if (!value) { + return fallback + } + + const normalizedValue = value.includes('T') ? value : value.replace(' ', 'T') + const date = new Date(normalizedValue) + if (Number.isNaN(date.getTime())) { + return value + } + + return new Intl.DateTimeFormat('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + }).format(date) +} + +export function compactNumber(value?: number | null) { + return new Intl.NumberFormat('zh-CN').format(value ?? 0) +} diff --git a/frontend_admin/src/utils/http.ts b/frontend_admin/src/utils/http.ts new file mode 100644 index 0000000..e40a7cb --- /dev/null +++ b/frontend_admin/src/utils/http.ts @@ -0,0 +1,84 @@ +import axios from 'axios' +import type { AxiosError, InternalAxiosRequestConfig } from 'axios' +import { ElMessage } from 'element-plus' + +import type { ApiErrorPayload, ApiResponse } from '@/types/common' +import { clearAccessToken, getAccessToken } from '@/utils/auth' + +interface RequestConfig extends InternalAxiosRequestConfig { + silentError?: boolean +} + +function normalizeBasePath(basePath: string) { + if (!basePath || basePath === '/') { + return '' + } + return basePath.endsWith('/') ? basePath.slice(0, -1) : basePath +} + +function stripBasePath(pathname: string, basePath: string) { + if (!basePath || !pathname.startsWith(basePath)) { + return pathname || '/' + } + return pathname.slice(basePath.length) || '/' +} + +const appBasePath = normalizeBasePath(import.meta.env.BASE_URL || '/') +const loginPath = `${appBasePath}/login` || '/login' + +export const http = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL || `${appBasePath || ''}`, + timeout: 10000, +}) + +http.interceptors.request.use((config) => { + const nextConfig = config as RequestConfig + const token = getAccessToken() + const requestUrl = nextConfig.url || '' + const skipAuth = requestUrl.includes('/api/v1/auth/login') + if (token && !skipAuth) { + nextConfig.headers.Authorization = `Bearer ${token}` + } + return nextConfig +}) + +http.interceptors.response.use( + (response) => { + const payload = response.data as ApiResponse + if (!payload || typeof payload.code !== 'string') { + return response.data + } + if (payload.code === '0') { + return payload.data + } + + const error: ApiErrorPayload = { + code: payload.code, + message: payload.message || '请求失败', + status: response.status, + } + ElMessage.error(error.message) + return Promise.reject(error) + }, + (error: AxiosError>) => { + const status = error.response?.status + const payload = error.response?.data + const message = payload?.message || error.message || '网络异常' + const apiError: ApiErrorPayload = { + code: payload?.code || 'HTTP_ERROR', + message, + status, + } + + if (status === 401) { + clearAccessToken() + if (window.location.pathname !== loginPath) { + const redirectPath = stripBasePath(window.location.pathname, appBasePath) + window.location.href = `${loginPath}?redirect=${encodeURIComponent(redirectPath)}` + } + } + + ElMessage.error(apiError.message) + return Promise.reject(apiError) + }, +) diff --git a/frontend_admin/src/utils/role.ts b/frontend_admin/src/utils/role.ts new file mode 100644 index 0000000..fb997cb --- /dev/null +++ b/frontend_admin/src/utils/role.ts @@ -0,0 +1,24 @@ +import type { RoleCode } from '@/types/common' + +const roleLabelMap: Record = { + PLATFORM_SUPER_ADMIN: '平台超级管理员', + TENANT_ADMIN: '租户管理员', + TENANT_USER: '普通用户', +} + +export function getRoleLabel(role?: string | null) { + if (!role) { + return '-' + } + return roleLabelMap[role as RoleCode] ?? role +} + +export function resolveRoleLabel(roleCodes?: RoleCode[], fallback?: string | null) { + if (roleCodes && roleCodes.length > 0) { + const matched = roleLabelMap[roleCodes[0]] + if (matched) { + return matched + } + } + return getRoleLabel(fallback) +} diff --git a/frontend_admin/src/views/card/MyCardView.vue b/frontend_admin/src/views/card/MyCardView.vue new file mode 100644 index 0000000..315c82b --- /dev/null +++ b/frontend_admin/src/views/card/MyCardView.vue @@ -0,0 +1,1334 @@ + + + + + diff --git a/frontend_admin/src/views/dashboard/DashboardView.vue b/frontend_admin/src/views/dashboard/DashboardView.vue new file mode 100644 index 0000000..4460e24 --- /dev/null +++ b/frontend_admin/src/views/dashboard/DashboardView.vue @@ -0,0 +1,285 @@ + + + + + diff --git a/frontend_admin/src/views/system/ArchiveCenterView.vue b/frontend_admin/src/views/system/ArchiveCenterView.vue new file mode 100644 index 0000000..b5f4caf --- /dev/null +++ b/frontend_admin/src/views/system/ArchiveCenterView.vue @@ -0,0 +1,37 @@ + diff --git a/frontend_admin/src/views/system/LoginView.vue b/frontend_admin/src/views/system/LoginView.vue new file mode 100644 index 0000000..fa34b2d --- /dev/null +++ b/frontend_admin/src/views/system/LoginView.vue @@ -0,0 +1,388 @@ + + + + + diff --git a/frontend_admin/src/views/system/ProfileView.vue b/frontend_admin/src/views/system/ProfileView.vue new file mode 100644 index 0000000..dd7f693 --- /dev/null +++ b/frontend_admin/src/views/system/ProfileView.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/frontend_admin/src/views/system/SystemSettingsView.vue b/frontend_admin/src/views/system/SystemSettingsView.vue new file mode 100644 index 0000000..7448f0c --- /dev/null +++ b/frontend_admin/src/views/system/SystemSettingsView.vue @@ -0,0 +1,35 @@ + diff --git a/frontend_admin/src/views/tenant/FirmProfileView.vue b/frontend_admin/src/views/tenant/FirmProfileView.vue new file mode 100644 index 0000000..22f4884 --- /dev/null +++ b/frontend_admin/src/views/tenant/FirmProfileView.vue @@ -0,0 +1,750 @@ + + + + + diff --git a/frontend_admin/src/views/tenant/LawyerListView.vue b/frontend_admin/src/views/tenant/LawyerListView.vue new file mode 100644 index 0000000..5c03058 --- /dev/null +++ b/frontend_admin/src/views/tenant/LawyerListView.vue @@ -0,0 +1,291 @@ + + + + + diff --git a/frontend_admin/src/views/tenant/MiniappConfigView.vue b/frontend_admin/src/views/tenant/MiniappConfigView.vue new file mode 100644 index 0000000..2c950c6 --- /dev/null +++ b/frontend_admin/src/views/tenant/MiniappConfigView.vue @@ -0,0 +1,260 @@ + + + diff --git a/frontend_admin/src/views/tenant/TenantListView.vue b/frontend_admin/src/views/tenant/TenantListView.vue new file mode 100644 index 0000000..7f26a4d --- /dev/null +++ b/frontend_admin/src/views/tenant/TenantListView.vue @@ -0,0 +1,431 @@ + + + + + diff --git a/frontend_admin/src/views/tenant/TenantMiniappBindingView.vue b/frontend_admin/src/views/tenant/TenantMiniappBindingView.vue new file mode 100644 index 0000000..ef1a9b4 --- /dev/null +++ b/frontend_admin/src/views/tenant/TenantMiniappBindingView.vue @@ -0,0 +1,335 @@ + + + + + diff --git a/frontend_admin/src/views/tenant/UserListView.vue b/frontend_admin/src/views/tenant/UserListView.vue new file mode 100644 index 0000000..b4ec147 --- /dev/null +++ b/frontend_admin/src/views/tenant/UserListView.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/frontend_admin/tsconfig.app.json b/frontend_admin/tsconfig.app.json new file mode 100644 index 0000000..ea27948 --- /dev/null +++ b/frontend_admin/tsconfig.app.json @@ -0,0 +1,20 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "baseUrl": ".", + "paths": { + "@/*": [ + "./src/*" + ] + }, + "types": [ + "vite/client" + ] + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.vue" + ] +} diff --git a/frontend_admin/tsconfig.json b/frontend_admin/tsconfig.json new file mode 100644 index 0000000..ea9d0cd --- /dev/null +++ b/frontend_admin/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/frontend_admin/tsconfig.node.json b/frontend_admin/tsconfig.node.json new file mode 100644 index 0000000..6d5cc04 --- /dev/null +++ b/frontend_admin/tsconfig.node.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "composite": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "allowSyntheticDefaultImports": true + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/frontend_admin/vite.config.ts b/frontend_admin/vite.config.ts new file mode 100644 index 0000000..f7c31d9 --- /dev/null +++ b/frontend_admin/vite.config.ts @@ -0,0 +1,35 @@ +import { fileURLToPath, URL } from 'node:url' + +import vue from '@vitejs/plugin-vue' +import { defineConfig } from 'vite' + +export default defineConfig({ + base: '/card/', + plugins: [vue()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, + build: { + rollupOptions: { + output: { + manualChunks: { + vue: ['vue', 'vue-router', 'pinia'], + elementPlus: ['element-plus', '@element-plus/icons-vue'], + }, + }, + }, + }, + server: { + host: '0.0.0.0', + port: 5173, + proxy: { + '/card/api': { + target: 'http://127.0.0.1:8112', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/card/, ''), + }, + }, + }, +})