Browse Source

Merge remote-tracking branch 'origin/master'

luoyb 1 month ago
parent
commit
edd68d3495
2 changed files with 151 additions and 19 deletions
  1. 14 1
      src/api/payment/account/index.ts
  2. 137 18
      src/views/payment/account/facePhoto.vue

+ 14 - 1
src/api/payment/account/index.ts

@@ -169,6 +169,18 @@ export const closeAccount = (userId: string | number | Array<string | number>) =
169
     method: 'put'
169
     method: 'put'
170
   });
170
   });
171
 };
171
 };
172
+
173
+export const photoBatchUpload = (data) => {
174
+  return request({
175
+    url: '/backstage/payment/ptUserAccount/photoBatchUpload',
176
+    method: 'post',
177
+    data: data,
178
+    headers: {
179
+      'Content-Type': 'multipart/form-data'
180
+    }
181
+  });
182
+};
183
+
172
 export default {
184
 export default {
173
   listPtUserAccount,
185
   listPtUserAccount,
174
   listPtUserAccount4Select,
186
   listPtUserAccount4Select,
@@ -184,5 +196,6 @@ export default {
184
   resetCardType,
196
   resetCardType,
185
   resetConsumePwd,
197
   resetConsumePwd,
186
   openAccount,
198
   openAccount,
187
-  closeAccount
199
+  closeAccount,
200
+  photoBatchUpload
188
 };
201
 };

+ 137 - 18
src/views/payment/account/facePhoto.vue

@@ -57,9 +57,11 @@
57
                 :before-upload="beforeAvatarUpload"
57
                 :before-upload="beforeAvatarUpload"
58
                 :on-success="handleAvatarSuccess"
58
                 :on-success="handleAvatarSuccess"
59
                 :headers="headers"
59
                 :headers="headers"
60
+                accept=".jpg,.jpeg,.png"
61
+                :limit="1"
60
               >
62
               >
61
-                <el-image v-if="user.photo" :src="baseUrl + '/backstage/upload/' + user.photo" />
62
-                <el-icon v-else><Plus /></el-icon>
63
+                <el-image v-if="user.photo" :src="baseUrl + '/backstage/upload/' + user.photo" fit="fill" class="imageClass" />
64
+                <el-icon v-else class="avatar-uploader-icon-2"><Plus /></el-icon>
63
               </el-upload>
65
               </el-upload>
64
             </div>
66
             </div>
65
           </div>
67
           </div>
@@ -69,21 +71,29 @@
69
     </el-row>
71
     </el-row>
70
 
72
 
71
     <!--批量上传照片弹窗-->
73
     <!--批量上传照片弹窗-->
72
-    <el-dialog v-model="dialogVisible" title="批量上传人员照片" width="500">
74
+    <el-dialog v-model="dialogVisible" title="批量上传人员照片" width="30%" @close="handleClickClose">
73
       <el-upload
75
       <el-upload
76
+        ref="upload"
74
         :headers="headers"
77
         :headers="headers"
75
-        :action="`${baseUrl}/backstage/payment/ptUserAccount/photoBatchUpload`"
76
         :show-file-list="true"
78
         :show-file-list="true"
77
-        :before-upload="beforeAvatarUpload"
78
-        :on-success="handleAvatarSuccess"
79
+        :auto-upload="false"
80
+        accept=".jpg,.png,.jpeg"
79
         multiple
81
         multiple
80
         :limit="20"
82
         :limit="20"
83
+        :on-change="onChange"
84
+        :before-remove="beforeRemove"
85
+        :file-list="fileList"
86
+        action="#"
87
+        class="flex w-full h-full items-center justify-center overflow-auto"
81
       >
88
       >
82
-        选择照片
89
+        <el-icon class="avatar-uploader-icon">
90
+          <Plus />
91
+        </el-icon>
83
       </el-upload>
92
       </el-upload>
84
-      <template #footer>
85
-        <span style="color: crimson">*照片名称必须是身份证号</span>
86
-      </template>
93
+      <div class="flex justify-between mt-5">
94
+        <div class="mt-3 mb-3 font-20" style="color: crimson">*照片名称必须是身份证号</div>
95
+        <el-button type="primary" @click="uploadBatch">确定</el-button>
96
+      </div>
87
     </el-dialog>
97
     </el-dialog>
88
   </div>
98
   </div>
89
 </template>
99
 </template>
@@ -107,10 +117,13 @@ const total = ref(0);
107
 const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
117
 const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
108
 const deptName = ref('');
118
 const deptName = ref('');
109
 const deptOptions = ref<DeptVO[]>([]);
119
 const deptOptions = ref<DeptVO[]>([]);
120
+const fileList = ref<UploadFile[]>([]);
110
 
121
 
111
 const deptTreeRef = ref<ElTreeInstance>();
122
 const deptTreeRef = ref<ElTreeInstance>();
112
 const queryFormRef = ref<ElFormInstance>();
123
 const queryFormRef = ref<ElFormInstance>();
113
 
124
 
125
+const upload = ref();
126
+
114
 const expandKeys = ref([]);
127
 const expandKeys = ref([]);
115
 const dialogVisible = ref(false);
128
 const dialogVisible = ref(false);
116
 const initFormData: PtUserAccountForm = {
129
 const initFormData: PtUserAccountForm = {
@@ -205,7 +218,7 @@ onMounted(async () => {
205
   expandKeys.value = [first.id as number];
218
   expandKeys.value = [first.id as number];
206
 });
219
 });
207
 
220
 
208
-import type { UploadProps } from 'element-plus';
221
+import type { UploadFiles, UploadProps } from 'element-plus';
209
 import { globalHeaders } from '@/utils/request';
222
 import { globalHeaders } from '@/utils/request';
210
 
223
 
211
 const baseUrl = import.meta.env.VITE_APP_BASE_API;
224
 const baseUrl = import.meta.env.VITE_APP_BASE_API;
@@ -222,14 +235,87 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
222
   return true;
235
   return true;
223
 };
236
 };
224
 
237
 
238
+const ACCEPTED_EXTENSIONS = ['png', 'jpg', 'jpeg'];
239
+
240
+/**
241
+ * 请求前判断文件是否符合要求
242
+ * 如果符合则添加到上传队列
243
+ */
244
+function beforeUpload(file) {
245
+  console.log('beforeUpload', file);
246
+  const extension = file.name.split('.').pop().toLowerCase();
247
+  if (!ACCEPTED_EXTENSIONS.includes(extension)) {
248
+    ElMessage({
249
+      type: 'error',
250
+      message: '仅支持 png, jpg 和 jpeg 格式的文件'
251
+    });
252
+    return false;
253
+  }
254
+  if (file.size / 1024 / 1024 > 2) {
255
+    ElMessage.error('上传图片大小不能超过 2MB!');
256
+    return false;
257
+  }
258
+  return true;
259
+}
260
+
261
+/**
262
+ * 文件选择改变时触发
263
+ */
264
+function onChange(file, fileListVal) {
265
+  fileList.value = fileListVal;
266
+}
267
+
268
+function beforeRemove(file: UploadFile, fileListVal: UploadFiles) {
269
+  fileList.value = fileListVal;
270
+  return true;
271
+}
272
+
273
+// 清空附件列表
274
+const clearAttachments = () => {
275
+  if (upload.value) {
276
+    upload.value.clearFiles(); // 调用实例方法 `clearFiles` 清空附件列表
277
+    console.log('已清空附件列表');
278
+  }
279
+};
280
+
281
+/**点击close触发 */
282
+const handleClickClose = () => {
283
+  fileList.value = [];
284
+  clearAttachments();
285
+  dialogVisible.value = false;
286
+};
287
+const uploadBatch = async () => {
288
+  if (!fileList.value.length) {
289
+    ElMessage.error('请先选择文件');
290
+    return;
291
+  }
292
+  for (let i = 0; i < fileList.value.length; i++) {
293
+    console.log('fileList.value[i]', fileList.value[i]);
294
+    let rs = beforeUpload(fileList.value[i]);
295
+    if (!rs) {
296
+      return;
297
+    }
298
+  }
299
+  const formData = new FormData();
300
+  console.log('fileList', fileList.value);
301
+  fileList.value.forEach((file) => {
302
+    formData.append('file', file.raw);
303
+  });
304
+  const res = await api.photoBatchUpload(formData);
305
+  ElMessage.success(res.msg);
306
+  dialogVisible.value = false;
307
+  getList();
308
+};
309
+
225
 const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
310
 const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
311
+  console.log('uploadFile', uploadFile);
226
   getList();
312
   getList();
227
 };
313
 };
228
 </script>
314
 </script>
229
 
315
 
230
 <style lang="scss" scoped>
316
 <style lang="scss" scoped>
231
 .list-image .block {
317
 .list-image .block {
232
-  padding: 30px 0;
318
+  padding: 15px 0;
233
   text-align: center;
319
   text-align: center;
234
   border-right: solid 1px var(--el-border-color);
320
   border-right: solid 1px var(--el-border-color);
235
   display: inline-block;
321
   display: inline-block;
@@ -244,28 +330,61 @@ const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) =>
244
   display: block;
330
   display: block;
245
   color: var(--el-text-color-secondary);
331
   color: var(--el-text-color-secondary);
246
   font-size: 14px;
332
   font-size: 14px;
247
-  margin-bottom: 20px;
333
+  margin-bottom: 15px;
248
 }
334
 }
249
 
335
 
250
 .avatar-uploader {
336
 .avatar-uploader {
251
-  width: 60%;
252
-  height: 110px;
337
+  width: 160px;
338
+  height: 150px;
253
   margin-left: auto;
339
   margin-left: auto;
254
   margin-right: auto;
340
   margin-right: auto;
255
   display: flex;
341
   display: flex;
256
   justify-content: center;
342
   justify-content: center;
257
   align-items: center;
343
   align-items: center;
344
+  border: 1px dashed var(--el-border-color);
258
 }
345
 }
259
 
346
 
260
-.avatar-uploader {
261
-  border: 1px dashed var(--el-border-color);
347
+.avatar-uploader:hover {
348
+  border: 1px dashed blue;
349
+  height: 150px;
350
+  width: 160px;
262
   border-radius: 6px;
351
   border-radius: 6px;
263
   cursor: pointer;
352
   cursor: pointer;
264
   position: relative;
353
   position: relative;
265
-  overflow: hidden;
266
   transition: var(--el-transition-duration-fast);
354
   transition: var(--el-transition-duration-fast);
267
 }
355
 }
268
 
356
 
357
+.el-icon.avatar-uploader-icon {
358
+  border: 1px dashed #8c939d;
359
+  font-size: 28px;
360
+  color: #8c939d;
361
+  width: 110px;
362
+  height: 110px;
363
+  text-align: center;
364
+  transition: var(--el-transition-duration-fast);
365
+}
366
+
367
+.el-icon.avatar-uploader-icon-2 {
368
+  padding: 2px;
369
+  font-size: 28px;
370
+  color: #8c939d;
371
+  width: 160px;
372
+  height: 150px;
373
+  text-align: center;
374
+}
375
+.imageClass {
376
+  padding: 2px;
377
+  font-size: 28px;
378
+  color: #8c939d;
379
+  width: 160px;
380
+  height: 150px;
381
+  text-align: center;
382
+}
383
+
384
+.el-icon.avatar-uploader-icon:hover {
385
+  border-color: blue;
386
+}
387
+
269
 .el-tree > :nth-child(n + 1) {
388
 .el-tree > :nth-child(n + 1) {
270
   display: inline-block !important;
389
   display: inline-block !important;
271
   min-width: 100% !important;
390
   min-width: 100% !important;