Compare commits
15 Commits
40b2ae3126
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| edcc8611e5 | |||
| 783ea21d55 | |||
| 13b320ca93 | |||
| 1a82dfab35 | |||
| 3b6fb0cae1 | |||
| f18c9cdc8d | |||
| c77d6855a9 | |||
| 8b09394295 | |||
| 82a2acbdbe | |||
| 2dfb891465 | |||
| 4f679e8eb6 | |||
| 67db6e8d53 | |||
| d4c2572cf3 | |||
| 9d18d05a58 | |||
| d01117c6ea |
275
bun.lock
275
bun.lock
@@ -6,20 +6,31 @@
|
||||
"name": "aioj_frontend",
|
||||
"dependencies": {
|
||||
"@arco-design/web-vue": "^2.57.0",
|
||||
"@types/spark-md5": "^3.0.5",
|
||||
"axios": "^1.13.2",
|
||||
"json-bigint": "^1.0.0",
|
||||
"pinia": "^3.0.4",
|
||||
"pinia-plugin-persistedstate": "^4.7.1",
|
||||
"spark-md5": "^3.0.2",
|
||||
"vue": "^3.5.24",
|
||||
"vue-router": "4",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/node": "^24.10.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vue/tsconfig": "^0.8.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-vue": "^9.23.0",
|
||||
"openapi-typescript-codegen": "^0.29.0",
|
||||
"prettier": "^3.2.5",
|
||||
"sass-embedded": "^1.93.3",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "npm:rolldown-vite@7.2.2",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-tsc": "^3.1.3",
|
||||
},
|
||||
},
|
||||
@@ -50,12 +61,32 @@
|
||||
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
|
||||
|
||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
||||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@2.1.4", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@8.57.1", "", {}, "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="],
|
||||
|
||||
"@humanwhocodes/config-array": ["@humanwhocodes/config-array@0.13.0", "", { "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="],
|
||||
|
||||
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
|
||||
|
||||
"@humanwhocodes/object-schema": ["@humanwhocodes/object-schema@2.0.3", "", {}, "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
|
||||
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="],
|
||||
|
||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||
|
||||
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
||||
|
||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
|
||||
"@oxc-project/runtime": ["@oxc-project/runtime@0.96.0", "", {}, "sha512-34lh4o9CcSw09Hx6fKihPu85+m+4pmDlkXwJrLvN5nMq5JrcGhhihVM415zDqT8j8IixO1PYYdQZRN4SwQCncg=="],
|
||||
|
||||
"@oxc-project/types": ["@oxc-project/types@0.96.0", "", {}, "sha512-r/xkmoXA0xEpU6UGtn18CNVjXH6erU3KCpCDbpLmbVxBFor1U9MqN5Z2uMmCHJuXjJzlnDR+hWY+yPoLo8oHDw=="],
|
||||
@@ -120,10 +151,32 @@
|
||||
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
"@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
|
||||
|
||||
"@types/spark-md5": ["@types/spark-md5@3.0.5", "", {}, "sha512-lWf05dnD42DLVKQJZrDHtWFidcLrHuip01CtnC2/S6AMhX4t9ZlEUj4iuRlAnts0PQk7KESOqKxeGE/b6sIPGg=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@7.18.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/type-utils": "7.18.0", "@typescript-eslint/utils": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0", "eslint": "^8.56.0" } }, "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@7.18.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0" } }, "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@7.18.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@7.18.0", "", {}, "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@7.18.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg=="],
|
||||
|
||||
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
||||
|
||||
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.1", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-beta.29" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", "vue": "^3.2.25" } }, "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw=="],
|
||||
|
||||
"@volar/language-core": ["@volar/language-core@2.4.23", "", { "dependencies": { "@volar/source-map": "2.4.23" } }, "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ=="],
|
||||
@@ -160,10 +213,22 @@
|
||||
|
||||
"@vue/tsconfig": ["@vue/tsconfig@0.8.1", "", { "peerDependencies": { "typescript": "5.x", "vue": "^3.4.0" }, "optionalPeers": ["typescript", "vue"] }, "sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g=="],
|
||||
|
||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||
|
||||
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||
|
||||
"alien-signals": ["alien-signals@3.1.0", "", {}, "sha512-yufC6VpSy8tK3I0lO67pjumo5JvDQVQyr38+3OHqe6CHl1t2VZekKZ7EKKZSqk0cRmE7U7tfZbpXiKNzuc+ckg=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="],
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="],
|
||||
@@ -172,23 +237,35 @@
|
||||
|
||||
"b-validate": ["b-validate@1.5.3", "", {}, "sha512-iCvCkGFskbaYtfQ0a3GmcQCHl/Sv1GufXFGuUQ+FE+WJa7A/espLOuFIn09B944V8/ImPj71T4+rTASxO2PAuA=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
||||
|
||||
"birpc": ["birpc@2.8.0", "", {}, "sha512-Bz2a4qD/5GRhiHSwj30c/8kC8QGj12nNDwz3D4ErQ4Xhy35dsSDvF+RA/tWpjyU0pdGtSDiEk6B5fBGE1qNVhw=="],
|
||||
|
||||
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
"buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||
|
||||
"color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="],
|
||||
|
||||
"color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||
|
||||
@@ -200,18 +277,32 @@
|
||||
|
||||
"compute-scroll-into-view": ["compute-scroll-into-view@1.0.20", "", {}, "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||
|
||||
"csstype": ["csstype@3.2.0", "", {}, "sha512-si++xzRAY9iPp60roQiFta7OFbhrgvcthrhlNAGeQptSY25uJjkfUV8OArC3KLocB8JT8ohz+qgxWCmz8RhjIg=="],
|
||||
|
||||
"dayjs": ["dayjs@1.11.19", "", {}, "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
|
||||
"defu": ["defu@6.1.4", "https://registry.npmmirror.com/defu/-/defu-6.1.4.tgz", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
|
||||
|
||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
|
||||
|
||||
"doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="],
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||
@@ -224,18 +315,60 @@
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"eslint": ["eslint@8.57.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", "@eslint/js": "8.57.1", "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.2", "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" } }, "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA=="],
|
||||
|
||||
"eslint-config-prettier": ["eslint-config-prettier@9.1.2", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ=="],
|
||||
|
||||
"eslint-plugin-vue": ["eslint-plugin-vue@9.33.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "vue-eslint-parser": "^9.4.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="],
|
||||
|
||||
"eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
"espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="],
|
||||
|
||||
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
||||
|
||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||
|
||||
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||
|
||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||
|
||||
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
||||
|
||||
"fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"file-entry-cache": ["file-entry-cache@6.0.1", "", { "dependencies": { "flat-cache": "^3.0.4" } }, "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
|
||||
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
||||
|
||||
"flat-cache": ["flat-cache@3.2.0", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw=="],
|
||||
|
||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
||||
|
||||
"follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
|
||||
|
||||
"form-data": ["form-data@4.0.4", "", { "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" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
||||
|
||||
"fs-extra": ["fs-extra@11.3.2", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A=="],
|
||||
|
||||
"fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
@@ -244,10 +377,20 @@
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
"globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="],
|
||||
|
||||
"globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
|
||||
|
||||
"handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
@@ -260,8 +403,18 @@
|
||||
|
||||
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
|
||||
|
||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
|
||||
"immutable": ["immutable@5.1.4", "", {}, "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
@@ -270,12 +423,28 @@
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="],
|
||||
|
||||
"is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||
|
||||
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
||||
|
||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||
|
||||
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
||||
|
||||
"jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
|
||||
|
||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
|
||||
|
||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
|
||||
@@ -300,34 +469,68 @@
|
||||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
|
||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
|
||||
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
||||
|
||||
"number-precision": ["number-precision@1.6.0", "", {}, "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"openapi-typescript-codegen": ["openapi-typescript-codegen@0.29.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.5.4", "camelcase": "^6.3.0", "commander": "^12.0.0", "fs-extra": "^11.2.0", "handlebars": "^4.7.8" }, "bin": { "openapi": "bin/index.js" } }, "sha512-/wC42PkD0LGjDTEULa/XiWQbv4E9NwLjwLjsaJ/62yOsoYhwvmBR31kPttn1DzQ2OlGe5stACcF/EIkZk43M6w=="],
|
||||
|
||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||
|
||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
|
||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||
|
||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||
|
||||
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
|
||||
|
||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
|
||||
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
|
||||
|
||||
"perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
@@ -340,16 +543,34 @@
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
"prettier": ["prettier@3.7.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA=="],
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||
|
||||
"resize-observer-polyfill": ["resize-observer-polyfill@1.5.1", "", {}, "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||
|
||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
||||
|
||||
"rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
|
||||
"rolldown": ["rolldown@1.0.0-beta.47", "", { "dependencies": { "@oxc-project/types": "=0.96.0", "@rolldown/pluginutils": "1.0.0-beta.47" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.47", "@rolldown/binding-darwin-arm64": "1.0.0-beta.47", "@rolldown/binding-darwin-x64": "1.0.0-beta.47", "@rolldown/binding-freebsd-x64": "1.0.0-beta.47", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.47", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.47", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.47", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.47", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.47", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.47", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.47", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.47", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.47", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.47" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Mid74GckX1OeFAOYz9KuXeWYhq3xkXbMziYIC+ULVdUzPTG9y70OBSBQDQn9hQP8u/AfhuYw1R0BSg15nBI4Dg=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
|
||||
|
||||
"sass": ["sass@1.93.3", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg=="],
|
||||
@@ -394,14 +615,28 @@
|
||||
|
||||
"scroll-into-view-if-needed": ["scroll-into-view-if-needed@2.2.31", "", { "dependencies": { "compute-scroll-into-view": "^1.0.20" } }, "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA=="],
|
||||
|
||||
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="],
|
||||
|
||||
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"spark-md5": ["spark-md5@3.0.2", "", {}, "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw=="],
|
||||
|
||||
"speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||
|
||||
"superjson": ["superjson@2.2.5", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-zWPTX96LVsA/eVYnqOM2+ofcdPqdS1dAF1LN4TS2/MWuUpfitd9ctTa87wt4xrYnZnkLtS69xpBdSxVBP5Rm6w=="],
|
||||
|
||||
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
@@ -410,12 +645,20 @@
|
||||
|
||||
"sync-message-port": ["sync-message-port@1.1.3", "", {}, "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg=="],
|
||||
|
||||
"text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"ts-api-utils": ["ts-api-utils@1.4.3", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||
|
||||
"type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
|
||||
@@ -424,6 +667,10 @@
|
||||
|
||||
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
|
||||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="],
|
||||
|
||||
"vite": ["rolldown-vite@7.2.2", "", { "dependencies": { "@oxc-project/runtime": "0.96.0", "fdir": "^6.5.0", "lightningcss": "^1.30.2", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-beta.47", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "esbuild": "^0.25.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-Fl3ZdmJhDMJGcqrr342pPVrhugXdOcuNBRBauz4S7QGSRXbQy7y8q5QYJtgkcrG8XjY0EENSZeTk58c3m20FxA=="],
|
||||
@@ -432,20 +679,42 @@
|
||||
|
||||
"vue": ["vue@3.5.24", "", { "dependencies": { "@vue/compiler-dom": "3.5.24", "@vue/compiler-sfc": "3.5.24", "@vue/runtime-dom": "3.5.24", "@vue/server-renderer": "3.5.24", "@vue/shared": "3.5.24" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-uTHDOpVQTMjcGgrqFPSb8iO2m1DUvo+WbGqoXQz8Y1CeBYQ0FXf2z1gLRaBtHjlRz7zZUBHxjVB5VTLzYkvftg=="],
|
||||
|
||||
"vue-eslint-parser": ["vue-eslint-parser@9.4.3", "", { "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", "eslint-visitor-keys": "^3.3.0", "espree": "^9.3.1", "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.6" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg=="],
|
||||
|
||||
"vue-router": ["vue-router@4.6.3", "", { "dependencies": { "@vue/devtools-api": "^6.6.4" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg=="],
|
||||
|
||||
"vue-tsc": ["vue-tsc@3.1.3", "", { "dependencies": { "@volar/typescript": "2.4.23", "@vue/language-core": "3.1.3" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "./bin/vue-tsc.js" } }, "sha512-StMNfZHwPIXQgY3KxPKM0Jsoc8b46mDV3Fn2UlHCBIwRJApjqrSwqeMYgWf0zpN+g857y74pv7GWuBm+UqQe1w=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||
|
||||
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"xml-name-validator": ["xml-name-validator@4.0.0", "", {}, "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
|
||||
|
||||
"color-string/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"color/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.47", "", {}, "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw=="],
|
||||
|
||||
"vue-router/@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
}
|
||||
}
|
||||
|
||||
1802
package-lock.json
generated
1802
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@@ -10,25 +10,59 @@
|
||||
"build:prod": "vue-tsc -b && vite build --mode prod",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint . --ext .ts,.vue",
|
||||
"lint:fix": "eslint . --ext .ts,.vue --fix",
|
||||
"format": "prettier . --write",
|
||||
"format:check": "prettier . --check",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"build:types": "vue-tsc --declaration --emitDeclarationOnly"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es2022": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/vue3-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"parser": "vue-eslint-parser",
|
||||
"parserOptions": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@arco-design/web-vue": "^2.57.0",
|
||||
"@types/spark-md5": "^3.0.5",
|
||||
"axios": "^1.13.2",
|
||||
"json-bigint": "^1.0.0",
|
||||
"pinia": "^3.0.4",
|
||||
"pinia-plugin-persistedstate": "^4.7.1",
|
||||
"spark-md5": "^3.0.2",
|
||||
"vue": "^3.5.24",
|
||||
"vue-router": "4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/node": "^24.10.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vue/tsconfig": "^0.8.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-vue": "^9.23.0",
|
||||
"openapi-typescript-codegen": "^0.29.0",
|
||||
"prettier": "^3.2.5",
|
||||
"sass-embedded": "^1.93.3",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "npm:rolldown-vite@7.2.2",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-tsc": "^3.1.3"
|
||||
},
|
||||
"overrides": {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import request from "@/plugins/axios";
|
||||
import type { ApiResponse } from "../response";
|
||||
import { HttpMethod } from "@/constants";
|
||||
|
||||
/**
|
||||
* 认证服务 API 类型定义
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// 登录请求参数
|
||||
export interface LoginRequest {
|
||||
userAccount: string;
|
||||
@@ -24,6 +23,20 @@ export interface LoginResponse {
|
||||
refreshTokenExpireTime: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册请求参数
|
||||
*/
|
||||
export interface RegisterRequest {
|
||||
userAccount: string;
|
||||
userPassword: string;
|
||||
checkPassword: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册响应数据
|
||||
*/
|
||||
export type RegisterResponse = string;
|
||||
|
||||
// 刷新令牌响应数据
|
||||
export interface RefreshTokenResponse {
|
||||
id: number | null;
|
||||
@@ -44,8 +57,29 @@ export interface RefreshTokenResponse {
|
||||
* @param data 登录请求参数
|
||||
* @returns 登录响应数据
|
||||
*/
|
||||
export const login = (data: LoginRequest): Promise<ApiResponse<LoginResponse>> => {
|
||||
return request.post("/v1/auth/login", data);
|
||||
export const login = (
|
||||
data: LoginRequest
|
||||
): Promise<ApiResponse<LoginResponse>> => {
|
||||
return request({
|
||||
url: "/v1/auth/login",
|
||||
method: HttpMethod.POST,
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
* @param data 注册请求参数
|
||||
* @returns 注册响应数据
|
||||
*/
|
||||
export const register = (
|
||||
data: RegisterRequest
|
||||
): Promise<ApiResponse<RegisterResponse>> => {
|
||||
return request({
|
||||
url: "/v1/user/register",
|
||||
method: HttpMethod.POST,
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -53,8 +87,12 @@ export const login = (data: LoginRequest): Promise<ApiResponse<LoginResponse>> =
|
||||
* @param refreshToken 刷新令牌
|
||||
* @returns 新的令牌信息
|
||||
*/
|
||||
export const refreshToken = (refreshToken: string): Promise<ApiResponse<RefreshTokenResponse>> => {
|
||||
return request.post("/v1/auth/refresh", null, {
|
||||
export const refreshToken = (
|
||||
refreshToken: string
|
||||
): Promise<ApiResponse<RefreshTokenResponse>> => {
|
||||
return request({
|
||||
url: "/v1/auth/refresh",
|
||||
method: HttpMethod.POST,
|
||||
params: {
|
||||
refreshToken,
|
||||
},
|
||||
@@ -66,8 +104,14 @@ export const refreshToken = (refreshToken: string): Promise<ApiResponse<RefreshT
|
||||
* @param data 登录请求参数
|
||||
* @returns 访问令牌字符串
|
||||
*/
|
||||
export const getAccessToken = (data: LoginRequest): Promise<ApiResponse<string>> => {
|
||||
return request.post("/v1/auth/auth", data);
|
||||
export const getAccessToken = (
|
||||
data: LoginRequest
|
||||
): Promise<ApiResponse<string>> => {
|
||||
return request({
|
||||
url: "/v1/auth/auth",
|
||||
method: HttpMethod.POST,
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -75,5 +119,8 @@ export const getAccessToken = (data: LoginRequest): Promise<ApiResponse<string>>
|
||||
* @returns 验证结果
|
||||
*/
|
||||
export const validateToken = (): Promise<ApiResponse<boolean>> => {
|
||||
return request.post("/v1/auth/validate");
|
||||
return request({
|
||||
url: "/v1/auth/validate",
|
||||
method: HttpMethod.POST,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,10 +3,13 @@ export { chatAPI, type ChatMessage, type ChatRequest } from '../aiChat'
|
||||
// 认证 API
|
||||
export {
|
||||
login,
|
||||
register,
|
||||
refreshToken,
|
||||
getAccessToken,
|
||||
validateToken,
|
||||
type LoginRequest,
|
||||
type LoginResponse,
|
||||
type RegisterRequest,
|
||||
type RegisterResponse,
|
||||
type RefreshTokenResponse,
|
||||
} from './auth'
|
||||
@@ -1,70 +1,190 @@
|
||||
import request from "@/plugins/axios";
|
||||
import type { ApiResponse } from "../response";
|
||||
import { HttpMethod } from "@/constants";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
* 用户信息
|
||||
*/
|
||||
export interface UserInfo {
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
id: number;
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
id: number;
|
||||
|
||||
/**
|
||||
* 用户账号
|
||||
*/
|
||||
userAccount: string;
|
||||
/**
|
||||
* 用户账号
|
||||
*/
|
||||
userAccount: string;
|
||||
|
||||
/**
|
||||
* 开放平台id
|
||||
*/
|
||||
unionId?: string;
|
||||
|
||||
/**
|
||||
* 开放平台id
|
||||
*/
|
||||
unionId?: string;
|
||||
/**
|
||||
* 公众号openId
|
||||
*/
|
||||
mpOpenId?: string;
|
||||
|
||||
/**
|
||||
* 公众号openId
|
||||
*/
|
||||
mpOpenId?: string;
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
userName: string;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
userName: string;
|
||||
/**
|
||||
* 用户头像 是一个文件id,需要去文件服务查询文件详情,拿到文件url,和当前前端url + “/file/” 拼接起来,才能访问到文件
|
||||
*/
|
||||
userAvatar?: string;
|
||||
|
||||
/**
|
||||
* 用户头像
|
||||
*/
|
||||
userAvatar?: string;
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
userEmail?: string;
|
||||
|
||||
/**
|
||||
* 用户简介
|
||||
*/
|
||||
userProfile?: string;
|
||||
/**
|
||||
* 用户邮箱是否验证
|
||||
*/
|
||||
userEmailVerified?: boolean;
|
||||
|
||||
/**
|
||||
* 用户角色:user/admin/ban
|
||||
*/
|
||||
userRole: 'user' | 'admin' | 'ban';
|
||||
/**
|
||||
* 用户简介
|
||||
*/
|
||||
userProfile?: string;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime: string;
|
||||
/**
|
||||
* 用户角色:user/admin/ban
|
||||
*/
|
||||
userRole: "user" | "admin" | "ban";
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
updateTime: string;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime: string;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
updateTime: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户信息
|
||||
* @returns 当前登录用户信息
|
||||
*/
|
||||
export const getUserInfoByToken = () => {
|
||||
return request<ApiResponse<UserInfo>>({
|
||||
url: "/v1/auth/getUserInfo",
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
export const getUserInfoByToken = (): Promise<ApiResponse<UserInfo>> => {
|
||||
return request({
|
||||
url: "/v1/auth/getUserInfo",
|
||||
method: HttpMethod.GET,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新用户头像
|
||||
* @param fileId 文件id
|
||||
* @returns
|
||||
*/
|
||||
export const updateUserAvatar = (
|
||||
fileId: string,
|
||||
): Promise<ApiResponse<void>> => {
|
||||
return request({
|
||||
url: "/v1/user/avatar",
|
||||
method: HttpMethod.PUT,
|
||||
data: {
|
||||
fileId: fileId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 发送邮箱验证码
|
||||
* @param email 邮箱
|
||||
* @returns
|
||||
*/
|
||||
export const sendEmailVerifyCode = (
|
||||
email: string,
|
||||
): Promise<ApiResponse<void>> => {
|
||||
return request({
|
||||
url: "/v1/user/email/send-code",
|
||||
method: HttpMethod.GET,
|
||||
params: {
|
||||
email: email,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 绑定邮箱
|
||||
* @param email 邮箱
|
||||
* @param verifyCode 验证码
|
||||
* @returns
|
||||
*/
|
||||
export const bindEmail = (
|
||||
email: string,
|
||||
verifyCode: string,
|
||||
): Promise<ApiResponse<void>> => {
|
||||
return request({
|
||||
url: "/v1/user/email/bind",
|
||||
method: HttpMethod.POST,
|
||||
data: {
|
||||
email: email,
|
||||
verifyCode: verifyCode,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 解绑邮箱
|
||||
* @param email 邮箱
|
||||
* @returns
|
||||
*/
|
||||
export const unbindEmail = (email: string): Promise<ApiResponse<void>> => {
|
||||
return request({
|
||||
url: "/v1/user/email/unbind",
|
||||
method: HttpMethod.POST,
|
||||
data: {
|
||||
email: email,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改用户密码
|
||||
* @param oldPassword 旧密码
|
||||
* @param newPassword 新密码
|
||||
* @returns
|
||||
*/
|
||||
export const updateUserPassword = (
|
||||
oldPassword: string,
|
||||
newPassword: string,
|
||||
): Promise<ApiResponse<void>> => {
|
||||
return request({
|
||||
url: "/v1/user/password",
|
||||
method: HttpMethod.PUT,
|
||||
data: {
|
||||
oldPassword: oldPassword,
|
||||
newPassword: newPassword,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 更新请求体对象
|
||||
export interface UpdateUserProfileRequest {
|
||||
userName?: string;
|
||||
userProfile?: string;
|
||||
}
|
||||
/**
|
||||
* 更新用户个人信息
|
||||
* @param userProfile 更新用户个人信息请求体
|
||||
* @returns
|
||||
*/
|
||||
export const updateUserProfile = (
|
||||
userProfile: UpdateUserProfileRequest,
|
||||
): Promise<ApiResponse<void>> => {
|
||||
return request({
|
||||
url: "/v1/user/profile",
|
||||
method: HttpMethod.PUT,
|
||||
data: userProfile,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
125
src/api/file/file.ts
Normal file
125
src/api/file/file.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import request from "@/plugins/axios";
|
||||
import type { ApiResponse } from "../response";
|
||||
import { HttpMethod } from "@/constants";
|
||||
|
||||
/**
|
||||
* 分页查询文件列表
|
||||
*/
|
||||
export const getFileList = async(current: number,size: number) =>{
|
||||
return request({
|
||||
url: "/v1/file/page",
|
||||
method: HttpMethod.GET,
|
||||
params: {
|
||||
current,
|
||||
size,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询文件详情
|
||||
* @param id 文件id
|
||||
* @returns
|
||||
*/
|
||||
export const getFileById = async (id: string): Promise<ApiResponse<FileListItem>> => {
|
||||
return request({
|
||||
url: "/v1/file/" + id,
|
||||
method: HttpMethod.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否已经上传,本地计算文件哈希
|
||||
* @param hash
|
||||
* @returns
|
||||
*/
|
||||
export const checkHash = async (hash: string) => {
|
||||
return request({
|
||||
url: "/v1/file/check",
|
||||
method: HttpMethod.GET,
|
||||
params: {
|
||||
hash,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param file
|
||||
* @returns
|
||||
*/
|
||||
export const uploadFile = async (file: File, hash: string) : Promise<ApiResponse<FileListItem>> => {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
formData.append("hash", hash);
|
||||
return request({
|
||||
url: "/v1/file/upload",
|
||||
method: HttpMethod.POST,
|
||||
data: formData,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
export const deleteFile = async (id: number) => {
|
||||
return request({
|
||||
url: "/v1/file/" + id,
|
||||
method: HttpMethod.DELETE,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface FileListItem {
|
||||
|
||||
/* 文件记录的唯一标识 ID */
|
||||
id: string;
|
||||
|
||||
/* 文件的原始名称(不包含扩展名) */
|
||||
fileName: string;
|
||||
|
||||
/* 文件扩展名,例如 "png"、"jpg"、"pdf" 等 */
|
||||
fileExtension: string;
|
||||
|
||||
/* 文件大小,单位为字节(Byte) */
|
||||
fileSize: number;
|
||||
|
||||
/* 文件内容的哈希值(例如 MD5 或 SHA-256),用于校验与秒传 */
|
||||
fileHash: string;
|
||||
|
||||
/* 文件的 MIME 类型,例如 "image/png"、"application/pdf" 等 */
|
||||
mimeType: string;
|
||||
|
||||
/* 文件存储方式类型,例如本地存储、对象存储等 */
|
||||
storageType: string;
|
||||
|
||||
/* 文件在存储系统中的物理或逻辑路径 */
|
||||
storagePath: string;
|
||||
|
||||
/* 业务类型标识,用于区分文件所属的业务场景 */
|
||||
businessType: string;
|
||||
|
||||
/* 关联的业务主键 ID,例如订单 ID、用户资料 ID 等 */
|
||||
businessId: number;
|
||||
|
||||
/* 上传该文件的用户 ID */
|
||||
userId: number;
|
||||
|
||||
/* 图片文件的附加信息,例如宽高、分辨率等(非图片可为空) */
|
||||
imageInfo: string;
|
||||
|
||||
/* 逻辑删除标记,0 表示未删除,1 表示已删除 */
|
||||
isDeleted: number;
|
||||
|
||||
/* 记录创建时间信息 */
|
||||
createdAt: Record<string, unknown>;
|
||||
|
||||
/* 记录最近一次更新时间信息 */
|
||||
updatedAt: Record<string, unknown>;
|
||||
|
||||
}
|
||||
|
||||
export type FileListArray = FileListItem[];
|
||||
@@ -1,6 +1,11 @@
|
||||
// 统一响应格式
|
||||
export interface ApiResponse<T = any> {
|
||||
success: boolean;
|
||||
message: string;
|
||||
code?: string | number;
|
||||
success?: boolean;
|
||||
message?: string | null;
|
||||
data: T;
|
||||
}
|
||||
}
|
||||
|
||||
export const isApiSuccess = (response: ApiResponse<unknown>): boolean => {
|
||||
return response?.success === true || response?.code === 0 || response?.code === "0";
|
||||
};
|
||||
|
||||
@@ -41,7 +41,12 @@
|
||||
<a-dropdown v-else trigger="hover" position="br">
|
||||
<div class="user-info">
|
||||
<a-avatar :size="36" class="user-avatar">
|
||||
<IconUser />
|
||||
<img
|
||||
v-if="avatarUrl"
|
||||
:src="avatarUrl"
|
||||
alt="avatar"
|
||||
/>
|
||||
<IconUser v-else />
|
||||
</a-avatar>
|
||||
<span class="username">{{ userStore.loginUser.userName }}</span>
|
||||
<icon-down class="dropdown-icon" />
|
||||
@@ -70,7 +75,7 @@
|
||||
<script setup lang="ts">
|
||||
import { routes } from "../router/index.ts";
|
||||
import { useRouter } from "vue-router";
|
||||
import { computed, ref } from "vue";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { Message } from "@arco-design/web-vue";
|
||||
import {
|
||||
IconUser,
|
||||
@@ -82,13 +87,42 @@ import checkAccess from "../access/checkAccess.ts";
|
||||
import { useUserStore } from "../store/user.ts";
|
||||
import { clearTokens } from "@/utils/token";
|
||||
import ACCESS_ENUM from "@/access/accessEnum";
|
||||
import { getFileById } from "@/api/file/file";
|
||||
import { isApiSuccess } from "@/api/response";
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const avatarUrl = ref("");
|
||||
|
||||
// 默认主页
|
||||
const selectedKeys = ref(["/"]);
|
||||
|
||||
// 加载用户头像
|
||||
const loadAvatarUrl = async () => {
|
||||
if (!userStore.loginUser.userAvatar) {
|
||||
avatarUrl.value = "";
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await getFileById(userStore.loginUser.userAvatar);
|
||||
if (isApiSuccess(res) && res.data && res.data.storagePath) {
|
||||
// 拼接 /file/ 前缀,通过 vite 代理访问后端静态资源
|
||||
avatarUrl.value = `/api/file/${res.data.storagePath}`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("加载头像失败", error);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听用户头像变化
|
||||
watch(
|
||||
() => userStore.loginUser.userAvatar,
|
||||
() => {
|
||||
loadAvatarUrl();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const doMenuItemClick = (path: string) => {
|
||||
router.push({ path });
|
||||
};
|
||||
@@ -120,7 +154,7 @@ const goToRegister = () => {
|
||||
|
||||
// 跳转到个人中心
|
||||
const goToProfile = () => {
|
||||
Message.info("个人中心功能开发中");
|
||||
router.push("/user/profile");
|
||||
};
|
||||
|
||||
// 跳转到设置页
|
||||
@@ -131,10 +165,7 @@ const goToSettings = () => {
|
||||
// 退出登录
|
||||
const handleLogout = () => {
|
||||
clearTokens();
|
||||
userStore.updateUserLoginStatus({
|
||||
userName: "未登录",
|
||||
userRole: ACCESS_ENUM.NOT_LOGIN,
|
||||
});
|
||||
userStore.logout();
|
||||
Message.success("已退出登录");
|
||||
router.push("/home");
|
||||
};
|
||||
@@ -308,6 +339,11 @@ router.afterEach((to) => {
|
||||
|
||||
.user-avatar {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
|
||||
:deep(img) {
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.username {
|
||||
|
||||
0
src/components/file_upload/FileUpload.vue
Normal file
0
src/components/file_upload/FileUpload.vue
Normal file
15
src/constants/http.ts
Normal file
15
src/constants/http.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* HTTP 请求方法常量
|
||||
*/
|
||||
export const HttpMethod = {
|
||||
GET: 'GET',
|
||||
POST: 'POST',
|
||||
PUT: 'PUT',
|
||||
DELETE: 'DELETE',
|
||||
PATCH: 'PATCH',
|
||||
HEAD: 'HEAD',
|
||||
OPTIONS: 'OPTIONS',
|
||||
} as const;
|
||||
|
||||
// 导出类型以供使用
|
||||
export type HttpMethod = (typeof HttpMethod)[keyof typeof HttpMethod];
|
||||
1
src/constants/index.ts
Normal file
1
src/constants/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './http';
|
||||
@@ -10,12 +10,98 @@ import {
|
||||
clearTokens,
|
||||
} from "@/utils/token";
|
||||
import { Message } from "@arco-design/web-vue";
|
||||
import { isApiSuccess } from "@/api/response";
|
||||
import {
|
||||
ErrorCode,
|
||||
ErrorMessages,
|
||||
isNotLoginError,
|
||||
isNoAuthError,
|
||||
isParamsError,
|
||||
isServerError,
|
||||
} from "@/types/errorCode";
|
||||
|
||||
// 扩展 Axios 请求配置类型
|
||||
declare module "axios" {
|
||||
interface InternalAxiosRequestConfig {
|
||||
_retry?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
// 是否正在刷新 token
|
||||
let isRefreshing = false;
|
||||
// 存储因为 token 过期而挂起的请求
|
||||
let requests: ((token: string) => void)[] = [];
|
||||
|
||||
// 统一的刷新 token 并重试请求的函数
|
||||
const refreshTokenAndRetry = async (originalRequest: InternalAxiosRequestConfig) => {
|
||||
// 如果正在刷新,将当前请求加入队列等待
|
||||
if (isRefreshing) {
|
||||
return new Promise((resolve) => {
|
||||
requests.push((token: string) => {
|
||||
originalRequest.headers.Authorization = `Bearer ${token}`;
|
||||
resolve(request(originalRequest));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
originalRequest._retry = true;
|
||||
isRefreshing = true;
|
||||
|
||||
try {
|
||||
const refreshToken = getRefreshToken();
|
||||
if (!refreshToken) {
|
||||
throw new Error("No refresh token available");
|
||||
}
|
||||
|
||||
// 使用原生 axios 发送刷新请求,避免拦截器循环
|
||||
const response = await axios.post(
|
||||
`${ENV.API_BASE_URL}/v1/auth/refresh`,
|
||||
null,
|
||||
{
|
||||
params: { refreshToken },
|
||||
}
|
||||
);
|
||||
|
||||
if (isApiSuccess(response.data)) {
|
||||
const { accessToken, refreshToken: newRefreshToken } =
|
||||
response.data.data;
|
||||
// 更新本地存储
|
||||
setTokens(accessToken, newRefreshToken);
|
||||
|
||||
// 执行队列中的请求
|
||||
requests.forEach((cb) => cb(accessToken));
|
||||
requests = [];
|
||||
|
||||
// 重试当前请求
|
||||
originalRequest.headers.Authorization = `Bearer ${accessToken}`;
|
||||
return request(originalRequest);
|
||||
} else {
|
||||
throw new Error("Refresh token failed");
|
||||
}
|
||||
} catch (refreshError) {
|
||||
console.error("Token 刷新失败:", refreshError);
|
||||
// 清除过期 token
|
||||
clearTokens();
|
||||
|
||||
// 动态导入 userStore,确保 Pinia 已初始化
|
||||
import("@/store/user").then(({ useUserStore }) => {
|
||||
const userStore = useUserStore();
|
||||
userStore.logout();
|
||||
});
|
||||
|
||||
Message.error("登录已过期,请重新登录");
|
||||
|
||||
// 跳转到登录页
|
||||
setTimeout(() => {
|
||||
window.location.href = "/user/login";
|
||||
}, 1000);
|
||||
|
||||
return Promise.reject(refreshError);
|
||||
} finally {
|
||||
isRefreshing = false;
|
||||
}
|
||||
};
|
||||
|
||||
const request: AxiosInstance = axios.create({
|
||||
baseURL: ENV.API_BASE_URL,
|
||||
timeout: 10000,
|
||||
@@ -43,80 +129,58 @@ request.interceptors.request.use(
|
||||
// =======================
|
||||
request.interceptors.response.use(
|
||||
(response) => {
|
||||
// console.log("响应: ", response);
|
||||
const data = response.data;
|
||||
/**TODO: 增加响应码处理 */
|
||||
const originalRequest = response.config;
|
||||
const code = data?.code;
|
||||
|
||||
// 未登录错误 (40100)
|
||||
if (isNotLoginError(code)) {
|
||||
clearTokens();
|
||||
import("@/store/user").then(({ useUserStore }) => {
|
||||
const userStore = useUserStore();
|
||||
userStore.logout();
|
||||
});
|
||||
Message.error(data?.message || ErrorMessages[ErrorCode.NOT_LOGIN_ERROR]);
|
||||
setTimeout(() => {
|
||||
window.location.href = "/user/login";
|
||||
}, 1000);
|
||||
return Promise.reject(new Error(data?.message || ErrorMessages[ErrorCode.NOT_LOGIN_ERROR]));
|
||||
}
|
||||
|
||||
// 无权限/token 过期错误 (40101) - 尝试刷新 token
|
||||
if (isNoAuthError(code) && !originalRequest._retry) {
|
||||
return refreshTokenAndRetry(originalRequest);
|
||||
}
|
||||
|
||||
// 参数错误 (40000)
|
||||
if (isParamsError(code)) {
|
||||
Message.warning(data?.message || ErrorMessages[ErrorCode.PARAMS_ERROR]);
|
||||
return data;
|
||||
}
|
||||
|
||||
// 服务端错误 (5xxxx)
|
||||
if (isServerError(code)) {
|
||||
Message.error(data?.message || ErrorMessages[ErrorCode.SYSTEM_ERROR]);
|
||||
return data;
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
async (error) => {
|
||||
const originalRequest = error.config;
|
||||
|
||||
// 处理 401 未授权情况 (Token 过期)
|
||||
// 处理 HTTP 401 未授权情况 (Token 过期)
|
||||
// 确保不是刷新 token 的请求本身 (避免死循环)
|
||||
if (
|
||||
error.response?.status === 401 &&
|
||||
!originalRequest._retry &&
|
||||
!originalRequest.url.includes("/auth/refresh")
|
||||
) {
|
||||
// 如果正在刷新,将当前请求加入队列等待
|
||||
if (isRefreshing) {
|
||||
return new Promise((resolve) => {
|
||||
requests.push((token: string) => {
|
||||
originalRequest.headers.Authorization = `Bearer ${token}`;
|
||||
resolve(request(originalRequest));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
originalRequest._retry = true;
|
||||
isRefreshing = true;
|
||||
|
||||
try {
|
||||
const refreshToken = getRefreshToken();
|
||||
if (!refreshToken) {
|
||||
throw new Error("No refresh token available");
|
||||
}
|
||||
|
||||
// 使用原生 axios 发送刷新请求,避免拦截器循环
|
||||
const response = await axios.post(
|
||||
`${ENV.API_BASE_URL}/v1/auth/refresh`,
|
||||
null,
|
||||
{
|
||||
params: { refreshToken },
|
||||
}
|
||||
);
|
||||
|
||||
if (response.data?.success) {
|
||||
const { accessToken, refreshToken: newRefreshToken } =
|
||||
response.data.data;
|
||||
// 更新本地存储
|
||||
setTokens(accessToken, newRefreshToken);
|
||||
|
||||
// 执行队列中的请求
|
||||
requests.forEach((cb) => cb(accessToken));
|
||||
requests = [];
|
||||
|
||||
// 重试当前请求
|
||||
originalRequest.headers.Authorization = `Bearer ${accessToken}`;
|
||||
return request(originalRequest);
|
||||
} else {
|
||||
throw new Error("Refresh token failed");
|
||||
}
|
||||
} catch (refreshError) {
|
||||
console.error("Token 刷新失败:", refreshError);
|
||||
// 清除过期 token
|
||||
clearTokens();
|
||||
Message.error("登录已过期,请重新登录");
|
||||
// 这里可以选择跳转到登录页,例如 window.location.href = '/user/login'
|
||||
// 建议让路由守卫或者页面自行处理未登录状态
|
||||
return Promise.reject(refreshError);
|
||||
} finally {
|
||||
isRefreshing = false;
|
||||
}
|
||||
return refreshTokenAndRetry(originalRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Promise.reject(error) 用来 返回一个状态为 rejected 的 Promise,相当于“主动抛出错误”,
|
||||
* Promise.reject(error) 用来 返回一个状态为 rejected 的 Promise,相当于"主动抛出错误",
|
||||
*
|
||||
* 让调用者能够在 .catch() 或 try/catch 中捕获这个错误。
|
||||
* 它在 异步流程、拦截器、错误处理 中非常常见。
|
||||
|
||||
@@ -4,11 +4,18 @@ import AboutView from "../views/AboutView.vue";
|
||||
import ACCESS_ENUM from "../access/accessEnum";
|
||||
import UserLoginView from "../views/user/UserLoginView.vue";
|
||||
import UserRegisterView from "../views/user/UserRegisterView.vue";
|
||||
import UserProfileView from "../views/user/UserProfileView.vue";
|
||||
import AiChatView from "../views/ai/AiChatView.vue";
|
||||
/**
|
||||
* 路由配置
|
||||
*/
|
||||
export const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: "/",
|
||||
name: "root",
|
||||
redirect: "/home",
|
||||
meta: { hideInMenu: true },
|
||||
},
|
||||
{
|
||||
path: "/home",
|
||||
name: "HomeView",
|
||||
@@ -39,4 +46,10 @@ export const routes: Array<RouteRecordRaw> = [
|
||||
component: UserRegisterView,
|
||||
meta: { hideInMenu: true, access: ACCESS_ENUM.NOT_LOGIN },
|
||||
},
|
||||
{
|
||||
path: "/user/profile",
|
||||
name: "UserProfileView",
|
||||
component: UserProfileView,
|
||||
meta: { hideInMenu: true, access: ACCESS_ENUM.USER },
|
||||
},
|
||||
];
|
||||
|
||||
15
src/store/types.d.ts
vendored
15
src/store/types.d.ts
vendored
@@ -1,5 +1,16 @@
|
||||
|
||||
export interface LoginUesr {
|
||||
userName: string;
|
||||
id?: number;
|
||||
userName?: string;
|
||||
userAccount?: string;
|
||||
userAvatar?: string;
|
||||
userRole?: string;
|
||||
}
|
||||
userProfile?: string;
|
||||
userEmail?: string;
|
||||
userPhone?: string;
|
||||
unionId?: string;
|
||||
mpOpenId?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineStore } from "pinia";
|
||||
import ACCESS_ENUM from "../access/accessEnum";
|
||||
import type { LoginUesr } from "../store/types";
|
||||
import { getUserInfoByToken } from "@/api/auth/user";
|
||||
import { isApiSuccess } from "@/api/response";
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -23,10 +24,10 @@ export const useUserStore = defineStore("user", {
|
||||
try {
|
||||
const res = await getUserInfoByToken();
|
||||
console.log("获取登录用户成功", res);
|
||||
if(res.data.success === true){
|
||||
this.updateUserLoginStatus(res.data.data);
|
||||
if (isApiSuccess(res)) {
|
||||
this.updateUserLoginStatus(res.data);
|
||||
}
|
||||
}catch(e) {
|
||||
} catch (e) {
|
||||
console.error("获取登录用户失败", e);
|
||||
// 网络错误情况也视为未登录
|
||||
this.loginUser = {
|
||||
@@ -38,6 +39,13 @@ export const useUserStore = defineStore("user", {
|
||||
// 手动更新用户状态
|
||||
updateUserLoginStatus(user: LoginUesr) {
|
||||
this.loginUser = user;
|
||||
},
|
||||
// 退出登录(清除登录状态)
|
||||
logout() {
|
||||
this.loginUser = {
|
||||
userName: "未登录",
|
||||
userRole: ACCESS_ENUM.NOT_LOGIN,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
80
src/types/errorCode.ts
Normal file
80
src/types/errorCode.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 错误码常量
|
||||
* 与后端保持一致
|
||||
*/
|
||||
export const ErrorCode = {
|
||||
// 成功
|
||||
SUCCESS: "0",
|
||||
|
||||
// 客户端错误 4xxxx
|
||||
PARAMS_ERROR: "40000", // 请求参数错误
|
||||
NOT_LOGIN_ERROR: "40100", // 未登录
|
||||
NO_AUTH_ERROR: "40101", // 无权限
|
||||
NOT_FOUND_ERROR: "40400", // 请求数据不存在
|
||||
FORBIDDEN_ERROR: "40300", // 禁止访问
|
||||
|
||||
// 服务端错误 5xxxx
|
||||
SYSTEM_ERROR: "50000", // 系统内部异常
|
||||
OPERATION_ERROR: "50001", // 操作失败
|
||||
API_REQUEST_ERROR: "50010", // 接口调用失败
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* 错误码类型
|
||||
*/
|
||||
export type ErrorCodeType = (typeof ErrorCode)[keyof typeof ErrorCode];
|
||||
|
||||
/**
|
||||
* 错误码对应的消息映射
|
||||
* 用于当后端未返回 message 时使用
|
||||
*/
|
||||
export const ErrorMessages: Record<string, string> = {
|
||||
[ErrorCode.SUCCESS]: "操作成功",
|
||||
[ErrorCode.PARAMS_ERROR]: "请求参数错误",
|
||||
[ErrorCode.NOT_LOGIN_ERROR]: "未登录,请先登录",
|
||||
[ErrorCode.NO_AUTH_ERROR]: "无权限访问",
|
||||
[ErrorCode.NOT_FOUND_ERROR]: "请求的数据不存在",
|
||||
[ErrorCode.FORBIDDEN_ERROR]: "禁止访问",
|
||||
[ErrorCode.SYSTEM_ERROR]: "系统内部异常,请稍后重试",
|
||||
[ErrorCode.OPERATION_ERROR]: "操作失败,请稍后重试",
|
||||
[ErrorCode.API_REQUEST_ERROR]: "接口调用失败,请稍后重试",
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断是否为成功错误码
|
||||
*/
|
||||
export const isSuccessCode = (code: string | number | undefined): boolean => {
|
||||
return code === ErrorCode.SUCCESS || code === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断是否为未登录错误码
|
||||
*/
|
||||
export const isNotLoginError = (code: string | number | undefined): boolean => {
|
||||
return code === ErrorCode.NOT_LOGIN_ERROR;
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断是否为无权限错误码
|
||||
*/
|
||||
export const isNoAuthError = (code: string | number | undefined): boolean => {
|
||||
return code === ErrorCode.NO_AUTH_ERROR;
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断是否为参数错误
|
||||
*/
|
||||
export const isParamsError = (code: string | number | undefined): boolean => {
|
||||
return code === ErrorCode.PARAMS_ERROR;
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断是否为服务端错误 (5xxxx)
|
||||
*/
|
||||
export const isServerError = (code: string | number | undefined): boolean => {
|
||||
return (
|
||||
code === ErrorCode.SYSTEM_ERROR ||
|
||||
code === ErrorCode.OPERATION_ERROR ||
|
||||
code === ErrorCode.API_REQUEST_ERROR
|
||||
);
|
||||
};
|
||||
@@ -78,6 +78,7 @@ import { login } from "@/api/auth/auth";
|
||||
import { setTokens } from "@/utils/token";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import ACCESS_ENUM from "@/access/accessEnum";
|
||||
import { isApiSuccess } from "@/api/response";
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
@@ -114,7 +115,7 @@ const handleSubmit = async (data: any) => {
|
||||
userPassword: form.userPassword,
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
if (isApiSuccess(response)) {
|
||||
Message.success("登录成功!");
|
||||
|
||||
// 存储 token
|
||||
|
||||
860
src/views/user/UserProfileView.vue
Normal file
860
src/views/user/UserProfileView.vue
Normal file
@@ -0,0 +1,860 @@
|
||||
<template>
|
||||
<div id="userProfileView">
|
||||
<a-row :gutter="24">
|
||||
<!-- 左侧:个人信息展示 -->
|
||||
<a-col :span="8" :xs="24" :sm="24" :md="8">
|
||||
<a-card title="个人名片" :bordered="false" class="profile-card">
|
||||
<div class="profile-left">
|
||||
<a-upload
|
||||
action="/"
|
||||
:custom-request="customUpload"
|
||||
:show-file-list="false"
|
||||
:auto-upload="true"
|
||||
accept="image/*"
|
||||
>
|
||||
<template #upload-button>
|
||||
<div class="avatar-wrapper">
|
||||
<a-avatar :size="120" trigger-type="mask">
|
||||
<img
|
||||
v-if="avatarUrl"
|
||||
:src="avatarUrl"
|
||||
alt="avatar"
|
||||
/>
|
||||
<span v-else class="avatar-text">{{
|
||||
loginUser.userName?.charAt(0)?.toUpperCase()
|
||||
}}</span>
|
||||
<template #trigger-icon>
|
||||
<icon-camera />
|
||||
</template>
|
||||
</a-avatar>
|
||||
<div class="avatar-hint">点击更换头像</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-upload>
|
||||
<div class="user-name">{{ loginUser.userName }}</div>
|
||||
<div class="user-role">
|
||||
<a-tag :color="roleColor">{{ roleText }}</a-tag>
|
||||
</div>
|
||||
<a-divider />
|
||||
<a-descriptions :data="staticData" :column="1" size="medium" />
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<!-- 右侧:编辑表单和账号安全 -->
|
||||
<a-col :span="16" :xs="24" :sm="24" :md="16">
|
||||
<a-space direction="vertical" size="large" fill>
|
||||
<!-- 编辑资料卡片 -->
|
||||
<a-card title="编辑资料" :bordered="false" class="edit-card">
|
||||
<a-form
|
||||
:model="formData"
|
||||
:label-col-props="{ span: 4 }"
|
||||
:wrapper-col-props="{ span: 20 }"
|
||||
layout="horizontal"
|
||||
@submit="handleSubmit"
|
||||
>
|
||||
<a-form-item label="昵称" field="userName">
|
||||
<a-input
|
||||
v-model="formData.userName"
|
||||
placeholder="请输入昵称"
|
||||
max-length="20"
|
||||
show-word-limit
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="个人简介" field="userProfile">
|
||||
<a-textarea
|
||||
v-model="formData.userProfile"
|
||||
placeholder="介绍一下自己..."
|
||||
:max-length="200"
|
||||
show-word-limit
|
||||
:auto-size="{ minRows: 4, maxRows: 8 }"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :wrapper-col-props="{ offset: 4, span: 20 }">
|
||||
<a-space>
|
||||
<a-button type="primary" html-type="submit" :loading="loading">
|
||||
保存修改
|
||||
</a-button>
|
||||
<a-button @click="handleReset">重置</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<!-- 账号安全卡片 -->
|
||||
<a-card title="账号安全" :bordered="false" class="security-card">
|
||||
<div class="security-list">
|
||||
<!-- 修改密码 -->
|
||||
<div class="security-item">
|
||||
<div class="security-item-left">
|
||||
<icon-lock class="security-icon" />
|
||||
<span class="security-label">登录密码</span>
|
||||
</div>
|
||||
<span class="security-status">已设置</span>
|
||||
<a class="security-action" @click="showPasswordModal = true">修改密码</a>
|
||||
</div>
|
||||
|
||||
<!-- 绑定手机 -->
|
||||
<div class="security-item">
|
||||
<div class="security-item-left">
|
||||
<icon-phone class="security-icon" />
|
||||
<span class="security-label">手机号</span>
|
||||
</div>
|
||||
<span class="security-status">
|
||||
{{ loginUser.userPhone ? maskPhone(loginUser.userPhone) : '未绑定' }}
|
||||
</span>
|
||||
<a class="security-action" @click="showPhoneModal = true">
|
||||
{{ loginUser.userPhone ? '更换手机' : '绑定手机' }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- 绑定邮箱 -->
|
||||
<div class="security-item">
|
||||
<div class="security-item-left">
|
||||
<icon-email class="security-icon" />
|
||||
<span class="security-label">邮箱</span>
|
||||
</div>
|
||||
<span class="security-status">
|
||||
{{ loginUser.userEmail ? maskEmail(loginUser.userEmail) : '未绑定' }}
|
||||
</span>
|
||||
<a class="security-action" @click="showEmailModal = true">
|
||||
{{ loginUser.userEmail ? '更换邮箱' : '绑定邮箱' }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- 微信绑定 -->
|
||||
<div class="security-item">
|
||||
<div class="security-item-left">
|
||||
<icon-wechat class="security-icon wechat-color" />
|
||||
<span class="security-label">微信</span>
|
||||
</div>
|
||||
<span class="security-status">
|
||||
{{ loginUser.mpOpenId ? '已授权绑定微信账号' : '未绑定' }}
|
||||
</span>
|
||||
<a
|
||||
v-if="!loginUser.mpOpenId"
|
||||
class="security-action"
|
||||
@click="handleBindWechat"
|
||||
>
|
||||
绑定
|
||||
</a>
|
||||
<a v-else class="security-action" @click="handleUnbindWechat">解除绑定</a>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<!-- 修改密码弹窗 -->
|
||||
<a-modal
|
||||
v-model:visible="showPasswordModal"
|
||||
title="修改密码"
|
||||
@before-ok="handlePasswordSubmit"
|
||||
@cancel="handlePasswordReset"
|
||||
:ok-loading="passwordLoading"
|
||||
>
|
||||
<a-form :model="passwordForm" layout="vertical">
|
||||
<a-form-item label="当前密码" field="oldPassword">
|
||||
<a-input-password
|
||||
v-model="passwordForm.oldPassword"
|
||||
placeholder="请输入当前密码"
|
||||
max-length="20"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="新密码" field="newPassword">
|
||||
<a-input-password
|
||||
v-model="passwordForm.newPassword"
|
||||
placeholder="请输入新密码(6-20位)"
|
||||
max-length="20"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="确认密码" field="confirmPassword">
|
||||
<a-input-password
|
||||
v-model="passwordForm.confirmPassword"
|
||||
placeholder="请再次输入新密码"
|
||||
max-length="20"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 绑定手机弹窗 -->
|
||||
<a-modal
|
||||
v-model:visible="showPhoneModal"
|
||||
:title="loginUser.userPhone ? '更换手机号' : '绑定手机号'"
|
||||
@before-ok="handlePhoneSubmit"
|
||||
@cancel="handlePhoneReset"
|
||||
:ok-loading="phoneLoading"
|
||||
>
|
||||
<a-form :model="phoneForm" layout="vertical">
|
||||
<a-form-item label="手机号" field="phone">
|
||||
<a-input
|
||||
v-model="phoneForm.phone"
|
||||
placeholder="请输入手机号"
|
||||
max-length="11"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="验证码" field="code">
|
||||
<a-input-group style="width: 100%">
|
||||
<a-input
|
||||
v-model="phoneForm.code"
|
||||
placeholder="请输入验证码"
|
||||
:max-length="6"
|
||||
/>
|
||||
<a-button
|
||||
type="outline"
|
||||
:loading="codeSending"
|
||||
:disabled="phoneCountdown > 0 || !phoneForm.phone"
|
||||
@click="handleSendPhoneCode"
|
||||
>
|
||||
{{ phoneCountdown > 0 ? `${phoneCountdown}秒后重试` : '发送验证码' }}
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 绑定邮箱弹窗 -->
|
||||
<a-modal
|
||||
v-model:visible="showEmailModal"
|
||||
:title="loginUser.userEmail ? '更换邮箱' : '绑定邮箱'"
|
||||
@before-ok="handleEmailSubmit"
|
||||
@cancel="handleEmailReset"
|
||||
:ok-loading="emailLoading"
|
||||
>
|
||||
<a-form :model="emailForm" layout="vertical">
|
||||
<a-form-item label="邮箱地址" field="email">
|
||||
<a-input
|
||||
v-model="emailForm.email"
|
||||
placeholder="请输入邮箱地址"
|
||||
type="email"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="验证码" field="code">
|
||||
<a-input-group style="width: 100%">
|
||||
<a-input
|
||||
v-model="emailForm.code"
|
||||
placeholder="请输入验证码"
|
||||
:max-length="6"
|
||||
/>
|
||||
<a-button
|
||||
type="outline"
|
||||
:loading="codeSending"
|
||||
:disabled="emailCountdown > 0 || !emailForm.email"
|
||||
@click="handleSendEmailCode"
|
||||
>
|
||||
{{ emailCountdown > 0 ? `${emailCountdown}秒后重试` : '发送验证码' }}
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, watch, reactive } from 'vue';
|
||||
import { useUserStore } from '@/store/user';
|
||||
import { uploadFile, getFileById } from '@/api/file/file';
|
||||
import {
|
||||
updateUserAvatar,
|
||||
updateUserPassword,
|
||||
updateUserProfile,
|
||||
sendEmailVerifyCode,
|
||||
bindEmail,
|
||||
} from '@/api/auth/user';
|
||||
import { isApiSuccess } from '@/api/response';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import {
|
||||
IconCamera,
|
||||
IconLock,
|
||||
IconPhone,
|
||||
IconEmail,
|
||||
IconWechat
|
||||
} from '@arco-design/web-vue/es/icon';
|
||||
import * as SparkMD5 from 'spark-md5';
|
||||
import type { RequestOption } from '@arco-design/web-vue/es/upload/interfaces';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const loginUser = computed(() => userStore.loginUser);
|
||||
const avatarUrl = ref('');
|
||||
const loading = ref(false);
|
||||
const passwordLoading = ref(false);
|
||||
const phoneLoading = ref(false);
|
||||
const emailLoading = ref(false);
|
||||
const codeSending = ref(false);
|
||||
|
||||
// 验证码倒计时
|
||||
const emailCountdown = ref(0);
|
||||
const phoneCountdown = ref(0);
|
||||
let emailTimer: number | null = null;
|
||||
let phoneTimer: number | null = null;
|
||||
|
||||
// 弹窗显示状态
|
||||
const showPasswordModal = ref(false);
|
||||
const showPhoneModal = ref(false);
|
||||
const showEmailModal = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
userName: '',
|
||||
userProfile: '',
|
||||
});
|
||||
|
||||
// 修改密码表单
|
||||
const passwordForm = reactive({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
});
|
||||
|
||||
// 手机号表单
|
||||
const phoneForm = reactive({
|
||||
phone: '',
|
||||
code: '',
|
||||
});
|
||||
|
||||
// 邮箱表单
|
||||
const emailForm = reactive({
|
||||
email: '',
|
||||
code: '',
|
||||
});
|
||||
|
||||
// 角色颜色
|
||||
const roleColor = computed(() => {
|
||||
const role = loginUser.value.userRole;
|
||||
if (role === 'admin') return 'red';
|
||||
if (role === 'user') return 'arcoblue';
|
||||
return 'gray';
|
||||
});
|
||||
|
||||
// 角色文字
|
||||
const roleText = computed(() => {
|
||||
const role = loginUser.value.userRole;
|
||||
if (role === 'admin') return '管理员';
|
||||
if (role === 'user') return '普通用户';
|
||||
if (role === 'ban') return '被封禁';
|
||||
return '未知';
|
||||
});
|
||||
|
||||
// 静态数据(不可编辑)
|
||||
const staticData = computed(() => [
|
||||
{ label: '用户ID', value: loginUser.value.id?.toString() || '-' },
|
||||
{ label: '账号', value: loginUser.value.userAccount || '-' },
|
||||
{ label: '注册时间', value: loginUser.value.createTime || '-' },
|
||||
]);
|
||||
|
||||
// 手机号脱敏
|
||||
const maskPhone = (phone: string) => {
|
||||
if (!phone) return '';
|
||||
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
|
||||
};
|
||||
|
||||
// 邮箱脱敏
|
||||
const maskEmail = (email: string) => {
|
||||
if (!email) return '';
|
||||
const parts = email.split('@');
|
||||
if (parts.length !== 2 || !parts[0] || !parts[1]) return email;
|
||||
const [name = '', domain = ''] = parts;
|
||||
if (name.length <= 2) return email;
|
||||
return `${name.slice(0, 2)}***@${domain}`;
|
||||
};
|
||||
|
||||
// 加载用户头像
|
||||
const loadAvatarUrl = async () => {
|
||||
if (!loginUser.value.userAvatar) {
|
||||
avatarUrl.value = '';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await getFileById(loginUser.value.userAvatar);
|
||||
if (isApiSuccess(res) && res.data && res.data.storagePath) {
|
||||
avatarUrl.value = `/api/file/${res.data.storagePath}`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载头像失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化表单数据
|
||||
const initFormData = () => {
|
||||
formData.userName = loginUser.value.userName || '';
|
||||
formData.userProfile = loginUser.value.userProfile || '';
|
||||
};
|
||||
|
||||
// 监听用户头像变化
|
||||
watch(() => loginUser.value.userAvatar, () => {
|
||||
loadAvatarUrl();
|
||||
}, { immediate: true });
|
||||
|
||||
// 监听用户信息变化,更新表单
|
||||
watch(() => loginUser.value, () => {
|
||||
initFormData();
|
||||
}, { immediate: true, deep: true });
|
||||
|
||||
// 头像上传
|
||||
const customUpload = async (option: RequestOption) => {
|
||||
const { fileItem, onSuccess, onError } = option;
|
||||
if (!fileItem.file) return;
|
||||
|
||||
try {
|
||||
const hash = await computeFileHash(fileItem.file);
|
||||
const res = await uploadFile(fileItem.file, hash);
|
||||
if (isApiSuccess(res) && res.data) {
|
||||
const fileId: string = String(res.data.id);
|
||||
if (!fileId) {
|
||||
throw new Error('上传返回数据缺少文件ID');
|
||||
}
|
||||
const updateRes = await updateUserAvatar(fileId);
|
||||
if (isApiSuccess(updateRes)) {
|
||||
Message.success('头像更新成功');
|
||||
await userStore.getLoginUser();
|
||||
onSuccess(res);
|
||||
} else {
|
||||
throw new Error(updateRes.message || '更新头像失败');
|
||||
}
|
||||
} else {
|
||||
throw new Error(res.message || '上传失败');
|
||||
}
|
||||
} catch (err: any) {
|
||||
Message.error('上传出错: ' + err.message);
|
||||
onError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const computeFileHash = (file: File): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fileReader = new FileReader();
|
||||
const spark = new SparkMD5.ArrayBuffer();
|
||||
|
||||
fileReader.onload = (e) => {
|
||||
if (e.target?.result) {
|
||||
spark.append(e.target.result as ArrayBuffer);
|
||||
resolve(spark.end());
|
||||
} else {
|
||||
reject(new Error('File read failed'));
|
||||
}
|
||||
};
|
||||
|
||||
fileReader.onerror = () => reject(new Error('File read failed'));
|
||||
fileReader.readAsArrayBuffer(file);
|
||||
});
|
||||
};
|
||||
|
||||
// 提交资料表单
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await updateUserProfile({
|
||||
userName: formData.userName,
|
||||
userProfile: formData.userProfile,
|
||||
});
|
||||
if (isApiSuccess(res)) {
|
||||
Message.success('资料更新成功');
|
||||
await userStore.getLoginUser();
|
||||
} else {
|
||||
Message.error(res.message || '更新失败');
|
||||
}
|
||||
} catch (err: any) {
|
||||
Message.error('更新出错: ' + (err.message || '未知错误'));
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置资料表单
|
||||
const handleReset = () => {
|
||||
initFormData();
|
||||
Message.info('已重置');
|
||||
};
|
||||
|
||||
// 修改密码
|
||||
const handlePasswordSubmit = async () => {
|
||||
if (!passwordForm.oldPassword) {
|
||||
Message.warning('请输入当前密码');
|
||||
return false;
|
||||
}
|
||||
if (!passwordForm.newPassword) {
|
||||
Message.warning('请输入新密码');
|
||||
return false;
|
||||
}
|
||||
if (passwordForm.newPassword.length < 6 || passwordForm.newPassword.length > 20) {
|
||||
Message.warning('新密码长度应为6-20位');
|
||||
return false;
|
||||
}
|
||||
if (passwordForm.newPassword !== passwordForm.confirmPassword) {
|
||||
Message.warning('两次输入的密码不一致');
|
||||
return false;
|
||||
}
|
||||
if (passwordForm.oldPassword === passwordForm.newPassword) {
|
||||
Message.warning('新密码不能与当前密码相同');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
passwordLoading.value = true;
|
||||
const res = await updateUserPassword(
|
||||
passwordForm.oldPassword,
|
||||
passwordForm.newPassword
|
||||
);
|
||||
if (isApiSuccess(res)) {
|
||||
Message.success('密码修改成功,请重新登录');
|
||||
handlePasswordReset();
|
||||
// 修改密码后跳转到登录页
|
||||
setTimeout(() => {
|
||||
window.location.href = '/user/login';
|
||||
}, 1500);
|
||||
return true;
|
||||
} else {
|
||||
Message.error(res.message || '修改密码失败');
|
||||
return false;
|
||||
}
|
||||
} catch (err: any) {
|
||||
Message.error('修改密码出错: ' + (err.message || '未知错误'));
|
||||
return false;
|
||||
} finally {
|
||||
passwordLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置密码表单
|
||||
const handlePasswordReset = () => {
|
||||
passwordForm.oldPassword = '';
|
||||
passwordForm.newPassword = '';
|
||||
passwordForm.confirmPassword = '';
|
||||
};
|
||||
|
||||
// 绑定手机号
|
||||
const handlePhoneSubmit = async () => {
|
||||
if (!phoneForm.phone) {
|
||||
Message.warning('请输入手机号');
|
||||
return false;
|
||||
}
|
||||
if (!/^1[3-9]\d{9}$/.test(phoneForm.phone)) {
|
||||
Message.warning('请输入正确的手机号');
|
||||
return false;
|
||||
}
|
||||
if (!phoneForm.code) {
|
||||
Message.warning('请输入验证码');
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: 等后端接口提供后对接
|
||||
Message.info('绑定手机号接口开发中...');
|
||||
console.log('绑定手机号:', phoneForm);
|
||||
return false;
|
||||
};
|
||||
|
||||
// 发送手机验证码
|
||||
const handleSendPhoneCode = async () => {
|
||||
if (!phoneForm.phone) {
|
||||
Message.warning('请先输入手机号');
|
||||
return;
|
||||
}
|
||||
if (!/^1[3-9]\d{9}$/.test(phoneForm.phone)) {
|
||||
Message.warning('请输入正确的手机号');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: 等后端接口提供后对接
|
||||
Message.info('发送验证码接口开发中...');
|
||||
// 模拟倒计时(实际对接后端后移到成功回调中)
|
||||
phoneCountdown.value = 60;
|
||||
if (phoneTimer) clearInterval(phoneTimer);
|
||||
phoneTimer = window.setInterval(() => {
|
||||
phoneCountdown.value--;
|
||||
if (phoneCountdown.value <= 0) {
|
||||
if (phoneTimer) clearInterval(phoneTimer);
|
||||
phoneTimer = null;
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// 重置手机表单
|
||||
const handlePhoneReset = () => {
|
||||
phoneForm.phone = '';
|
||||
phoneForm.code = '';
|
||||
// 清理倒计时
|
||||
if (phoneTimer) {
|
||||
clearInterval(phoneTimer);
|
||||
phoneTimer = null;
|
||||
}
|
||||
phoneCountdown.value = 0;
|
||||
};
|
||||
|
||||
// 绑定邮箱
|
||||
const handleEmailSubmit = async () => {
|
||||
if (!emailForm.email) {
|
||||
Message.warning('请输入邮箱');
|
||||
return false;
|
||||
}
|
||||
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailForm.email)) {
|
||||
Message.warning('请输入正确的邮箱地址');
|
||||
return false;
|
||||
}
|
||||
if (!emailForm.code) {
|
||||
Message.warning('请输入验证码');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
emailLoading.value = true;
|
||||
const res = await bindEmail(emailForm.email, emailForm.code);
|
||||
if (isApiSuccess(res)) {
|
||||
Message.success('邮箱绑定成功');
|
||||
handleEmailReset();
|
||||
await userStore.getLoginUser();
|
||||
return true;
|
||||
} else {
|
||||
Message.error(res.message || '绑定失败');
|
||||
return false;
|
||||
}
|
||||
} catch (err: any) {
|
||||
Message.error('绑定邮箱出错: ' + (err.message || '未知错误'));
|
||||
return false;
|
||||
} finally {
|
||||
emailLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 发送邮箱验证码
|
||||
const handleSendEmailCode = async () => {
|
||||
if (!emailForm.email) {
|
||||
Message.warning('请先输入邮箱');
|
||||
return;
|
||||
}
|
||||
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailForm.email)) {
|
||||
Message.warning('请输入正确的邮箱地址');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
codeSending.value = true;
|
||||
const res = await sendEmailVerifyCode(emailForm.email);
|
||||
if (isApiSuccess(res)) {
|
||||
Message.success('验证码已发送,请查收邮箱');
|
||||
// 开始倒计时
|
||||
emailCountdown.value = 60;
|
||||
if (emailTimer) clearInterval(emailTimer);
|
||||
emailTimer = window.setInterval(() => {
|
||||
emailCountdown.value--;
|
||||
if (emailCountdown.value <= 0) {
|
||||
if (emailTimer) clearInterval(emailTimer);
|
||||
emailTimer = null;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
Message.error(res.message || '发送失败');
|
||||
}
|
||||
} catch (err: any) {
|
||||
Message.error('发送验证码出错: ' + (err.message || '未知错误'));
|
||||
} finally {
|
||||
codeSending.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置邮箱表单
|
||||
const handleEmailReset = () => {
|
||||
emailForm.email = '';
|
||||
emailForm.code = '';
|
||||
// 清理倒计时
|
||||
if (emailTimer) {
|
||||
clearInterval(emailTimer);
|
||||
emailTimer = null;
|
||||
}
|
||||
emailCountdown.value = 0;
|
||||
};
|
||||
|
||||
// 绑定微信
|
||||
const handleBindWechat = () => {
|
||||
// TODO: 等后端接口提供后对接
|
||||
Message.info('微信绑定接口开发中...');
|
||||
};
|
||||
|
||||
// 解绑微信
|
||||
const handleUnbindWechat = () => {
|
||||
// TODO: 等后端接口提供后对接
|
||||
Message.info('微信解绑接口开发中...');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
userStore.getLoginUser();
|
||||
});
|
||||
|
||||
// 清理定时器
|
||||
onUnmounted(() => {
|
||||
if (emailTimer) {
|
||||
clearInterval(emailTimer);
|
||||
emailTimer = null;
|
||||
}
|
||||
if (phoneTimer) {
|
||||
clearInterval(phoneTimer);
|
||||
phoneTimer = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#userProfileView {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.profile-card {
|
||||
height: 100%;
|
||||
|
||||
.profile-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
|
||||
.avatar-hint {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(img) {
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.avatar-hint {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #86909c;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
.user-name {
|
||||
margin-top: 20px;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
}
|
||||
|
||||
.user-role {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-card,
|
||||
.security-card {
|
||||
:deep(.arco-form-item) {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.arco-input-wrapper),
|
||||
:deep(.arco-textarea) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
// 验证码输入组样式
|
||||
:deep(.arco-input-group) {
|
||||
.arco-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.arco-btn {
|
||||
flex-shrink: 0;
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.security-card {
|
||||
.security-list {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.security-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.security-item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.security-icon {
|
||||
font-size: 20px;
|
||||
color: #4e5969;
|
||||
|
||||
&.wechat-color {
|
||||
color: #07c160;
|
||||
}
|
||||
}
|
||||
|
||||
.security-label {
|
||||
font-size: 15px;
|
||||
color: #1d2129;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.security-status {
|
||||
font-size: 14px;
|
||||
color: #86909c;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.security-action {
|
||||
font-size: 14px;
|
||||
color: #165dff;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
color: #4080ff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
#userProfileView {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.profile-card,
|
||||
.edit-card,
|
||||
.security-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -94,6 +94,8 @@ import { reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message } from "@arco-design/web-vue";
|
||||
import { IconUser, IconLock } from "@arco-design/web-vue/es/icon";
|
||||
import { register } from "@/api/auth/auth";
|
||||
import { isApiSuccess } from "@/api/response";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -151,27 +153,18 @@ const handleSubmit = async (data: any) => {
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
// TODO: 调用注册 API
|
||||
// 目前后端文档中没有注册接口,这里模拟注册成功
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
const res = await register({
|
||||
userAccount: form.userAccount,
|
||||
userPassword: form.userPassword,
|
||||
checkPassword: form.confirmPassword,
|
||||
});
|
||||
|
||||
Message.success("注册成功!请登录");
|
||||
|
||||
// 跳转到登录页
|
||||
router.push("/user/login");
|
||||
|
||||
// 实际实现时应该调用后端注册接口:
|
||||
// const response = await register({
|
||||
// userAccount: form.userAccount,
|
||||
// userPassword: form.userPassword,
|
||||
// });
|
||||
//
|
||||
// if (response.success) {
|
||||
// Message.success("注册成功!请登录");
|
||||
// router.push("/user/login");
|
||||
// } else {
|
||||
// Message.error(response.message || "注册失败");
|
||||
// }
|
||||
if (isApiSuccess(res)) {
|
||||
Message.success("注册成功!请登录");
|
||||
router.push("/user/login");
|
||||
} else {
|
||||
Message.error(res.message || "注册失败");
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("注册失败:", error);
|
||||
Message.error(error.response?.data?.message || "注册失败,请稍后重试");
|
||||
|
||||
@@ -28,12 +28,17 @@ export default defineConfig(({ command, mode }) => {
|
||||
proxy: {
|
||||
// 代理所有 /api 开头的请求
|
||||
'/api': {
|
||||
target: 'http://localhost:8085', // 后端服务器地址
|
||||
target: 'http://localhost:18085', // 后端服务器地址
|
||||
changeOrigin: true, // 改变请求头中的 origin
|
||||
secure: false, // 支持 https
|
||||
// 如果后端 API 路径不包含 /api,可以重写路径
|
||||
// rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
},
|
||||
'/file': {
|
||||
target: 'http://localhost:18085',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user