leadal-auth 0.0.1

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 (91) hide show
  1. package/README.md +83 -0
  2. package/babel.config.js +5 -0
  3. package/jsconfig.json +19 -0
  4. package/ld-auth/demo.html +1 -0
  5. package/ld-auth/ld-auth.common.js +44730 -0
  6. package/ld-auth/ld-auth.css +1 -0
  7. package/ld-auth/ld-auth.umd.js +44730 -0
  8. package/ld-auth/ld-auth.umd.min.js +55 -0
  9. package/package.json +58 -0
  10. package/public/favicon.ico +0 -0
  11. package/public/index.html +17 -0
  12. package/public/models/age_gender_model-shard1 +0 -0
  13. package/public/models/age_gender_model-weights_manifest.json +1 -0
  14. package/public/models/face_expression_model-shard1 +0 -0
  15. package/public/models/face_expression_model-weights_manifest.json +1 -0
  16. package/public/models/face_landmark_68_model-shard1 +0 -0
  17. package/public/models/face_landmark_68_model-weights_manifest.json +1 -0
  18. package/public/models/face_landmark_68_tiny_model-shard1 +0 -0
  19. package/public/models/face_landmark_68_tiny_model-weights_manifest.json +1 -0
  20. package/public/models/face_recognition_model-shard1 +0 -0
  21. package/public/models/face_recognition_model-shard2 +6 -0
  22. package/public/models/face_recognition_model-weights_manifest.json +1 -0
  23. package/public/models/mtcnn_model-shard1 +0 -0
  24. package/public/models/mtcnn_model-weights_manifest.json +1 -0
  25. package/public/models/ssd_mobilenetv1_model-shard1 +0 -0
  26. package/public/models/ssd_mobilenetv1_model-shard2 +145 -0
  27. package/public/models/ssd_mobilenetv1_model-weights_manifest.json +1 -0
  28. package/public/models/tiny_face_detector_model-shard1 +0 -0
  29. package/public/models/tiny_face_detector_model-weights_manifest.json +1 -0
  30. package/src/App.vue +19 -0
  31. package/src/api/card.js +58 -0
  32. package/src/api/face.js +37 -0
  33. package/src/api/finger.js +64 -0
  34. package/src/api/index.js +100 -0
  35. package/src/assets/BIN.png +0 -0
  36. package/src/assets/CLOSE.svg +11 -0
  37. package/src/assets/blue-left.png +0 -0
  38. package/src/assets/blue-right.png +0 -0
  39. package/src/assets/finger-ready.png +0 -0
  40. package/src/assets/finger-select.png +0 -0
  41. package/src/assets/finger-status-1-last.png +0 -0
  42. package/src/assets/finger-status-1.gif +0 -0
  43. package/src/assets/finger-status-2-last.png +0 -0
  44. package/src/assets/finger-status-2.gif +0 -0
  45. package/src/assets/finger-status-3-last.png +0 -0
  46. package/src/assets/finger-status-3.gif +0 -0
  47. package/src/assets/finger-status-compeleted.png +0 -0
  48. package/src/assets/finger-status-start.png +0 -0
  49. package/src/assets/icon-camera.png +0 -0
  50. package/src/assets/icon-picture.png +0 -0
  51. package/src/assets/icon-success.png +0 -0
  52. package/src/assets/img-camera.png +0 -0
  53. package/src/assets/img-card.png +0 -0
  54. package/src/assets/img-loading.png +0 -0
  55. package/src/assets/left.png +0 -0
  56. package/src/assets/logo.png +0 -0
  57. package/src/assets/right.png +0 -0
  58. package/src/assets/ukey1.png +0 -0
  59. package/src/assets/ukey2.png +0 -0
  60. package/src/assets//346/214/207/347/272/271/350/257/206/345/210/2531.png +0 -0
  61. package/src/assets//346/214/207/347/272/271/350/257/206/345/210/2532.png +0 -0
  62. package/src/components/auth-com.vue +100 -0
  63. package/src/components/card-register/components/CardTable.vue +94 -0
  64. package/src/components/card-register/components/RegisterDialog.vue +137 -0
  65. package/src/components/card-register/index.vue +110 -0
  66. package/src/components/edit-user-dialog.vue +141 -0
  67. package/src/components/empty.vue +13 -0
  68. package/src/components/face-register/components/ChooseCameraOrPicture.vue +59 -0
  69. package/src/components/face-register/components/FaceDetected.vue +543 -0
  70. package/src/components/face-register/components/FaceInfo.vue +171 -0
  71. package/src/components/face-register/components/FacePicture.vue +85 -0
  72. package/src/components/face-register/components/UploadPicture.vue +336 -0
  73. package/src/components/face-register/index.vue +242 -0
  74. package/src/components/finger-register/index.vue +685 -0
  75. package/src/components/organ-tree.vue +211 -0
  76. package/src/components/tree-select.vue +131 -0
  77. package/src/components/user-drawer.vue +147 -0
  78. package/src/components/user-info.vue +272 -0
  79. package/src/components/user-table.vue +405 -0
  80. package/src/main.js +26 -0
  81. package/src/package/auth-manage/index.vue +461 -0
  82. package/src/package/index.js +22 -0
  83. package/src/store/index.js +39 -0
  84. package/src/styles/common.scss +183 -0
  85. package/src/styles/index.scss +38 -0
  86. package/src/utils/dict.js +47 -0
  87. package/src/utils/event-bus.js +6 -0
  88. package/src/utils/request-auth.js +64 -0
  89. package/src/utils/request.js +64 -0
  90. package/src/utils/websocket.js +282 -0
  91. package/vue.config.js +43 -0
@@ -0,0 +1,685 @@
1
+ <template>
2
+ <div class="flex-center align-center h100 w100">
3
+ <!-- 指纹注册弹窗 -->
4
+ <div class="finger-dialog">
5
+ <div class="finger-register-content">
6
+ <div
7
+ style="
8
+ color: #333;
9
+ font-size: 24px;
10
+ margin-bottom: 12px;
11
+ padding-top: 48px;
12
+ text-align: center;
13
+ margin-top: 24px;
14
+ "
15
+ >
16
+ {{ stepTips }}
17
+ </div>
18
+ <div
19
+ style="
20
+ display: flex;
21
+ justify-content: center;
22
+ align-items: center;
23
+ padding-top: 50px;
24
+ "
25
+ >
26
+ <!-- 左手区域 -->
27
+ <div class="hand-area left-hand">
28
+ <div class="hand-image-wrapper">
29
+ <img :src="leftHandleImg" class="hand-image" />
30
+ <!-- 左手指尖按钮 -->
31
+ <div class="finger-buttons-overlay">
32
+ <div
33
+ v-for="(finger, index) in leftFingers"
34
+ :key="'left-' + index"
35
+ :class="[
36
+ 'finger-circle',
37
+ {
38
+ active:
39
+ selectedFinger && selectedFinger.value === finger.value,
40
+ ready: !!finger.fingerInfo,
41
+ },
42
+ ]"
43
+ :style="{ top: finger.top + 'px', left: finger.left + 'px' }"
44
+ @click="handleSelectFinger(finger)"
45
+ ></div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+
50
+ <!-- 右手区域 -->
51
+ <div class="hand-area right-hand">
52
+ <div class="hand-image-wrapper">
53
+ <img :src="rightHandleImg" class="hand-image" />
54
+ <!-- 右手指尖按钮 -->
55
+ <div class="finger-buttons-overlay">
56
+ <div
57
+ v-for="(finger, index) in rightFingers"
58
+ :key="'right-' + index"
59
+ :class="[
60
+ 'finger-circle',
61
+ {
62
+ active:
63
+ selectedFinger && selectedFinger.value === finger.value,
64
+ ready: !!finger.fingerInfo,
65
+ },
66
+ ]"
67
+ :style="{ top: finger.top + 'px', left: finger.left + 'px' }"
68
+ @click="handleSelectFinger(finger)"
69
+ ></div>
70
+ </div>
71
+ </div>
72
+ </div>
73
+
74
+ <!-- 指纹状态区域 -->
75
+ <div class="fingerprint-status">
76
+ <div class="fingerprint-image-container">
77
+ <div class="delete-button">
78
+ <el-button
79
+ type="text"
80
+ size="large"
81
+ @click="handleDeleteFinger"
82
+ v-if="selectedFinger && selectedFinger.fingerInfo"
83
+ >
84
+ <i class="el-icon-delete" style="font-size: 20px; color: #999;"></i>
85
+ </el-button>
86
+ </div>
87
+ <img :src="currentFingerprintImage" class="fingerprint-image" />
88
+ <p class="status-text">
89
+ {{ fingerStatusText }}
90
+ </p>
91
+ <!-- fingerInfo存在 显示删除按钮 固定在右上角 -->
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- <div class="flex-center align-center w100">
98
+ <el-button
99
+ type="primary"
100
+ style="
101
+ width: 214px;
102
+ height: 40px;
103
+ border-radius: 20px;
104
+ font-size: 16px;
105
+ "
106
+ :loading="loading"
107
+ :disabled="!selectedFinger || fingerRegisterStep !== 5 || !fingerTemp"
108
+ @click="handleSaveFingerprint"
109
+ >保存</el-button
110
+ >
111
+ </div> -->
112
+ </div>
113
+ </div>
114
+ </template>
115
+
116
+ <script>
117
+ import {
118
+ uploadFingerApi,
119
+ getMaxFingerSeqApi,
120
+ findByUserIdApi,
121
+ deleteFingerApi,
122
+ } from "@/api/finger";
123
+
124
+ export default {
125
+ name: "FingerRegisterView",
126
+ props: {
127
+ row: {
128
+ type: Object,
129
+ default: () => {},
130
+ },
131
+ },
132
+ data() {
133
+ return {
134
+ // -1:指纹录入失败,请重试
135
+ // 0:请选择需要采集的手指
136
+ // 1:请将手指放在设备上
137
+ // 2:再次将手指放在设备上
138
+ // 3:最后一次将手指放在设备上
139
+ // 4:指纹采集完成
140
+ // 5:正在录入
141
+ // 6:指纹录入完成
142
+ fingerRegisterStep: 0,
143
+ currentFingerprintImage: require("@/assets/finger-status-start.png"),
144
+ gifTimeoutId: null,
145
+ selectedFinger: null,
146
+ fingerTemp: null, // 指纹模板(base64 字符串)
147
+ fingerId: null, // 后端接口指纹id
148
+ fid: null, // 指纹仪唯一id
149
+ loading: false,
150
+ leftFingers: [
151
+ {
152
+ label: "大拇指",
153
+ value: "left-thumb",
154
+ top: 122,
155
+ left: 6,
156
+ index: 0,
157
+ fingerInfo: null,
158
+ },
159
+ {
160
+ label: "食指",
161
+ value: "left-index",
162
+ top: 20,
163
+ left: 60,
164
+ index: 1,
165
+ fingerInfo: null,
166
+ },
167
+ {
168
+ label: "中指",
169
+ value: "left-middle",
170
+ top: 3,
171
+ left: 98,
172
+ index: 2,
173
+ fingerInfo: null,
174
+ },
175
+ {
176
+ label: "无名指",
177
+ value: "left-ring",
178
+ top: 12,
179
+ left: 136,
180
+ index: 3,
181
+ fingerInfo: null,
182
+ },
183
+ {
184
+ label: "小拇指",
185
+ value: "left-little",
186
+ top: 35,
187
+ left: 176,
188
+ index: 4,
189
+ fingerInfo: null,
190
+ },
191
+ ],
192
+ rightFingers: [
193
+ {
194
+ label: "大拇指",
195
+ value: "right-thumb",
196
+ top: 118,
197
+ left: 178,
198
+ index: 5,
199
+ fingerInfo: null,
200
+ },
201
+ {
202
+ label: "食指",
203
+ value: "right-index",
204
+ top: 16,
205
+ left: 121,
206
+ index: 6,
207
+ fingerInfo: null,
208
+ },
209
+ {
210
+ label: "中指",
211
+ value: "right-middle",
212
+ top: 0,
213
+ left: 83,
214
+ index: 7,
215
+ fingerInfo: null,
216
+ },
217
+ {
218
+ label: "无名指",
219
+ value: "right-ring",
220
+ top: 11,
221
+ left: 43,
222
+ index: 8,
223
+ fingerInfo: null,
224
+ },
225
+ {
226
+ label: "小拇指",
227
+ value: "right-little",
228
+ top: 42,
229
+ left: 5,
230
+ index: 9,
231
+ fingerInfo: null,
232
+ },
233
+ ],
234
+ };
235
+ },
236
+ computed: {
237
+ // ...mapGetters(["userId", "devSn", "devType", "tenantId"]),
238
+ userId() {
239
+ return this.row.userId;
240
+ },
241
+ devSn() {
242
+ return this.$store.getters.getFingerprintDeviceSN;
243
+ },
244
+ devType() {
245
+ return 1;
246
+ },
247
+ tenantId() {
248
+ return null;
249
+ },
250
+ leftHandleImg() {
251
+ return this.selectedFinger && this.selectedFinger.value.includes("left")
252
+ ? require("@/assets/blue-left.png")
253
+ : require("@/assets/left.png");
254
+ },
255
+ rightHandleImg() {
256
+ return this.selectedFinger && this.selectedFinger.value.includes("right")
257
+ ? require("@/assets/blue-right.png")
258
+ : require("@/assets/right.png");
259
+ },
260
+ stepTips() {
261
+ if (this.fingerRegisterStep === -1) {
262
+ return "指纹采集异常,请重试!";
263
+ }
264
+
265
+ return this.fingerRegisterStep === 0
266
+ ? "请选择需要采集的手指"
267
+ : this.fingerRegisterStep === 1
268
+ ? "请将手指放在设备上"
269
+ : this.fingerRegisterStep === 2
270
+ ? "请再次将手指放在设备上"
271
+ : this.fingerRegisterStep === 3
272
+ ? "最后一次将手指放在设备上"
273
+ : this.fingerRegisterStep === 4
274
+ ? "正在指纹采集"
275
+ : this.fingerRegisterStep === 5
276
+ ? "指纹采集成功"
277
+ : "未知状态";
278
+ },
279
+ fingerStatusText() {
280
+ if (this.fingerRegisterStep === -1) {
281
+ return "指纹采集异常,请重试!";
282
+ }
283
+ return this.fingerRegisterStep === 0
284
+ ? "采集指纹一共需要三次按压"
285
+ : this.fingerRegisterStep === 1
286
+ ? "请将手指放在设备上"
287
+ : this.fingerRegisterStep === 2
288
+ ? "请再次将手指放在设备上"
289
+ : this.fingerRegisterStep === 3
290
+ ? "最后一次将手指放在设备上"
291
+ : this.fingerRegisterStep === 4
292
+ ? "正在处理指纹数据..."
293
+ : this.fingerRegisterStep === 5
294
+ ? "指纹采集成功"
295
+ : "准备采集指纹";
296
+ },
297
+ },
298
+ watch: {
299
+ fingerRegisterStep(newStep) {
300
+ clearTimeout(this.gifTimeoutId);
301
+ const gifDuration = 800;
302
+
303
+ if (newStep === 1 || newStep === 0 || newStep === -1) {
304
+ this.currentFingerprintImage = require("@/assets/finger-status-start.png");
305
+ } else if (newStep === 2) {
306
+ this.currentFingerprintImage = require("@/assets/finger-status-1.gif");
307
+ this.gifTimeoutId = setTimeout(() => {
308
+ this.currentFingerprintImage = require("@/assets/finger-status-1-last.png");
309
+ }, gifDuration);
310
+ } else if (newStep === 3) {
311
+ this.currentFingerprintImage = require("@/assets/finger-status-2.gif");
312
+ this.gifTimeoutId = setTimeout(() => {
313
+ this.currentFingerprintImage = require("@/assets/finger-status-2-last.png");
314
+ }, gifDuration);
315
+ } else if (newStep === 4) {
316
+ this.currentFingerprintImage = require("@/assets/finger-status-3.gif");
317
+ this.gifTimeoutId = setTimeout(() => {
318
+ this.currentFingerprintImage = require("@/assets/finger-status-3-last.png");
319
+ }, gifDuration);
320
+ } else if (newStep === 5) {
321
+ this.currentFingerprintImage = require("@/assets/finger-status-compeleted.png");
322
+ }
323
+ },
324
+ },
325
+ mounted() {
326
+ this.loadCurrentUserFingerInfo();
327
+ this.$authEventBus.$on(
328
+ "startCollectionMessage",
329
+ this.startCollectionMessage
330
+ );
331
+ },
332
+ beforeDestroy() {
333
+ clearTimeout(this.gifTimeoutId);
334
+ this.$authEventBus.$off(
335
+ "startCollectionMessage",
336
+ this.startCollectionMessage
337
+ );
338
+ },
339
+ methods: {
340
+ startCollectionMessage(data) {
341
+ console.log("startCollectionMessage:", data);
342
+
343
+ if (data.status === 200 || data.result === 0) {
344
+ // 采集成功
345
+ const { count, temp, image } = data.data;
346
+
347
+ console.log(`指纹采集进度: ${count}/4`);
348
+
349
+ // 根据count更新采集步骤
350
+ if (count === 1) {
351
+ this.fingerRegisterStep = 2; // 第一次采集完成,提示第二次
352
+ } else if (count === 2) {
353
+ this.fingerRegisterStep = 3; // 第二次采集完成,提示第三次
354
+ } else if (count === 3) {
355
+ this.fingerRegisterStep = 4; // 第三次采集完成,正在处理
356
+ } else if (count === 4) {
357
+ // 采集完成,获取到指纹模板
358
+ this.fingerRegisterStep = 5; // 指纹采集成功
359
+ this.fingerTemp = temp; // 保存指纹模板
360
+ console.log("✅ 指纹采集完成,获取到指纹模板");
361
+
362
+ // 自动保存指纹
363
+ this.$nextTick(() => {
364
+ this.addFingerprint();
365
+ });
366
+ }
367
+
368
+ // 如果有指纹图像,可以显示(可选)
369
+ if (image) {
370
+ console.log("收到指纹图像数据");
371
+ }
372
+
373
+ } else {
374
+ // 采集失败
375
+ console.error("指纹采集失败:", data.msg || "未知错误");
376
+ this.fingerRegisterStep = -1; // 采集异常
377
+ this.$message?.error?.(data.msg || "指纹采集失败,请重试");
378
+ }
379
+ },
380
+ handleClose() {
381
+ // 如果在采集过程中,建议添加确认关闭的提示
382
+ },
383
+ async handleSelectFinger(finger) {
384
+ if (this.fingerRegisterStep > 0 && this.fingerRegisterStep < 5) {
385
+ this.$message({
386
+ message: "指纹采集尚未完成,请先完成当前采集",
387
+ type: "warning",
388
+ });
389
+ return;
390
+ }
391
+
392
+ if (!finger.fingerInfo) {
393
+ try {
394
+ const res = await getMaxFingerSeqApi({
395
+ devSn: this.devSn,
396
+ devType: this.devType,
397
+ fingerNo: finger.index,
398
+ tenantId: this.tenantId,
399
+ userId: this.userId,
400
+ });
401
+
402
+ this.fingerId = res.data.fingerId;
403
+ this.fid = res.data.fingerSeq;
404
+ this.selectedFinger = finger;
405
+ this.fingerRegisterStep = 1;
406
+ this.fingerTemp = null; // 重置指纹模板
407
+
408
+ console.log(`开始采集 ${finger.label} 指纹,fingerId: ${this.fingerId}, fid: ${this.fid}`);
409
+ this.startCollection();
410
+ } catch (error) {
411
+ console.error("获取指纹信息失败:", error);
412
+ }
413
+ } else {
414
+ this.selectedFinger = finger;
415
+ }
416
+ },
417
+ handleSaveFingerprint() {
418
+ this.addFingerprint();
419
+ },
420
+ handleDeleteFinger() {
421
+ this.$confirm("确定删除指纹吗?")
422
+ .then(() => {
423
+ deleteFingerApi({ fingerId: this.selectedFinger.fingerInfo.id })
424
+ .then(() => {
425
+ this.selectedFinger = null;
426
+ this.fingerRegisterStep = 0;
427
+ this.$message.success("删除成功");
428
+ this.loadCurrentUserFingerInfo();
429
+ })
430
+ })
431
+ .catch(() => {});
432
+ },
433
+ startCollection() {
434
+ // 开始采集指纹
435
+ this.$authEventBus.$emit("startCollection");
436
+ },
437
+ loadCurrentUserFingerInfo() {
438
+ findByUserIdApi({
439
+ devType: this.devType,
440
+ tenantId: this.tenantId,
441
+ userId: this.userId,
442
+ }).then((res) => {
443
+ const data = res.data;
444
+ const newLeftArr = this.leftFingers.map((r) => {
445
+ const item = data.find((a) => a.fingerNo === r.index);
446
+ return { ...r, fingerInfo: item };
447
+ });
448
+
449
+ const newRightArr = this.rightFingers.map((r) => {
450
+ const item = data.find((a) => a.fingerNo === r.index);
451
+ return { ...r, fingerInfo: item };
452
+ });
453
+ this.leftFingers = newLeftArr;
454
+ this.rightFingers = newRightArr;
455
+ });
456
+ },
457
+ addFingerprint() {
458
+ if (!this.fingerId) {
459
+ this.$message.error("未获取到指纹ID");
460
+ return;
461
+ }
462
+
463
+ if (!this.fingerTemp) {
464
+ this.$message.error("未获取到指纹模板");
465
+ return;
466
+ }
467
+
468
+ if (!this.selectedFinger) {
469
+ this.$message.error("请先选择手指");
470
+ return;
471
+ }
472
+ if (!this.fid) {
473
+ this.$message.error("未获取到指纹序列号");
474
+ return;
475
+ }
476
+
477
+ this.loading = true;
478
+ console.log("开始保存指纹到服务器...");
479
+
480
+ uploadFingerApi({
481
+ data: this.fingerTemp,
482
+ fingerId: this.fingerId,
483
+ })
484
+ .then(() => {
485
+ console.log("✅ 指纹保存成功");
486
+ this.loadCurrentUserFingerInfo();
487
+
488
+ // 重置状态
489
+ this.selectedFinger = null;
490
+ this.fingerRegisterStep = 0;
491
+ this.fingerTemp = null;
492
+ this.fingerId = null;
493
+ this.fid = null;
494
+
495
+ this.$message.success("指纹录入成功!");
496
+ })
497
+ .catch((error) => {
498
+ console.error("❌ 指纹保存失败:", error);
499
+ this.fingerRegisterStep = -1;
500
+ })
501
+ .finally(() => {
502
+ this.loading = false;
503
+ });
504
+ },
505
+ },
506
+ };
507
+ </script>
508
+
509
+ <style scoped>
510
+ /* 弹窗样式 */
511
+ .finger-dialog {
512
+ width: 100%;
513
+ height: 100%;
514
+ border-radius: 12px;
515
+ overflow: hidden;
516
+ background: #f8f8fb;
517
+ }
518
+
519
+ .dialog-header {
520
+ display: flex;
521
+ justify-content: space-between;
522
+ align-items: center;
523
+ padding: 16px 20px;
524
+ border-bottom: 1px solid #eee;
525
+ }
526
+
527
+ .title {
528
+ font-size: 18px;
529
+ font-weight: 500;
530
+ color: #333;
531
+ }
532
+
533
+ .close-icon {
534
+ width: 16px;
535
+ height: 16px;
536
+ cursor: pointer;
537
+ }
538
+
539
+ /* 内容布局 */
540
+ .finger-register-content {
541
+ height: calc(100% - 182px);
542
+ margin-left: 24px;
543
+ margin-right: 24px;
544
+ border-radius: 12px;
545
+ }
546
+
547
+ /* 手部区域样式 */
548
+ .hand-area {
549
+ width: 210px;
550
+ display: flex;
551
+ flex-direction: column;
552
+ margin-left: 20px;
553
+ }
554
+
555
+ .hand-image-wrapper {
556
+ display: flex;
557
+ justify-content: center;
558
+ align-items: center;
559
+ position: relative;
560
+ margin-bottom: 20px;
561
+ }
562
+
563
+ .hand-image {
564
+ width: 200px;
565
+ height: 260px;
566
+ object-fit: contain;
567
+ }
568
+
569
+ /* 指尖按钮样式 */
570
+ .finger-buttons-overlay {
571
+ position: absolute;
572
+ top: 0;
573
+ left: 0;
574
+ width: 100%;
575
+ height: 100%;
576
+ }
577
+
578
+ .finger-circle {
579
+ position: absolute;
580
+ width: 26px;
581
+ height: 26px;
582
+ border-radius: 50%;
583
+ border: 3px solid #c0c0c0;
584
+ background-color: #f8f8fb;
585
+ cursor: pointer;
586
+ transition: all 0.3s;
587
+ }
588
+
589
+ .finger-circle:hover {
590
+ transform: scale(1.1);
591
+ box-shadow: 0 0 5px rgba(59, 128, 239, 0.5);
592
+ }
593
+
594
+ .finger-circle.active {
595
+ border: 3px solid #3b80ef;
596
+ background: #3b80ef3f;
597
+ }
598
+
599
+ .finger-circle.ready {
600
+ width: 25px;
601
+ height: 25px;
602
+ background: url(@/assets/finger-ready.png) no-repeat;
603
+ background-size: 100% 100%;
604
+ }
605
+
606
+ /* 指纹状态区域 */
607
+ .fingerprint-status {
608
+ width: 300px;
609
+ height: 300px;
610
+ margin-left: 32px;
611
+ display: flex;
612
+ flex-direction: column;
613
+ border: 1px dashed #d6d9e1;
614
+ background: white;
615
+ border-radius: 12px;
616
+ }
617
+
618
+ .status-header {
619
+ padding: 12px;
620
+ background-color: #f5f5f5;
621
+ border-bottom: 1px solid #eee;
622
+ }
623
+
624
+ .status-title {
625
+ font-size: 14px;
626
+ color: #666;
627
+ }
628
+
629
+ .fingerprint-image-container {
630
+ flex: 1;
631
+ display: flex;
632
+ flex-direction: column;
633
+ justify-content: center;
634
+ align-items: center;
635
+ padding: 0px 20px 20px 20px;
636
+ }
637
+
638
+ .fingerprint-image {
639
+ width: 120px;
640
+ height: 120px;
641
+ margin-bottom: 20px;
642
+ }
643
+
644
+ .status-text {
645
+ font-size: 14px;
646
+ color: #999;
647
+ text-align: center;
648
+ }
649
+
650
+ .collect-progress {
651
+ margin: 0 20px 20px;
652
+ }
653
+
654
+ .progress-text {
655
+ font-size: 14px;
656
+ color: #666;
657
+ margin-bottom: 5px;
658
+ }
659
+
660
+ .progress-bar {
661
+ height: 8px;
662
+ background-color: #eee;
663
+ border-radius: 4px;
664
+ overflow: hidden;
665
+ }
666
+
667
+ .progress-inner {
668
+ height: 100%;
669
+ background-color: #3b80ef;
670
+ transition: width 0.3s;
671
+ }
672
+
673
+ /* 底部按钮 */
674
+ .dialog-footer .el-button {
675
+ margin: 20px 10px;
676
+ }
677
+
678
+ .delete-button {
679
+ width: 100%;
680
+ height: 40px;
681
+ display: flex;
682
+ justify-content: flex-end;
683
+ align-items: center;
684
+ }
685
+ </style>