Bladeren bron

1. 总后台增加食品许可证上传多张需求,同时优化页面显示

Guos 1 maand geleden
bovenliggende
commit
2a331e6ed3
2 gewijzigde bestanden met toevoegingen van 229 en 24 verwijderingen
  1. 101 4
      src/views/hisStore/store/audit.vue
  2. 128 20
      src/views/hisStore/store/index.vue

+ 101 - 4
src/views/hisStore/store/audit.vue

@@ -370,11 +370,23 @@
             </el-row>
 
             <el-row>
-              <el-col :span="12">
+              <el-col :span="24">
                 <el-form-item label="食品经营许可证/备案凭证上传">
-                  <el-image v-if="dialogForm.foodLicense && dialogForm.foodLicense.trim()" style="width: 200px" :src="dialogForm.foodLicense" :preview-src-list="[dialogForm.foodLicense]"></el-image>
+                  <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
+                  <div v-if="dialogForm.foodLicense && dialogForm.foodLicense.length > 0" class="food-license-container">
+                    <div v-for="(url, index) in dialogForm.foodLicense" :key="index" class="food-license-item">
+                      <div class="avatar-wrapper">
+                        <img :src="url" class="avatar small-avatar" />
+                        <div class="button-group">
+                          <div class="preview-btn" @click.stop="previewImage(url)">
+                            <i class="el-icon-zoom-in"></i>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
                   <!-- 未上传图片时显示的默认图标 -->
-                  <div v-else class="no-image-placeholder">
+                  <div v-else class="no-image-placeholder small-placeholder">
                     <span>用户未上传</span>
                   </div>
                 </el-form-item>
@@ -654,6 +666,19 @@ export default {
       Promise.all([getStore(storeId), getStoreAuditLog(storeId)])
         .then(([storeResponse, auditResponse]) => {
           this.form = storeResponse.data;
+          // 处理食品经营许可证图片数据,支持逗号分隔的字符串
+          if (this.form.foodLicense) {
+            if (typeof this.form.foodLicense === 'string') {
+              // 如果是逗号分隔的字符串,则分割成数组
+              this.form.foodLicense = this.form.foodLicense.split(',').filter(url => url.trim() !== '');
+            } else if (!Array.isArray(this.form.foodLicense)) {
+              // 如果既不是字符串也不是数组,则初始化为空数组
+              this.form.foodLicense = [];
+            }
+          } else {
+            // 如果为空,则初始化为空数组
+            this.form.foodLicense = [];
+          }
           this.auditLogs = auditResponse.auditLog || [];
           this.reportFileList = this.urlToFileList(this.form.reportUrl);
           this.fileList = this.urlToFileList(this.form.filingUrl);
@@ -890,7 +915,12 @@ export default {
       } else {
         window.open(url, '_blank');
       }
-    }
+    },
+    // 添加图片预览方法
+    previewImage(url) {
+      this.previewImageUrl = url;
+      this.imagePreviewVisible = true;
+    },
   }
 };
 </script>
@@ -946,4 +976,71 @@ export default {
   position: relative;
   overflow: hidden;
 }
+
+/* 食品经营许可证容器 */
+.food-license-container {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  gap: 10px;
+  align-items: flex-start;
+  justify-content: flex-start;
+}
+
+/* 食品经营许可证单项 */
+.food-license-item {
+  position: relative;
+  display: inline-block;
+  text-align: center;
+}
+
+.avatar {
+  width: 200px;
+  height: 200px;
+  object-fit: cover;
+  border-radius: 4px;
+}
+
+.small-avatar {
+  width: 150px;
+  height: 150px;
+}
+
+/* 无图片占位符样式 */
+.small-placeholder {
+  width: 150px;
+  height: 150px;
+}
+
+.avatar-wrapper {
+  position: relative;
+  display: inline-block;
+}
+
+/* 并排按钮样式 */
+.button-group {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  display: flex;
+  gap: 5px;
+}
+
+.preview-btn {
+  width: 30px;
+  height: 30px;
+  border-radius: 50%;
+  background-color: rgba(0, 0, 0, 0.5);
+  color: white;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  font-size: 16px;
+  transition: background-color 0.3s;
+}
+
+.preview-btn:hover {
+  background-color: rgba(0, 0, 0, 0.7);
+}
 </style>

+ 128 - 20
src/views/hisStore/store/index.vue

@@ -587,34 +587,40 @@
             </el-col>
           </el-row>
           <el-row>
-            <el-col :span="12">
+            <el-col :span="24">
               <el-form-item label="食品经营许可证/备案凭证上传" prop="foodLicense">
                 <el-upload
                   class="avatar-uploader"
                   :action="uploadUrl"
                   :show-file-list="false"
-                  :on-success="(response, file) => handleFileSuccess(response, file, 'foodLicense')"
+                  :on-success="(response, file) => handleFoodLicenseSuccess(response, file)"
                   :before-upload="beforeAvatarUpload"
                   :disabled="isDeleting"
+                  :limit="3"
+                  :on-exceed="handleFoodLicenseExceed"
                 >
                   <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
-                  <div class="avatar-wrapper" v-if="form.foodLicense">
-                    <img :src="form.foodLicense" class="avatar" width="200px">
-                    <!-- 悬停显示的删除按钮 -->
-<!--                    <div class="delete-mask" @click.stop="handleDelete3">-->
-<!--                      <i class="el-icon-delete"></i>-->
-<!--                    </div>-->
-                    <div class="button-group">
-                      <div class="preview-btn" @click.stop="previewImage(form.foodLicense)">
-                        <i class="el-icon-zoom-in"></i>
-                      </div>
-                      <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete3">
-                        <i class="el-icon-delete"></i>
+                  <div v-if="form.foodLicense && form.foodLicense.length > 0" class="food-license-container">
+                    <div v-for="(url, index) in form.foodLicense" :key="index" class="food-license-item">
+                      <div class="avatar-wrapper">
+                        <img :src="url" class="avatar small-avatar" />
+                        <div class="button-group">
+                          <div class="preview-btn" @click.stop="previewImage(url)">
+                            <i class="el-icon-zoom-in"></i>
+                          </div>
+                          <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDeleteFoodLicense(index)">
+                            <i class="el-icon-delete"></i>
+                          </div>
+                        </div>
                       </div>
                     </div>
+                    <!-- 添加上传按钮,当图片数量少于3张时显示 -->
+                    <div v-if="form.foodLicense.length < 3 && !isViewMode" class="avatar-wrapper add-btn small-avatar">
+                      <i class="el-icon-plus avatar-uploader-icon"></i>
+                    </div>
                   </div>
                   <!-- 未上传图片时显示的默认图标 -->
-                  <div v-else class="no-image-placeholder">
+                  <div v-else class="no-image-placeholder small-placeholder">
                     <span v-if="isViewMode">用户未上传</span>
                     <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                   </div>
@@ -1109,7 +1115,8 @@ export default {
         qualityAssuranceAgreement: null,
         qualityAssuranceAgreementFileName: null, // 新增:存储文件名
         otherSpecialQualification: null,
-        otherSpecialQualificationFileName: null // 新增:存储文件名
+        otherSpecialQualificationFileName: null, // 新增:存储文件名
+        foodLicense: [], // 食品经营许可证/备案凭证上传(支持多张图片)
 
       },
       // 表单校验
@@ -1155,7 +1162,16 @@ export default {
           { required: true, message: "3类器械经营许可证有效期不能为空", trigger: "blur" }
         ],
         foodLicense: [
-          { required: true, message: "食品经营许可证不能为空", trigger: "blur" }
+          { 
+            validator: (rule, value, callback) => {
+              if (!value || (Array.isArray(value) && value.length === 0)) {
+                callback(new Error('请至少上传一张食品经营许可证图片'));
+              } else {
+                callback();
+              }
+            }, 
+            trigger: 'change' 
+          }
         ],
         foodCode: [
           { required: true, message: "食品经营许可证编号不能为空", trigger: "blur" }
@@ -1371,6 +1387,24 @@ export default {
         this.msgError(response.msg);
       }
     },
+    // 食品经营许可证上传成功处理函数
+    handleFoodLicenseSuccess(response, file) {
+      if (response.code === 200) {
+        // 初始化数组(如果尚未初始化)
+        if (!Array.isArray(this.form.foodLicense)) {
+          this.$set(this.form, 'foodLicense', []);
+        }
+        // 添加新上传的图片URL到数组中
+        this.form.foodLicense.push(response.url);
+        this.$forceUpdate();
+      } else {
+        this.msgError(response.msg);
+      }
+    },
+    // 食品经营许可证上传超出限制处理函数
+    handleFoodLicenseExceed(files, fileList) {
+      this.$message.warning(`当前最多只能上传 3 张图片`);
+    },
 
     /** 查询店铺管理列表 */
     getList() {
@@ -1438,7 +1472,7 @@ export default {
         medicalDevice3: null,         // 三类器械经营许可证文件
         medicalDevice3Expiry: null,       // 三类器械经营许可证有效期
         // 其他许可证相关字段
-        foodLicense: null,               // 食品经营许可证文件
+        foodLicense: [],               // 食品经营许可证文件(支持多张图片)
         foodLicenseExpiry: null,             // 食品经营许可证有效期
         medicalLicense: null,  // 医疗机构执业许可证文件
         medicalLicenseExpiry: null, // 医疗机构执业许可证有效期
@@ -1503,8 +1537,19 @@ export default {
     handleDelete2() {
       this.deleteImage('medicalDevice3', '3类器械经营许可证');
     },
-    handleDelete3() {
-      this.deleteImage('foodLicense', '食品经营许可证');
+    // 删除指定索引的食品经营许可证图片
+    handleDeleteFoodLicense(index) {
+      this.$confirm(`确定要删除这张食品经营许可证图片吗?`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.form.foodLicense.splice(index, 1);
+        this.$message.success('图片已删除');
+        this.$forceUpdate();
+      }).catch(() => {
+        this.$message.info('已取消删除');
+      });
     },
     handleDelete5() {
       this.deleteImage('businessLicense', '营业执照');
@@ -1616,6 +1661,20 @@ export default {
         }
         this.reportFileList = this.urlToFileList(this.form.reportUrl);
         this.fileList = this.urlToFileList(this.form.filingUrl);
+        
+        // 处理食品经营许可证图片数据,支持逗号分隔的字符串
+        if (this.form.foodLicense) {
+          if (typeof this.form.foodLicense === 'string') {
+            // 如果是逗号分隔的字符串,则分割成数组
+            this.form.foodLicense = this.form.foodLicense.split(',').filter(url => url.trim() !== '');
+          } else if (!Array.isArray(this.form.foodLicense)) {
+            // 如果既不是字符串也不是数组,则初始化为空数组
+            this.form.foodLicense = [];
+          }
+        } else {
+          // 如果为空,则初始化为空数组
+          this.form.foodLicense = [];
+        }
       });
     },
     /** 提交按钮 */
@@ -1692,6 +1751,11 @@ export default {
           formData.isEffectivePermanent1 = this.medicalLicenseExpiryValue1 ? 1 : 0;
           formData.isEffectivePermanent2 = this.medicalLicenseExpiryValue2 ? 1 : 0;
           formData.isEffectivePermanent3 = this.medicalLicenseExpiryValue3 ? 1 : 0;
+          
+          // 处理食品经营许可证图片数据,转换为逗号分隔的字符串
+          if (Array.isArray(formData.foodLicense)) {
+            formData.foodLicense = formData.foodLicense.join(',');
+          }
 
           if (formData.storeId != null) {
             updateStore(formData).then(response => {
@@ -2136,6 +2200,11 @@ export default {
   background-color: #fafafa;
 }
 
+.small-placeholder {
+  width: 150px;
+  height: 150px;
+}
+
 .avatar-wrapper {
   position: relative;
   display: inline-block;
@@ -2148,5 +2217,44 @@ export default {
   border-radius: 4px;
 }
 
+.small-avatar {
+  width: 150px;
+  height: 150px;
+}
+
+/* 食品经营许可证容器 */
+.food-license-container {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  gap: 10px;
+  align-items: flex-start;
+  justify-content: flex-start;
+}
+
+/* 食品经营许可证单项 */
+.food-license-item {
+  position: relative;
+  display: inline-block;
+  text-align: center;
+}
+
+/* 添加按钮样式 */
+.add-btn {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  border: 1px dashed #d9d9d9;
+  background-color: #fafafa;
+  width: 150px;
+  height: 150px;
+}
+
+.add-btn:hover {
+  border-color: #409EFF;
+  background-color: #f0f7ff;
+}
+
 
 </style>