af-mobile-client-vue3 1.3.11 → 1.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.cursorrules +60 -60
  3. package/.editorconfig +9 -9
  4. package/.env +10 -10
  5. package/.env.development +1 -1
  6. package/.env.production +1 -1
  7. package/.node-version +1 -1
  8. package/.vscode/extensions.json +12 -12
  9. package/.vscode/settings.json +66 -66
  10. package/CLAUDE.md +189 -184
  11. package/README.md +182 -181
  12. package/af-example-mobile-vue-web.iml +9 -9
  13. package/build/vite/index.ts +98 -98
  14. package/build/vite/optimize.ts +34 -34
  15. package/build/vite/vconsole.ts +47 -47
  16. package/commitlint.config.ts +32 -32
  17. package/compress.js +36 -36
  18. package/eslint.config.ts +30 -30
  19. package/index.html +23 -23
  20. package/mock/data.ts +20 -20
  21. package/mock/index.ts +7 -7
  22. package/mock/modules/prose.mock.ts +13 -13
  23. package/mock/modules/user.mock.ts +152 -152
  24. package/mock/util.ts +19 -19
  25. package/netlify.toml +12 -12
  26. package/package.json +114 -114
  27. package/postcss.config.ts +27 -27
  28. package/public/favicon.svg +4 -4
  29. package/public/safari-pinned-tab.svg +4 -4
  30. package/scripts/verifyCommit.js +19 -19
  31. package/src/App.vue +79 -79
  32. package/src/api/mock/index.ts +30 -30
  33. package/src/api/user/index.ts +40 -40
  34. package/src/assets/img/user/login/background-shadow-1.svg +20 -20
  35. package/src/assets/img/user/login/logo-background.svg +20 -20
  36. package/src/bootstrap.ts +26 -26
  37. package/src/components/core/BeautifulLoading/index.vue +52 -52
  38. package/src/components/core/ImageUploader/index.vue +244 -244
  39. package/src/components/core/NavBar/index.vue +53 -53
  40. package/src/components/core/Tabbar/index.vue +32 -32
  41. package/src/components/core/Uploader/index.vue +124 -124
  42. package/src/components/core/XGridDropOption/index.vue +154 -156
  43. package/src/components/core/XMultiSelect/index.vue +183 -183
  44. package/src/components/core/XSelect/index.vue +149 -149
  45. package/src/components/data/InfoDisplay/index.vue +132 -0
  46. package/src/components/data/UserDetail/api.ts +24 -0
  47. package/src/components/data/UserDetail/index.vue +539 -0
  48. package/src/components/data/UserDetail/recordEntries.ts +159 -0
  49. package/src/components/data/UserDetail/types.ts +26 -0
  50. package/src/components/data/XBadge/index.vue +82 -82
  51. package/src/components/data/XCellDetail/index.vue +105 -105
  52. package/src/components/data/XCellList/XCellList.md +313 -313
  53. package/src/components/data/XCellList/index.vue +1075 -1075
  54. package/src/components/data/XCellListFilter/QrScanner/index.vue +207 -207
  55. package/src/components/data/XCellListFilter/QrScanner/startScanAnimation.ts +53 -53
  56. package/src/components/data/XCellListFilter/VpnRecognition/index.vue +119 -119
  57. package/src/components/data/XCellListFilter/index.vue +705 -705
  58. package/src/components/data/XForm/index.vue +659 -659
  59. package/src/components/data/XFormGroup/doc/DeviceForm.vue +121 -121
  60. package/src/components/data/XFormGroup/doc/FormGroupDemo.vue +56 -56
  61. package/src/components/data/XFormGroup/doc/README.md +286 -273
  62. package/src/components/data/XFormGroup/doc/UserForm.vue +101 -101
  63. package/src/components/data/XFormGroup/index.vue +240 -240
  64. package/src/components/data/XFormItem/index.vue +1310 -1310
  65. package/src/components/data/XOlMap/README.md +227 -227
  66. package/src/components/data/XOlMap/XLocationPicker/index.vue +226 -225
  67. package/src/components/data/XOlMap/index.vue +1490 -1490
  68. package/src/components/data/XOlMap/types.ts +149 -149
  69. package/src/components/data/XOlMap/utils/wgs84ToGcj02.js +154 -154
  70. package/src/components/data/XReportForm/DateTimeSecondsPicker.vue +208 -208
  71. package/src/components/data/XReportForm/XReportFormJsonRender.vue +220 -220
  72. package/src/components/data/XReportForm/index.vue +1393 -1393
  73. package/src/components/data/XReportGrid/XAddReport/XAddReport.vue +198 -198
  74. package/src/components/data/XReportGrid/XAddReport/index.js +3 -3
  75. package/src/components/data/XReportGrid/XAddReport/index.md +53 -52
  76. package/src/components/data/XReportGrid/XAddReport/index.ts +10 -10
  77. package/src/components/data/XReportGrid/XReport.vue +960 -960
  78. package/src/components/data/XReportGrid/XReportDesign.vue +597 -597
  79. package/src/components/data/XReportGrid/XReportDrawer/XReportDrawer.vue +148 -148
  80. package/src/components/data/XReportGrid/XReportDrawer/index.js +3 -3
  81. package/src/components/data/XReportGrid/XReportDrawer/index.ts +10 -10
  82. package/src/components/data/XReportGrid/XReportJsonRender.vue +399 -399
  83. package/src/components/data/XReportGrid/XReportTrGroup.vue +592 -592
  84. package/src/components/data/XReportGrid/index.md +46 -42
  85. package/src/components/data/XSignature/index.vue +284 -285
  86. package/src/components/data/XTag/index.vue +10 -10
  87. package/src/components/layout/NormalDataLayout/index.vue +69 -69
  88. package/src/components/layout/TabBarLayout/index.vue +40 -40
  89. package/src/composables/dark.ts +5 -5
  90. package/src/config/routes.ts +9 -9
  91. package/src/constants/index.ts +2 -2
  92. package/src/enums/requestEnum.ts +25 -25
  93. package/src/expression/ExpressionRunner.ts +28 -28
  94. package/src/expression/TestExpression.ts +510 -510
  95. package/src/expression/core/Delegate.ts +116 -116
  96. package/src/expression/core/Expression.ts +1359 -1359
  97. package/src/expression/core/Program.ts +985 -985
  98. package/src/expression/core/Token.ts +29 -29
  99. package/src/expression/enums/ExpressionType.ts +81 -81
  100. package/src/expression/enums/TokenType.ts +11 -11
  101. package/src/expression/exception/BreakWayException.ts +2 -2
  102. package/src/expression/exception/ContinueWayException.ts +2 -2
  103. package/src/expression/exception/ExpressionException.ts +29 -29
  104. package/src/expression/exception/ReturnWayException.ts +14 -14
  105. package/src/expression/exception/ServiceException.ts +22 -22
  106. package/src/expression/instances/JSONArray.ts +52 -52
  107. package/src/expression/instances/JSONObject.ts +118 -118
  108. package/src/expression/instances/LogicConsole.ts +31 -31
  109. package/src/font-style/font.css +4 -4
  110. package/src/hooks/useBoolean.ts +26 -0
  111. package/src/hooks/useCommon.ts +9 -9
  112. package/src/hooks/useLogin.ts +97 -97
  113. package/src/icons/svg/check-in.svg +32 -32
  114. package/src/icons/svg/dark.svg +4 -4
  115. package/src/icons/svg/github.svg +4 -4
  116. package/src/icons/svg/light.svg +4 -4
  117. package/src/icons/svg/link.svg +4 -4
  118. package/src/icons/svgo.yml +22 -22
  119. package/src/layout/GridView/index.vue +16 -16
  120. package/src/layout/PageLayout.vue +9 -9
  121. package/src/layout/SingleLayout.vue +9 -9
  122. package/src/locales/en-US.json +128 -128
  123. package/src/locales/zh-CN.json +128 -128
  124. package/src/logic/LogicRunner.ts +67 -67
  125. package/src/logic/TestLogic.ts +13 -13
  126. package/src/logic/plugins/common/DateTools.ts +35 -35
  127. package/src/logic/plugins/common/VueTools.ts +30 -30
  128. package/src/logic/plugins/index.ts +7 -7
  129. package/src/main.ts +44 -44
  130. package/src/plugins/AppData.ts +38 -38
  131. package/src/plugins/GetLoginInfoService.ts +10 -10
  132. package/src/plugins/collectIcons.ts +10 -0
  133. package/src/plugins/index.ts +11 -11
  134. package/src/router/README.md +8 -8
  135. package/src/router/guards.ts +59 -59
  136. package/src/router/index.ts +35 -35
  137. package/src/router/invoiceRoutes.ts +33 -33
  138. package/src/router/routes.ts +341 -171
  139. package/src/router/types.ts +7 -7
  140. package/src/services/api/Login.ts +6 -6
  141. package/src/services/api/common.ts +109 -109
  142. package/src/services/api/index.ts +7 -7
  143. package/src/services/api/manage.ts +8 -8
  144. package/src/services/api/search.ts +16 -16
  145. package/src/services/api/user.ts +17 -17
  146. package/src/services/restTools.ts +56 -56
  147. package/src/services/v3Api.ts +147 -147
  148. package/src/stores/index.ts +11 -11
  149. package/src/stores/modules/counter.ts +19 -19
  150. package/src/stores/modules/routeCache.ts +23 -23
  151. package/src/stores/modules/setting.ts +76 -76
  152. package/src/stores/modules/user.ts +235 -235
  153. package/src/stores/mutation-type.ts +7 -7
  154. package/src/styles/app.less +36 -36
  155. package/src/styles/login.less +109 -109
  156. package/src/styles/var.less +16 -16
  157. package/src/types/env.d.ts +16 -16
  158. package/src/types/settings.ts +1 -1
  159. package/src/types/vue-router.d.ts +9 -9
  160. package/src/utils/Storage.ts +124 -124
  161. package/src/utils/authority-utils.ts +84 -84
  162. package/src/utils/common.ts +41 -41
  163. package/src/utils/crypto.ts +39 -39
  164. package/src/utils/dataUtil.ts +42 -42
  165. package/src/utils/dictUtil.ts +52 -52
  166. package/src/utils/http/index.ts +199 -199
  167. package/src/utils/i18n.ts +72 -72
  168. package/src/utils/indexedDB.ts +195 -195
  169. package/src/utils/inline-px-to-vw.ts +28 -28
  170. package/src/utils/mobileUtil.ts +34 -34
  171. package/src/utils/progress.ts +19 -19
  172. package/src/utils/queryFormDefaultRangePicker.ts +57 -57
  173. package/src/utils/routerUtil.ts +271 -271
  174. package/src/utils/runEvalFunction.ts +13 -13
  175. package/src/utils/secureStorage.ts +71 -71
  176. package/src/utils/set-page-title.ts +5 -5
  177. package/src/utils/validate.ts +6 -6
  178. package/src/utils/wechatUtil.ts +9 -9
  179. package/src/views/chat/index.vue +153 -153
  180. package/src/views/common/LoadError.vue +63 -63
  181. package/src/views/common/NotFound.vue +67 -67
  182. package/src/views/component/EvaluateRecordView/index.vue +40 -40
  183. package/src/views/component/IconifyView/index.vue +504 -507
  184. package/src/views/component/UserDetailView/UserDetailPage.vue +77 -0
  185. package/src/views/component/UserDetailView/index.vue +224 -0
  186. package/src/views/component/XCellDetailView/index.vue +217 -217
  187. package/src/views/component/XCellListView/index.vue +108 -147
  188. package/src/views/component/XFormAppraiseView/index.vue +174 -174
  189. package/src/views/component/XFormGroupView/index.vue +78 -91
  190. package/src/views/component/XFormView/index.vue +27 -107
  191. package/src/views/component/XOlMapView/XLocationPicker/index.vue +118 -118
  192. package/src/views/component/XOlMapView/index.vue +434 -434
  193. package/src/views/component/XOlMapView/testData.ts +64 -64
  194. package/src/views/component/XReportFormIframeView/index.vue +47 -47
  195. package/src/views/component/XReportFormView/index.vue +13 -13
  196. package/src/views/component/XReportGridView/index.vue +17 -17
  197. package/src/views/component/XRequestView/index.vue +234 -234
  198. package/src/views/component/XSignatureView/index.vue +50 -50
  199. package/src/views/component/index.vue +181 -177
  200. package/src/views/component/menu.vue +117 -117
  201. package/src/views/component/notice.vue +46 -46
  202. package/src/views/component/topNav.vue +36 -36
  203. package/src/views/invoiceShow/index.vue +61 -61
  204. package/src/views/user/login/ForgetPasswordForm.vue +94 -94
  205. package/src/views/user/login/LoginForm.vue +346 -346
  206. package/src/views/user/login/LoginTitle.vue +76 -76
  207. package/src/views/user/login/LoginWave.vue +109 -109
  208. package/src/views/user/login/index.vue +22 -22
  209. package/src/views/user/my/comm/ModifyPassword.vue +346 -346
  210. package/src/views/user/my/index.vue +340 -340
  211. package/src/views/userRecords/AbnormalAlarmRecords.vue +21 -0
  212. package/src/views/userRecords/CardReplacementRecords.vue +21 -0
  213. package/src/views/userRecords/ChangeRecords.vue +19 -0
  214. package/src/views/userRecords/CommandViewRecords.vue +20 -0
  215. package/src/views/userRecords/GasCompensationRecords.vue +20 -0
  216. package/src/views/userRecords/InstrumentCollectionRecords.vue +21 -0
  217. package/src/views/userRecords/MeterRecords.vue +20 -0
  218. package/src/views/userRecords/OperateRecords.vue +51 -0
  219. package/src/views/userRecords/OtherChargeRecords.vue +19 -0
  220. package/src/views/userRecords/PaymentRecords.vue +28 -0
  221. package/src/views/userRecords/PriceAdjustmentRecords.vue +19 -0
  222. package/src/views/userRecords/ReplacementRecords.vue +19 -0
  223. package/src/views/userRecords/SafetyRecords.vue +19 -0
  224. package/src/views/userRecords/TransactionRecords.vue +21 -0
  225. package/src/views/userRecords/TransferRecords.vue +19 -0
  226. package/src/views/userRecords/operateRecordDetail/index.vue +316 -0
  227. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AddUserDetail.vue +124 -0
  228. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AdvanceDeliveryDetail.vue +88 -0
  229. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsCancelDetail.vue +205 -0
  230. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsDetail.vue +192 -0
  231. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankDkDetail.vue +192 -0
  232. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankPayDetail.vue +192 -0
  233. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BlacklistDetail.vue +153 -0
  234. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CancellationDetail.vue +101 -0
  235. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterCancelDetail.vue +127 -0
  236. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterDetail.vue +153 -0
  237. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardOverUserDetail.vue +153 -0
  238. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterCancelDetail.vue +166 -0
  239. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterDetail.vue +205 -0
  240. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/DisableManageDetail.vue +127 -0
  241. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/EnableManageDetail.vue +114 -0
  242. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FaZheChangeDetail.vue +124 -0
  243. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FeeDeductionDetail.vue +153 -0
  244. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/GasPriceChangeDetail.vue +126 -0
  245. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/InputtorChangeDetail.vue +126 -0
  246. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterCancelDetail.vue +114 -0
  247. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterDetail.vue +127 -0
  248. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotOpenDetail.vue +88 -0
  249. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineCardDetail.vue +101 -0
  250. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterCancelDetail.vue +218 -0
  251. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterDetail.vue +153 -0
  252. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OffGasAddGasDetail.vue +140 -0
  253. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeCancelDetail.vue +127 -0
  254. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeDetail.vue +114 -0
  255. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OverUserChangeDetail.vue +127 -0
  256. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReBillDetail.vue +127 -0
  257. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/RefundDetail.vue +114 -0
  258. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageCancelDetail.vue +127 -0
  259. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageDetail.vue +114 -0
  260. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/SaleCardGasDetail.vue +140 -0
  261. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageCancelDetail.vue +152 -0
  262. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageDetail.vue +178 -0
  263. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/UserChangeDetail.vue +123 -0
  264. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/WechatPayDetail.vue +192 -0
  265. package/src/views/userRecords/types.ts +66 -0
  266. package/tsconfig.json +39 -39
  267. package/uno.config.ts +82 -78
  268. package/vite.config.ts +118 -118
@@ -1,346 +1,346 @@
1
- <script setup lang="ts">
2
- import { modifyPassword } from '@af-mobile-client-vue3/services/api/user'
3
- import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
4
- import { showDialog, showToast, Button as vanButton, Field as vanField, Form as vanForm, Icon as vanIcon, Popup as vanPopup } from 'vant'
5
- import { reactive, ref, watch } from 'vue'
6
- import { useRouter } from 'vue-router'
7
-
8
- // 定义 props 和 emits
9
- const props = defineProps<{
10
- visible: boolean
11
- }>()
12
-
13
- const emit = defineEmits<{
14
- (event: 'update:visible', value: boolean): void
15
- }>()
16
-
17
- const router = useRouter()
18
- const userStore = useUserStore()
19
-
20
- // 表单引用
21
- const formRef = ref()
22
-
23
- // 表单数据
24
- const formData = reactive({
25
- oldPassword: '',
26
- newPassword: '',
27
- confirmPassword: '',
28
- })
29
-
30
- // 密码显示状态
31
- const showOldPassword = ref(false)
32
- const showNewPassword = ref(false)
33
- const showConfirmPassword = ref(false)
34
-
35
- // 加载状态
36
- const loading = ref(false)
37
-
38
- // 密码强度验证正则
39
- const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
40
-
41
- // 验证密码强度
42
- function validatePasswordStrength(password: string): boolean {
43
- return strongPasswordRegex.test(password)
44
- }
45
-
46
- // 验证确认密码
47
- function validateConfirmPassword(value: string): boolean {
48
- return value === formData.newPassword
49
- }
50
-
51
- // 表单验证规则
52
- const rules = {
53
- oldPassword: [
54
- { required: true, message: '请输入旧密码' },
55
- ],
56
- newPassword: [
57
- { required: true, message: '请输入新密码' },
58
- {
59
- validator: (value: string) => {
60
- if (value && !validatePasswordStrength(value)) {
61
- return '新密码必须包含大小写字母、数字和特殊字符,且长度不少于8位'
62
- }
63
- return true
64
- },
65
- },
66
- ],
67
- confirmPassword: [
68
- { required: true, message: '请再次输入新密码' },
69
- {
70
- validator: (value: string) => {
71
- if (value && !validateConfirmPassword(value)) {
72
- return '两次密码输入不一致'
73
- }
74
- return true
75
- },
76
- },
77
- ],
78
- }
79
-
80
- // 提交表单
81
- async function handleSubmit() {
82
- try {
83
- loading.value = true
84
-
85
- // 验证表单
86
- await formRef.value?.validate()
87
-
88
- // 调用修改密码API
89
- const result = await handleModifyPassword({ data: {
90
- ename: userStore.getUserInfo().username,
91
- password: formData.oldPassword,
92
- newpassword: formData.newPassword,
93
- affirmpassword: formData.confirmPassword,
94
- } })
95
- if (result.success) {
96
- showDialog({
97
- title: '成功',
98
- message: '修改密码成功,请重新登录',
99
- confirmButtonText: '立即重新登录',
100
- }).then(() => {
101
- // 退出登录
102
- userStore.logout()
103
- // 跳转到登录页
104
- router.push('/login')
105
- })
106
- }
107
- else {
108
- showToast(result.message || '修改密码失败')
109
- }
110
- }
111
- catch (error) {
112
- console.error('修改密码失败:', error)
113
- showToast('修改密码失败,请检查输入信息')
114
- }
115
- finally {
116
- loading.value = false
117
- }
118
- }
119
-
120
- // 关闭弹窗
121
- function closeModal() {
122
- emit('update:visible', false)
123
- }
124
-
125
- // 修改密码API调用
126
- async function handleModifyPassword(data: any) {
127
- try {
128
- const res = await modifyPassword(data)
129
- if (res && res === 'true') {
130
- return {
131
- success: true,
132
- message: '修改成功',
133
- }
134
- }
135
- else {
136
- return {
137
- success: false,
138
- message: '修改密码失败,请检查原始密码是否正确!',
139
- }
140
- }
141
- }
142
- catch (error: any) {
143
- return {
144
- success: false,
145
- message: error?.message || '修改密码失败',
146
- }
147
- }
148
- }
149
-
150
- // 监听visible变化,重置表单
151
- watch(() => props.visible, (newVal) => {
152
- if (!newVal) {
153
- // 弹窗关闭时重置表单
154
- formData.oldPassword = ''
155
- formData.newPassword = ''
156
- formData.confirmPassword = ''
157
- showOldPassword.value = false
158
- showNewPassword.value = false
159
- showConfirmPassword.value = false
160
- }
161
- })
162
- </script>
163
-
164
- <template>
165
- <van-popup
166
- :show="props.visible"
167
- position="center"
168
- :close-on-click-overlay="false"
169
- round
170
- class="modify-password-popup"
171
- @update:show="emit('update:visible', $event)"
172
- >
173
- <div class="popup-content">
174
- <!-- 标题 -->
175
- <div class="popup-header">
176
- <h3 class="popup-title">
177
- 修改密码
178
- </h3>
179
- <van-icon name="cross" class="close-icon" @click="closeModal" />
180
- </div>
181
-
182
- <!-- 表单 -->
183
- <van-form ref="formRef" class="password-form" @submit="handleSubmit">
184
- <!-- 旧密码 -->
185
- <van-field
186
- v-model="formData.oldPassword"
187
- name="oldPassword"
188
- label="旧密码"
189
- placeholder="请输入旧密码"
190
- :type="showOldPassword ? 'text' : 'password'"
191
- :rules="rules.oldPassword"
192
- @click-right-icon="showOldPassword = !showOldPassword"
193
- >
194
- <template #right-icon>
195
- <van-icon
196
- :name="showOldPassword ? 'eye-o' : 'closed-eye'"
197
- color="#666"
198
- />
199
- </template>
200
- </van-field>
201
-
202
- <!-- 新密码 -->
203
- <van-field
204
- v-model="formData.newPassword"
205
- name="newPassword"
206
- label="新密码"
207
- placeholder="请输入新密码"
208
- :type="showNewPassword ? 'text' : 'password'"
209
- :rules="rules.newPassword"
210
- @click-right-icon="showNewPassword = !showNewPassword"
211
- >
212
- <template #right-icon>
213
- <van-icon
214
- :name="showNewPassword ? 'eye-o' : 'closed-eye'"
215
- color="#666"
216
- />
217
- </template>
218
- </van-field>
219
-
220
- <!-- 确认新密码 -->
221
- <van-field
222
- v-model="formData.confirmPassword"
223
- name="confirmPassword"
224
- label="确认新密码"
225
- placeholder="请再次输入新密码"
226
- :type="showConfirmPassword ? 'text' : 'password'"
227
- :rules="rules.confirmPassword"
228
- @click-right-icon="showConfirmPassword = !showConfirmPassword"
229
- >
230
- <template #right-icon>
231
- <van-icon
232
- :name="showConfirmPassword ? 'eye-o' : 'closed-eye'"
233
- color="#666"
234
- />
235
- </template>
236
- </van-field>
237
-
238
- <!-- 按钮组 -->
239
- <div class="form-buttons">
240
- <van-button
241
- plain
242
- type="default"
243
- size="large"
244
- class="cancel-btn"
245
- @click="closeModal"
246
- >
247
- 取消
248
- </van-button>
249
- <van-button
250
- type="primary"
251
- size="large"
252
- native-type="submit"
253
- :loading="loading"
254
- class="submit-btn"
255
- >
256
- 确认修改
257
- </van-button>
258
- </div>
259
- </van-form>
260
- </div>
261
- </van-popup>
262
- </template>
263
-
264
- <style scoped lang="less">
265
- .modify-password-popup {
266
- width: 90%;
267
- max-width: 400px;
268
-
269
- .popup-content {
270
- padding: 20px;
271
-
272
- .popup-header {
273
- display: flex;
274
- justify-content: space-between;
275
- align-items: center;
276
- margin-bottom: 20px;
277
-
278
- .popup-title {
279
- font-size: 18px;
280
- font-weight: 600;
281
- color: #333;
282
- margin: 0;
283
- }
284
-
285
- .close-icon {
286
- font-size: 20px;
287
- color: #999;
288
- cursor: pointer;
289
- padding: 4px;
290
-
291
- &:hover {
292
- color: #666;
293
- }
294
- }
295
- }
296
-
297
- .password-form {
298
- .form-buttons {
299
- display: flex;
300
- gap: 12px;
301
- margin-top: 24px;
302
-
303
- .cancel-btn,
304
- .submit-btn {
305
- flex: 1;
306
- height: 44px;
307
- border-radius: 8px;
308
- font-size: 16px;
309
- }
310
-
311
- .cancel-btn {
312
- border-color: #ddd;
313
- color: #666;
314
- }
315
-
316
- .submit-btn {
317
- background-color: #3b82f6;
318
- border-color: #3b82f6;
319
- }
320
- }
321
- }
322
- }
323
- }
324
-
325
- // 覆盖vant默认样式
326
- :deep(.van-field) {
327
- padding: 12px 0;
328
-
329
- .van-field__label {
330
- color: #333;
331
- font-weight: 500;
332
- }
333
-
334
- .van-field__control {
335
- color: #333;
336
- }
337
-
338
- .van-field__right-icon {
339
- padding: 4px;
340
- }
341
- }
342
-
343
- :deep(.van-popup) {
344
- border-radius: 12px;
345
- }
346
- </style>
1
+ <script setup lang="ts">
2
+ import { modifyPassword } from '@af-mobile-client-vue3/services/api/user'
3
+ import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
4
+ import { showDialog, showToast, Button as vanButton, Field as vanField, Form as vanForm, Icon as vanIcon, Popup as vanPopup } from 'vant'
5
+ import { reactive, ref, watch } from 'vue'
6
+ import { useRouter } from 'vue-router'
7
+
8
+ // 定义 props 和 emits
9
+ const props = defineProps<{
10
+ visible: boolean
11
+ }>()
12
+
13
+ const emit = defineEmits<{
14
+ (event: 'update:visible', value: boolean): void
15
+ }>()
16
+
17
+ const router = useRouter()
18
+ const userStore = useUserStore()
19
+
20
+ // 表单引用
21
+ const formRef = ref()
22
+
23
+ // 表单数据
24
+ const formData = reactive({
25
+ oldPassword: '',
26
+ newPassword: '',
27
+ confirmPassword: '',
28
+ })
29
+
30
+ // 密码显示状态
31
+ const showOldPassword = ref(false)
32
+ const showNewPassword = ref(false)
33
+ const showConfirmPassword = ref(false)
34
+
35
+ // 加载状态
36
+ const loading = ref(false)
37
+
38
+ // 密码强度验证正则
39
+ const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
40
+
41
+ // 验证密码强度
42
+ function validatePasswordStrength(password: string): boolean {
43
+ return strongPasswordRegex.test(password)
44
+ }
45
+
46
+ // 验证确认密码
47
+ function validateConfirmPassword(value: string): boolean {
48
+ return value === formData.newPassword
49
+ }
50
+
51
+ // 表单验证规则
52
+ const rules = {
53
+ oldPassword: [
54
+ { required: true, message: '请输入旧密码' },
55
+ ],
56
+ newPassword: [
57
+ { required: true, message: '请输入新密码' },
58
+ {
59
+ validator: (value: string) => {
60
+ if (value && !validatePasswordStrength(value)) {
61
+ return '新密码必须包含大小写字母、数字和特殊字符,且长度不少于8位'
62
+ }
63
+ return true
64
+ },
65
+ },
66
+ ],
67
+ confirmPassword: [
68
+ { required: true, message: '请再次输入新密码' },
69
+ {
70
+ validator: (value: string) => {
71
+ if (value && !validateConfirmPassword(value)) {
72
+ return '两次密码输入不一致'
73
+ }
74
+ return true
75
+ },
76
+ },
77
+ ],
78
+ }
79
+
80
+ // 提交表单
81
+ async function handleSubmit() {
82
+ try {
83
+ loading.value = true
84
+
85
+ // 验证表单
86
+ await formRef.value?.validate()
87
+
88
+ // 调用修改密码API
89
+ const result = await handleModifyPassword({ data: {
90
+ ename: userStore.getUserInfo().username,
91
+ password: formData.oldPassword,
92
+ newpassword: formData.newPassword,
93
+ affirmpassword: formData.confirmPassword,
94
+ } })
95
+ if (result.success) {
96
+ showDialog({
97
+ title: '成功',
98
+ message: '修改密码成功,请重新登录',
99
+ confirmButtonText: '立即重新登录',
100
+ }).then(() => {
101
+ // 退出登录
102
+ userStore.logout()
103
+ // 跳转到登录页
104
+ router.push('/login')
105
+ })
106
+ }
107
+ else {
108
+ showToast(result.message || '修改密码失败')
109
+ }
110
+ }
111
+ catch (error) {
112
+ console.error('修改密码失败:', error)
113
+ showToast('修改密码失败,请检查输入信息')
114
+ }
115
+ finally {
116
+ loading.value = false
117
+ }
118
+ }
119
+
120
+ // 关闭弹窗
121
+ function closeModal() {
122
+ emit('update:visible', false)
123
+ }
124
+
125
+ // 修改密码API调用
126
+ async function handleModifyPassword(data: any) {
127
+ try {
128
+ const res = await modifyPassword(data)
129
+ if (res && res === 'true') {
130
+ return {
131
+ success: true,
132
+ message: '修改成功',
133
+ }
134
+ }
135
+ else {
136
+ return {
137
+ success: false,
138
+ message: '修改密码失败,请检查原始密码是否正确!',
139
+ }
140
+ }
141
+ }
142
+ catch (error: any) {
143
+ return {
144
+ success: false,
145
+ message: error?.message || '修改密码失败',
146
+ }
147
+ }
148
+ }
149
+
150
+ // 监听visible变化,重置表单
151
+ watch(() => props.visible, (newVal) => {
152
+ if (!newVal) {
153
+ // 弹窗关闭时重置表单
154
+ formData.oldPassword = ''
155
+ formData.newPassword = ''
156
+ formData.confirmPassword = ''
157
+ showOldPassword.value = false
158
+ showNewPassword.value = false
159
+ showConfirmPassword.value = false
160
+ }
161
+ })
162
+ </script>
163
+
164
+ <template>
165
+ <van-popup
166
+ :show="props.visible"
167
+ position="center"
168
+ :close-on-click-overlay="false"
169
+ round
170
+ class="modify-password-popup"
171
+ @update:show="emit('update:visible', $event)"
172
+ >
173
+ <div class="popup-content">
174
+ <!-- 标题 -->
175
+ <div class="popup-header">
176
+ <h3 class="popup-title">
177
+ 修改密码
178
+ </h3>
179
+ <van-icon name="cross" class="close-icon" @click="closeModal" />
180
+ </div>
181
+
182
+ <!-- 表单 -->
183
+ <van-form ref="formRef" class="password-form" @submit="handleSubmit">
184
+ <!-- 旧密码 -->
185
+ <van-field
186
+ v-model="formData.oldPassword"
187
+ name="oldPassword"
188
+ label="旧密码"
189
+ placeholder="请输入旧密码"
190
+ :type="showOldPassword ? 'text' : 'password'"
191
+ :rules="rules.oldPassword"
192
+ @click-right-icon="showOldPassword = !showOldPassword"
193
+ >
194
+ <template #right-icon>
195
+ <van-icon
196
+ :name="showOldPassword ? 'eye-o' : 'closed-eye'"
197
+ color="#666"
198
+ />
199
+ </template>
200
+ </van-field>
201
+
202
+ <!-- 新密码 -->
203
+ <van-field
204
+ v-model="formData.newPassword"
205
+ name="newPassword"
206
+ label="新密码"
207
+ placeholder="请输入新密码"
208
+ :type="showNewPassword ? 'text' : 'password'"
209
+ :rules="rules.newPassword"
210
+ @click-right-icon="showNewPassword = !showNewPassword"
211
+ >
212
+ <template #right-icon>
213
+ <van-icon
214
+ :name="showNewPassword ? 'eye-o' : 'closed-eye'"
215
+ color="#666"
216
+ />
217
+ </template>
218
+ </van-field>
219
+
220
+ <!-- 确认新密码 -->
221
+ <van-field
222
+ v-model="formData.confirmPassword"
223
+ name="confirmPassword"
224
+ label="确认新密码"
225
+ placeholder="请再次输入新密码"
226
+ :type="showConfirmPassword ? 'text' : 'password'"
227
+ :rules="rules.confirmPassword"
228
+ @click-right-icon="showConfirmPassword = !showConfirmPassword"
229
+ >
230
+ <template #right-icon>
231
+ <van-icon
232
+ :name="showConfirmPassword ? 'eye-o' : 'closed-eye'"
233
+ color="#666"
234
+ />
235
+ </template>
236
+ </van-field>
237
+
238
+ <!-- 按钮组 -->
239
+ <div class="form-buttons">
240
+ <van-button
241
+ plain
242
+ type="default"
243
+ size="large"
244
+ class="cancel-btn"
245
+ @click="closeModal"
246
+ >
247
+ 取消
248
+ </van-button>
249
+ <van-button
250
+ type="primary"
251
+ size="large"
252
+ native-type="submit"
253
+ :loading="loading"
254
+ class="submit-btn"
255
+ >
256
+ 确认修改
257
+ </van-button>
258
+ </div>
259
+ </van-form>
260
+ </div>
261
+ </van-popup>
262
+ </template>
263
+
264
+ <style scoped lang="less">
265
+ .modify-password-popup {
266
+ width: 90%;
267
+ max-width: 400px;
268
+
269
+ .popup-content {
270
+ padding: 20px;
271
+
272
+ .popup-header {
273
+ display: flex;
274
+ justify-content: space-between;
275
+ align-items: center;
276
+ margin-bottom: 20px;
277
+
278
+ .popup-title {
279
+ font-size: 18px;
280
+ font-weight: 600;
281
+ color: #333;
282
+ margin: 0;
283
+ }
284
+
285
+ .close-icon {
286
+ font-size: 20px;
287
+ color: #999;
288
+ cursor: pointer;
289
+ padding: 4px;
290
+
291
+ &:hover {
292
+ color: #666;
293
+ }
294
+ }
295
+ }
296
+
297
+ .password-form {
298
+ .form-buttons {
299
+ display: flex;
300
+ gap: 12px;
301
+ margin-top: 24px;
302
+
303
+ .cancel-btn,
304
+ .submit-btn {
305
+ flex: 1;
306
+ height: 44px;
307
+ border-radius: 8px;
308
+ font-size: 16px;
309
+ }
310
+
311
+ .cancel-btn {
312
+ border-color: #ddd;
313
+ color: #666;
314
+ }
315
+
316
+ .submit-btn {
317
+ background-color: #3b82f6;
318
+ border-color: #3b82f6;
319
+ }
320
+ }
321
+ }
322
+ }
323
+ }
324
+
325
+ // 覆盖vant默认样式
326
+ :deep(.van-field) {
327
+ padding: 12px 0;
328
+
329
+ .van-field__label {
330
+ color: #333;
331
+ font-weight: 500;
332
+ }
333
+
334
+ .van-field__control {
335
+ color: #333;
336
+ }
337
+
338
+ .van-field__right-icon {
339
+ padding: 4px;
340
+ }
341
+ }
342
+
343
+ :deep(.van-popup) {
344
+ border-radius: 12px;
345
+ }
346
+ </style>