From 5bae1f8c126b1548b0220059b1bbec4abe1f8eec Mon Sep 17 00:00:00 2001 From: zhouwentao Date: Thu, 18 Dec 2025 21:05:25 +0800 Subject: [PATCH] feat:axios --- .env.development | 10 +- .env.production | 5 +- docs/api1.md | 184 +++++++++++++ package.json | 3 + pnpm-lock.yaml | 447 +++++-------------------------- project_codebase.md | 31 +++ project_doing.md | 14 + project_index.md | 8 + project_task.md | 9 + src/auto-imports.d.ts | 3 + src/components/TheNavigation.vue | 22 +- src/service/api/auth.ts | 24 ++ src/service/request/index.ts | 138 ++++++++++ src/stores/user.ts | 72 +++-- src/utils/message.ts | 75 ++++++ task_detail.md | 14 + tasks/Task1.md | 5 + vite.config.ts | 285 ++++++++++---------- 18 files changed, 799 insertions(+), 550 deletions(-) create mode 100644 docs/api1.md create mode 100644 project_codebase.md create mode 100644 project_doing.md create mode 100644 project_index.md create mode 100644 project_task.md create mode 100644 src/service/api/auth.ts create mode 100644 src/service/request/index.ts create mode 100644 src/utils/message.ts create mode 100644 task_detail.md diff --git a/.env.development b/.env.development index 932410b..722ca9b 100644 --- a/.env.development +++ b/.env.development @@ -1,8 +1,14 @@ # Development environment variables # API base URL -VITE_API_BASE_URL=https://api.dev.example.com +VITE_API_BASE_URL=/api + +# Proxy Target (Where the /api requests are forwarded to) 改完后需要重启 +VITE_API_PROXY_TARGET=http://localhost:8080 # Other development-specific variables VITE_APP_TITLE=My App (Development) -VITE_DEBUG_MODE=true \ No newline at end of file +VITE_DEBUG_MODE=true + +# API Signature Secret +VITE_API_SECRET='yts@2025#secure' diff --git a/.env.production b/.env.production index d04be5b..6e0b641 100644 --- a/.env.production +++ b/.env.production @@ -5,4 +5,7 @@ VITE_API_BASE_URL=https://api.example.com # Other production-specific variables VITE_APP_TITLE=My App -VITE_DEBUG_MODE=false \ No newline at end of file +VITE_DEBUG_MODE=false + +# API Signature Secret +VITE_API_SECRET=yts@2025#secure diff --git a/docs/api1.md b/docs/api1.md new file mode 100644 index 0000000..930d650 --- /dev/null +++ b/docs/api1.md @@ -0,0 +1,184 @@ +--- +title: 艺考招生管理系统 API +language_tabs: + - shell: Shell + - http: HTTP + - javascript: JavaScript + - ruby: Ruby + - python: Python + - php: PHP + - java: Java + - go: Go +toc_footers: [] +includes: [] +search: true +code_clipboard: true +highlight_theme: darkula +headingLevel: 2 +generator: "@tarslib/widdershins v4.0.30" + +--- + +# 艺考招生管理系统 API + +提供用户认证、院校专业、历年招生、计算专业的管理接口 + +Base URLs: + +* 开发环境: http://localhost:8080/api + +# Authentication + +# 认证 + +## GET 获取当前登录用户信息 + +GET /auth/info + +> 返回示例 + +> 200 Response + +``` +{"code":0,"data":null,"message":"string"} +``` + +### 返回结果 + +|状态码|状态码含义|说明|数据模型| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[common.Response](#schemacommon.response)| + +## POST 用户登录 + +POST /auth/login + +> Body 请求参数 + +```json +{ + "username": "18639433190", + "password": "123456" +} +``` + +### 请求参数 + +|名称|位置|类型|必选|说明| +|---|---|---|---|---| +|body|body|[controller.LoginRequest](#schemacontroller.loginrequest)| 是 |none| + +> 返回示例 + +> 200 Response + +```json +{ + "code": 200, + "message": "success", + "data": { + "token": "140a1289-1a0a-4c14-82f6-ba1feb36351a", + "user": { + "id": "1779515858733772802", + "username": "dyT3c2tV", + "realname": "用户-dyT3c2tV", + "avatar": "", + "phone": "18639433190", + "email": "", + "token": "140a1289-1a0a-4c14-82f6-ba1feb36351a" + } + } +} +``` + +### 返回结果 + +|状态码|状态码含义|说明|数据模型| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|Inline| + +### 返回数据结构 + +状态码 **200** + +|名称|类型|必选|约束|中文名|说明| +|---|---|---|---|---|---| +|» code|integer|true|none|状态码|none| +|» message|string|true|none|状态描述|none| +|» data|object|true|none||none| +|»» token|string|true|none|登录TOKEN|none| +|»» user|object|true|none||none| +|»»» id|string|true|none|用户ID|none| +|»»» username|string|true|none|用户名|none| +|»»» realname|string|true|none||none| +|»»» avatar|string|true|none|头像|none| +|»»» phone|string|true|none|手机号|none| +|»»» email|string|true|none||none| +|»»» token|string|true|none||none| + +## POST 用户登出 + +POST /auth/logout + +> 返回示例 + +> 200 Response + +``` +{"code":200,"message":"success","data":null} +``` + +### 返回结果 + +|状态码|状态码含义|说明|数据模型| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[common.Response](#schemacommon.response)| + +# 数据模型 + +

common.Response

+ + + + + + +```json +{ + "code": 0, + "data": null, + "message": "string" +} + +``` + +### 属性 + +|名称|类型|必选|约束|中文名|说明| +|---|---|---|---|---|---| +|code|integer|false|none||none| +|data|any|false|none||none| +|message|string|false|none||none| + +

controller.LoginRequest

+ + + + + + +```json +{ + "password": "string", + "username": "string" +} + +``` + +### 属性 + +|名称|类型|必选|约束|中文名|说明| +|---|---|---|---|---|---| +|password|string|true|none||none| +|username|string|true|none||none| + diff --git a/package.json b/package.json index 3520630..00bea82 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "@unhead/vue": "catalog:frontend", "@unocss/reset": "catalog:frontend", "@vueuse/core": "catalog:frontend", + "axios": "^1.13.2", + "crypto-js": "^4.2.0", "nprogress": "catalog:frontend", "pinia": "catalog:frontend", "vue": "catalog:frontend", @@ -33,6 +35,7 @@ "@iconify-json/carbon": "catalog:dev", "@intlify/unplugin-vue-i18n": "catalog:build", "@shikijs/markdown-it": "catalog:build", + "@types/crypto-js": "^4.2.2", "@types/markdown-it-link-attributes": "catalog:types", "@types/nprogress": "catalog:types", "@unocss/eslint-config": "catalog:build", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7692b34..8ad8b96 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -177,6 +177,12 @@ importers: '@vueuse/core': specifier: catalog:frontend version: 13.0.0(vue@3.5.13(typescript@5.8.2)) + axios: + specifier: ^1.13.2 + version: 1.13.2 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 nprogress: specifier: catalog:frontend version: 0.2.0 @@ -208,6 +214,9 @@ importers: '@shikijs/markdown-it': specifier: catalog:build version: 3.2.1(markdown-it-async@2.2.0) + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 '@types/markdown-it-link-attributes': specifier: catalog:types version: 3.0.5 @@ -1862,6 +1871,9 @@ packages: '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -2656,9 +2668,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} - array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -2682,10 +2691,6 @@ packages: resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.2: - resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} - engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.4: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} @@ -2734,10 +2739,6 @@ packages: peerDependencies: postcss: ^8.1.0 - available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -2748,6 +2749,9 @@ packages: aws4@1.12.0: resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + babel-plugin-polyfill-corejs2@0.3.3: resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} peerDependencies: @@ -3081,6 +3085,9 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + crypto-random-string@2.0.0: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} @@ -3206,10 +3213,6 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} - define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} - engines: {node: '>= 0.4'} - define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -3336,10 +3339,6 @@ packages: error-stack-parser-es@1.0.5: resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} - es-abstract@1.22.2: - resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==} - engines: {node: '>= 0.4'} - es-abstract@1.24.1: resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} engines: {node: '>= 0.4'} @@ -3367,10 +3366,6 @@ packages: resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} engines: {node: '>= 0.4'} - es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - es-to-primitive@1.3.0: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} @@ -3808,6 +3803,15 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -3822,6 +3826,10 @@ packages: resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -3848,10 +3856,6 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - function.prototype.name@1.1.8: resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} @@ -3901,10 +3905,6 @@ packages: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} - get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - get-symbol-description@1.1.0: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} @@ -3955,10 +3955,6 @@ packages: resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==} engines: {node: '>=18'} - globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -3994,10 +3990,6 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - has-proto@1.2.0: resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} @@ -4010,10 +4002,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -4148,10 +4136,6 @@ packages: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} - internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} - engines: {node: '>= 0.4'} - internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -4160,9 +4144,6 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -4174,9 +4155,6 @@ packages: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} - is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - is-bigint@1.1.0: resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} engines: {node: '>= 0.4'} @@ -4185,10 +4163,6 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - is-boolean-object@1.2.2: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} @@ -4278,18 +4252,10 @@ packages: is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} - is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -4313,10 +4279,6 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -4329,9 +4291,6 @@ packages: resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} - is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - is-shared-array-buffer@1.0.4: resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} engines: {node: '>= 0.4'} @@ -4348,10 +4307,6 @@ packages: resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} engines: {node: '>=18'} - is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} @@ -4364,10 +4319,6 @@ packages: resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} - is-typed-array@1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} - engines: {node: '>= 0.4'} - is-typed-array@1.1.15: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} @@ -4387,9 +4338,6 @@ packages: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} - is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - is-weakref@1.1.1: resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} engines: {node: '>= 0.4'} @@ -4982,10 +4930,6 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} - object.assign@4.1.7: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} @@ -5325,6 +5269,9 @@ packages: proxy-from-env@1.0.0: resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} @@ -5425,10 +5372,6 @@ packages: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true - regexp.prototype.flags@1.5.1: - resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} - engines: {node: '>= 0.4'} - regexp.prototype.flags@1.5.4: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} @@ -5519,10 +5462,6 @@ packages: rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - safe-array-concat@1.0.1: - resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} - engines: {node: '>=0.4'} - safe-array-concat@1.1.3: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} @@ -5537,9 +5476,6 @@ packages: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} - safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - safe-regex-test@1.1.0: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} @@ -5593,10 +5529,6 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} - set-function-name@2.0.1: - resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} - engines: {node: '>= 0.4'} - set-function-name@2.0.2: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} @@ -5775,20 +5707,10 @@ packages: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} - string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} - string.prototype.trimend@1.0.9: resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} engines: {node: '>= 0.4'} - string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} - string.prototype.trimstart@1.0.8: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} @@ -6050,33 +5972,18 @@ packages: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - typed-array-buffer@1.0.0: - resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} - engines: {node: '>= 0.4'} - typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} - typed-array-byte-length@1.0.0: - resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} - engines: {node: '>= 0.4'} - typed-array-byte-length@1.0.3: resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} - engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.4: resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} engines: {node: '>= 0.4'} - typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} - typed-array-length@1.0.7: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} @@ -6097,9 +6004,6 @@ packages: engines: {node: '>=0.8.0'} hasBin: true - unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -6535,9 +6439,6 @@ packages: whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -6550,10 +6451,6 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-typed-array@1.1.11: - resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} - engines: {node: '>= 0.4'} - which-typed-array@1.1.19: resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} @@ -8246,6 +8143,8 @@ snapshots: tslib: 2.8.1 optional: true + '@types/crypto-js@4.2.2': {} + '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -8506,7 +8405,7 @@ snapshots: '@unocss/eslint-plugin@65.4.0(eslint@9.23.0(jiti@1.21.7))(typescript@5.8.2)': dependencies: - '@typescript-eslint/utils': 8.28.0(eslint@9.23.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/utils': 8.50.0(eslint@9.23.0(jiti@1.21.7))(typescript@5.8.2) '@unocss/config': 65.4.0 '@unocss/core': 65.4.0 magic-string: 0.30.17 @@ -9280,11 +9179,6 @@ snapshots: argparse@2.0.1: {} - array-buffer-byte-length@1.0.0: - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.2 - array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -9327,16 +9221,6 @@ snapshots: es-abstract: 1.24.1 es-shim-unscopables: 1.1.0 - arraybuffer.prototype.slice@1.0.2: - dependencies: - array-buffer-byte-length: 1.0.0 - call-bind: 1.0.7 - define-properties: 1.2.0 - es-abstract: 1.22.2 - get-intrinsic: 1.3.0 - is-array-buffer: 3.0.2 - is-shared-array-buffer: 1.0.2 - arraybuffer.prototype.slice@1.0.4: dependencies: array-buffer-byte-length: 1.0.2 @@ -9385,8 +9269,6 @@ snapshots: postcss: 8.5.3 postcss-value-parser: 4.2.0 - available-typed-arrays@1.0.5: {} - available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -9395,6 +9277,14 @@ snapshots: aws4@1.12.0: {} + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.25.2): dependencies: '@babel/compat-data': 7.25.2 @@ -9736,6 +9626,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypto-js@4.2.0: {} + crypto-random-string@2.0.0: {} css-select@5.1.0: @@ -9892,11 +9784,6 @@ snapshots: define-lazy-prop@3.0.0: {} - define-properties@1.2.0: - dependencies: - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -10015,48 +9902,6 @@ snapshots: error-stack-parser-es@1.0.5: {} - es-abstract@1.22.2: - dependencies: - array-buffer-byte-length: 1.0.0 - arraybuffer.prototype.slice: 1.0.2 - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.3.0 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.2.0 - has: 1.0.3 - has-property-descriptors: 1.0.2 - has-proto: 1.0.1 - has-symbols: 1.1.0 - internal-slot: 1.0.5 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.12 - is-weakref: 1.0.2 - object-inspect: 1.13.3 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.1 - safe-array-concat: 1.0.1 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.8 - string.prototype.trimend: 1.0.7 - string.prototype.trimstart: 1.0.7 - typed-array-buffer: 1.0.0 - typed-array-byte-length: 1.0.0 - typed-array-byte-offset: 1.0.0 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.11 - es-abstract@1.24.1: dependencies: array-buffer-byte-length: 1.0.2 @@ -10135,12 +9980,6 @@ snapshots: dependencies: hasown: 2.0.2 - es-to-primitive@1.2.1: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - es-to-primitive@1.3.0: dependencies: is-callable: 1.2.7 @@ -10785,6 +10624,8 @@ snapshots: flatted@3.3.1: {} + follow-redirects@1.15.11: {} + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -10802,6 +10643,14 @@ snapshots: es-set-tostringtag: 2.1.0 mime-types: 2.1.35 + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + forwarded@0.2.0: {} fraction.js@5.3.4: {} @@ -10822,13 +10671,6 @@ snapshots: function-bind@1.1.2: {} - function.prototype.name@1.1.6: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.0 - es-abstract: 1.22.2 - functions-have-names: 1.2.3 - function.prototype.name@1.1.8: dependencies: call-bind: 1.0.8 @@ -10881,11 +10723,6 @@ snapshots: '@sec-ant/readable-stream': 0.4.1 is-stream: 4.0.1 - get-symbol-description@1.0.0: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.3.0 - get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 @@ -10941,10 +10778,6 @@ snapshots: globals@16.0.0: {} - globalthis@1.0.3: - dependencies: - define-properties: 1.2.0 - globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -10977,8 +10810,6 @@ snapshots: dependencies: es-define-property: 1.0.1 - has-proto@1.0.1: {} - has-proto@1.2.0: dependencies: dunder-proto: 1.0.1 @@ -10989,10 +10820,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - has@1.0.3: - dependencies: - function-bind: 1.1.2 - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -11159,12 +10986,6 @@ snapshots: ini@2.0.0: {} - internal-slot@1.0.5: - dependencies: - get-intrinsic: 1.3.0 - has: 1.0.3 - side-channel: 1.1.0 - internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -11173,12 +10994,6 @@ snapshots: ipaddr.js@1.9.1: {} - is-array-buffer@3.0.2: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.3.0 - is-typed-array: 1.1.12 - is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -11195,10 +11010,6 @@ snapshots: has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 - is-bigint@1.0.4: - dependencies: - has-bigints: 1.0.2 - is-bigint@1.1.0: dependencies: has-bigints: 1.0.2 @@ -11207,11 +11018,6 @@ snapshots: dependencies: binary-extensions: 2.2.0 - is-boolean-object@1.1.2: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - is-boolean-object@1.2.2: dependencies: call-bound: 1.0.4 @@ -11291,14 +11097,8 @@ snapshots: is-module@1.0.0: {} - is-negative-zero@2.0.2: {} - is-negative-zero@2.0.3: {} - is-number-object@1.0.7: - dependencies: - has-tostringtag: 1.0.2 - is-number-object@1.1.1: dependencies: call-bound: 1.0.4 @@ -11314,11 +11114,6 @@ snapshots: is-potential-custom-element-name@1.0.1: {} - is-regex@1.1.4: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -11330,10 +11125,6 @@ snapshots: is-set@2.0.3: {} - is-shared-array-buffer@1.0.2: - dependencies: - call-bind: 1.0.7 - is-shared-array-buffer@1.0.4: dependencies: call-bound: 1.0.4 @@ -11344,10 +11135,6 @@ snapshots: is-stream@4.0.1: {} - is-string@1.0.7: - dependencies: - has-tostringtag: 1.0.2 - is-string@1.1.1: dependencies: call-bound: 1.0.4 @@ -11363,10 +11150,6 @@ snapshots: has-symbols: 1.1.0 safe-regex-test: 1.1.0 - is-typed-array@1.1.12: - dependencies: - which-typed-array: 1.1.11 - is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.19 @@ -11379,10 +11162,6 @@ snapshots: is-weakmap@2.0.2: {} - is-weakref@1.0.2: - dependencies: - call-bind: 1.0.7 - is-weakref@1.1.1: dependencies: call-bound: 1.0.4 @@ -12134,13 +11913,6 @@ snapshots: object-keys@1.1.1: {} - object.assign@4.1.4: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.0 - has-symbols: 1.1.0 - object-keys: 1.1.1 - object.assign@4.1.7: dependencies: call-bind: 1.0.8 @@ -12465,6 +12237,8 @@ snapshots: proxy-from-env@1.0.0: {} + proxy-from-env@1.1.0: {} + pump@3.0.0: dependencies: end-of-stream: 1.4.4 @@ -12582,12 +12356,6 @@ snapshots: regexp-tree@0.1.27: {} - regexp.prototype.flags@1.5.1: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.0 - set-function-name: 2.0.1 - regexp.prototype.flags@1.5.4: dependencies: call-bind: 1.0.8 @@ -12699,13 +12467,6 @@ snapshots: dependencies: tslib: 2.8.1 - safe-array-concat@1.0.1: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - isarray: 2.0.5 - safe-array-concat@1.1.3: dependencies: call-bind: 1.0.8 @@ -12723,12 +12484,6 @@ snapshots: es-errors: 1.3.0 isarray: 2.0.5 - safe-regex-test@1.0.0: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.3.0 - is-regex: 1.1.4 - safe-regex-test@1.1.0: dependencies: call-bound: 1.0.4 @@ -12802,12 +12557,6 @@ snapshots: gopd: 1.2.0 has-property-descriptors: 1.0.2 - set-function-name@2.0.1: - dependencies: - define-data-property: 1.1.4 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - set-function-name@2.0.2: dependencies: define-data-property: 1.1.4 @@ -13014,13 +12763,13 @@ snapshots: string.prototype.matchall@4.0.8: dependencies: - call-bind: 1.0.7 - define-properties: 1.2.0 - es-abstract: 1.22.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 get-intrinsic: 1.3.0 has-symbols: 1.1.0 - internal-slot: 1.0.5 - regexp.prototype.flags: 1.5.1 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 side-channel: 1.1.0 string.prototype.trim@1.2.10: @@ -13033,18 +12782,6 @@ snapshots: es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 - string.prototype.trim@1.2.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.0 - es-abstract: 1.22.2 - - string.prototype.trimend@1.0.7: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.0 - es-abstract: 1.22.2 - string.prototype.trimend@1.0.9: dependencies: call-bind: 1.0.8 @@ -13052,12 +12789,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - string.prototype.trimstart@1.0.7: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.0 - es-abstract: 1.22.2 - string.prototype.trimstart@1.0.8: dependencies: call-bind: 1.0.8 @@ -13336,25 +13067,12 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 - typed-array-buffer@1.0.0: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.3.0 - is-typed-array: 1.1.12 - typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 es-errors: 1.3.0 is-typed-array: 1.1.15 - typed-array-byte-length@1.0.0: - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 - typed-array-byte-length@1.0.3: dependencies: call-bind: 1.0.8 @@ -13363,14 +13081,6 @@ snapshots: has-proto: 1.2.0 is-typed-array: 1.1.15 - typed-array-byte-offset@1.0.0: - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 - typed-array-byte-offset@1.0.4: dependencies: available-typed-arrays: 1.0.7 @@ -13381,12 +13091,6 @@ snapshots: is-typed-array: 1.1.15 reflect.getprototypeof: 1.0.10 - typed-array-length@1.0.4: - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - is-typed-array: 1.1.12 - typed-array-length@1.0.7: dependencies: call-bind: 1.0.8 @@ -13404,13 +13108,6 @@ snapshots: uglify-js@3.17.4: {} - unbox-primitive@1.0.2: - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.1.0 - which-boxed-primitive: 1.0.2 - unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -13988,14 +13685,6 @@ snapshots: tr46: 1.0.1 webidl-conversions: 4.0.2 - which-boxed-primitive@1.0.2: - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -14027,14 +13716,6 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-typed-array@1.1.11: - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 diff --git a/project_codebase.md b/project_codebase.md new file mode 100644 index 0000000..8508b23 --- /dev/null +++ b/project_codebase.md @@ -0,0 +1,31 @@ +# Project Codebase + +## Function Overview + +### `src/utils/message.ts` +- **Purpose**: Provides a global interface for showing toast messages. +- **Methods**: `success(msg, duration)`, `error(msg, duration)`, `warning(msg, duration)`, `info(msg, duration)`. +- **Implementation**: Programmatically mounts `WMessage.vue`. + +### `src/service/request/index.ts` +- **Purpose**: Encapsulates Axios for API requests. +- **Features**: + - Request Interceptor: + - Adds `token` to headers. + - Adds `X-App-Sign` (MD5(timestamp + secret)) and `X-App-Timestamp` headers for security. + - Starts `NProgress`. + - Response Interceptor: Unwraps `data`; handles global errors (401, 403, 500); stops `NProgress`. + - Config: `showLoading`, `showError`. + +### `src/service/api/auth.ts` +- **Purpose**: API definitions for authentication. +- **Methods**: `login`, `logout`, `getUserInfo`. + +### `src/stores/user.ts` +- **Purpose**: Manages user session state. +- **State**: `token`, `userInfo`. +- **Actions**: `login` (calls API), `logout`, `setToken`, `setUserInfo`. +- **Persistence**: Loads/Saves state to `localStorage`. + +### `src/components/TheNavigation.vue` +- **Updated**: Added integration with `userStore` for login/logout and `message` for notifications. diff --git a/project_doing.md b/project_doing.md new file mode 100644 index 0000000..6093cb5 --- /dev/null +++ b/project_doing.md @@ -0,0 +1,14 @@ +# Project Doing + +## 2025-12-18 + +### [Task 1] Global Message Component, API Encapsulation, and Login/Logout Integration +- **Time**: 2025-12-18 +- **Goal**: Implement global message, encapsulate axios, and integrate login. +- **Scope**: + - `src/components/ui/WMessage.vue` (Review/Update) + - `package.json` (Add axios) + - `src/service/request/index.ts` (Create) + - `src/service/api/auth.ts` (Create) + - `src/stores/user.ts` (Update) + - `src/components/TheNavigation.vue` (Update) diff --git a/project_index.md b/project_index.md new file mode 100644 index 0000000..894da7a --- /dev/null +++ b/project_index.md @@ -0,0 +1,8 @@ +# Project File Index + +- `src/utils/message.ts`: Global message utility. +- `src/service/request/index.ts`: Axios wrapper. +- `src/service/api/auth.ts`: Authentication API. +- `src/stores/user.ts`: User Pinia store. +- `src/components/ui/WMessage.vue`: Message component UI. +- `src/components/TheNavigation.vue`: Main navigation component. diff --git a/project_task.md b/project_task.md new file mode 100644 index 0000000..0d14a0f --- /dev/null +++ b/project_task.md @@ -0,0 +1,9 @@ +# Project Tasks + +- [ ] [Task 1] Global Message Component, API Encapsulation, and Login/Logout Integration + - [ ] Check/Implement Global Message Component + - [ ] Install axios + - [ ] Create `src/service/request/index.ts` + - [ ] Create `src/service/api/auth.ts` + - [ ] Update `src/stores/user.ts` (Pinia + Persistence) + - [ ] Integrate Login/Logout in `TheNavigation.vue` diff --git a/src/auto-imports.d.ts b/src/auto-imports.d.ts index 842a7b7..d6ad0a4 100644 --- a/src/auto-imports.d.ts +++ b/src/auto-imports.d.ts @@ -324,6 +324,9 @@ declare global { // @ts-ignore export type { RequestConfig, RequestResponse } from './composables/request' import('./composables/request') + // @ts-ignore + export type { UserInfo } from './stores/user' + import('./stores/user') } // for vue template auto import diff --git a/src/components/TheNavigation.vue b/src/components/TheNavigation.vue index c9b7a09..4f8134f 100644 --- a/src/components/TheNavigation.vue +++ b/src/components/TheNavigation.vue @@ -4,6 +4,7 @@ import { useWindowScroll } from '@vueuse/core' // 假设你使用了 VueUse import { ref, watch } from 'vue' import { useRoute } from 'vue-router' import { useUserStore } from '../stores/user' +import message from '~/utils/message' const userStore = useUserStore() const isLoginModalOpen = ref(false) @@ -78,19 +79,32 @@ function closeLoginModal() { error.value = '' } -function handleLogin() { +async function handleLogin() { if (!username.value || !password.value) { error.value = '请输入用户名和密码' return } - userStore.login(username.value, password.value) - closeLoginModal() + try { + await userStore.login({ username: username.value, password: password.value }) + message.success('登录成功') + closeLoginModal() + router.push('/') + } catch (e: any) { + error.value = e.message || '登录失败' + } } -function handleLogout() { +async function handleLogout() { + try { + await apiLogout() + } catch (e) { + console.error(e) + } userStore.logout() + message.success('退出登录成功') // 登出后关闭菜单 isMobileMenuOpen.value = false + router.push('/') } // 新增:切换移动端菜单 diff --git a/src/service/api/auth.ts b/src/service/api/auth.ts new file mode 100644 index 0000000..ee0dad7 --- /dev/null +++ b/src/service/api/auth.ts @@ -0,0 +1,24 @@ +import request from '../request' +import type { UserInfo } from '~/stores/user' + +export interface LoginParams { + username: string + password: string +} + +export interface LoginResult { + token: string + user: UserInfo +} + +export function login(params: LoginParams) { + return request.post('/auth/login', params) +} + +export function logout() { + return request.post('/auth/logout') +} + +export function getUserInfo() { + return request.get('/auth/info') +} diff --git a/src/service/request/index.ts b/src/service/request/index.ts new file mode 100644 index 0000000..9dd927a --- /dev/null +++ b/src/service/request/index.ts @@ -0,0 +1,138 @@ +import axios, { type AxiosInstance, type AxiosRequestConfig, type AxiosResponse } from 'axios' +import NProgress from 'nprogress' +import CryptoJS from 'crypto-js' +import { useUserStore } from '~/stores/user' +import message from '~/utils/message' + +export interface RequestConfig extends AxiosRequestConfig { + showLoading?: boolean + showError?: boolean +} + +interface ApiResponse { + code: number + message: string + data: T +} + +class Request { + private instance: AxiosInstance + + constructor(config: AxiosRequestConfig) { + this.instance = axios.create(config) + + // Request interceptor + this.instance.interceptors.request.use( + (config: RequestConfig) => { + if (config.showLoading !== false) { + NProgress.start() + } + + const userStore = useUserStore() + config.headers = config.headers || {} + + if (userStore.token) { + config.headers.token = userStore.token + } + + // Add Signature + const timestamp = Date.now().toString() + const secret = import.meta.env.VITE_API_SECRET || '' + const sign = CryptoJS.MD5(timestamp + secret).toString() + console.log(timestamp) + config.headers['X-App-Sign'] = sign + config.headers['X-App-Timestamp'] = timestamp + + return config + }, + (error) => { + return Promise.reject(error) + } + ) + + // Response interceptor + this.instance.interceptors.response.use( + (response: AxiosResponse) => { + const config = response.config as RequestConfig + if (config.showLoading !== false) { + NProgress.done() + } + + const res = response.data + if (res.code === 200) { + return res.data + } else { + if (config.showError !== false) { + message.error(res.message || 'Error') + } + return Promise.reject(new Error(res.message || 'Error')) + } + }, + (error) => { + const config = error.config as RequestConfig + if (config?.showLoading !== false) { + NProgress.done() + } + + let msg = 'Network Error' + if (error.response) { + // 优先使用后端返回的错误信息 + const backendMsg = error.response.data?.message + + switch (error.response.status) { + case 401: + msg = backendMsg || 'Unauthorized' + const userStore = useUserStore() + userStore.logout() + // router push login? + break + case 403: + msg = backendMsg || 'Forbidden' + break + case 404: + msg = backendMsg || 'Not Found' + break + case 500: + msg = backendMsg || 'Internal Server Error' + break + default: + msg = backendMsg || error.message + } + } + + if (config?.showError !== false) { + message.error(msg) + } + // 返回包含具体错误信息的 Error 对象 + return Promise.reject(new Error(msg)) + } + ) + } + + request(config: RequestConfig): Promise { + return this.instance.request(config) + } + + get(url: string, config?: RequestConfig): Promise { + return this.instance.get(url, config) + } + + post(url: string, data?: any, config?: RequestConfig): Promise { + return this.instance.post(url, data, config) + } + + put(url: string, data?: any, config?: RequestConfig): Promise { + return this.instance.put(url, data, config) + } + + delete(url: string, config?: RequestConfig): Promise { + return this.instance.delete(url, config) + } +} + +const request = new Request({ + baseURL: import.meta.env.VITE_API_BASE_URL, + timeout: 10000, +}) + +export default request diff --git a/src/stores/user.ts b/src/stores/user.ts index dd52e79..638e182 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -1,46 +1,70 @@ import { acceptHMRUpdate, defineStore } from 'pinia' +import { ref } from 'vue' -interface User { +export interface UserInfo { + id: string username: string - password: string + realname: string + avatar: string + phone: string + email: string } -export const useUserStore = defineStore('user', () => { - /** - * Current logged-in user. - */ - const user = ref(null) +import { login as apiLogin, type LoginParams } from '~/service/api/auth' - // Initialize user from localStorage +export const useUserStore = defineStore('user', () => { + const token = ref('') + const userInfo = ref(null) + + // Initialize from localStorage if (typeof window !== 'undefined') { + const savedToken = localStorage.getItem('token') const savedUser = localStorage.getItem('user') + if (savedToken) { + token.value = savedToken + } if (savedUser) { - user.value = JSON.parse(savedUser) + try { + userInfo.value = JSON.parse(savedUser) + } catch (e) { + console.error('Failed to parse user info', e) + } } } - /** - * Login the user. - * - * @param username - username to login with - * @param password - password to login with - */ - function login(username: string, password: string) { - const newUser = { username, password } - user.value = newUser - localStorage.setItem('user', JSON.stringify(newUser)) + function setToken(newToken: string) { + token.value = newToken + localStorage.setItem('token', newToken) + } + + function setUserInfo(info: UserInfo) { + userInfo.value = info + localStorage.setItem('user', JSON.stringify(info)) + } + + async function login(params: LoginParams) { + try { + const data = await apiLogin(params) + setToken(data.token) + setUserInfo(data.user) + return data + } catch (error) { + throw error + } } - /** - * Logout the user. - */ function logout() { - user.value = null + token.value = '' + userInfo.value = null + localStorage.removeItem('token') localStorage.removeItem('user') } return { - user, + token, + userInfo, + setToken, + setUserInfo, login, logout, } diff --git a/src/utils/message.ts b/src/utils/message.ts new file mode 100644 index 0000000..e63ecb1 --- /dev/null +++ b/src/utils/message.ts @@ -0,0 +1,75 @@ +import { createVNode, render } from 'vue' +import WMessage from '~/components/ui/WMessage.vue' + +let seed = 1 +const instances: any[] = [] + +type MessageType = 'success' | 'error' | 'warning' | 'info' + +interface MessageOptions { + message: string + type?: MessageType + duration?: number +} + +const Message = (options: MessageOptions) => { + const id = `message_${seed++}` + const container = document.createElement('div') + + // Create a container for the message if it doesn't exist + let messageContainer = document.querySelector('.w-message-container') + if (!messageContainer) { + messageContainer = document.createElement('div') + messageContainer.className = 'w-message-container fixed top-4 left-1/2 transform -translate-x-1/2 z-50 flex flex-col items-center pointer-events-none' + document.body.appendChild(messageContainer) + } + + const props = { + ...options, + id, + onClose: () => { + close(id, container) + }, + } + + const vnode = createVNode(WMessage, props) + + // Render the component into the container + // We append the container to the messageContainer + messageContainer.appendChild(container) + render(vnode, container) + + instances.push({ id, vnode, container }) +} + +function close(id: string, container: HTMLElement) { + const idx = instances.findIndex(vm => vm.id === id) + if (idx === -1) return + + const { vnode } = instances[idx] + // Manually call close on component if needed, but here we just unmount + // The component handles its own visibility transition + + // We wait for the transition to finish? The component calls onClose after transition. + // So we just remove it from DOM. + + render(null, container) + container.remove() + instances.splice(idx, 1) + + // Clean up container if empty + const messageContainer = document.querySelector('.w-message-container') + if (messageContainer && messageContainer.childNodes.length === 0) { + messageContainer.remove() + } +} + +// Helpers +export const message = { + success: (msg: string, duration?: number) => Message({ message: msg, type: 'success', duration }), + error: (msg: string, duration?: number) => Message({ message: msg, type: 'error', duration }), + warning: (msg: string, duration?: number) => Message({ message: msg, type: 'warning', duration }), + info: (msg: string, duration?: number) => Message({ message: msg, type: 'info', duration }), +} + +export default message diff --git a/task_detail.md b/task_detail.md new file mode 100644 index 0000000..d6a4e9f --- /dev/null +++ b/task_detail.md @@ -0,0 +1,14 @@ +# Task Detail + +## 2025-12-18 Session 5 + +### Execution Reason +User reported that the frontend was displaying a generic "Request failed with status code 401" error instead of the specific "用户不存在" message returned by the backend in the `data.message` field. + +### Execution Process +1. **Analysis**: Examined `src/service/request/index.ts`. The response interceptor's error handler (onRejected) was hardcoding messages for 401, 403, etc., ignoring the `message` field from the backend response body (`error.response.data.message`). +2. **Fix**: Updated the error handling logic to prioritize `error.response.data?.message` if it exists. If not, it falls back to the default status code descriptions. +3. **Refinement**: Ensured `Promise.reject` returns a new `Error` object with the refined message, so calling code (`try/catch`) receives the correct error text. + +### Execution Result +- The application will now display the specific error message returned by the backend (e.g., "用户不存在") in the global message toast and in `catch` blocks, improving the user experience and debugging capability. diff --git a/tasks/Task1.md b/tasks/Task1.md index e69de29..da1ff93 100644 --- a/tasks/Task1.md +++ b/tasks/Task1.md @@ -0,0 +1,5 @@ +首先我需要你帮我做一个全局的message提示组件,用于在全局范围内显示提示信息,如成功、失败、警告等。 +我需要你帮我参考#api1.md文件,根据接口文档内容,首先封装一个src/service/request/index.ts文件,用于封装axios请求,包括请求拦截器、响应拦截器、请求参数处理、响应数据处理等。然后封装一个src/service/api/xx.ts文件,用于封装每个接口的请求方法,包括请求参数、请求方法、请求路径等。 +接口请求时,可以直接调用封装好的请求方法,也可以在业务代码中直接调用axios请求。调用时可以根据需要传递参数,也可以在请求方法中直接传递参数。同时参数中可以传递一个config对象,用于配置请求参数,如请求头、请求体、超时时间等(不强制),以及是否加载,是否显示loading(loading时屏幕不可操作)等。 +针对登录接口,可以利用pinia存储登录状态,登录成功后将token存储在pinia中,后续请求在请求拦截器中添加token到请求头中。同时增加持久化存储,登录状态和token可以存储在localStorage中,避免页面刷新后登录状态丢失,需要防止持久化信息被恶意获取。 +登录和退出接口封装后,在业务代码中#TheNavigation.vue中调用登录和退出接口,登录成功后跳转到首页,退出登录后跳转到首页。 \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index bf7e45a..41cee0f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -11,157 +11,170 @@ import VueMacros from 'unplugin-vue-macros/vite' import Markdown from 'unplugin-vue-markdown/vite' import { VueRouterAutoImports } from 'unplugin-vue-router' import VueRouter from 'unplugin-vue-router/vite' -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import VueDevTools from 'vite-plugin-vue-devtools' import Layouts from 'vite-plugin-vue-layouts' import generateSitemap from 'vite-ssg-sitemap' import 'vitest/config' -export default defineConfig({ - resolve: { - alias: { - '~/': `${path.resolve(__dirname, 'src')}/`, +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), '') + + return { + resolve: { + alias: { + '~/': `${path.resolve(__dirname, 'src')}/`, + }, }, - }, - plugins: [ - // https://github.com/posva/unplugin-vue-router - VueRouter({ - extensions: ['.vue', '.md'], - dts: 'src/typed-router.d.ts', - }), - - VueMacros({ - plugins: { - vue: Vue({ - include: [/\.vue$/, /\.md$/], - }), - }, - }), - - // https://github.com/JohnCampionJr/vite-plugin-vue-layouts - Layouts(), - - // https://github.com/antfu/unplugin-auto-import - AutoImport({ - include: [/\.[jt]sx?$/, /\.vue$/, /\.vue\?vue/, /\.md$/], - imports: [ - 'vue', - 'vue-i18n', - '@vueuse/core', - unheadVueComposablesImports, - VueRouterAutoImports, - { - // add any other imports you were relying on - 'vue-router/auto': ['useLink'], + server: { + proxy: { + '/api': { + target: env.VITE_API_PROXY_TARGET || 'http://localhost:8080', + changeOrigin: true, }, - ], - dts: 'src/auto-imports.d.ts', - dirs: [ - 'src/composables', - 'src/stores', - ], - vueTemplate: true, - }), - - // https://github.com/antfu/unplugin-vue-components - Components({ - // allow auto load markdown components under `./src/components/` - extensions: ['vue', 'md'], - // allow auto import and register components used in markdown - include: [/\.vue$/, /\.vue\?vue/, /\.md$/], - dts: 'src/components.d.ts', - }), - - // https://github.com/antfu/unocss - // see uno.config.ts for config - Unocss(), - - // https://github.com/unplugin/unplugin-vue-markdown - // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite - Markdown({ - wrapperClasses: 'prose prose-sm m-auto text-left', - headEnabled: true, - async markdownItSetup(md) { - md.use(LinkAttributes, { - matcher: (link: string) => /^https?:\/\//.test(link), - attrs: { - target: '_blank', - rel: 'noopener', - }, - }) - md.use(await Shiki({ - defaultColor: false, - themes: { - light: 'vitesse-light', - dark: 'vitesse-dark', - }, - })) }, - }), + }, - // https://github.com/antfu/vite-plugin-pwa - VitePWA({ - registerType: 'autoUpdate', - includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'], - manifest: { - name: 'Vitesse', - short_name: 'Vitesse', - theme_color: '#ffffff', - icons: [ + plugins: [ + // https://github.com/posva/unplugin-vue-router + VueRouter({ + extensions: ['.vue', '.md'], + dts: 'src/typed-router.d.ts', + }), + + VueMacros({ + plugins: { + vue: Vue({ + include: [/\.vue$/, /\.md$/], + }), + }, + }), + + // https://github.com/JohnCampionJr/vite-plugin-vue-layouts + Layouts(), + + // https://github.com/antfu/unplugin-auto-import + AutoImport({ + include: [/\.[jt]sx?$/, /\.vue$/, /\.vue\?vue/, /\.md$/], + imports: [ + 'vue', + 'vue-i18n', + '@vueuse/core', + unheadVueComposablesImports, + VueRouterAutoImports, { - src: '/pwa-192x192.png', - sizes: '192x192', - type: 'image/png', - }, - { - src: '/pwa-512x512.png', - sizes: '512x512', - type: 'image/png', - }, - { - src: '/pwa-512x512.png', - sizes: '512x512', - type: 'image/png', - purpose: 'any maskable', + // add any other imports you were relying on + 'vue-router/auto': ['useLink'], }, ], + dts: 'src/auto-imports.d.ts', + dirs: [ + 'src/composables', + 'src/stores', + ], + vueTemplate: true, + }), + + // https://github.com/antfu/unplugin-vue-components + Components({ + // allow auto load markdown components under `./src/components/` + extensions: ['vue', 'md'], + // allow auto import and register components used in markdown + include: [/\.vue$/, /\.vue\?vue/, /\.md$/], + dts: 'src/components.d.ts', + }), + + // https://github.com/antfu/unocss + // see uno.config.ts for config + Unocss(), + + // https://github.com/unplugin/unplugin-vue-markdown + // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite + Markdown({ + wrapperClasses: 'prose prose-sm m-auto text-left', + headEnabled: true, + async markdownItSetup(md) { + md.use(LinkAttributes, { + matcher: (link: string) => /^https?:\/\//.test(link), + attrs: { + target: '_blank', + rel: 'noopener', + }, + }) + md.use(await Shiki({ + defaultColor: false, + themes: { + light: 'vitesse-light', + dark: 'vitesse-dark', + }, + })) + }, + }), + + // https://github.com/antfu/vite-plugin-pwa + VitePWA({ + registerType: 'autoUpdate', + includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'], + manifest: { + name: 'Vitesse', + short_name: 'Vitesse', + theme_color: '#ffffff', + icons: [ + { + src: '/pwa-192x192.png', + sizes: '192x192', + type: 'image/png', + }, + { + src: '/pwa-512x512.png', + sizes: '512x512', + type: 'image/png', + }, + { + src: '/pwa-512x512.png', + sizes: '512x512', + type: 'image/png', + purpose: 'any maskable', + }, + ], + }, + }), + + // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n + VueI18n({ + runtimeOnly: true, + compositionOnly: true, + fullInstall: true, + include: [path.resolve(__dirname, 'locales/**')], + }), + + // https://github.com/webfansplz/vite-plugin-vue-devtools + VueDevTools(), + ], + + // https://github.com/vitest-dev/vitest + test: { + include: ['test/**/*.test.ts'], + environment: 'jsdom', + }, + + // https://github.com/antfu/vite-ssg + ssgOptions: { + script: 'async', + formatting: 'minify', + beastiesOptions: { + reduceInlineStyles: false, + }, + onFinished() { + generateSitemap() }, - }), - - // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n - VueI18n({ - runtimeOnly: true, - compositionOnly: true, - fullInstall: true, - include: [path.resolve(__dirname, 'locales/**')], - }), - - // https://github.com/webfansplz/vite-plugin-vue-devtools - VueDevTools(), - ], - - // https://github.com/vitest-dev/vitest - test: { - include: ['test/**/*.test.ts'], - environment: 'jsdom', - }, - - // https://github.com/antfu/vite-ssg - ssgOptions: { - script: 'async', - formatting: 'minify', - beastiesOptions: { - reduceInlineStyles: false, }, - onFinished() { - generateSitemap() - }, - }, - ssr: { - // TODO: workaround until they support native ESM - noExternal: ['workbox-window', /vue-i18n/], - }, + ssr: { + // TODO: workaround until they support native ESM + noExternal: ['workbox-window', /vue-i18n/], + }, + } })