af-mobile-client-vue3 1.3.36 → 1.3.37

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 (281) hide show
  1. package/.cursorrules +60 -60
  2. package/.editorconfig +9 -9
  3. package/.env +10 -10
  4. package/.env.development +1 -1
  5. package/.env.production +1 -1
  6. package/.node-version +1 -1
  7. package/.vscode/extensions.json +12 -12
  8. package/.vscode/settings.json +68 -68
  9. package/CLAUDE.md +218 -218
  10. package/README.md +182 -182
  11. package/af-example-mobile-vue-web.iml +9 -9
  12. package/build/vite/index.ts +98 -98
  13. package/build/vite/optimize.ts +34 -34
  14. package/build/vite/vconsole.ts +47 -47
  15. package/commitlint.config.ts +32 -32
  16. package/compress.js +36 -36
  17. package/eslint.config.ts +31 -31
  18. package/index.html +23 -23
  19. package/mock/data.ts +20 -20
  20. package/mock/index.ts +7 -7
  21. package/mock/modules/prose.mock.ts +13 -13
  22. package/mock/modules/user.mock.ts +95 -95
  23. package/mock/util.ts +19 -19
  24. package/netlify.toml +12 -12
  25. package/package.json +114 -114
  26. package/postcss.config.ts +27 -27
  27. package/public/favicon.svg +4 -4
  28. package/public/safari-pinned-tab.svg +4 -4
  29. package/scripts/verifyCommit.js +19 -19
  30. package/src/App.vue +79 -79
  31. package/src/api/auth/index.ts +77 -77
  32. package/src/api/auth/types.ts +200 -200
  33. package/src/api/mock/index.ts +30 -30
  34. package/src/api/user/index.ts +40 -40
  35. package/src/assets/img/user/login/background-shadow-1.svg +20 -20
  36. package/src/assets/img/user/login/logo-background.svg +20 -20
  37. package/src/bootstrap.ts +26 -26
  38. package/src/components/core/BeautifulLoading/index.vue +52 -52
  39. package/src/components/core/ImageUploader/index.vue +251 -251
  40. package/src/components/core/NavBar/index.vue +53 -53
  41. package/src/components/core/Tabbar/index.vue +32 -32
  42. package/src/components/core/Uploader/index.vue +124 -124
  43. package/src/components/core/XGridDropOption/index.vue +154 -154
  44. package/src/components/core/XMultiSelect/index.vue +183 -183
  45. package/src/components/core/XSelect/index.vue +149 -149
  46. package/src/components/data/CardContainer/CardContainer.vue +118 -118
  47. package/src/components/data/CardContainer/CardHeader.vue +99 -99
  48. package/src/components/data/InfoDisplay/index.vue +132 -132
  49. package/src/components/data/UserDetail/api.ts +24 -24
  50. package/src/components/data/UserDetail/index.vue +620 -620
  51. package/src/components/data/UserDetail/recordEntries.ts +159 -159
  52. package/src/components/data/UserDetail/types.ts +26 -26
  53. package/src/components/data/XBadge/index.vue +82 -82
  54. package/src/components/data/XCellDetail/index.vue +105 -105
  55. package/src/components/data/XCellList/XCellList.md +432 -432
  56. package/src/components/data/XCellList/index.vue +1436 -1436
  57. package/src/components/data/XCellListFilter/QrScanner/index.vue +207 -207
  58. package/src/components/data/XCellListFilter/QrScanner/startScanAnimation.ts +53 -53
  59. package/src/components/data/XCellListFilter/VpnRecognition/index.vue +119 -119
  60. package/src/components/data/XCellListFilter/index.vue +705 -705
  61. package/src/components/data/XForm/index.vue +659 -659
  62. package/src/components/data/XFormGroup/doc/DeviceForm.vue +122 -122
  63. package/src/components/data/XFormGroup/doc/FormGroupDemo.vue +56 -56
  64. package/src/components/data/XFormGroup/doc/README.md +286 -286
  65. package/src/components/data/XFormGroup/doc/UserForm.vue +102 -102
  66. package/src/components/data/XFormGroup/index.vue +240 -240
  67. package/src/components/data/XFormItem/index.vue +1311 -1311
  68. package/src/components/data/XOlMap/README.md +227 -227
  69. package/src/components/data/XOlMap/XLocationPicker/index.vue +226 -226
  70. package/src/components/data/XOlMap/index.vue +1490 -1490
  71. package/src/components/data/XOlMap/types.ts +149 -149
  72. package/src/components/data/XOlMap/utils/wgs84ToGcj02.ts +171 -171
  73. package/src/components/data/XReportForm/DateTimeSecondsPicker.vue +208 -208
  74. package/src/components/data/XReportForm/XReportFormJsonRender.vue +220 -220
  75. package/src/components/data/XReportForm/index.vue +1393 -1393
  76. package/src/components/data/XReportGrid/XAddReport/XAddReport.vue +198 -198
  77. package/src/components/data/XReportGrid/XAddReport/index.js +3 -3
  78. package/src/components/data/XReportGrid/XAddReport/index.md +53 -53
  79. package/src/components/data/XReportGrid/XAddReport/index.ts +10 -10
  80. package/src/components/data/XReportGrid/XReport.vue +960 -960
  81. package/src/components/data/XReportGrid/XReportDemo.vue +33 -33
  82. package/src/components/data/XReportGrid/XReportDesign.vue +597 -597
  83. package/src/components/data/XReportGrid/XReportDrawer/XReportDrawer.vue +148 -148
  84. package/src/components/data/XReportGrid/XReportDrawer/index.js +3 -3
  85. package/src/components/data/XReportGrid/XReportDrawer/index.ts +10 -10
  86. package/src/components/data/XReportGrid/XReportJsonRender.vue +399 -399
  87. package/src/components/data/XReportGrid/XReportTrGroup.vue +592 -592
  88. package/src/components/data/XReportGrid/index.md +46 -46
  89. package/src/components/data/XReportGrid/print.js +184 -184
  90. package/src/components/data/XSignature/index.vue +284 -284
  91. package/src/components/data/XTag/index.vue +10 -10
  92. package/src/components/layout/NormalDataLayout/index.vue +69 -69
  93. package/src/components/layout/TabBarLayout/index.vue +40 -40
  94. package/src/composables/dark.ts +5 -5
  95. package/src/config/routes.ts +9 -9
  96. package/src/constants/index.ts +2 -2
  97. package/src/enums/requestEnum.ts +25 -25
  98. package/src/expression/ExpressionRunner.ts +28 -28
  99. package/src/expression/TestExpression.ts +510 -510
  100. package/src/expression/core/Delegate.ts +116 -116
  101. package/src/expression/core/Expression.ts +1359 -1359
  102. package/src/expression/core/Program.ts +985 -985
  103. package/src/expression/core/Token.ts +29 -29
  104. package/src/expression/enums/ExpressionType.ts +81 -81
  105. package/src/expression/enums/TokenType.ts +11 -11
  106. package/src/expression/exception/BreakWayException.ts +2 -2
  107. package/src/expression/exception/ContinueWayException.ts +2 -2
  108. package/src/expression/exception/ExpressionException.ts +29 -29
  109. package/src/expression/exception/ReturnWayException.ts +14 -14
  110. package/src/expression/exception/ServiceException.ts +22 -22
  111. package/src/expression/instances/JSONArray.ts +52 -52
  112. package/src/expression/instances/JSONObject.ts +118 -118
  113. package/src/expression/instances/LogicConsole.ts +31 -31
  114. package/src/font-style/font.css +4 -4
  115. package/src/hooks/useBoolean.ts +26 -26
  116. package/src/hooks/useCommon.ts +9 -9
  117. package/src/hooks/useLoading.ts +16 -16
  118. package/src/hooks/useLogin.ts +97 -97
  119. package/src/icons/svg/check-in.svg +32 -32
  120. package/src/icons/svg/dark.svg +4 -4
  121. package/src/icons/svg/github.svg +4 -4
  122. package/src/icons/svg/light.svg +4 -4
  123. package/src/icons/svg/link.svg +4 -4
  124. package/src/icons/svgo.yml +22 -22
  125. package/src/layout/GridView/index.vue +16 -16
  126. package/src/layout/PageLayout.vue +9 -9
  127. package/src/layout/SingleLayout.vue +9 -9
  128. package/src/locales/en-US.json +128 -128
  129. package/src/locales/zh-CN.json +128 -128
  130. package/src/logic/LogicRunner.ts +67 -67
  131. package/src/logic/TestLogic.ts +13 -13
  132. package/src/logic/plugins/common/DateTools.ts +35 -35
  133. package/src/logic/plugins/common/VueTools.ts +30 -30
  134. package/src/logic/plugins/index.ts +7 -7
  135. package/src/main.ts +44 -44
  136. package/src/plugins/AppData.ts +38 -38
  137. package/src/plugins/GetLoginInfoService.ts +10 -10
  138. package/src/plugins/collectIcons.ts +10 -10
  139. package/src/plugins/index.ts +11 -11
  140. package/src/router/README.md +8 -8
  141. package/src/router/external-routes.ts +60 -60
  142. package/src/router/guards.ts +131 -131
  143. package/src/router/index.ts +35 -35
  144. package/src/router/invoiceRoutes.ts +33 -33
  145. package/src/router/routes.ts +421 -421
  146. package/src/services/api/Login.ts +6 -6
  147. package/src/services/api/common.ts +109 -109
  148. package/src/services/api/index.ts +7 -7
  149. package/src/services/api/manage.ts +8 -8
  150. package/src/services/api/search.ts +16 -16
  151. package/src/services/api/user.ts +17 -17
  152. package/src/services/restTools.ts +56 -56
  153. package/src/services/v3Api.ts +147 -147
  154. package/src/stores/index.ts +13 -13
  155. package/src/stores/modules/counter.ts +19 -19
  156. package/src/stores/modules/homeApp.ts +55 -55
  157. package/src/stores/modules/routeCache.ts +22 -22
  158. package/src/stores/modules/setting.ts +87 -87
  159. package/src/stores/modules/user.ts +326 -326
  160. package/src/stores/mutation-type.ts +12 -12
  161. package/src/styles/app.less +36 -36
  162. package/src/styles/login.less +109 -109
  163. package/src/styles/var.less +25 -25
  164. package/src/types/auth.ts +89 -89
  165. package/src/types/env.d.ts +16 -16
  166. package/src/types/platform.ts +194 -194
  167. package/src/types/settings.ts +1 -1
  168. package/src/types/vue-router.d.ts +13 -13
  169. package/src/utils/Storage.ts +124 -124
  170. package/src/utils/authority-utils.ts +84 -84
  171. package/src/utils/common.ts +41 -41
  172. package/src/utils/crypto.ts +39 -39
  173. package/src/utils/dataUtil.ts +42 -42
  174. package/src/utils/dictUtil.ts +52 -52
  175. package/src/utils/http/index.ts +201 -201
  176. package/src/utils/i18n.ts +72 -72
  177. package/src/utils/indexedDB.ts +195 -195
  178. package/src/utils/inline-px-to-vw.ts +28 -28
  179. package/src/utils/mobileUtil.ts +33 -33
  180. package/src/utils/platform-auth.ts +135 -135
  181. package/src/utils/progress.ts +19 -19
  182. package/src/utils/queryFormDefaultRangePicker.ts +57 -57
  183. package/src/utils/routerUtil.ts +271 -271
  184. package/src/utils/runEvalFunction.ts +13 -13
  185. package/src/utils/secureStorage.ts +70 -70
  186. package/src/utils/set-page-title.ts +5 -5
  187. package/src/utils/validate.ts +6 -6
  188. package/src/views/chat/index.vue +153 -153
  189. package/src/views/common/Forbidden.vue +97 -97
  190. package/src/views/common/LoadError.vue +63 -63
  191. package/src/views/common/NotFound.vue +67 -67
  192. package/src/views/component/EvaluateRecordView/index.vue +40 -40
  193. package/src/views/component/IconifyView/index.vue +504 -504
  194. package/src/views/component/UserDetailView/UserDetailPage.vue +77 -77
  195. package/src/views/component/UserDetailView/index.vue +234 -234
  196. package/src/views/component/XCellDetailView/index.vue +217 -217
  197. package/src/views/component/XCellListView/index.vue +108 -108
  198. package/src/views/component/XFormAppraiseView/index.vue +174 -174
  199. package/src/views/component/XFormGroupView/index.vue +78 -78
  200. package/src/views/component/XFormView/index.vue +27 -27
  201. package/src/views/component/XOlMapView/index.vue +434 -434
  202. package/src/views/component/XOlMapView/testData.ts +64 -64
  203. package/src/views/component/XReportFormIframeView/index.vue +47 -47
  204. package/src/views/component/XReportFormView/index.vue +13 -13
  205. package/src/views/component/XReportGridView/index.vue +17 -17
  206. package/src/views/component/XRequestView/index.vue +234 -234
  207. package/src/views/component/XSignatureView/index.vue +50 -50
  208. package/src/views/component/index.vue +181 -181
  209. package/src/views/component/menu.vue +117 -117
  210. package/src/views/component/notice.vue +46 -46
  211. package/src/views/component/topNav.vue +36 -36
  212. package/src/views/external/index.vue +152 -152
  213. package/src/views/invoiceShow/index.vue +61 -61
  214. package/src/views/loading/AuthLoading.vue +345 -345
  215. package/src/views/user/login/ForgetPasswordForm.vue +94 -94
  216. package/src/views/user/login/LoginForm.vue +350 -350
  217. package/src/views/user/login/LoginTitle.vue +76 -76
  218. package/src/views/user/login/LoginWave.vue +109 -109
  219. package/src/views/user/login/index.vue +22 -22
  220. package/src/views/user/my/comm/ModifyPassword.vue +346 -346
  221. package/src/views/user/my/index.vue +507 -507
  222. package/src/views/user/register/index.vue +952 -952
  223. package/src/views/userRecords/AbnormalAlarmRecords.vue +21 -21
  224. package/src/views/userRecords/CardReplacementRecords.vue +21 -21
  225. package/src/views/userRecords/ChangeRecords.vue +19 -19
  226. package/src/views/userRecords/CommandViewRecords.vue +20 -20
  227. package/src/views/userRecords/GasCompensationRecords.vue +20 -20
  228. package/src/views/userRecords/InstrumentCollectionRecords.vue +21 -21
  229. package/src/views/userRecords/MeterRecords.vue +20 -20
  230. package/src/views/userRecords/OperateRecords.vue +51 -51
  231. package/src/views/userRecords/OtherChargeRecords.vue +19 -19
  232. package/src/views/userRecords/PaymentRecords.vue +28 -28
  233. package/src/views/userRecords/PriceAdjustmentRecords.vue +19 -19
  234. package/src/views/userRecords/ReplacementRecords.vue +19 -19
  235. package/src/views/userRecords/SafetyRecords.vue +19 -19
  236. package/src/views/userRecords/TransactionRecords.vue +21 -21
  237. package/src/views/userRecords/TransferRecords.vue +19 -19
  238. package/src/views/userRecords/operateRecordDetail/index.vue +316 -316
  239. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AddUserDetail.vue +124 -124
  240. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AdvanceDeliveryDetail.vue +88 -88
  241. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsCancelDetail.vue +205 -205
  242. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsDetail.vue +192 -192
  243. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankDkDetail.vue +192 -192
  244. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankPayDetail.vue +192 -192
  245. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BlacklistDetail.vue +153 -153
  246. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CancellationDetail.vue +101 -101
  247. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterCancelDetail.vue +127 -127
  248. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterDetail.vue +153 -153
  249. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardOverUserDetail.vue +153 -153
  250. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterCancelDetail.vue +166 -166
  251. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterDetail.vue +205 -205
  252. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/DisableManageDetail.vue +127 -127
  253. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/EnableManageDetail.vue +114 -114
  254. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FaZheChangeDetail.vue +124 -124
  255. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FeeDeductionDetail.vue +153 -153
  256. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/GasPriceChangeDetail.vue +126 -126
  257. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/InputtorChangeDetail.vue +126 -126
  258. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterCancelDetail.vue +114 -114
  259. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterDetail.vue +127 -127
  260. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotOpenDetail.vue +88 -88
  261. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineCardDetail.vue +101 -101
  262. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterCancelDetail.vue +218 -218
  263. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterDetail.vue +153 -153
  264. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OffGasAddGasDetail.vue +140 -140
  265. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeCancelDetail.vue +127 -127
  266. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeDetail.vue +114 -114
  267. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OverUserChangeDetail.vue +127 -127
  268. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReBillDetail.vue +127 -127
  269. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/RefundDetail.vue +114 -114
  270. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageCancelDetail.vue +127 -127
  271. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageDetail.vue +114 -114
  272. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/SaleCardGasDetail.vue +140 -140
  273. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageCancelDetail.vue +152 -152
  274. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageDetail.vue +178 -178
  275. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/UserChangeDetail.vue +123 -123
  276. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/WechatPayDetail.vue +192 -192
  277. package/src/views/userRecords/types.ts +66 -66
  278. package/tsconfig.json +39 -39
  279. package/uno.config.ts +82 -82
  280. package/vite.config.ts +114 -114
  281. package/.claude/settings.local.json +0 -14
@@ -1,207 +1,207 @@
1
- <script setup lang="ts">
2
- import { Icon as VanIcon } from 'vant'
3
- import { nextTick, onMounted, onUnmounted, ref } from 'vue'
4
- import { startScanAnimation, stopScanAnimation } from './startScanAnimation'
5
-
6
- // 扫码框的引用
7
- const scannerRef = ref<HTMLDivElement>()
8
- // 扫码动画的引用
9
- const scanLineRef = ref<HTMLDivElement>()
10
- // 闪光灯状态
11
- const isLightOn = ref(false)
12
-
13
- // 初始化扫描动画
14
- async function initScanAnimation() {
15
- // 确保元素已渲染完成
16
- await nextTick()
17
- // 添加延迟确保元素尺寸已计算完成
18
- setTimeout(() => {
19
- if (scannerRef.value && scanLineRef.value) {
20
- // 设置初始位置
21
- scanLineRef.value.style.top = '0px'
22
- startScanAnimation(scanLineRef, scannerRef)
23
- }
24
- }, 300)
25
- }
26
-
27
- // 切换闪光灯
28
- function toggleLight() {
29
- isLightOn.value = !isLightOn.value
30
- }
31
-
32
- onMounted(() => {
33
- initScanAnimation()
34
- })
35
-
36
- onUnmounted(() => {
37
- stopScanAnimation()
38
- })
39
- </script>
40
-
41
- <template>
42
- <div class="qr-scanner">
43
- <div class="scanner-container">
44
- <div class="scanner-bg">
45
- <div ref="scannerRef" class="scanner-box">
46
- <div class="corner-lt" />
47
- <div class="corner-rt" />
48
- <div class="corner-lb" />
49
- <div class="corner-rb" />
50
- <div ref="scanLineRef" class="scan-line" />
51
- <div class="light-btn" @click="toggleLight">
52
- <VanIcon :name="isLightOn ? 'bulb-o' : 'bulb'" class="light-icon" />
53
- </div>
54
- </div>
55
- <div class="scanner-tip">
56
- 将二维码放入框内,即可自动扫描
57
- </div>
58
- </div>
59
- </div>
60
- </div>
61
- </template>
62
-
63
- <style scoped lang="less">
64
- .qr-scanner {
65
- width: 100%;
66
- height: 100%;
67
- background-color: #fff;
68
- display: flex;
69
- flex-direction: column;
70
- border-radius: 8px;
71
- overflow: hidden;
72
-
73
- .scanner-container {
74
- flex: 1;
75
- display: flex;
76
- flex-direction: column;
77
- align-items: center;
78
- justify-content: center;
79
- padding: 20px;
80
- background-color: #fff;
81
-
82
- .scanner-bg {
83
- width: 320px;
84
- height: 320px;
85
- background-color: #f0f0f0;
86
- border-radius: 8px;
87
- padding: 20px;
88
- display: flex;
89
- flex-direction: column;
90
- align-items: center;
91
- justify-content: flex-start;
92
- padding-top: 40px;
93
- }
94
-
95
- .scanner-box {
96
- width: 200px;
97
- height: 200px;
98
- position: relative;
99
- background-color: transparent;
100
- border: 1px solid #1989fa;
101
- border-radius: 0;
102
- box-sizing: border-box;
103
- margin: 0;
104
-
105
- &::before {
106
- content: '';
107
- position: absolute;
108
- top: 0;
109
- left: 0;
110
- right: 0;
111
- bottom: 0;
112
- border: none;
113
- z-index: 1;
114
- }
115
-
116
- .corner-lt,
117
- .corner-rt,
118
- .corner-lb,
119
- .corner-rb {
120
- position: absolute;
121
- width: 24px;
122
- height: 24px;
123
- border-color: #1989fa;
124
- border-style: solid;
125
- z-index: 2;
126
- margin: 0;
127
- }
128
-
129
- .corner-lt {
130
- top: -3px;
131
- left: -3px;
132
- border-width: 3px 0 0 3px;
133
- border-radius: 0;
134
- margin: -8px 0 0 -8px;
135
- }
136
-
137
- .corner-rt {
138
- top: -3px;
139
- right: -3px;
140
- border-width: 3px 3px 0 0;
141
- border-radius: 0;
142
- margin: -8px -8px 0 0;
143
- }
144
-
145
- .corner-lb {
146
- bottom: -3px;
147
- left: -3px;
148
- border-width: 0 0 3px 3px;
149
- border-radius: 0;
150
- margin: 0 0 -8px -8px;
151
- }
152
-
153
- .corner-rb {
154
- bottom: -3px;
155
- right: -3px;
156
- border-width: 0 3px 3px 0;
157
- border-radius: 0;
158
- margin: 0 -8px -8px 0;
159
- }
160
-
161
- .scan-line {
162
- position: absolute;
163
- left: 0;
164
- top: 0;
165
- width: 100%;
166
- height: 2px;
167
- background: linear-gradient(to right, transparent, #1989fa, transparent);
168
- box-shadow: 0 0 4px #1989fa;
169
- z-index: 3;
170
- }
171
-
172
- .light-btn {
173
- position: absolute;
174
- right: -20px;
175
- bottom: -20px;
176
- width: 40px;
177
- height: 40px;
178
- border-radius: 50%;
179
- background-color: rgba(44, 44, 44, 0.5);
180
- display: flex;
181
- align-items: center;
182
- justify-content: center;
183
- cursor: pointer;
184
- z-index: 3;
185
-
186
- .light-icon {
187
- font-size: 20px;
188
- color: #fff;
189
- }
190
-
191
- &:active {
192
- opacity: 0.8;
193
- }
194
- }
195
- }
196
-
197
- .scanner-tip {
198
- color: #666;
199
- font-size: 14px;
200
- text-align: center;
201
- margin-top: 30px;
202
- margin-bottom: 0;
203
- width: 100%;
204
- }
205
- }
206
- }
207
- </style>
1
+ <script setup lang="ts">
2
+ import { Icon as VanIcon } from 'vant'
3
+ import { nextTick, onMounted, onUnmounted, ref } from 'vue'
4
+ import { startScanAnimation, stopScanAnimation } from './startScanAnimation'
5
+
6
+ // 扫码框的引用
7
+ const scannerRef = ref<HTMLDivElement>()
8
+ // 扫码动画的引用
9
+ const scanLineRef = ref<HTMLDivElement>()
10
+ // 闪光灯状态
11
+ const isLightOn = ref(false)
12
+
13
+ // 初始化扫描动画
14
+ async function initScanAnimation() {
15
+ // 确保元素已渲染完成
16
+ await nextTick()
17
+ // 添加延迟确保元素尺寸已计算完成
18
+ setTimeout(() => {
19
+ if (scannerRef.value && scanLineRef.value) {
20
+ // 设置初始位置
21
+ scanLineRef.value.style.top = '0px'
22
+ startScanAnimation(scanLineRef, scannerRef)
23
+ }
24
+ }, 300)
25
+ }
26
+
27
+ // 切换闪光灯
28
+ function toggleLight() {
29
+ isLightOn.value = !isLightOn.value
30
+ }
31
+
32
+ onMounted(() => {
33
+ initScanAnimation()
34
+ })
35
+
36
+ onUnmounted(() => {
37
+ stopScanAnimation()
38
+ })
39
+ </script>
40
+
41
+ <template>
42
+ <div class="qr-scanner">
43
+ <div class="scanner-container">
44
+ <div class="scanner-bg">
45
+ <div ref="scannerRef" class="scanner-box">
46
+ <div class="corner-lt" />
47
+ <div class="corner-rt" />
48
+ <div class="corner-lb" />
49
+ <div class="corner-rb" />
50
+ <div ref="scanLineRef" class="scan-line" />
51
+ <div class="light-btn" @click="toggleLight">
52
+ <VanIcon :name="isLightOn ? 'bulb-o' : 'bulb'" class="light-icon" />
53
+ </div>
54
+ </div>
55
+ <div class="scanner-tip">
56
+ 将二维码放入框内,即可自动扫描
57
+ </div>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </template>
62
+
63
+ <style scoped lang="less">
64
+ .qr-scanner {
65
+ width: 100%;
66
+ height: 100%;
67
+ background-color: #fff;
68
+ display: flex;
69
+ flex-direction: column;
70
+ border-radius: 8px;
71
+ overflow: hidden;
72
+
73
+ .scanner-container {
74
+ flex: 1;
75
+ display: flex;
76
+ flex-direction: column;
77
+ align-items: center;
78
+ justify-content: center;
79
+ padding: 20px;
80
+ background-color: #fff;
81
+
82
+ .scanner-bg {
83
+ width: 320px;
84
+ height: 320px;
85
+ background-color: #f0f0f0;
86
+ border-radius: 8px;
87
+ padding: 20px;
88
+ display: flex;
89
+ flex-direction: column;
90
+ align-items: center;
91
+ justify-content: flex-start;
92
+ padding-top: 40px;
93
+ }
94
+
95
+ .scanner-box {
96
+ width: 200px;
97
+ height: 200px;
98
+ position: relative;
99
+ background-color: transparent;
100
+ border: 1px solid #1989fa;
101
+ border-radius: 0;
102
+ box-sizing: border-box;
103
+ margin: 0;
104
+
105
+ &::before {
106
+ content: '';
107
+ position: absolute;
108
+ top: 0;
109
+ left: 0;
110
+ right: 0;
111
+ bottom: 0;
112
+ border: none;
113
+ z-index: 1;
114
+ }
115
+
116
+ .corner-lt,
117
+ .corner-rt,
118
+ .corner-lb,
119
+ .corner-rb {
120
+ position: absolute;
121
+ width: 24px;
122
+ height: 24px;
123
+ border-color: #1989fa;
124
+ border-style: solid;
125
+ z-index: 2;
126
+ margin: 0;
127
+ }
128
+
129
+ .corner-lt {
130
+ top: -3px;
131
+ left: -3px;
132
+ border-width: 3px 0 0 3px;
133
+ border-radius: 0;
134
+ margin: -8px 0 0 -8px;
135
+ }
136
+
137
+ .corner-rt {
138
+ top: -3px;
139
+ right: -3px;
140
+ border-width: 3px 3px 0 0;
141
+ border-radius: 0;
142
+ margin: -8px -8px 0 0;
143
+ }
144
+
145
+ .corner-lb {
146
+ bottom: -3px;
147
+ left: -3px;
148
+ border-width: 0 0 3px 3px;
149
+ border-radius: 0;
150
+ margin: 0 0 -8px -8px;
151
+ }
152
+
153
+ .corner-rb {
154
+ bottom: -3px;
155
+ right: -3px;
156
+ border-width: 0 3px 3px 0;
157
+ border-radius: 0;
158
+ margin: 0 -8px -8px 0;
159
+ }
160
+
161
+ .scan-line {
162
+ position: absolute;
163
+ left: 0;
164
+ top: 0;
165
+ width: 100%;
166
+ height: 2px;
167
+ background: linear-gradient(to right, transparent, #1989fa, transparent);
168
+ box-shadow: 0 0 4px #1989fa;
169
+ z-index: 3;
170
+ }
171
+
172
+ .light-btn {
173
+ position: absolute;
174
+ right: -20px;
175
+ bottom: -20px;
176
+ width: 40px;
177
+ height: 40px;
178
+ border-radius: 50%;
179
+ background-color: rgba(44, 44, 44, 0.5);
180
+ display: flex;
181
+ align-items: center;
182
+ justify-content: center;
183
+ cursor: pointer;
184
+ z-index: 3;
185
+
186
+ .light-icon {
187
+ font-size: 20px;
188
+ color: #fff;
189
+ }
190
+
191
+ &:active {
192
+ opacity: 0.8;
193
+ }
194
+ }
195
+ }
196
+
197
+ .scanner-tip {
198
+ color: #666;
199
+ font-size: 14px;
200
+ text-align: center;
201
+ margin-top: 30px;
202
+ margin-bottom: 0;
203
+ width: 100%;
204
+ }
205
+ }
206
+ }
207
+ </style>
@@ -1,53 +1,53 @@
1
- import type { Ref } from 'vue'
2
-
3
- let animationTimer: ReturnType<typeof setInterval> | null = null
4
-
5
- // 开始扫码动画
6
- export function startScanAnimation(scanLineRef: Ref<HTMLDivElement | undefined>, scannerRef: Ref<HTMLDivElement | undefined>) {
7
- // 先停止之前的动画
8
- stopScanAnimation()
9
-
10
- if (!scanLineRef.value || !scannerRef.value)
11
- return
12
-
13
- // 确保扫描线初始位置正确
14
- scanLineRef.value.style.top = '0px'
15
-
16
- let direction = 'down'
17
- let position = 0
18
- const speed = 2
19
- const maxPosition = scannerRef.value.offsetHeight || 200
20
-
21
- // 确保maxPosition不为0
22
- if (maxPosition <= 10) {
23
- // 如果容器高度获取失败,使用一个默认延迟后再尝试
24
- setTimeout(() => {
25
- startScanAnimation(scanLineRef, scannerRef)
26
- }, 500)
27
- return
28
- }
29
-
30
- animationTimer = setInterval(() => {
31
- if (direction === 'down') {
32
- position += speed
33
- if (position >= maxPosition - 2)
34
- direction = 'up'
35
- }
36
- else {
37
- position -= speed
38
- if (position <= 0)
39
- direction = 'down'
40
- }
41
- if (scanLineRef.value)
42
- scanLineRef.value.style.top = `${position}px`
43
- }, 20)
44
-
45
- return animationTimer
46
- }
47
-
48
- export function stopScanAnimation() {
49
- if (animationTimer) {
50
- clearInterval(animationTimer)
51
- animationTimer = null
52
- }
53
- }
1
+ import type { Ref } from 'vue'
2
+
3
+ let animationTimer: ReturnType<typeof setInterval> | null = null
4
+
5
+ // 开始扫码动画
6
+ export function startScanAnimation(scanLineRef: Ref<HTMLDivElement | undefined>, scannerRef: Ref<HTMLDivElement | undefined>) {
7
+ // 先停止之前的动画
8
+ stopScanAnimation()
9
+
10
+ if (!scanLineRef.value || !scannerRef.value)
11
+ return
12
+
13
+ // 确保扫描线初始位置正确
14
+ scanLineRef.value.style.top = '0px'
15
+
16
+ let direction = 'down'
17
+ let position = 0
18
+ const speed = 2
19
+ const maxPosition = scannerRef.value.offsetHeight || 200
20
+
21
+ // 确保maxPosition不为0
22
+ if (maxPosition <= 10) {
23
+ // 如果容器高度获取失败,使用一个默认延迟后再尝试
24
+ setTimeout(() => {
25
+ startScanAnimation(scanLineRef, scannerRef)
26
+ }, 500)
27
+ return
28
+ }
29
+
30
+ animationTimer = setInterval(() => {
31
+ if (direction === 'down') {
32
+ position += speed
33
+ if (position >= maxPosition - 2)
34
+ direction = 'up'
35
+ }
36
+ else {
37
+ position -= speed
38
+ if (position <= 0)
39
+ direction = 'down'
40
+ }
41
+ if (scanLineRef.value)
42
+ scanLineRef.value.style.top = `${position}px`
43
+ }, 20)
44
+
45
+ return animationTimer
46
+ }
47
+
48
+ export function stopScanAnimation() {
49
+ if (animationTimer) {
50
+ clearInterval(animationTimer)
51
+ animationTimer = null
52
+ }
53
+ }