af-mobile-client-vue3 1.3.12 → 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 (270) 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 +122 -122
  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 +102 -102
  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/XReportDemo.vue +33 -33
  79. package/src/components/data/XReportGrid/XReportDesign.vue +597 -597
  80. package/src/components/data/XReportGrid/XReportDrawer/XReportDrawer.vue +148 -148
  81. package/src/components/data/XReportGrid/XReportDrawer/index.js +3 -3
  82. package/src/components/data/XReportGrid/XReportDrawer/index.ts +10 -10
  83. package/src/components/data/XReportGrid/XReportJsonRender.vue +399 -399
  84. package/src/components/data/XReportGrid/XReportTrGroup.vue +592 -592
  85. package/src/components/data/XReportGrid/index.md +46 -42
  86. package/src/components/data/XReportGrid/print.js +184 -184
  87. package/src/components/data/XSignature/index.vue +284 -285
  88. package/src/components/data/XTag/index.vue +10 -10
  89. package/src/components/layout/NormalDataLayout/index.vue +69 -69
  90. package/src/components/layout/TabBarLayout/index.vue +40 -40
  91. package/src/composables/dark.ts +5 -5
  92. package/src/config/routes.ts +9 -9
  93. package/src/constants/index.ts +2 -2
  94. package/src/enums/requestEnum.ts +25 -25
  95. package/src/expression/ExpressionRunner.ts +28 -28
  96. package/src/expression/TestExpression.ts +510 -510
  97. package/src/expression/core/Delegate.ts +116 -116
  98. package/src/expression/core/Expression.ts +1359 -1359
  99. package/src/expression/core/Program.ts +985 -985
  100. package/src/expression/core/Token.ts +29 -29
  101. package/src/expression/enums/ExpressionType.ts +81 -81
  102. package/src/expression/enums/TokenType.ts +11 -11
  103. package/src/expression/exception/BreakWayException.ts +2 -2
  104. package/src/expression/exception/ContinueWayException.ts +2 -2
  105. package/src/expression/exception/ExpressionException.ts +29 -29
  106. package/src/expression/exception/ReturnWayException.ts +14 -14
  107. package/src/expression/exception/ServiceException.ts +22 -22
  108. package/src/expression/instances/JSONArray.ts +52 -52
  109. package/src/expression/instances/JSONObject.ts +118 -118
  110. package/src/expression/instances/LogicConsole.ts +31 -31
  111. package/src/font-style/font.css +4 -4
  112. package/src/hooks/useBoolean.ts +26 -0
  113. package/src/hooks/useCommon.ts +9 -9
  114. package/src/hooks/useLogin.ts +97 -97
  115. package/src/icons/svg/check-in.svg +32 -32
  116. package/src/icons/svg/dark.svg +4 -4
  117. package/src/icons/svg/github.svg +4 -4
  118. package/src/icons/svg/light.svg +4 -4
  119. package/src/icons/svg/link.svg +4 -4
  120. package/src/icons/svgo.yml +22 -22
  121. package/src/layout/GridView/index.vue +16 -16
  122. package/src/layout/PageLayout.vue +9 -9
  123. package/src/layout/SingleLayout.vue +9 -9
  124. package/src/locales/en-US.json +128 -128
  125. package/src/locales/zh-CN.json +128 -128
  126. package/src/logic/LogicRunner.ts +67 -67
  127. package/src/logic/TestLogic.ts +13 -13
  128. package/src/logic/plugins/common/DateTools.ts +35 -35
  129. package/src/logic/plugins/common/VueTools.ts +30 -30
  130. package/src/logic/plugins/index.ts +7 -7
  131. package/src/main.ts +44 -44
  132. package/src/plugins/AppData.ts +38 -38
  133. package/src/plugins/GetLoginInfoService.ts +10 -10
  134. package/src/plugins/collectIcons.ts +10 -0
  135. package/src/plugins/index.ts +11 -11
  136. package/src/router/README.md +8 -8
  137. package/src/router/guards.ts +59 -59
  138. package/src/router/index.ts +35 -35
  139. package/src/router/invoiceRoutes.ts +33 -33
  140. package/src/router/routes.ts +341 -177
  141. package/src/router/types.ts +7 -7
  142. package/src/services/api/Login.ts +6 -6
  143. package/src/services/api/common.ts +109 -109
  144. package/src/services/api/index.ts +7 -7
  145. package/src/services/api/manage.ts +8 -8
  146. package/src/services/api/search.ts +16 -16
  147. package/src/services/api/user.ts +17 -17
  148. package/src/services/restTools.ts +56 -56
  149. package/src/services/v3Api.ts +147 -147
  150. package/src/stores/index.ts +11 -11
  151. package/src/stores/modules/counter.ts +19 -19
  152. package/src/stores/modules/routeCache.ts +23 -23
  153. package/src/stores/modules/setting.ts +76 -76
  154. package/src/stores/modules/user.ts +235 -235
  155. package/src/stores/mutation-type.ts +7 -7
  156. package/src/styles/app.less +36 -36
  157. package/src/styles/login.less +109 -109
  158. package/src/styles/var.less +16 -16
  159. package/src/types/env.d.ts +16 -16
  160. package/src/types/settings.ts +1 -1
  161. package/src/types/vue-router.d.ts +9 -9
  162. package/src/utils/Storage.ts +124 -124
  163. package/src/utils/authority-utils.ts +84 -84
  164. package/src/utils/common.ts +41 -41
  165. package/src/utils/crypto.ts +39 -39
  166. package/src/utils/dataUtil.ts +42 -42
  167. package/src/utils/dictUtil.ts +52 -52
  168. package/src/utils/http/index.ts +199 -199
  169. package/src/utils/i18n.ts +72 -72
  170. package/src/utils/indexedDB.ts +195 -195
  171. package/src/utils/inline-px-to-vw.ts +28 -28
  172. package/src/utils/mobileUtil.ts +34 -34
  173. package/src/utils/progress.ts +19 -19
  174. package/src/utils/routerUtil.ts +271 -271
  175. package/src/utils/runEvalFunction.ts +13 -13
  176. package/src/utils/secureStorage.ts +71 -71
  177. package/src/utils/set-page-title.ts +5 -5
  178. package/src/utils/validate.ts +6 -6
  179. package/src/utils/wechatUtil.ts +9 -9
  180. package/src/views/chat/index.vue +153 -153
  181. package/src/views/common/LoadError.vue +63 -63
  182. package/src/views/common/NotFound.vue +67 -67
  183. package/src/views/component/EvaluateRecordView/index.vue +40 -40
  184. package/src/views/component/IconifyView/index.vue +504 -507
  185. package/src/views/component/UserDetailView/UserDetailPage.vue +77 -0
  186. package/src/views/component/UserDetailView/index.vue +224 -0
  187. package/src/views/component/XCellDetailView/index.vue +217 -217
  188. package/src/views/component/XCellListView/index.vue +108 -157
  189. package/src/views/component/XFormAppraiseView/index.vue +174 -174
  190. package/src/views/component/XFormGroupView/index.vue +78 -82
  191. package/src/views/component/XFormView/index.vue +27 -27
  192. package/src/views/component/XOlMapView/XLocationPicker/index.vue +118 -118
  193. package/src/views/component/XOlMapView/index.vue +434 -434
  194. package/src/views/component/XOlMapView/testData.ts +64 -64
  195. package/src/views/component/XReportFormIframeView/index.vue +47 -47
  196. package/src/views/component/XReportFormView/index.vue +13 -13
  197. package/src/views/component/XReportGridView/index.vue +17 -17
  198. package/src/views/component/XRequestView/index.vue +234 -234
  199. package/src/views/component/XSignatureView/index.vue +50 -50
  200. package/src/views/component/index.vue +181 -177
  201. package/src/views/component/menu.vue +117 -117
  202. package/src/views/component/notice.vue +46 -46
  203. package/src/views/component/topNav.vue +36 -36
  204. package/src/views/invoiceShow/index.vue +61 -61
  205. package/src/views/user/login/ForgetPasswordForm.vue +94 -94
  206. package/src/views/user/login/LoginForm.vue +346 -346
  207. package/src/views/user/login/LoginTitle.vue +76 -76
  208. package/src/views/user/login/LoginWave.vue +109 -109
  209. package/src/views/user/login/index.vue +22 -22
  210. package/src/views/user/my/comm/ModifyPassword.vue +346 -346
  211. package/src/views/user/my/index.vue +340 -340
  212. package/src/views/userRecords/AbnormalAlarmRecords.vue +21 -0
  213. package/src/views/userRecords/CardReplacementRecords.vue +21 -0
  214. package/src/views/userRecords/ChangeRecords.vue +19 -0
  215. package/src/views/userRecords/CommandViewRecords.vue +20 -0
  216. package/src/views/userRecords/GasCompensationRecords.vue +20 -0
  217. package/src/views/userRecords/InstrumentCollectionRecords.vue +21 -0
  218. package/src/views/userRecords/MeterRecords.vue +20 -0
  219. package/src/views/userRecords/OperateRecords.vue +51 -0
  220. package/src/views/userRecords/OtherChargeRecords.vue +19 -0
  221. package/src/views/userRecords/PaymentRecords.vue +28 -0
  222. package/src/views/userRecords/PriceAdjustmentRecords.vue +19 -0
  223. package/src/views/userRecords/ReplacementRecords.vue +19 -0
  224. package/src/views/userRecords/SafetyRecords.vue +19 -0
  225. package/src/views/userRecords/TransactionRecords.vue +21 -0
  226. package/src/views/userRecords/TransferRecords.vue +19 -0
  227. package/src/views/userRecords/operateRecordDetail/index.vue +316 -0
  228. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AddUserDetail.vue +124 -0
  229. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AdvanceDeliveryDetail.vue +88 -0
  230. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsCancelDetail.vue +205 -0
  231. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsDetail.vue +192 -0
  232. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankDkDetail.vue +192 -0
  233. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankPayDetail.vue +192 -0
  234. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BlacklistDetail.vue +153 -0
  235. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CancellationDetail.vue +101 -0
  236. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterCancelDetail.vue +127 -0
  237. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterDetail.vue +153 -0
  238. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardOverUserDetail.vue +153 -0
  239. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterCancelDetail.vue +166 -0
  240. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterDetail.vue +205 -0
  241. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/DisableManageDetail.vue +127 -0
  242. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/EnableManageDetail.vue +114 -0
  243. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FaZheChangeDetail.vue +124 -0
  244. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FeeDeductionDetail.vue +153 -0
  245. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/GasPriceChangeDetail.vue +126 -0
  246. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/InputtorChangeDetail.vue +126 -0
  247. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterCancelDetail.vue +114 -0
  248. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterDetail.vue +127 -0
  249. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotOpenDetail.vue +88 -0
  250. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineCardDetail.vue +101 -0
  251. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterCancelDetail.vue +218 -0
  252. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterDetail.vue +153 -0
  253. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OffGasAddGasDetail.vue +140 -0
  254. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeCancelDetail.vue +127 -0
  255. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeDetail.vue +114 -0
  256. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OverUserChangeDetail.vue +127 -0
  257. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReBillDetail.vue +127 -0
  258. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/RefundDetail.vue +114 -0
  259. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageCancelDetail.vue +127 -0
  260. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageDetail.vue +114 -0
  261. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/SaleCardGasDetail.vue +140 -0
  262. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageCancelDetail.vue +152 -0
  263. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageDetail.vue +178 -0
  264. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/UserChangeDetail.vue +123 -0
  265. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/WechatPayDetail.vue +192 -0
  266. package/src/views/userRecords/types.ts +66 -0
  267. package/tsconfig.json +39 -39
  268. package/uno.config.ts +82 -78
  269. package/vite.config.ts +118 -118
  270. package/src/views/component/XFormGroupView/xformgroup222.vue +0 -97
@@ -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>