Browse Source

完成格式化问题修改

yuanmingze 8 months ago
parent
commit
6b4e406d61

+ 28 - 11
.eslintrc.cjs

@@ -1,15 +1,17 @@
 // .eslintrc.cjs
 module.exports = {
   root: true,
+
   env: {
     node: true,
     es2021: true,
   },
+
   globals: {
     uni: 'readonly',
     wx: 'readonly',
     my: 'readonly',
-    plus: 'readonly', // App Plus
+    plus: 'readonly',
     getApp: 'readonly',
     getCurrentPages: 'readonly',
   },
@@ -42,26 +44,41 @@ module.exports = {
     '@typescript-eslint/no-explicit-any': 'off',
     '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
 
-    /* ========= Import Sort ========= */
+    /* ========= Import Sort(核心) ========= */
     'simple-import-sort/imports': [
       'error',
       {
         groups: [
-          // 1. Vue 核心
-          ['^vue$', '^vue-router'],
-          // 2. 第三方库
+          // 1. Vue / 框架核心
+          ['^vue$', '^vue-router$', '^pinia$'],
+
+          // 2. 其他第三方依赖
           ['^@?\\w'],
-          // 3. 项目内部 - services
-          ['^@/services/.*/index$', '^@/services(?!/.*/type)', '^@/services/.*/type'],
-          // 4. 项目内部 - 其他模块
-          ['^@/(hooks|utils|stores|router|config|constants|types|icons|layout)'],
-          // 5. 相对路径
+
+          // 3. 项目基础设施
+          ['^@/(lib|plugins|config|themes|styles)(/.*)?$'],
+
+          // 4. services
+          ['^@/services(/.*)?$'],
+
+          // 5. 状态 / composables
+          ['^@/(stores|composables)(/.*)?$'],
+
+          // 6. utils / validators / constants / types
+          ['^@/(utils|validators|constants|types)(/.*)?$'],
+
+          // 7. components / pages
+          ['^@/(components|pages)(/.*)?$'],
+
+          // 8. 相对路径
           ['^\\.'],
-          // 6. 样式
+
+          // 9. 样式
           ['^.+\\.s?css$'],
         ],
       },
     ],
+
     'simple-import-sort/exports': 'error',
   },
 }

+ 1 - 8
.vscode/settings.json

@@ -1,22 +1,15 @@
 {
-  /* ========== TypeScript ========= */
   "typescript.tsdk": "node_modules/typescript/lib",
   "typescript.enablePromptUseWorkspaceTsdk": true,
 
-  /* ========== 保存行为 ========= */
   "editor.formatOnSave": true,
 
-  /* ========== 默认格式化器 ========= */
-  "editor.defaultFormatter": "esbenp.prettier-vscode",
-
-  /* ========== ESLint 参与格式化 ========= */
   "editor.codeActionsOnSave": {
     "source.fixAll.eslint": "explicit"
   },
 
-  /* ========== ESLint 生效文件 ========= */
   "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "vue"],
 
-  /* ========== Prettier 配合 ESLint ========= */
+  "editor.defaultFormatter": "esbenp.prettier-vscode",
   "prettier.requireConfig": true
 }

+ 4 - 3
package.json

@@ -51,8 +51,8 @@
     "@dcloudio/vite-plugin-uni": "3.0.0-4080420251103001",
     "@types/lodash-es": "^4.17.12",
     "@types/node": "^25.0.3",
-    "@typescript-eslint/eslint-plugin": "^8.52.0",
-    "@typescript-eslint/parser": "^8.52.0",
+    "@typescript-eslint/eslint-plugin": "^6.21.0",
+    "@typescript-eslint/parser": "^6.21.0",
     "@uni-helper/uni-app-types": "1.0.0-alpha.7",
     "@uni-helper/uni-ui-types": "1.0.0-alpha.7",
     "@uni-helper/vite-plugin-uni-components": "^0.2.6",
@@ -64,7 +64,7 @@
     "eslint": "^8.57.1",
     "eslint-config-prettier": "^10.1.8",
     "eslint-plugin-simple-import-sort": "^12.1.1",
-    "eslint-plugin-vue": "^10.6.2",
+    "eslint-plugin-vue": "^9.25.0",
     "jsonc-parser": "^3.3.1",
     "miniprogram-api-typings": "^4.1.2",
     "prettier": "^3.7.4",
@@ -75,6 +75,7 @@
     "unplugin-vue-components": "^30.0.0",
     "vite": "5.2.8",
     "vite-tsconfig-paths": "^6.0.3",
+    "vue-eslint-parser": "9.4.3",
     "vue-tsc": "^1.0.24"
   }
 }

+ 176 - 165
pnpm-lock.yaml

@@ -112,11 +112,11 @@ importers:
         specifier: ^25.0.3
         version: 25.0.3
       '@typescript-eslint/eslint-plugin':
-        specifier: ^8.52.0
-        version: 8.52.0(@typescript-eslint/parser@8.52.0(eslint@8.57.1)(typescript@4.9.5))(eslint@8.57.1)(typescript@4.9.5)
+        specifier: ^6.21.0
+        version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@4.9.5))(eslint@8.57.1)(typescript@4.9.5)
       '@typescript-eslint/parser':
-        specifier: ^8.52.0
-        version: 8.52.0(eslint@8.57.1)(typescript@4.9.5)
+        specifier: ^6.21.0
+        version: 6.21.0(eslint@8.57.1)(typescript@4.9.5)
       '@uni-helper/uni-app-types':
         specifier: 1.0.0-alpha.7
         version: 1.0.0-alpha.7(typescript@4.9.5)(vue@3.5.26(typescript@4.9.5))
@@ -151,8 +151,8 @@ importers:
         specifier: ^12.1.1
         version: 12.1.1(eslint@8.57.1)
       eslint-plugin-vue:
-        specifier: ^10.6.2
-        version: 10.6.2(@typescript-eslint/parser@8.52.0(eslint@8.57.1)(typescript@4.9.5))(eslint@8.57.1)(vue-eslint-parser@10.2.0(eslint@8.57.1))
+        specifier: ^9.25.0
+        version: 9.25.0(eslint@8.57.1)
       jsonc-parser:
         specifier: ^3.3.1
         version: 3.3.1
@@ -183,6 +183,9 @@ importers:
       vite-tsconfig-paths:
         specifier: ^6.0.3
         version: 6.0.3(typescript@4.9.5)(vite@5.2.8(@types/node@25.0.3)(sass@1.78.0)(terser@5.44.1))
+      vue-eslint-parser:
+        specifier: 9.4.3
+        version: 9.4.3(eslint@8.57.1)
       vue-tsc:
         specifier: ^1.0.24
         version: 1.8.27(typescript@4.9.5)
@@ -1746,6 +1749,9 @@ packages:
   '@types/istanbul-reports@3.0.4':
     resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
 
+  '@types/json-schema@7.0.15':
+    resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
   '@types/lodash-es@4.17.12':
     resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
 
@@ -1758,6 +1764,9 @@ packages:
   '@types/prettier@2.7.3':
     resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==}
 
+  '@types/semver@7.7.1':
+    resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
+
   '@types/stack-utils@2.0.3':
     resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
 
@@ -1767,64 +1776,63 @@ packages:
   '@types/yargs@16.0.11':
     resolution: {integrity: sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==}
 
-  '@typescript-eslint/eslint-plugin@8.52.0':
-    resolution: {integrity: sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      '@typescript-eslint/parser': ^8.52.0
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '>=4.8.4 <6.0.0'
-
-  '@typescript-eslint/parser@8.52.0':
-    resolution: {integrity: sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  '@typescript-eslint/eslint-plugin@6.21.0':
+    resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==}
+    engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '>=4.8.4 <6.0.0'
+      '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
+      eslint: ^7.0.0 || ^8.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
 
-  '@typescript-eslint/project-service@8.52.0':
-    resolution: {integrity: sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  '@typescript-eslint/parser@6.21.0':
+    resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==}
+    engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
-      typescript: '>=4.8.4 <6.0.0'
-
-  '@typescript-eslint/scope-manager@8.52.0':
-    resolution: {integrity: sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+      eslint: ^7.0.0 || ^8.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
 
-  '@typescript-eslint/tsconfig-utils@8.52.0':
-    resolution: {integrity: sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      typescript: '>=4.8.4 <6.0.0'
+  '@typescript-eslint/scope-manager@6.21.0':
+    resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==}
+    engines: {node: ^16.0.0 || >=18.0.0}
 
-  '@typescript-eslint/type-utils@8.52.0':
-    resolution: {integrity: sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  '@typescript-eslint/type-utils@6.21.0':
+    resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==}
+    engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '>=4.8.4 <6.0.0'
+      eslint: ^7.0.0 || ^8.0.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
 
-  '@typescript-eslint/types@8.52.0':
-    resolution: {integrity: sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  '@typescript-eslint/types@6.21.0':
+    resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==}
+    engines: {node: ^16.0.0 || >=18.0.0}
 
-  '@typescript-eslint/typescript-estree@8.52.0':
-    resolution: {integrity: sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  '@typescript-eslint/typescript-estree@6.21.0':
+    resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==}
+    engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
-      typescript: '>=4.8.4 <6.0.0'
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
 
-  '@typescript-eslint/utils@8.52.0':
-    resolution: {integrity: sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  '@typescript-eslint/utils@6.21.0':
+    resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==}
+    engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '>=4.8.4 <6.0.0'
+      eslint: ^7.0.0 || ^8.0.0
 
-  '@typescript-eslint/visitor-keys@8.52.0':
-    resolution: {integrity: sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  '@typescript-eslint/visitor-keys@6.21.0':
+    resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==}
+    engines: {node: ^16.0.0 || >=18.0.0}
 
   '@ungap/structured-clone@1.3.0':
     resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
@@ -2060,6 +2068,10 @@ packages:
   array-flatten@1.1.1:
     resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
 
+  array-union@2.1.0:
+    resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+    engines: {node: '>=8'}
+
   async-validator@4.2.5:
     resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
 
@@ -2445,6 +2457,10 @@ packages:
     resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==}
     engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
 
+  dir-glob@3.0.1:
+    resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+    engines: {node: '>=8'}
+
   doctrine@3.0.0:
     resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
     engines: {node: '>=6.0.0'}
@@ -2565,46 +2581,26 @@ packages:
     peerDependencies:
       eslint: '>=5.0.0'
 
-  eslint-plugin-vue@10.6.2:
-    resolution: {integrity: sha512-nA5yUs/B1KmKzvC42fyD0+l9Yd+LtEpVhWRbXuDj0e+ZURcTtyRbMDWUeJmTAh2wC6jC83raS63anNM2YT3NPw==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  eslint-plugin-vue@9.25.0:
+    resolution: {integrity: sha512-tDWlx14bVe6Bs+Nnh3IGrD+hb11kf2nukfm6jLsmJIhmiRQ1SUaksvwY9U5MvPB0pcrg0QK0xapQkfITs3RKOA==}
+    engines: {node: ^14.17.0 || >=16.0.0}
     peerDependencies:
-      '@stylistic/eslint-plugin': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
-      '@typescript-eslint/parser': ^7.0.0 || ^8.0.0
-      eslint: ^8.57.0 || ^9.0.0
-      vue-eslint-parser: ^10.0.0
-    peerDependenciesMeta:
-      '@stylistic/eslint-plugin':
-        optional: true
-      '@typescript-eslint/parser':
-        optional: true
+      eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
 
   eslint-scope@7.2.2:
     resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
 
-  eslint-scope@8.4.0:
-    resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
   eslint-visitor-keys@3.4.3:
     resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
 
-  eslint-visitor-keys@4.2.1:
-    resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
   eslint@8.57.1:
     resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
     hasBin: true
 
-  espree@10.4.0:
-    resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
   espree@9.6.1:
     resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -2809,6 +2805,10 @@ packages:
     resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
     engines: {node: '>=8'}
 
+  globby@11.1.0:
+    resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+    engines: {node: '>=10'}
+
   globrex@0.1.2:
     resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
 
@@ -2895,10 +2895,6 @@ packages:
     resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
     engines: {node: '>= 4'}
 
-  ignore@7.0.5:
-    resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
-    engines: {node: '>= 4'}
-
   immutable@4.3.7:
     resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
 
@@ -3365,6 +3361,10 @@ packages:
     resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==}
     engines: {node: '>=16 || 14 >=14.17'}
 
+  minimatch@9.0.3:
+    resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
   minimatch@9.0.5:
     resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
     engines: {node: '>=16 || 14 >=14.17'}
@@ -3538,6 +3538,10 @@ packages:
   path-to-regexp@0.1.10:
     resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==}
 
+  path-type@4.0.0:
+    resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+    engines: {node: '>=8'}
+
   pathe@2.0.3:
     resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
 
@@ -4072,11 +4076,11 @@ packages:
     resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==}
     engines: {node: '>=8'}
 
-  ts-api-utils@2.4.0:
-    resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
-    engines: {node: '>=18.12'}
+  ts-api-utils@1.4.3:
+    resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==}
+    engines: {node: '>=16'}
     peerDependencies:
-      typescript: '>=4.8.4'
+      typescript: '>=4.2.0'
 
   tsconfck@3.1.6:
     resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==}
@@ -4281,11 +4285,11 @@ packages:
       terser:
         optional: true
 
-  vue-eslint-parser@10.2.0:
-    resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+  vue-eslint-parser@9.4.3:
+    resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==}
+    engines: {node: ^14.17.0 || >=16.0.0}
     peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
+      eslint: '>=6.0.0'
 
   vue-i18n@9.14.5:
     resolution: {integrity: sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g==}
@@ -5223,7 +5227,7 @@ snapshots:
       '@babel/parser': 7.28.5
       '@babel/template': 7.27.2
       '@babel/types': 7.28.5
-      debug: 4.3.7
+      debug: 4.4.3
     transitivePeerDependencies:
       - supports-color
 
@@ -6721,6 +6725,8 @@ snapshots:
     dependencies:
       '@types/istanbul-lib-report': 3.0.3
 
+  '@types/json-schema@7.0.15': {}
+
   '@types/lodash-es@4.17.12':
     dependencies:
       '@types/lodash': 4.17.21
@@ -6733,6 +6739,8 @@ snapshots:
 
   '@types/prettier@2.7.3': {}
 
+  '@types/semver@7.7.1': {}
+
   '@types/stack-utils@2.0.3': {}
 
   '@types/yargs-parser@21.0.3': {}
@@ -6741,96 +6749,91 @@ snapshots:
     dependencies:
       '@types/yargs-parser': 21.0.3
 
-  '@typescript-eslint/eslint-plugin@8.52.0(@typescript-eslint/parser@8.52.0(eslint@8.57.1)(typescript@4.9.5))(eslint@8.57.1)(typescript@4.9.5)':
+  '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@4.9.5))(eslint@8.57.1)(typescript@4.9.5)':
     dependencies:
       '@eslint-community/regexpp': 4.12.2
-      '@typescript-eslint/parser': 8.52.0(eslint@8.57.1)(typescript@4.9.5)
-      '@typescript-eslint/scope-manager': 8.52.0
-      '@typescript-eslint/type-utils': 8.52.0(eslint@8.57.1)(typescript@4.9.5)
-      '@typescript-eslint/utils': 8.52.0(eslint@8.57.1)(typescript@4.9.5)
-      '@typescript-eslint/visitor-keys': 8.52.0
+      '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@4.9.5)
+      '@typescript-eslint/scope-manager': 6.21.0
+      '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@4.9.5)
+      '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@4.9.5)
+      '@typescript-eslint/visitor-keys': 6.21.0
+      debug: 4.4.3
       eslint: 8.57.1
-      ignore: 7.0.5
+      graphemer: 1.4.0
+      ignore: 5.3.2
       natural-compare: 1.4.0
-      ts-api-utils: 2.4.0(typescript@4.9.5)
+      semver: 7.7.3
+      ts-api-utils: 1.4.3(typescript@4.9.5)
+    optionalDependencies:
       typescript: 4.9.5
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/parser@8.52.0(eslint@8.57.1)(typescript@4.9.5)':
+  '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@4.9.5)':
     dependencies:
-      '@typescript-eslint/scope-manager': 8.52.0
-      '@typescript-eslint/types': 8.52.0
-      '@typescript-eslint/typescript-estree': 8.52.0(typescript@4.9.5)
-      '@typescript-eslint/visitor-keys': 8.52.0
+      '@typescript-eslint/scope-manager': 6.21.0
+      '@typescript-eslint/types': 6.21.0
+      '@typescript-eslint/typescript-estree': 6.21.0(typescript@4.9.5)
+      '@typescript-eslint/visitor-keys': 6.21.0
       debug: 4.4.3
       eslint: 8.57.1
+    optionalDependencies:
       typescript: 4.9.5
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/project-service@8.52.0(typescript@4.9.5)':
-    dependencies:
-      '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@4.9.5)
-      '@typescript-eslint/types': 8.52.0
-      debug: 4.4.3
-      typescript: 4.9.5
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/scope-manager@8.52.0':
+  '@typescript-eslint/scope-manager@6.21.0':
     dependencies:
-      '@typescript-eslint/types': 8.52.0
-      '@typescript-eslint/visitor-keys': 8.52.0
+      '@typescript-eslint/types': 6.21.0
+      '@typescript-eslint/visitor-keys': 6.21.0
 
-  '@typescript-eslint/tsconfig-utils@8.52.0(typescript@4.9.5)':
+  '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@4.9.5)':
     dependencies:
-      typescript: 4.9.5
-
-  '@typescript-eslint/type-utils@8.52.0(eslint@8.57.1)(typescript@4.9.5)':
-    dependencies:
-      '@typescript-eslint/types': 8.52.0
-      '@typescript-eslint/typescript-estree': 8.52.0(typescript@4.9.5)
-      '@typescript-eslint/utils': 8.52.0(eslint@8.57.1)(typescript@4.9.5)
+      '@typescript-eslint/typescript-estree': 6.21.0(typescript@4.9.5)
+      '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@4.9.5)
       debug: 4.4.3
       eslint: 8.57.1
-      ts-api-utils: 2.4.0(typescript@4.9.5)
+      ts-api-utils: 1.4.3(typescript@4.9.5)
+    optionalDependencies:
       typescript: 4.9.5
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/types@8.52.0': {}
+  '@typescript-eslint/types@6.21.0': {}
 
-  '@typescript-eslint/typescript-estree@8.52.0(typescript@4.9.5)':
+  '@typescript-eslint/typescript-estree@6.21.0(typescript@4.9.5)':
     dependencies:
-      '@typescript-eslint/project-service': 8.52.0(typescript@4.9.5)
-      '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@4.9.5)
-      '@typescript-eslint/types': 8.52.0
-      '@typescript-eslint/visitor-keys': 8.52.0
+      '@typescript-eslint/types': 6.21.0
+      '@typescript-eslint/visitor-keys': 6.21.0
       debug: 4.4.3
-      minimatch: 9.0.5
+      globby: 11.1.0
+      is-glob: 4.0.3
+      minimatch: 9.0.3
       semver: 7.7.3
-      tinyglobby: 0.2.15
-      ts-api-utils: 2.4.0(typescript@4.9.5)
+      ts-api-utils: 1.4.3(typescript@4.9.5)
+    optionalDependencies:
       typescript: 4.9.5
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/utils@8.52.0(eslint@8.57.1)(typescript@4.9.5)':
+  '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@4.9.5)':
     dependencies:
       '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
-      '@typescript-eslint/scope-manager': 8.52.0
-      '@typescript-eslint/types': 8.52.0
-      '@typescript-eslint/typescript-estree': 8.52.0(typescript@4.9.5)
+      '@types/json-schema': 7.0.15
+      '@types/semver': 7.7.1
+      '@typescript-eslint/scope-manager': 6.21.0
+      '@typescript-eslint/types': 6.21.0
+      '@typescript-eslint/typescript-estree': 6.21.0(typescript@4.9.5)
       eslint: 8.57.1
-      typescript: 4.9.5
+      semver: 7.7.3
     transitivePeerDependencies:
       - supports-color
+      - typescript
 
-  '@typescript-eslint/visitor-keys@8.52.0':
+  '@typescript-eslint/visitor-keys@6.21.0':
     dependencies:
-      '@typescript-eslint/types': 8.52.0
-      eslint-visitor-keys: 4.2.1
+      '@typescript-eslint/types': 6.21.0
+      eslint-visitor-keys: 3.4.3
 
   '@ungap/structured-clone@1.3.0': {}
 
@@ -7141,6 +7144,8 @@ snapshots:
 
   array-flatten@1.1.1: {}
 
+  array-union@2.1.0: {}
+
   async-validator@4.2.5: {}
 
   asynckit@0.4.0: {}
@@ -7517,6 +7522,10 @@ snapshots:
 
   diff-sequences@27.5.1: {}
 
+  dir-glob@3.0.1:
+    dependencies:
+      path-type: 4.0.0
+
   doctrine@3.0.0:
     dependencies:
       esutils: 2.0.3
@@ -7655,33 +7664,27 @@ snapshots:
     dependencies:
       eslint: 8.57.1
 
-  eslint-plugin-vue@10.6.2(@typescript-eslint/parser@8.52.0(eslint@8.57.1)(typescript@4.9.5))(eslint@8.57.1)(vue-eslint-parser@10.2.0(eslint@8.57.1)):
+  eslint-plugin-vue@9.25.0(eslint@8.57.1):
     dependencies:
       '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
       eslint: 8.57.1
+      globals: 13.24.0
       natural-compare: 1.4.0
       nth-check: 2.1.1
-      postcss-selector-parser: 7.1.1
+      postcss-selector-parser: 6.1.2
       semver: 7.7.3
-      vue-eslint-parser: 10.2.0(eslint@8.57.1)
+      vue-eslint-parser: 9.4.3(eslint@8.57.1)
       xml-name-validator: 4.0.0
-    optionalDependencies:
-      '@typescript-eslint/parser': 8.52.0(eslint@8.57.1)(typescript@4.9.5)
+    transitivePeerDependencies:
+      - supports-color
 
   eslint-scope@7.2.2:
     dependencies:
       esrecurse: 4.3.0
       estraverse: 5.3.0
 
-  eslint-scope@8.4.0:
-    dependencies:
-      esrecurse: 4.3.0
-      estraverse: 5.3.0
-
   eslint-visitor-keys@3.4.3: {}
 
-  eslint-visitor-keys@4.2.1: {}
-
   eslint@8.57.1:
     dependencies:
       '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
@@ -7725,12 +7728,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  espree@10.4.0:
-    dependencies:
-      acorn: 8.15.0
-      acorn-jsx: 5.3.2(acorn@8.15.0)
-      eslint-visitor-keys: 4.2.1
-
   espree@9.6.1:
     dependencies:
       acorn: 8.15.0
@@ -7975,6 +7972,15 @@ snapshots:
     dependencies:
       type-fest: 0.20.2
 
+  globby@11.1.0:
+    dependencies:
+      array-union: 2.1.0
+      dir-glob: 3.0.1
+      fast-glob: 3.3.3
+      ignore: 5.3.2
+      merge2: 1.4.1
+      slash: 3.0.0
+
   globrex@0.1.2: {}
 
   gopd@1.2.0: {}
@@ -8048,8 +8054,6 @@ snapshots:
 
   ignore@5.3.2: {}
 
-  ignore@7.0.5: {}
-
   immutable@4.3.7: {}
 
   import-fresh@3.3.1:
@@ -8716,6 +8720,10 @@ snapshots:
     dependencies:
       brace-expansion: 2.0.2
 
+  minimatch@9.0.3:
+    dependencies:
+      brace-expansion: 2.0.2
+
   minimatch@9.0.5:
     dependencies:
       brace-expansion: 2.0.2
@@ -8868,6 +8876,8 @@ snapshots:
 
   path-to-regexp@0.1.10: {}
 
+  path-type@4.0.0: {}
+
   pathe@2.0.3: {}
 
   perfect-debounce@1.0.0: {}
@@ -9405,7 +9415,7 @@ snapshots:
     dependencies:
       punycode: 2.3.1
 
-  ts-api-utils@2.4.0(typescript@4.9.5):
+  ts-api-utils@1.4.3(typescript@4.9.5):
     dependencies:
       typescript: 4.9.5
 
@@ -9602,14 +9612,15 @@ snapshots:
       sass: 1.78.0
       terser: 5.44.1
 
-  vue-eslint-parser@10.2.0(eslint@8.57.1):
+  vue-eslint-parser@9.4.3(eslint@8.57.1):
     dependencies:
       debug: 4.4.3
       eslint: 8.57.1
-      eslint-scope: 8.4.0
-      eslint-visitor-keys: 4.2.1
-      espree: 10.4.0
+      eslint-scope: 7.2.2
+      eslint-visitor-keys: 3.4.3
+      espree: 9.6.1
       esquery: 1.7.0
+      lodash: 4.17.21
       semver: 7.7.3
     transitivePeerDependencies:
       - supports-color

+ 2 - 1
src/App.ku.vue

@@ -1,7 +1,8 @@
 <script setup lang="ts">
-import { useTheme } from '@/composables/useTheme'
 import { useConfigProvider } from 'wot-design-uni'
 
+import { useTheme } from '@/composables/useTheme'
+
 const { theme, themeVars } = useTheme()
 
 useConfigProvider({

+ 16 - 17
src/components/auth/AuthInputItem.vue

@@ -9,7 +9,7 @@
     <view class="form-input">
       <input
         class="form-input-inner"
-        v-model="innerValue"
+        v-model="modelValue"
         :type="inputType"
         :password="passwordToggle && isPassword"
         :maxlength="maxlength"
@@ -49,9 +49,9 @@
 <script setup lang="ts">
 import { computed, ref, watch } from 'vue'
 
+/* ---------- props ---------- */
 interface Props {
   label?: string
-  modelValue: string
   placeholder?: string
   type?: 'text' | 'number' | 'password'
   maxlength?: number
@@ -67,31 +67,28 @@ const props = withDefaults(defineProps<Props>(), {
   passwordToggle: false,
 })
 
+/* ---------- emits ---------- */
 const emit = defineEmits<{
-  (e: 'update:modelValue', value: string): void
   (e: 'clear'): void
   (e: 'validate'): void
 }>()
 
+/* ---------- v-model ---------- */
+const modelValue = defineModel<string>({
+  default: '',
+})
+
+/* ---------- state ---------- */
 const CLEAR_ICON_COLOR = '#9CA3AF'
 
 const isFocused = ref(false)
 const isPassword = ref(true)
 
-/** v-model 桥接 */
-const innerValue = computed<string>({
-  get: () => props.modelValue,
-  set: (val) => {
-    emit('update:modelValue', val)
-  },
-})
-
-/** 记录上一次是否有值 */
+/* ---------- 清除检测 ---------- */
 const hadValue = ref(false)
 
-/** 统一的“清除检测” */
 watch(
-  () => innerValue.value,
+  () => modelValue.value,
   (val) => {
     const hasValue = !!val
     if (hadValue.value && !hasValue) {
@@ -102,6 +99,7 @@ watch(
   { immediate: true }
 )
 
+/* ---------- computed ---------- */
 const inputType = computed(() => {
   if (props.passwordToggle) {
     return isPassword.value ? 'password' : 'text'
@@ -109,21 +107,22 @@ const inputType = computed(() => {
   return props.type
 })
 
-const showClear = computed(() => !!innerValue.value)
+const showClear = computed(() => !!modelValue.value)
 
+/* ---------- handlers ---------- */
 const onFocus = () => {
   isFocused.value = true
 }
 
 const onBlur = () => {
   isFocused.value = false
-  if (innerValue.value) {
+  if (modelValue.value) {
     emit('validate')
   }
 }
 
 const clear = () => {
-  innerValue.value = ''
+  modelValue.value = ''
 }
 
 const togglePassword = () => {

+ 12 - 0
src/lib/wechatService.ts

@@ -0,0 +1,12 @@
+/*
+ * @Description: 微信相关 API 封装(含定位系统权限判断)
+ * @Author: hanyu
+ * @Date: 2020-06-17 17:24:39
+ * @LastEditTime: 2025-01-25
+ */
+
+export const getWXLoginCode = async () => {
+  return await uni.login({
+    provider: 'weixin',
+  })
+}

+ 139 - 55
src/pages/login/index.vue

@@ -1,9 +1,12 @@
 <template>
   <view class="auth-content">
     <wd-navbar fixed placeholder :title="title" left-arrow safeAreaInsetTop customClass="navbar" />
+
     <view class="auth-bg" />
+
     <view class="auth-body">
-      <view class="auth-title"> 欢迎登录 </view>
+      <view class="auth-title">欢迎登录</view>
+
       <view class="auth-form">
         <!-- 账号 -->
         <AuthInputItem
@@ -16,6 +19,8 @@
           @clear="clearFieldError('username')"
           @validate="validateField('username')"
         />
+
+        <!-- 密码 -->
         <AuthInputItem
           label="密码"
           v-model="form.password"
@@ -28,14 +33,16 @@
           @clear="clearFieldError('password')"
         >
           <template #suffix>
-            <view class="forget-password" @click="forgetPassword">忘记密码?</view>
+            <view class="forget-password" @click="forgetPassword"> 忘记密码? </view>
           </template>
         </AuthInputItem>
+
+        <!-- 验证码 -->
         <AuthInputItem
           label="验证码"
           v-model="form.code"
           type="number"
-          :maxlength="11"
+          :maxlength="6"
           placeholder="请输入验证码"
           :error="errors.code"
           @clear="clearFieldError('code')"
@@ -47,24 +54,28 @@
             </button>
           </template>
         </AuthInputItem>
+        <!-- 协议 -->
         <view class="agreement">
           <label class="agreement-label">
             <checkbox
-              :checked="agreementFlag"
-              @click.stop="agreementFlag = !agreementFlag"
+              :checked="agreementChecked"
               class="agreement-checkbox"
+              @click.stop="toggleAgreement"
             />
             <view class="txt">
               我已阅读并同意
-              <text @click.stop="agreementClick('agreement')">《要易云平台用户协议》</text>、
-              <text @click.stop="agreementClick('policy')">《隐私权政策》</text>、
-              <text @click.stop="agreementClick('personalInfo')">《个人信息使用授权书》</text>、
-              <text @click.stop="handleOpenPrivacyContractClick">《用户隐私保护指引》</text>
+              <text @click.stop="agreementClick('agreement')"> 《要易云平台用户协议》 </text>、
+              <text @click.stop="agreementClick('policy')"> 《隐私权政策》 </text>、
+              <text @click.stop="agreementClick('personalInfo')"> 《个人信息使用授权书》 </text>、
+              <text @click.stop="handleOpenPrivacyContractClick"> 《用户隐私保护指引》 </text>
             </view>
           </label>
+
+          <view class="error-text" :class="{ visible: agreementError }"> 请阅读并勾选协议 </view>
         </view>
+        <!-- 提交 -->
         <view class="submit">
-          <button class="submit-btn" @click.prevent="submit">登录</button>
+          <button class="submit-btn" type="default" @click="submit">登录</button>
         </view>
       </view>
     </view>
@@ -72,84 +83,157 @@
 </template>
 
 <script setup lang="ts">
-import AuthInputItem from '@/components/auth/AuthInputItem.vue'
-import { useFormValidator } from '@/composables/useFormValidator'
-import { resetPasswordRules } from '@/validators/authFormRules'
+import { onMounted, reactive, ref } from 'vue'
+
+import projectConfig from '@/config/presets'
 import { debounce } from '@/plugins/debounce'
+
+import { getAuthTokenApi, getMobileCodeApi } from '@/services/modules/auth'
+
 import { useCodeCountdown } from '@/composables/useCodeCountdown'
-import { getPwdCodeForNoAuthApi, updUserPwdApi } from '@/services/modules/auth/index'
-import projectConfig from '@/config/presets/index'
+import { useFormValidator } from '@/composables/useFormValidator'
+import { useUserStore } from '@/stores/modules/user'
+
+import { resetPasswordRules } from '@/validators/authFormRules'
 
+import AuthInputItem from '@/components/auth/AuthInputItem.vue'
+
+const userStore = useUserStore()
 const { title } = projectConfig
 
-const forgetPassword = () => {
-  uni.navigateTo({
-    url: '/pages/reset-password/index',
-  })
+const form = reactive({
+  username: '15093284672',
+  password: '284672',
+  code: '5657',
+})
+
+const { errors, validate, validateField, clearFieldError } = useFormValidator(
+  resetPasswordRules,
+  form
+)
+
+const agreementChecked = ref(false)
+const agreementError = ref(false)
+
+const toggleAgreement = () => {
+  agreementChecked.value = !agreementChecked.value
+  if (agreementChecked.value) agreementError.value = false
 }
 
-const form = reactive({
-  username: '',
-  code: '',
-  password: '',
+const agreementClick = (type: string) => {
+  // 打开你自己的协议页面
+}
+
+const privacyAuthed = ref(false)
+
+onMounted(() => {
+  checkPrivacyAuthorization()
 })
 
-const agreementFlag = ref(false)
+const checkPrivacyAuthorization = () => {
+  wx.getPrivacySetting({
+    success(res) {
+      if (res.needAuthorization) {
+        requirePrivacyAuthorization()
+      } else {
+        privacyAuthed.value = true
+      }
+    },
+    fail() {
+      requirePrivacyAuthorization()
+    },
+  })
+}
 
-const agreementClick = (type: string) => {}
+const requirePrivacyAuthorization = () => {
+  wx.requirePrivacyAuthorize({
+    success() {
+      privacyAuthed.value = true
+    },
+    fail() {
+      uni.showModal({
+        title: '提示',
+        content: '请同意隐私协议后再使用',
+        showCancel: false,
+      })
+    },
+  })
+}
 
 const handleOpenPrivacyContractClick = () => {
-  // 打开隐私协议页面
-  wx.openPrivacyContract({
-    success: () => {},
-    fail: () => {},
-    complete: () => {},
-  })
+  wx.openPrivacyContract({})
 }
 
-const { errors, validate, validateField, clearFieldError } = useFormValidator(
-  resetPasswordRules,
-  form
-)
+/* ---------------- 验证码 ---------------- */
 
 const { countdown, disabled: codeDisabled, start: startCountdown } = useCodeCountdown()
 
-const toast = (title: string, duration = 800) => uni.showToast({ title, icon: 'none', duration })
+const toast = (title: string) => uni.showToast({ title, icon: 'none', duration: 800 })
 
 const sendCodeImpl = async () => {
   if (codeDisabled.value) return
-  if (!(await validateField('username'))) return
 
-  const { code, data, msg } = await getPwdCodeForNoAuthApi(form.username)
-  if (code !== 0 || !data) {
-    toast(msg || '发送验证码失败')
-    return
-  }
+  const [usernameOk, passwordOk] = await Promise.all([
+    validateField('username'),
+    validateField('password'),
+  ])
 
-  toast('验证码已发送,请注意查收')
-  startCountdown(60)
+  if (!usernameOk || !passwordOk) return
+
+  const res = await getAuthTokenApi({
+    username: form.username,
+    password: form.password,
+  })
+
+  if (res.access_token) {
+    const codeRes = await getMobileCodeApi(form.username)
+    if (codeRes.code === 0) {
+      toast('验证码发送成功')
+      startCountdown(60)
+    } else {
+      toast(codeRes.msg || '验证码发送失败')
+    }
+  }
 }
+
 const sendCode = debounce(sendCodeImpl)
 
-const submitImpl = async () => {
-  console.log('cc')
+/* ---------------- 提交 ---------------- */
 
-  if (!(await validate())) return
+const submit = async () => {
+  console.log('qaq')
+  console.log('privacyAuthed.value', privacyAuthed.value)
 
-  const { code, data, msg } = await updUserPwdApi(form)
-  if (code !== 0 || !data) {
-    toast(msg || '修改密码失败')
+  if (!privacyAuthed.value) {
+    requirePrivacyAuthorization()
     return
   }
 
-  toast('密码重置成功,请使用新密码登录')
-  setTimeout(() => {
-    uni.reLaunch({ url: '/pages/login/index' })
-  }, 1000)
+  const agreementOk = agreementChecked.value
+  agreementError.value = !agreementOk
+
+  const formOk = await validate()
+  if (!agreementOk || !formOk) return
+
+  const res = await userStore.login({
+    username: form.username,
+    code: form.code,
+  })
+
+  // 后续处理(跳转 / 提示)
+}
+
+/* ---------------- 其他 ---------------- */
+
+const forgetPassword = () => {
+  uni.navigateTo({
+    url: '/pages/reset-password/index',
+  })
 }
-const submit = debounce(submitImpl)
 </script>
 
 <style lang="scss" scoped>
 @import '../../styles/modules/auth-page.scss';
 </style>
+
+当前页面 重构 登录请求必须继续放在 agreePrivacyAuthorization 事件中触发

+ 2 - 1
src/pages/reset-password/index.vue

@@ -62,11 +62,12 @@
 </template>
 
 <script setup lang="ts">
-import { reactive } from 'vue'
 import AuthInputItem from '@/components/auth/AuthInputItem.vue'
 import { useFormValidator } from '@/composables/useFormValidator'
 import { logingRules } from '@/validators/authFormRules'
 import { debounce } from '@/plugins/debounce'
+
+import { reactive } from 'vue'
 import { useCodeCountdown } from '@/composables/useCodeCountdown'
 import { getPwdCodeForNoAuthApi, updUserPwdApi } from '@/services/modules/auth/index'
 

+ 27 - 1
src/services/modules/auth/index.ts

@@ -1,5 +1,31 @@
 import http from '../../index'
-import type { UpdUserPwdRequest } from './type'
+import type { AuthTokenRequest, LoginRequest, UpdUserPwdRequest } from './type'
+import type { UserInfoResponse } from './userInfo'
+
+//  账号密码校验
+export const getAuthTokenApi = (data: AuthTokenRequest) => {
+  const passwordUrl = encodeURIComponent(data.password)
+
+  return http.postRaw(
+    `/auth/oauth/token?username=${data.username + '@mp'}&password=${passwordUrl}&grant_type=password&scope=server&mp=wechat`
+  )
+}
+
+// 登录
+export const getTokenBySmsApi = (data: LoginRequest) => {
+  return http.postRaw(
+    `/auth/mobile/token/sms?code=${data.code}&mobile=SMS@${data.username}&grant_type=mobile`,
+    {}
+  )
+}
+// 通过微信 code 获取用户信息
+export const getUserInfoByCodeApi = (wxCode: string, avatar?: string) => {
+  return http.get<UserInfoResponse>(`/admin/api/getUserInfoByCode?code=${wxCode}&avatar=${avatar}`)
+}
+
+export const getMobileCodeApi = (phone: string) => {
+  return http.get<boolean>(`/admin/mobile/${phone}`)
+}
 
 export const getPwdCodeForNoAuthApi = (username: string) => {
   return http.get<boolean>(`/admin/mobile/for-pwd-noauth?username=${username}`)

+ 9 - 0
src/services/modules/auth/type.d.ts

@@ -1,3 +1,12 @@
+export interface LoginRequest {
+  username: string
+  code: string
+}
+
+export interface AuthTokenRequest {
+  username: string
+  password: string
+}
 export interface UpdUserPwdRequest {
   username: string
   code: string

+ 136 - 0
src/services/modules/auth/userInfo.d.ts

@@ -0,0 +1,136 @@
+/** =========================
+ * userinfo 接口返回结构
+ * ========================= */
+
+export interface UserInfoResponse {
+  sumCount: number
+  completedCount: number
+  taskProgress: number
+  roles: number[]
+  userInfo: UserInfoItem[]
+}
+
+export interface UserInfoItem {
+  eidResult: EidResult
+  deptName: string
+  deptId: string
+  managementFlag: boolean
+  management: string
+  userId: string
+  userType: string
+  userNewFlag: boolean
+  phone: string
+  realname: string
+  avatar: string | null
+  idCardNumber: string
+  bankName: string
+  bankPhone: string
+  bankCardNumber: string
+  unpaid: number
+  paid: number
+  roles: number[]
+
+  subjectTypeAndChannel: Record<string, number>
+  subjectLocationList: string[]
+  subjectLocationEid: Record<string, boolean>
+
+  /** 签约/认证记录 */
+  certList: CertItem[]
+
+  /** 已签协议(动态 code) */
+  signedAgreement: string[]
+
+  /** 是否重新签署 */
+  reSignedAgreement: number
+
+  /** 协议签名状态 */
+  taxHelperAgreementSignature: number
+
+  /** 是否通过活体 */
+  asignIsLivenessAuth: boolean
+
+  /** 年龄相关 */
+  ageLimit: boolean
+  ageReminder: boolean
+  ageReminderInfo: unknown | null
+
+  /** 动态子模块 / 菜单 */
+  subList: string[]
+
+  /** 动态任务模板 */
+  hasTaskTypeTemplate: string[]
+
+  /** 认证相关 */
+  certStatus: string | null
+  rljCertStatus: string | null
+  certRemark: string | null
+  certToken: string
+
+  /** 操作状态 */
+  waitApprove: string
+  onTheWay: string
+  jumpFlag: string
+
+  /** 最近密码修改时间 */
+  latestChangePwdTime: string
+
+  /** 套餐 */
+  packageList: PackageItem[]
+
+  /** 客户成功经理 */
+  csm: CsmInfo
+
+  /** eid 是否已存在 */
+  existEidResult: boolean
+
+  /** 临时/扩展字段(保持原样) */
+  temp1: string | null
+  temp2: string | null
+  temp3: string | null
+  temp4: string | null
+  temp5: string | null
+}
+
+export interface EidResult {
+  idCardFrontUrl: string
+  idCardBackUrl: string
+}
+
+export interface CertItem {
+  id: number
+  userId: number
+  deptId: number
+  gigType: string
+  gigChannel: string
+  subjectLocation: string
+  callbackStatus: string
+  certStatus: string
+  certStatusDisplay: string | null
+  certRemark: string | null
+  userType: string | null
+  bankPhone: string | null
+  bankCardNumber: string | null
+  idCardFrontUrl: string | null
+  idCardBackUrl: string | null
+  certVideo1Url: string | null
+  certVideo2Url: string | null
+  agreementUrl: string | null
+  createTime: string
+  updateTime: string
+  createUser: number
+  updateUser: number
+}
+
+export interface PackageItem {
+  value: string
+  label: string
+}
+
+export interface CsmInfo {
+  recId: number
+  deptId: number
+  qrCodeId: string
+  corpId: string
+  csmName: string
+  userId: number
+}

+ 1 - 1
src/services/request/config.ts

@@ -8,4 +8,4 @@ export const TIMEOUT = 10000
 export const SUCCESS_CODE_LIST = [0, '0', 200, '200', 2000, '2000', '0000']
 
 export const NOT_OAUTH_BASIC_TOKEN = 'Basic cGlnOnBpZw=='
-export const OAUTH_BASIC_TOKEN = 'Basic cGlnOnBpZw=='
+export const OAUTH_BASIC_TOKEN = 'Basic dGVzdDp0ZXN0'

+ 5 - 4
src/services/request/index.ts

@@ -189,7 +189,7 @@ function resolveUrl(url: string) {
 }
 
 function isWhiteList(url: string) {
-  return ['/auth/oauth/token', '/auth/mobile/token/sms'].some((item) => url.includes(item))
+  return ['/auth/oauth/token'].some((item) => url.includes(item))
 }
 
 function buildHeaders(
@@ -201,15 +201,16 @@ function buildHeaders(
     ...(extraHeader || {}),
   }
 
-  const token = userStore.token
+  const access_token = userStore.access_token
 
   if (url.includes('auth/mobile/token/sms')) {
     headers.Authorization = NOT_OAUTH_BASIC_TOKEN
+    // headers['TENANT-ID'] = '1'
   } else if (url.includes('auth/oauth/token')) {
     headers.Authorization = OAUTH_BASIC_TOKEN
     headers['TENANT-ID'] = '1'
-  } else if (token) {
-    headers.Authorization = `Bearer ${token}`
+  } else if (access_token) {
+    headers.Authorization = `Bearer ${access_token}`
   }
 
   return headers

+ 40 - 1
src/stores/modules/user.ts

@@ -1,16 +1,55 @@
+
 import { defineStore } from 'pinia'
+
+import { getWXLoginCode } from '@/lib/wechatService'
+
+import { getTokenBySmsApi, getUserInfoByCodeApi } from '@/services/modules/auth'
+import type { LoginRequest } from '@/services/modules/auth/type'
+import type { UserInfoItem } from '@/services/modules/auth/userInfo'
+
 import { uniStorage } from '@/utils/uniStorage'
 
+
 interface UserState {
   token: string
+  access_token?: string
+
+
+  userInfoList: UserInfoItem[]
 }
 
 export const useUserStore = defineStore('user', {
+
+
   state: (): UserState => ({
-    token: 'asads',
+    token: '',
+    access_token: '',
+
+    userInfoList: [],
   }),
   actions: {
     setTokenInfo() {},
+    // 登录
+    async login(payload: LoginRequest) {
+      const res = await getTokenBySmsApi(payload)
+      if (res.access_token) {
+        this.access_token = res.access_token
+        // 获取用户信息
+        await this.getUserInfoByCode()
+        return true
+      }
+      return res
+    },
+    async getUserInfoByCode() {
+      const res = await getWXLoginCode()
+      if (res.code) {
+        const userInfoResult = await getUserInfoByCodeApi(res.code)
+        if (userInfoResult.code === 0 && userInfoResult.data) {
+          this.userInfoList = userInfoResult.data.userInfo
+        }
+        console.log('res', userInfoResult)
+      }
+    },
   },
   persist: {
     key: 'user-store',

+ 14 - 1
src/styles/modules/auth-page.scss

@@ -67,8 +67,8 @@
 
       .agreement {
         margin-top: 48rpx;
-        display: flex;
         color: var(--font-color-666);
+        position: relative;
 
         .agreement-label {
           display: flex;
@@ -86,6 +86,19 @@
           color: var(--main-color);
           font-size: 26rpx;
         }
+        .error-text {
+          position: absolute;
+          left: 0;
+          bottom: -28rpx;
+          font-size: 20rpx;
+          line-height: 20rpx;
+          color: #ff4d4f;
+          opacity: 0;
+          pointer-events: none; // 不影响点击
+        }
+        .error-text.visible {
+          opacity: 1;
+        }
       }
 
       .submit {

+ 1 - 1
src/validators/authFormRules.ts

@@ -1,5 +1,5 @@
 // validators/resetPassword.ts
-import type { Rules, RuleItem } from 'async-validator'
+import type { RuleItem,Rules } from 'async-validator'
 
 /** 是否开发环境 */
 const isDev = import.meta.env.VITE_MODE === 'development'