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,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
+ }