Bladeren bron

Merge branch 'yjb_ScrmStores' of http://1.14.104.71:10880/root/ylrz_his_scrm_adminUI into yjb_ScrmStores

xw 3 dagen geleden
bovenliggende
commit
4638d55e55

+ 10 - 3
src/api/hisStore/storeProduct.js

@@ -164,13 +164,20 @@ export function businessLicenseCheck(imageUrl) {
   })
 }
 
-
 // 检查店铺的经营许可证是否允许上传该类商品
-export function checkStoreLicense(storeId, cateId) {
+export function checkStoreLicense(storeId, cateId, medicalDeviceCode, productType) {
   return request({
     url: '/store/store/storeProduct/checkStoreDrugLicense',
     method: 'post',
-    data: { storeId: storeId, cateId: cateId }
+    data: { storeId: storeId, cateId: cateId, medicalDeviceCode: medicalDeviceCode, productType: productType }
+  })
+}
+
+// 获取器免列表
+export function getExemptSecondMedicalDeviceList() {
+  return request({
+    url: '/store/store/exemptSecondMedicalDevice/getList',
+    method: 'get'
   })
 }
 

+ 69 - 0
src/api/hisStore/verify.js

@@ -0,0 +1,69 @@
+import request from '@/utils/request'
+
+// 查询核销码列表
+export function listScrm(query) {
+  return request({
+    url: '/shop/scrm/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询核销码详细
+export function getScrm(id) {
+  return request({
+    url: '/shop/scrm/' + id,
+    method: 'get'
+  })
+}
+
+// 新增核销码
+export function addScrm(data) {
+  return request({
+    url: '/shop/scrm',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改核销码
+export function updateScrm(data) {
+  return request({
+    url: '/shop/scrm',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除核销码
+export function delScrm(id) {
+  return request({
+    url: '/shop/scrm/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出核销码
+export function exportScrm(query) {
+  return request({
+    url: '/shop/scrm/export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function importVerifyNoteTemplate() {
+  return request({
+    url: '/shop/scrm/downloadTemplate',
+    method: 'get'
+  })
+}
+
+// 核销核销码
+export function writeOff(data) {
+  return request({
+    url: '/shop/scrm/writeOff',
+    method: 'post',
+    data: data
+  })
+}

+ 345 - 0
src/api/storeVerify/index.vue

@@ -0,0 +1,345 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="用户自定义核销码" prop="verifyCode">
+        <el-input
+          v-model="queryParams.verifyCode"
+          placeholder="请输入用户自定义核销码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="出库状态" prop="outboundStatus">
+        <el-select v-model="queryParams.outboundStatus" placeholder="请选择出库状态" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="核销状态" prop="verifyStatus">
+        <el-select v-model="queryParams.verifyStatus" placeholder="请选择核销状态" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="数据状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择数据状态" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="是否删除" prop="isDel">
+        <el-input
+          v-model="queryParams.isDel"
+          placeholder="请输入是否删除"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['shop:scrm:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['shop:scrm:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['shop:scrm:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['shop:scrm:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="scrmList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="主键ID" align="center" prop="id" />
+      <el-table-column label="用户自定义核销码" align="center" prop="verifyCode" />
+      <el-table-column label="关联商品ID" align="center" prop="productId" />
+      <el-table-column label="出库状态" align="center" prop="outboundStatus" />
+      <el-table-column label="核销状态" align="center" prop="verifyStatus" />
+      <el-table-column label="数据状态" align="center" prop="status" />
+      <el-table-column label="是否删除" align="center" prop="isDel" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['shop:scrm:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['shop:scrm:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改核销码对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="用户自定义核销码" prop="verifyCode">
+          <el-input v-model="form.verifyCode" placeholder="请输入用户自定义核销码" />
+        </el-form-item>
+        <el-form-item label="出库状态">
+          <el-radio-group v-model="form.outboundStatus">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="核销状态">
+          <el-radio-group v-model="form.verifyStatus">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="数据状态">
+          <el-radio-group v-model="form.status">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="是否删除" prop="isDel">
+          <el-input v-model="form.isDel" placeholder="请输入是否删除" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listScrm, getScrm, delScrm, addScrm, updateScrm, exportScrm } from "@/api/shop/scrm";
+
+export default {
+  name: "Scrm",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 核销码表格数据
+      scrmList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        verifyCode: null,
+        productId: null,
+        outboundStatus: null,
+        verifyStatus: null,
+        status: null,
+        isDel: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        verifyCode: [
+          { required: true, message: "用户自定义核销码不能为空", trigger: "blur" }
+        ],
+        productId: [
+          { required: true, message: "关联商品ID不能为空", trigger: "blur" }
+        ],
+        outboundStatus: [
+          { required: true, message: "出库状态不能为空", trigger: "blur" }
+        ],
+        verifyStatus: [
+          { required: true, message: "核销状态不能为空", trigger: "blur" }
+        ],
+        status: [
+          { required: true, message: "数据状态不能为空", trigger: "blur" }
+        ],
+        isDel: [
+          { required: true, message: "是否删除不能为空", trigger: "blur" }
+        ],
+        createTime: [
+          { required: true, message: "创建时间不能为空", trigger: "blur" }
+        ],
+        updateTime: [
+          { required: true, message: "更新时间不能为空", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询核销码列表 */
+    getList() {
+      this.loading = true;
+      listScrm(this.queryParams).then(response => {
+        this.scrmList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        verifyCode: null,
+        productId: null,
+        outboundStatus: 0,
+        verifyStatus: 0,
+        status: 0,
+        isDel: null,
+        createTime: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加核销码";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getScrm(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改核销码";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateScrm(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addScrm(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除核销码编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delScrm(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有核销码数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportScrm(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 5 - 0
src/views/hisStore/components/productAfterSalesOrder.vue

@@ -134,6 +134,11 @@
               <p>{{JSON.parse(scope.row.jsonInfo).productName}}</p>
             </template>
           </el-table-column>
+          <el-table-column label="溯源码" width="300" align="center">
+            <template slot-scope="scope">
+              <p>{{JSON.parse(scope.row.jsonInfo).verifyCods}}</p>
+            </template>
+          </el-table-column>
           <el-table-column label="单价" width="240" align="center">
             <template slot-scope="scope">
               <p>¥{{JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}</p>

+ 5 - 0
src/views/hisStore/components/productOrder.vue

@@ -238,6 +238,11 @@
             <p>{{JSON.parse(scope.row.jsonInfo).productName}}</p>
           </template>
         </el-table-column>
+        <el-table-column label="溯源码" width="300" align="center">
+          <template slot-scope="scope">
+            <p>{{JSON.parse(scope.row.jsonInfo).verifyCods}}</p>
+          </template>
+        </el-table-column>
         <el-table-column label="单价" width="240" align="center">
           <template slot-scope="scope">
             <p>¥{{JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}</p>

+ 100 - 67
src/views/hisStore/store/audit.vue

@@ -148,31 +148,6 @@
           </el-button>
         </template>
       </el-table-column>
-<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="130px" v-if="medicalMallConfig.isAudit">-->
-<!--        <template slot-scope="scope">-->
-<!--          <el-button-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            icon="el-icon-s-promotion"-->
-<!--            @click="handledetails(scope.row)"-->
-<!--          >-->
-<!--            <span v-if="scope.row.isAudit===0">审核</span>-->
-<!--            <span v-else>详情</span>-->
-<!--          </el-button>-->
-<!--        </template>-->
-<!--      </el-table-column>-->
-<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="130px">-->
-<!--        <template slot-scope="scope">-->
-<!--          <el-button-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            icon="el-icon-s-promotion"-->
-<!--            @click="handleUpdate(scope.row)"-->
-<!--          >-->
-<!--            <span>审核</span>-->
-<!--          </el-button>-->
-<!--        </template>-->
-<!--      </el-table-column>-->
     </el-table>
 
     <pagination
@@ -278,32 +253,27 @@
               <el-col :span="12">
                 <el-form-item label="药品经营许可证">
                   <el-image v-if="dialogForm.drugLicense" style="width: 200px" :src="dialogForm.drugLicense" :preview-src-list="[dialogForm.drugLicense]"></el-image>
+                  <!-- 未上传图片时显示的默认图标 -->
+                  <div v-else class="no-image-placeholder">
+                    <span>用户未上传</span>
+                  </div>
                 </el-form-item>
+
                 <el-form-item label="药品经营许可证编号" style="margin-left: 5px">
                   <el-input v-model="dialogForm.drugCode" />
                 </el-form-item>
               </el-col>
-              <el-col :span="12">
-                <el-form-item label="药品经营许可证有效期">
-                  <span v-if="dialogForm.isDrugLicensePermanent == 1">长期有效</span>
-                  <span v-else>{{dialogForm.drugLicenseExpiryStart}} - {{dialogForm.drugLicenseExpiryEnd}}</span>
-                </el-form-item>
-              </el-col>
-            </el-row>
 
-            <el-row>
-              <el-col :span="12">
-                <el-form-item label="1类器械生产备案">
-                  <el-image v-if="dialogForm.medicalDevice1" style="width: 200px" :src="dialogForm.medicalDevice1" :preview-src-list="[dialogForm.medicalDevice1]"></el-image>
-                </el-form-item>
-                <el-form-item label="1类器械生产备案编号" style="margin-left: 5px">
-                  <el-input v-model="dialogForm.medicalDevice1Code" />
+              <el-col :sapn="24">
+                <el-form-item label="药品经营许可证范围" prop="drugLicenseBusinessScope" style="margin-left: 5px">
+                  <el-input v-model="form.drugLicenseBusinessScope" placeholder="请输入药品经营许可证范围" type="textarea"/>
                 </el-form-item>
               </el-col>
+
               <el-col :span="12">
-                <el-form-item label="1类生产备案有效期">
-                  <span v-if="dialogForm.isMedicalDevice1ExpiryPermanent == 1">长期有效</span>
-                  <span v-else>{{dialogForm.medicalDevice1ExpiryStart}} - {{dialogForm.medicalDevice1ExpiryEnd}}</span>
+                <el-form-item label="药品经营许可证有效期">
+                  <span v-if="dialogForm.isDrugLicensePermanent == 1">长期有效</span>
+                  <span v-else>{{dialogForm.drugLicenseExpiryStart}} - {{dialogForm.drugLicenseExpiryEnd}}</span>
                 </el-form-item>
               </el-col>
             </el-row>
@@ -312,69 +282,118 @@
               <el-col :span="12">
                 <el-form-item label="2类医疗器械备案证书">
                   <el-image v-if="dialogForm.medicalDevice2" style="width: 200px" :src="dialogForm.medicalDevice2" :preview-src-list="[dialogForm.medicalDevice2]"></el-image>
+                  <!-- 未上传图片时显示的默认图标 -->
+                  <div v-else class="no-image-placeholder">
+                    <span>用户未上传</span>
+                  </div>
                 </el-form-item>
                 <el-form-item label="2类器械生产备案编号" style="margin-left: 5px">
                   <el-input v-model="dialogForm.medicalDevice2Code" />
                 </el-form-item>
               </el-col>
+
               <el-col :span="12">
-                <el-form-item label="2类医疗器械备案有效期">
-                  <span v-if="dialogForm.isMedicalDevice2ExpiryPermanent == 1">长期有效</span>
-                  <span v-else>{{dialogForm.medicalDevice2ExpiryStart}} - {{dialogForm.medicalDevice2ExpiryEnd}}</span>
+                <el-form-item label="2类器械经营许可证是否长期有效" prop="isMedicalDevice2ExpiryPermanent">
+                  <el-switch
+                    @change="switchChange()"
+                    v-model="dialogForm.isMedicalDevice2ExpiryPermanent"
+                    :active-value="1"
+                    :inactive-value="0"
+                    active-color="#13ce66"
+                    inactive-color="#ff4949">
+                  </el-switch>
+                </el-form-item>
+
+                <el-form-item label="2类器械经营许可证有效期" prop="foodLicenseExpiry" v-if="dialogForm.isMedicalDevice2ExpiryPermanent != 1">
+                  <span>{{dialogForm.medicalDevice2ExpiryStart}} - {{dialogForm.medicalDevice2ExpiryEnd}}</span>
                 </el-form-item>
               </el-col>
+
+              <el-col :sapn="24">
+                <el-form-item label="2类器械经营范围" prop="medicalDevice2BusinessScope" style="margin-left: 5px">
+                  <el-input v-model="form.medicalDevice2BusinessScope" placeholder="请输入2类器械经营范围" type="textarea"/>
+                </el-form-item>
+              </el-col>
+
             </el-row>
 
             <el-row>
               <el-col :span="12">
                 <el-form-item label="3类器械经营许可证">
                   <el-image v-if="dialogForm.medicalDevice3" style="width: 200px" :src="dialogForm.medicalDevice3" :preview-src-list="[dialogForm.medicalDevice3]"></el-image>
+                  <!-- 未上传图片时显示的默认图标 -->
+                  <div v-else class="no-image-placeholder">
+                    <span>用户未上传</span>
+                  </div>
                 </el-form-item>
                 <el-form-item label="3类器械生产备案编号" style="margin-left: 5px">
                   <el-input v-model="dialogForm.medicalDevice3Code" />
                 </el-form-item>
               </el-col>
+
               <el-col :span="12">
-                <el-form-item label="3类器械经营许可证有效期">
-                  <span v-if="dialogForm.isMedicalDevice3ExpiryPermanent == 1">长期有效</span>
-                  <span v-else>{{dialogForm.medicalDevice3ExpiryStart}} - {{dialogForm.medicalDevice3ExpiryEnd}}</span>
+                <el-form-item label="3类器械经营许可证是否长期有效" prop="isMedicalDevice3ExpiryPermanent">
+                  <el-switch
+                    @change="switchChange()"
+                    v-model="dialogForm.isMedicalDevice3ExpiryPermanent"
+                    :active-value="1"
+                    :inactive-value="0"
+                    active-color="#13ce66"
+                    inactive-color="#ff4949">
+                  </el-switch>
+                </el-form-item>
+
+                <el-form-item label="3类器械经营许可证有效期" prop="foodLicenseExpiry" v-if="dialogForm.isMedicalDevice3ExpiryPermanent != 1">
+                  <span>{{dialogForm.medicalDevice3ExpiryStart}} - {{dialogForm.medicalDevice3ExpiryEnd}}</span>
+                </el-form-item>
+              </el-col>
+
+              <el-col :sapn="24">
+                <el-form-item label="3类器械经营范围" prop="medicalDevice3BusinessScope" style="margin-left: 5px">
+                  <el-input v-model="form.medicalDevice3BusinessScope" placeholder="请输入3类器械经营范围" type="textarea"/>
                 </el-form-item>
               </el-col>
+
             </el-row>
 
             <el-row>
               <el-col :span="12">
-                <el-form-item label="食品经营许可证">
-                  <el-image v-if="dialogForm.foodLicense" style="width: 200px" :src="dialogForm.foodLicense" :preview-src-list="[dialogForm.foodLicense]"></el-image>
+                <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-else class="no-image-placeholder">
+                    <span>用户未上传</span>
+                  </div>
                 </el-form-item>
-                <el-form-item label="食品经营许可证编号" style="margin-left: 5px">
+                <el-form-item label="食品经营许可证/备案凭证编号" style="margin-left: 5px">
                   <el-input v-model="dialogForm.foodCode" />
                 </el-form-item>
               </el-col>
               <el-col :span="12">
-                <el-form-item label="食品经营许可证有效期">
-                  <span v-if="dialogForm.isFoodLicenseExpiryPermanent == 1">长期有效</span>
-                  <span v-else>{{dialogForm.foodLicenseExpiryStart}} - {{dialogForm.foodLicenseExpiryEnd}}</span>
+                <el-form-item label="食品经营许可证/备案凭证是否长期有效" prop="isFoodLicenseExpiryPermanent">
+                  <el-switch
+                    @change="switchChange()"
+                    v-model="dialogForm.isFoodLicenseExpiryPermanent"
+                    :active-value="1"
+                    :inactive-value="0"
+                    active-color="#13ce66"
+                    inactive-color="#ff4949">
+                  </el-switch>
                 </el-form-item>
-              </el-col>
-            </el-row>
 
-            <el-row>
-              <el-col :span="12">
-                <el-form-item label="医疗机构执业许可证">
-                  <el-image v-if="dialogForm.medicalLicense" style="width: 200px" :src="dialogForm.medicalLicense" :preview-src-list="[dialogForm.medicalLicense]"></el-image>
-                </el-form-item>
-                <el-form-item label="医疗机构执业许可证编号" style="margin-left: 5px">
-                  <el-input v-model="dialogForm.medicalCode" />
+                <el-form-item label="食品经营许可证/备案凭证有效期" prop="foodLicenseExpiry" v-if="dialogForm.isFoodLicenseExpiryPermanent != 1">
+                  <span>{{dialogForm.foodLicenseExpiryStart}} - {{dialogForm.foodLicenseExpiryEnd}}</span>
                 </el-form-item>
               </el-col>
-              <el-col :span="12">
-                <el-form-item label="医疗机构执业许可证有效期">
-                  <span v-if="dialogForm.isMedicalLicenseExpiryPermanent == 1">长期有效</span>
-                  <span v-else>{{dialogForm.medicalLicenseExpiryStart}} - {{dialogForm.medicalLicenseExpiryEnd}}</span>
+
+              <el-col :sapn="24">
+                <el-form-item label="食品经营许可证/备案凭证经营范围" prop="foodLicenseBusinessScope">
+                  <el-input v-model="form.foodLicenseBusinessScope" placeholder="请输入食品经营许可证/备案凭证经营范围" type="textarea"/>
                 </el-form-item>
               </el-col>
+
             </el-row>
+
           </div>
 
           <el-divider content-position="left">店铺配置信息</el-divider>
@@ -787,6 +806,7 @@ export default {
   position: relative;
   overflow: hidden;
 }
+
 .avatar-uploader .el-upload:hover {
   border-color: #409EFF;
 }
@@ -799,4 +819,17 @@ export default {
   line-height: 150px;
   text-align: center;
 }
+
+/* 无图片占位符样式 */
+.no-image-placeholder {
+  width: 200px;
+  height: 200px;
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #999;
+  background-color: #fafafa;
+}
 </style>

+ 229 - 85
src/views/hisStore/store/index.vue

@@ -148,28 +148,6 @@
       </el-table-column>
       <el-table-column label="地址" align="center" prop="address" width="200px"/>
       <el-table-column label="店铺电话" align="center" prop="phone" width="120px"/>
-      <!--      <el-table-column label="资质证书" align="center" prop="licenseImages" width="100px">
-              <template slot-scope="scope">
-                <el-popover
-                  placement="right"
-                  title=""
-                  trigger="hover">
-                  <img slot="reference" :src="scope.row.licenseImages" width="80px">
-                  <img :src="scope.row.licenseImages" style="max-width: 150px;">
-                </el-popover>
-              </template>
-            </el-table-column>
-            <el-table-column label="营业执照" align="center" prop="bizLicense" width="100px">
-              <template slot-scope="scope">
-                <el-popover
-                  placement="right"
-                  title=""
-                  trigger="hover">
-                  <img slot="reference" :src="scope.row.bizLicense" width="80px">
-                  <img :src="scope.row.bizLicense" style="max-width: 150px;">
-                </el-popover>
-              </template>
-            </el-table-column>-->
       <el-table-column label="审核状态" align="center" prop="isAudit">
         <template slot-scope="scope">
           <dict-tag :options="isAuditOptions" :value="scope.row.isAudit"/>
@@ -235,6 +213,7 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
+
     <!-- 添加或修改店铺管理对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body :close-on-click-modal="false">
       <el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="top" :disabled="isViewMode">
@@ -270,10 +249,23 @@
                 <!-- 图片容器(包含图片和删除按钮,仅在有图片时显示) -->
                 <div class="avatar-wrapper" v-if="form.logoUrl">
                   <img :src="form.logoUrl" class="avatar" width="200px">
-                  <!-- 悬停显示的删除按钮 -->
-                  <div class="delete-mask" @click.stop="handleDeleteLogo">
-                    <i class="el-icon-delete"></i>
+                  <!-- 显示删除还是显示放大是更具编辑或者详情来的 -->
+<!--                  <div v-if="isViewMode" class="view-mask" @click.stop="previewImage(form.logoUrl)">-->
+<!--                    <i class="el-icon-zoom-in"></i>-->
+<!--                  </div>-->
+<!--                  <div v-else class="delete-mask" @click.stop="handleDeleteLogo">-->
+<!--                    <i class="el-icon-delete"></i>-->
+<!--                  </div>-->
+<!--                  并排显示就好了-->
+                  <div class="button-group">
+                    <div class="preview-btn" @click.stop="previewImage(form.logoUrl)">
+                      <i class="el-icon-zoom-in"></i>
+                    </div>
+                    <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDeleteLogo">
+                      <i class="el-icon-delete"></i>
+                    </div>
                   </div>
+
                 </div>
                 <!-- 未上传图片时显示的默认图标 -->
                 <i v-else class="el-icon-plus avatar-uploader-icon"></i>
@@ -341,11 +333,24 @@
                 <div class="avatar-wrapper" v-if="form.businessLicense">
                   <img :src="form.businessLicense" class="avatar" width="200px">
                   <!-- 悬停显示的删除按钮 -->
-                  <div class="delete-mask" @click.stop="handleDelete5">
-                    <i class="el-icon-delete"></i>
+<!--                  <div class="delete-mask" @click.stop="handleDelete5">-->
+<!--                    <i class="el-icon-delete"></i>-->
+<!--                  </div>-->
+                  <div class="button-group">
+                    <div class="preview-btn" @click.stop="previewImage(form.businessLicense)">
+                      <i class="el-icon-zoom-in"></i>
+                    </div>
+                    <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete5">
+                      <i class="el-icon-delete"></i>
+                    </div>
                   </div>
                 </div>
-                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                <!-- 未上传图片时显示的默认图标 -->
+                <div v-else class="no-image-placeholder">
+                  <span v-if="isViewMode">用户未上传</span>
+                  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                </div>
+
               </el-upload>
             </el-form-item>
             <el-col :span="12">
@@ -393,14 +398,32 @@
                   <div class="avatar-wrapper" v-if="form.drugLicense">
                     <img :src="form.drugLicense" class="avatar" width="200px">
                     <!-- 悬停显示的删除按钮 -->
-                    <div class="delete-mask" @click.stop="handleDelete6">
-                      <i class="el-icon-delete"></i>
+<!--                    <div class="delete-mask" @click.stop="handleDelete6">-->
+<!--                      <i class="el-icon-delete"></i>-->
+<!--                    </div>-->
+                    <div class="button-group">
+                      <div class="preview-btn" @click.stop="previewImage(form.drugLicense)">
+                        <i class="el-icon-zoom-in"></i>
+                      </div>
+                      <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete6">
+                        <i class="el-icon-delete"></i>
+                      </div>
                     </div>
                   </div>
-
-                  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  <!-- 未上传图片时显示的默认图标 -->
+                  <div v-else class="no-image-placeholder">
+                    <span v-if="isViewMode">用户未上传</span>
+                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  </div>
                 </el-upload>
               </el-form-item>
+
+              <el-col :sapn="24">
+                <el-form-item label="药品经营许可证范围" prop="drugLicenseBusinessScope" style="margin-left: 5px">
+                  <el-input v-model="form.drugLicenseBusinessScope" placeholder="请输入药品经营许可证范围" type="textarea"/>
+                </el-form-item>
+              </el-col>
+
               <el-col :span="14">
                 <el-form-item label="药品经营许可证编号" prop="drugCode" style="margin-left: 5px">
                   <el-input v-model="form.drugCode" placeholder="请输入药品经营许可证编号" />
@@ -408,15 +431,7 @@
               </el-col>
             </el-col>
             <el-col :span="12">
-              <el-form-item label="药品经营许可证是否长期有效" prop="isDrugLicensePermanent">
-                <el-switch
-                  @change="switchChange()"
-                  v-model="drugLicenseValue"
-                  active-color="#13ce66"
-                  inactive-color="#ff4949">
-                </el-switch>
-              </el-form-item>
-              <el-form-item label="药品经营许可证有效期" prop="drugLicenseExpiry" v-if="!drugLicenseValue">
+              <el-form-item label="药品经营许可证有效期" prop="drugLicenseExpiry">
                 <el-date-picker
                   v-model="form.drugLicenseExpiry"
                   type="daterange"
@@ -444,19 +459,37 @@
                   <div class="avatar-wrapper" v-if="form.medicalDevice2">
                     <img :src="form.medicalDevice2" class="avatar" width="200px">
                     <!-- 悬停显示的删除按钮 -->
-                    <div class="delete-mask" @click.stop="handleDelete7">
-                      <i class="el-icon-delete"></i>
+<!--                    <div class="delete-mask" @click.stop="handleDelete7">-->
+<!--                      <i class="el-icon-delete"></i>-->
+<!--                    </div>-->
+                    <div class="button-group">
+                      <div class="preview-btn" @click.stop="previewImage(form.medicalDevice2)">
+                        <i class="el-icon-zoom-in"></i>
+                      </div>
+                      <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete7">
+                        <i class="el-icon-delete"></i>
+                      </div>
                     </div>
                   </div>
-                  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  <!-- 未上传图片时显示的默认图标 -->
+                  <div v-else class="no-image-placeholder">
+                    <span v-if="isViewMode">用户未上传</span>
+                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  </div>
                 </el-upload>
               </el-form-item>
+
+              <el-col :sapn="24">
+                <el-form-item label="2类器械经营范围" prop="medicalDevice2BusinessScope" style="margin-left: 5px">
+                  <el-input v-model="form.medicalDevice2BusinessScope" placeholder="请输入2类器械经营范围" type="textarea"/>
+                </el-form-item>
+              </el-col>
+
               <el-col :span="14">
                 <el-form-item label="2类器械生产备案编号" prop="medicalDevice2Code" style="margin-left: 5px">
                   <el-input v-model="form.medicalDevice2Code" placeholder="请输入2类器械生产备案编号" />
                 </el-form-item>
               </el-col>
-
             </el-col>
             <el-col :span="12"></el-col>
             <el-col :span="12">
@@ -480,6 +513,7 @@
               </el-form-item>
             </el-col>
           </el-row>
+
           <el-row>
             <el-col :span="12">
               <el-form-item label="3类器械经营许可证上传" prop="medicalDevice3">
@@ -495,28 +529,39 @@
                   <div class="avatar-wrapper" v-if="form.medicalDevice3">
                     <img :src="form.medicalDevice3" class="avatar" width="200px">
                     <!-- 悬停显示的删除按钮 -->
-                    <div class="delete-mask" @click.stop="handleDelete2">
-                      <i class="el-icon-delete"></i>
+<!--                    <div class="delete-mask" @click.stop="handleDelete2">-->
+<!--                      <i class="el-icon-delete"></i>-->
+<!--                    </div>-->
+                    <div class="button-group">
+                      <div class="preview-btn" @click.stop="previewImage(form.medicalDevice3)">
+                        <i class="el-icon-zoom-in"></i>
+                      </div>
+                      <div v-if="!isViewMode" class="delete-btn" @click.stop="handleDelete2">
+                        <i class="el-icon-delete"></i>
+                      </div>
                     </div>
                   </div>
-                  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  <!-- 未上传图片时显示的默认图标 -->
+                  <div v-else class="no-image-placeholder">
+                    <span v-if="isViewMode">用户未上传</span>
+                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  </div>
                 </el-upload>
               </el-form-item>
+
+              <el-col :sapn="24">
+                <el-form-item label="3类器械经营范围" prop="medicalDevice3BusinessScope" style="margin-left: 5px">
+                  <el-input v-model="form.medicalDevice3BusinessScope" placeholder="请输入3类器械经营范围" type="textarea"/>
+                </el-form-item>
+              </el-col>
+
               <el-form-item label="3类器械生产备案编号" prop="medicalDevice3Code" style="margin-left: 5px">
                 <el-input v-model="form.medicalDevice3Code" placeholder="请输入3类器械生产备案编号" />
               </el-form-item>
             </el-col>
             <el-col :span="12"></el-col>
             <el-col :span="12">
-              <el-form-item label="3类器械经营许可证是否长期有效" prop="isMedicalDevice3ExpiryPermanent">
-                <el-switch
-                  @change="switchChange()"
-                  v-model="medicalDevice3ExpiryValue"
-                  active-color="#13ce66"
-                  inactive-color="#ff4949">
-                </el-switch>
-              </el-form-item>
-              <el-form-item label="3类器械经营许可证有效期" prop="medicalDevice3Expiry" v-if="!medicalDevice3ExpiryValue">
+              <el-form-item label="3类器械经营许可证有效期" prop="medicalDevice3Expiry">
                 <el-date-picker
                   v-model="form.medicalDevice3Expiry"
                   type="daterange"
@@ -530,7 +575,7 @@
           </el-row>
           <el-row>
             <el-col :span="12">
-              <el-form-item label="食品经营许可证上传" prop="foodLicense">
+              <el-form-item label="食品经营许可证/备案凭证上传" prop="foodLicense">
                 <el-upload
                   class="avatar-uploader"
                   :action="uploadUrl"
@@ -543,20 +588,32 @@
                   <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 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>
                     </div>
                   </div>
-                  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  <!-- 未上传图片时显示的默认图标 -->
+                  <div v-else class="no-image-placeholder">
+                    <span v-if="isViewMode">用户未上传</span>
+                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                  </div>
                 </el-upload>
               </el-form-item>
-              <el-form-item label="食品经营许可证编号" prop="foodCode" style="margin-left: 5px">
-                <el-input v-model="form.foodCode" placeholder="请输入食品经营许可证编号" />
+              <el-form-item label="食品经营许可证/备案凭证编号" prop="foodCode" style="margin-left: 5px">
+                <el-input v-model="form.foodCode" placeholder="请输入食品经营许可证/备案凭证编号" />
               </el-form-item>
             </el-col>
             <el-col :span="12"></el-col>
             <el-col :span="12">
-              <el-form-item label="食品经营许可证是否长期有效" prop="isFoodLicenseExpiryPermanent">
+              <el-form-item label="食品经营许可证/备案凭证是否长期有效" prop="isFoodLicenseExpiryPermanent">
                 <el-switch
                   @change="switchChange()"
                   v-model="foodLicenseExpiryValue"
@@ -564,7 +621,7 @@
                   inactive-color="#ff4949">
                 </el-switch>
               </el-form-item>
-              <el-form-item label="食品经营许可证有效期" prop="foodLicenseExpiry" v-if="!foodLicenseExpiryValue">
+              <el-form-item label="食品经营许可证/备案凭证有效期" prop="foodLicenseExpiry" v-if="!foodLicenseExpiryValue">
                 <el-date-picker
                   v-model="form.foodLicenseExpiry"
                   type="daterange"
@@ -575,6 +632,13 @@
                 </el-date-picker>
               </el-form-item>
             </el-col>
+
+            <el-col :sapn="24">
+              <el-form-item label="食品经营许可证/备案凭证经营范围" prop="foodLicenseBusinessScope">
+                <el-input v-model="form.foodLicenseBusinessScope" placeholder="请输入食品经营许可证/备案凭证经营范围" type="textarea"/>
+              </el-form-item>
+            </el-col>
+
           </el-row>
         </div>
         <div v-hasPermi="['his:store:AgreementSigned']">
@@ -879,6 +943,10 @@
       </div>
     </el-dialog>
 
+    <!-- 修改图片预览对话框,增加更大的预览尺寸 -->
+    <el-dialog :visible.sync="imagePreviewVisible" width="1100px" append-to-body :modal-append-to-body="false" @close="imagePreviewVisible = false">
+      <img :src="previewImageUrl" style="width: 100%; height: auto; max-height: 700px; object-fit: contain;" />
+    </el-dialog>
 
 
     <el-dialog
@@ -907,6 +975,8 @@ export default {
   components: { storeDetails, StoreDialog },
   data() {
     return {
+      previewImageUrl: '', // 添加预览图片URL
+      imagePreviewVisible: false,// 添加图片预览对话框可见性控制
       // 新增:控制LOGO上传组件禁用状态
       isDeleting: false,
       promptList:[],
@@ -920,11 +990,9 @@ export default {
       auditLogs: [],
       switchValue:false,
       switchMedicalValue:false,
-      drugLicenseValue:false,
       medicalDevice2ExpiryValue:false,
-      medicalDevice3ExpiryValue:false,
-      foodLicenseExpiryValue:false,
       medicalLicenseExpiryValue:false,
+      foodLicenseExpiryValue:false,
       medicalLicenseExpiryValue1:false,//协议有效期控制
       medicalLicenseExpiryValue2:false,//协议有效期控制
       medicalLicenseExpiryValue3:false,//协议有效期控制
@@ -982,6 +1050,8 @@ export default {
       },
       // 表单参数
       form: {
+        medicalDevice3BusinessScope: null,
+        medicalDevice2BusinessScope: null,
         settlementAgreementFileType: '', // 入驻协议文件类型(如 application/pdf)
         qualityAssuranceAgreementFileType: '', // 质量保证协议文件类型
         otherSpecialQualificationFileType: '', // 其他特殊资质文件类型
@@ -995,6 +1065,9 @@ export default {
       },
       // 表单校验
       rules: {
+        drugLicenseBusinessScope: [
+          { required: true, message: "药品经营许可证范围不能为空", trigger: "blur" }
+        ],
         storeName: [
           { required: true, message: "店铺名称不能为空", trigger: "blur" }
         ],
@@ -1010,15 +1083,33 @@ export default {
         businessCode:[
           { required: true, message: "营业执照编号不能为空", trigger: "blur" }
         ],
-        drugLicense:[
+        drugLicense: [
           { required: true, message: "药品经营许可证不能为空", trigger: "blur" }
         ],
-        drugLicenseExpiry:[
-          { required: true, message: "药品经营许可证有效期不能为空", trigger: "blur" }
-        ],
         drugCode:[
           { required: true, message: "药品经营许可证编号不能为空", trigger: "blur" }
         ],
+        drugLicenseExpiry: [
+          { required: true, message: "药品经营许可证有效期不能为空", trigger: "blur" }
+        ],
+        medicalDevice3: [
+          { required: true, message: "3类器械经营许可证不能为空", trigger: "blur" }
+        ],
+        medicalDevice3Code: [
+          { required: true, message: "3类器械生产备案编号不能为空", trigger: "blur" }
+        ],
+        medicalDevice3Expiry: [
+          { required: true, message: "3类器械经营许可证有效期不能为空", trigger: "blur" }
+        ],
+        foodLicense: [
+          { required: true, message: "食品经营许可证不能为空", trigger: "blur" }
+        ],
+        foodCode: [
+          { required: true, message: "食品经营许可证编号不能为空", trigger: "blur" }
+        ],
+        foodLicenseExpiry: [
+          { required: true, message: "食品经营许可证有效期不能为空", trigger: "blur" }
+        ],
         logoUrl: [
           { required: true, message: "店铺LOGO不能为空", trigger: "blur" }
         ],
@@ -1112,6 +1203,11 @@ export default {
     })
   },
   methods: {
+    // 添加图片预览方法
+    previewImage(url) {
+      this.previewImageUrl = url;
+      this.imagePreviewVisible = true;
+    },
     handleNoticeInfo() {
       qualifications()
         .then(response => {
@@ -1303,6 +1399,7 @@ export default {
         otherSpecialQualification: null,//其它特殊资质
         otherSpecialQualificationExpiry: null,//其它特殊资质有效期
         businessCode: null,
+        drugLicenseBusinessScope:null,
         drugCode:null,
         medicalDevice1Code:null,
         medicalDevice2Code:null,
@@ -1315,7 +1412,6 @@ export default {
         titleNameOne: null,
         titleNameTwo: null,
         titleNameThree: null,
-
         settlementAgreementFileType: '',
         qualityAssuranceAgreementFileType: '',
         otherSpecialQualificationFileType: ''
@@ -1395,24 +1491,18 @@ export default {
         if(this.form.isMedicalDevice1ExpiryPermanent == 1){
           this.switchMedicalValue = true;
         }
-        if(this.form.isDrugLicensePermanent == 1){
-          this.drugLicenseValue = true;
-        }
         if(this.form.isMedicalDevice2ExpiryPermanent == 1){
           this.medicalDevice2ExpiryValue = true;
         }
-        if(this.form.isMedicalDevice3ExpiryPermanent == 1){
-          this.medicalDevice3ExpiryValue = true;
-        }
-        if(this.form.isFoodLicenseExpiryPermanent == 1){
-          this.foodLicenseExpiryValue = true;
-        }
         if(this.form.isMedicalLicenseExpiryPermanent == 1){
           this.medicalLicenseExpiryValue = true;
         }
         if(this.form.isEffectivePermanent1 == 1){
           this.medicalLicenseExpiryValue1 = true;
         }
+        if(this.form.isFoodLicenseExpiryPermanent == 1){
+          this.foodLicenseExpiryValue = true;
+        }
         if(this.form.isEffectivePermanent2 == 1){
           this.medicalLicenseExpiryValue2 = true;
         }
@@ -1534,12 +1624,10 @@ export default {
           }
 
           // 处理各类许可证是否永久有效的开关状态
+          formData.isFoodLicenseExpiryPermanent = this.foodLicenseExpiryValue ? 1 : 0;
           formData.isBusinessLicensePermanent = this.switchValue ? 1 : 0;
           formData.isMedicalDevice1ExpiryPermanent = this.switchMedicalValue ? 1 : 0;
-          formData.isDrugLicensePermanent = this.drugLicenseValue ? 1 : 0;
           formData.isMedicalDevice2ExpiryPermanent = this.medicalDevice2ExpiryValue ? 1 : 0;
-          formData.isMedicalDevice3ExpiryPermanent = this.medicalDevice3ExpiryValue ? 1 : 0;
-          formData.isFoodLicenseExpiryPermanent = this.foodLicenseExpiryValue ? 1 : 0;
           formData.isMedicalLicenseExpiryPermanent = this.medicalLicenseExpiryValue ? 1 : 0;
           formData.isEffectivePermanent1 = this.medicalLicenseExpiryValue1 ? 1 : 0;
           formData.isEffectivePermanent2 = this.medicalLicenseExpiryValue2 ? 1 : 0;
@@ -1919,6 +2007,62 @@ export default {
 .agreement-section .el-date-editor--daterange.el-input__inner {
   width: 100%;
 }
+/* 并排按钮样式 */
+.button-group {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  display: flex;
+  gap: 5px;
+}
+
+.preview-btn,
+.delete-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);
+}
+
+.delete-btn:hover {
+  background-color: #f56c6c;
+}
+
+/* 无图片占位符样式 */
+.no-image-placeholder {
+  width: 200px;
+  height: 200px;
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #999;
+  background-color: #fafafa;
+}
+
+.avatar-wrapper {
+  position: relative;
+  display: inline-block;
+}
+
+.avatar {
+  width: 200px;
+  height: 200px;
+  object-fit: cover;
+  border-radius: 4px;
+}
 
 
 </style>

+ 11 - 1
src/views/hisStore/storeAfterSales/index.vue

@@ -259,7 +259,15 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-
+      <el-form-item label="溯源码" prop="verifyCodes">
+        <el-input
+          v-model="queryParams.verifyCodes"
+          clearable
+          placeholder="请输入溯源码"
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
 
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -288,6 +296,7 @@
       <el-table-column label="所属公司" align="center" prop="companyName" />
       <el-table-column label="所属员工" align="center" prop="companyUserNickName" />
       <el-table-column label="订单单号" align="center" prop="orderCode" />
+      <el-table-column label="溯源码" align="center" prop="verifyCodes" width="200px" />
       <el-table-column align="center" label="处方编号" prop="serialNo"/>
       <el-table-column label="会员手机号" align="center" prop="userPhone" />
       <el-table-column label="退款金额" align="center" prop="refundAmount" />
@@ -528,6 +537,7 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
+      this.queryParams.verifyCodes = null;
       this.handleQuery();
     },
     // 多选框选中数据

+ 12 - 1
src/views/hisStore/storeOrder/healthStoreList.vue

@@ -300,7 +300,15 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-
+      <el-form-item label="溯源码" prop="verifyCode">
+        <el-input
+          v-model="queryParams.verifyCodes"
+          clearable
+          placeholder="请输入溯源码"
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
       <el-form-item>
         <el-button icon="el-icon-search" size="mini" type="cyan" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -398,6 +406,7 @@
     <el-table v-loading="loading" :data="storeOrderList" border height="500" @selection-change="handleSelectionChange">
       <el-table-column align="center" type="selection" width="55"/>
       <el-table-column align="center" label="订单号" prop="orderCode" width="200px"/>
+      <el-table-column label="溯源码" align="center" prop="verifyCodes" width="200px" />
       <el-table-column align="center" label="店铺名称" prop="storeName" width="150px">
         <template slot-scope="scope">
           <span>{{ scope.row.storeName }} </span>
@@ -885,6 +894,7 @@ export default {
         isDel: null,
         cost: null,
         verifyCode: null,
+        verifyCodes:null,
         storeId: null,
         shippingType: null,
         isChannel: null,
@@ -1147,6 +1157,7 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm('queryForm')
+      this.queryParams.verifyCodes = null;
       this.handleQuery()
     },
     // 多选框选中数据

+ 13 - 0
src/views/hisStore/storeOrder/index.vue

@@ -304,6 +304,16 @@
         />
       </el-form-item>
 
+      <el-form-item label="溯源码" prop="verifyCodes">
+        <el-input
+          v-model="queryParams.verifyCodes"
+          clearable
+          placeholder="请输入溯源码"
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -400,6 +410,7 @@
     <el-table  height="500" border v-loading="loading" :data="storeOrderList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="订单号" align="center" prop="orderCode" width="200px" />
+      <el-table-column label="溯源码" align="center" prop="verifyCodes" width="200px" />
       <el-table-column label="店铺名称" align="center" prop="storeName" width="150px" >
         <template slot-scope="scope">
           <span>{{scope.row.storeName}} </span>
@@ -894,6 +905,7 @@ export default {
         isDel: null,
         cost: null,
         verifyCode: null,
+        verifyCodes:null,
         storeId: null,
         shippingType: null,
         isChannel: null,
@@ -1205,6 +1217,7 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
+      this.queryParams.verifyCodes=null;
       this.handleQuery();
     },
     // 多选框选中数据

+ 28 - 0
src/views/hisStore/storePayment/index.vue

@@ -11,6 +11,18 @@
           />
         </el-select>
       </el-form-item>
+
+      <el-form-item label="是否发货同步" prop="isShipment">
+        <el-select v-model="queryParams.isShipment" clearable placeholder="请选择同步状态" size="small">
+          <el-option
+            v-for="item in shipmentList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+
       <el-form-item label="付款单号" prop="payCode">
         <el-input
           v-model="queryParams.payCode"
@@ -187,6 +199,12 @@
     >
       <el-table-column align="center" type="selection" width="55"/>
       <el-table-column align="center" label="ID" prop="paymentId"/>
+      <el-table-column align="center" label="是否发货" prop="payMode">
+        <template slot-scope="scope">
+        <span v-if="scope.row.isShipment === 1">是</span>
+          <span v-else>否</span>
+        </template>
+      </el-table-column>
       <el-table-column align="center" label="付款单号" prop="payCode" width="120px"/>
       <el-table-column align="center" label="订单号" prop="orderCode" width="120px"/>
       <el-table-column align="center" label="外部订单号" prop="tradeNo" width="120px"/>
@@ -410,6 +428,16 @@ export default {
   name: 'HisStorePayment',
   data() {
     return {
+      shipmentList:[
+        {
+          label: '是',
+          value: '1'
+        },
+        {
+          label: '否',
+          value: '0'
+        },
+      ],
       payModeOptions: [
         { dictLabel: '微信支付', dictValue: 'wx' },
         { dictLabel: '汇付', dictValue: 'hf' }

+ 403 - 93
src/views/hisStore/storeProduct/index.vue

@@ -419,6 +419,13 @@
             v-hasPermi="['his:storeProduct:copyProduct']"
           >一键复制
           </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-document-copy"
+            @click="openVerify(scope.row)"
+          >溯源码管理
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -479,10 +486,11 @@
           <el-col :span="12">
             <el-form-item label="商品分类" prop="cateId">
               <treeselect v-model="form.cateId" :options="categoryOptions" :normalizer="normalizer"
-                          placeholder="请选择上级分类"/>
+                          placeholder="请选择上级分类" @input="onCategoryOrStoreChange"/>
             </el-form-item>
           </el-col>
         </el-row>
+
         <el-row>
           <el-col :span="12">
             <el-form-item label="商品类型" prop="productType">
@@ -499,7 +507,7 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="所属店铺" prop="storeId" v-if="medicalMallConfig.isStores">
-              <el-select style="width: 240px" v-model="form.storeId" placeholder="请选择店铺" clearable size="small">
+              <el-select style="width: 240px" v-model="form.storeId" placeholder="请选择店铺" clearable size="small" @change="onCategoryOrStoreChange">
                 <el-option
                   v-for="item in storeOptions"
                   :key="item.storeId"
@@ -511,6 +519,15 @@
           </el-col>
         </el-row>
 
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="器械编码" prop="medicalDeviceCode" v-if="showMedicalDeviceCode">
+              <el-input v-model="form.medicalDeviceCode" placeholder="请输入器械编码" @blur="onCategoryOrStoreChange" style="width: calc(100% - 120px);"/>
+              <el-button type="primary" @click="showExemptDeviceDialog" style="margin-left: 10px;" v-if="shouldShowExemptDeviceButton">显示器免</el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
         <el-row>
           <el-col :span="12">
             <el-form-item label="关键字" prop="keyword">
@@ -526,7 +543,7 @@
         </el-row>
         <el-row :gutter="10">
           <el-col :span="12">
-            <el-form-item label="是否药品" prop="isDrug">
+            <el-form-item label="是否药品" prop="isDrug" v-if="!isMedicalDeviceCategory">
               <el-radio-group v-model="form.isDrug">
                 <el-radio
                   v-for="item in isDrugOptions"
@@ -539,18 +556,18 @@
           </el-col>
         </el-row>
         <div v-if="form.isDrug === '1' ">
-          <el-form-item label="药品展示图" prop="drugImage">
+          <el-form-item label="头图展示" prop="drugImage">
             <Material v-model="drugImageArr" type="image" :num="1" :width="150" :height="150"/>
           </el-form-item>
           <div v-if="medicalMallConfig.isMedicalMall">
             <el-row>
               <el-col :span="12">
-                <el-form-item label="药品注册证书编号" prop="drugRegCertNo">
-                  <el-input v-model="form.drugRegCertNo" placeholder="请输入药品注册证书编号"/>
+                <el-form-item :label="isMedicalDeviceCategory ? '注册证号/备案凭证号' : '批准文号'" prop="drugRegCertNo">
+                  <el-input v-model="form.drugRegCertNo" :placeholder="isMedicalDeviceCategory ?'请输入注册证号/备案凭证号' : '请输入批准文号'"/>
                 </el-form-item>
               </el-col>
               <el-col :span="12">
-                <el-form-item label="通用名称" prop="commonName">
+                <el-form-item label="通用名称" prop="commonName" v-if="!isMedicalDeviceCategory">
                   <el-input v-model="form.commonName" placeholder="请输入通用名称"/>
                 </el-form-item>
               </el-col>
@@ -558,7 +575,7 @@
 
             <el-row>
               <el-col :span="12">
-                <el-form-item label="剂型" prop="dosageForm">
+                <el-form-item label="剂型" prop="dosageForm" v-if="!isMedicalDeviceCategory">
                   <el-input v-model="form.dosageForm" placeholder="请输入剂型"/>
                 </el-form-item>
               </el-col>
@@ -607,13 +624,14 @@
                 </el-form-item>
               </el-col>
             </el-row>
+
             <el-collapse v-model="activeValue" accordion>
               <el-collapse-item title="" name="1">
-                <el-form-item label="功能主治" prop="indications">
+                <el-form-item label="功能主治" prop="indications" v-if="!isMedicalDeviceCategory">
                   <el-input v-model="form.indications" type="textarea" placeholder="请输入功能主治"/>
                 </el-form-item>
 
-                <el-form-item label="成分" prop="ingredient" v-if="!displayDemo">
+                <el-form-item label="成分" prop="ingredient" v-if="!isMedicalDeviceCategory">
                   <el-input
                     v-model="form.ingredient"
                     type="textarea"
@@ -624,19 +642,19 @@
                   <div v-if="ingredientError" class="el-form-item__error">{{ ingredientError }}</div>
                 </el-form-item>
 
-                <el-form-item label="用法用量" prop="dosage">
+                <el-form-item label="用法用量" prop="dosage" v-if="!isMedicalDeviceCategory">
                   <el-input v-model="form.dosage" type="textarea" placeholder="请输入用法用量"/>
                 </el-form-item>
 
-                <el-form-item label="不良反应" prop="adverseReactions">
+                <el-form-item label="不良反应" prop="adverseReactions" v-if="!isMedicalDeviceCategory">
                   <el-input v-model="form.adverseReactions" type="textarea" placeholder="请输入不良反应"/>
                 </el-form-item>
 
-                <el-form-item label="禁忌" prop="contraindications">
+                <el-form-item label="禁忌" prop="contraindications" v-if="!isMedicalDeviceCategory">
                   <el-input v-model="form.contraindications" type="textarea" placeholder="请输入禁忌"/>
                 </el-form-item>
 
-                <el-form-item label="注意事项" prop="precautions">
+                <el-form-item label="注意事项" prop="precautions" v-if="!isMedicalDeviceCategory">
                   <el-input v-model="form.precautions" type="textarea" placeholder="请输入注意事项"/>
                 </el-form-item>
               </el-collapse-item>
@@ -953,61 +971,63 @@
           <Material v-model="businessArr" type="image" :num="1" :width="150" :height="150"/>
         </el-form-item>
 
-        <el-form-item v-if="form.isShow === '1' && businessArr.length > 0" label="营业执照有效期" prop="businessExpire">
-          <el-date-picker
-            v-model="form.businessExpire"
-            type="daterange"
-            value-format="yyyy-MM-dd"
-            range-separator="至"
-            start-placeholder="开始日期"
-            end-placeholder="结束日期"
-            @change="validateBusinessExpire">
-          </el-date-picker>
-          <div v-if="businessExpireError" style="color: #F56C6C; font-size: 12px; line-height: 1; padding-top: 4px;">
-            <i class="el-icon-warning"></i> {{ businessExpireError }}
-          </div>
+        <el-form-item v-if="form.isShow === '1' && businessArr.length > 0" label="生产企业营业执照是否长期有效" prop="isBusinessPermanent">
+          <el-switch @change="switchChange()" v-model="businessValue" active-color="#13ce66" inactive-color="#ff4949" />
         </el-form-item>
 
+          <el-form-item v-if="form.isShow === '1' && businessArr.length > 0 && !businessValue" prop="businessExpire">
+            <el-date-picker
+              v-model="form.businessExpire"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+
         <!--生产企业的生产许可证/备案凭证-->
         <el-form-item v-if="form.isShow === '1'" label="生产企业的生产许可证/备案凭证" prop="license">
           <Material v-model="licenseArr" type="image" :num="1" :width="150" :height="150"/>
         </el-form-item>
 
-        <el-form-item v-if="form.isShow === '1' && licenseArr.length > 0" label="生产许可证有效期" prop="licenseExpire">
-          <el-date-picker
-            v-model="form.licenseExpire"
-            type="daterange"
-            value-format="yyyy-MM-dd"
-            range-separator="至"
-            start-placeholder="开始日期"
-            end-placeholder="结束日期"
-            @change="validateLicenseExpire">
-          </el-date-picker>
-          <div v-if="licenseExpireError" style="color: #F56C6C; font-size: 12px; line-height: 1; padding-top: 4px;">
-            <i class="el-icon-warning"></i> {{ licenseExpireError }}
-          </div>
+        <el-form-item v-if="form.isShow === '1' && licenseArr.length > 0" label="生产企业的生产许可证/备案凭证是否长期有效" prop="isLicensePermanent">
+            <el-switch @change="switchChange()" v-model="licenseValue" active-color="#13ce66" inactive-color="#ff4949" />
         </el-form-item>
 
+          <el-form-item v-if="form.isShow === '1' && licenseArr.length > 0 && !licenseValue" prop="licenseExpire">
+            <el-date-picker
+              v-model="form.licenseExpire"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+
         <!--商品注册证/备案凭证-->
         <el-form-item v-if="form.isShow === '1'" label="商品注册证/备案凭证" prop="certificate">
           <Material v-model="certificateArr" type="image" :num="1" :width="150" :height="150"/>
         </el-form-item>
 
-        <el-form-item v-if="form.isShow === '1' && certificateArr.length > 0" label="注册证有效期" prop="certificateExpire">
+        <el-form-item v-if="form.isShow === '1' && licenseArr.length > 0" label="商品注册证/备案凭证是否长期有效" prop="isCertificatePermanent">
+          <el-switch @change="switchChange()" v-model="certificateValue" active-color="#13ce66" inactive-color="#ff4949" />
+        </el-form-item>
+
+        <el-form-item v-if="form.isShow === '1' && certificateArr.length > 0 && !certificateValue" prop="certificateExpire">
           <el-date-picker
-            v-model="form.certificateExpire"
-            type="daterange"
-            value-format="yyyy-MM-dd"
-            range-separator="至"
-            start-placeholder="开始日期"
-            end-placeholder="结束日期"
-            @change="validateCertificateExpire">
+              v-model="form.certificateExpire"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
           </el-date-picker>
-          <div v-if="certificateExpireError" style="color: #F56C6C; font-size: 12px; line-height: 1; padding-top: 4px;">
-            <i class="el-icon-warning"></i> {{ certificateExpireError }}
-          </div>
         </el-form-item>
         </div>
+
+
         <el-form-item label="国药准字" v-if="form.productType==2" prop="prescribeCode">
           <el-input v-model="form.prescribeCode" placeholder="请输入国药准字"/>
         </el-form-item>
@@ -1096,8 +1116,53 @@
         </el-table-column>
       </el-table>
       <span slot="footer" class="dialog-footer">
-    <el-button type="primary" @click="authVisible = false">关 闭</el-button>
-  </span>
+        <el-button type="primary" @click="authVisible = false">关 闭</el-button>
+      </span>
+    </el-dialog>
+
+<!-- 免于经营备案的第二类医疗器械产品弹窗 -->
+<el-dialog title="免于经营备案的第二类医疗器械产品" :visible.sync="exemptDeviceDialogVisible" width="80%" append-to-body :modal-append-to-body="false" z-index="9999" top="5vh" custom-class="exempt-device-dialog">
+  <el-form :model="exemptDeviceQueryParams" ref="exemptDeviceQueryForm" :inline="true" label-width="80px">
+    <el-form-item label="产品名称">
+      <el-input v-model="exemptDeviceQueryParams.productName" placeholder="请输入产品名称" clearable size="small" @keyup.enter.native="handleExemptDeviceQuery" />
+    </el-form-item>
+    <el-form-item>
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleExemptDeviceQuery">搜索</el-button>
+      <el-button icon="el-icon-refresh" size="mini" @click="resetExemptDeviceQuery">重置</el-button>
+    </el-form-item>
+  </el-form>
+
+  <el-table v-loading="exemptDeviceLoading" :data="exemptDeviceList" border>
+    <el-table-column label="产品序号" align="center" prop="serialNumber" />
+    <el-table-column label="产品名称" align="center" prop="productName" />
+    <el-table-column label="目录名称" align="center" prop="directoryName" />
+    <el-table-column label="产品描述" align="center" prop="productDescription" />
+    <el-table-column label="产品用途" align="center" prop="usageStr" />
+<!--    <el-table-column label="创建时间" align="center" prop="createTime" width="180" />-->
+<!--    <el-table-column label="更新时间" align="center" prop="updateTime" width="180" />-->
+  </el-table>
+
+  <div slot="footer" class="dialog-footer">
+    <el-button @click="exemptDeviceDialogVisible = false">关 闭</el-button>
+  </div>
+</el-dialog>
+
+
+
+
+    <!-- 溯源码管理弹窗 -->
+    <el-dialog
+      :title="titleVisible"
+      :visible.sync="verifyDialogVisible"
+      width="90%"
+      append-to-body
+      :before-close="handleVerifyDialogClose"
+    >
+      <VerifyCode
+        v-if="verifyDialogVisible"
+        :product-id="currentProductId"
+        ref="verifyCodeRef"
+      />
     </el-dialog>
   </div>
 </template>
@@ -1113,7 +1178,7 @@ import {
   importTemplate,
   batchModify,
   sync580,
-  updateIsShow, exportDrugProduct,getAuthInfo,copyProduct,selectForbiddenKeywords,checkStoreLicense
+  updateIsShow, exportDrugProduct,getAuthInfo,copyProduct,selectForbiddenKeywords,checkStoreLicense,getExemptSecondMedicalDeviceList
 } from "@/api/hisStore/storeProduct";
 import {getAllStoreProductCategory} from "@/api/hisStore/storeProductCategory";
 import {getAllStoreProductRule} from "@/api/hisStore/storeProductRule";
@@ -1128,6 +1193,7 @@ import {getCompanyList} from "@/api/company/company";
 import {listStore} from '@/api/hisStore/store'
 import {getConfigByKey} from '@/api/system/config'
 import {qualifications} from "@/api/hisStore/storeProduct";
+import VerifyCode from '@/views/hisStore/storeVerify/index.vue';
 
 export default {
   name: "HisStoreProduct",
@@ -1135,7 +1201,8 @@ export default {
     Treeselect,
     Editor,
     Material,
-    singleImg,
+    VerifyCode,
+    singleImg
   },
   created() {
     this.$nextTick(() => {
@@ -1185,6 +1252,21 @@ export default {
     this.getTreeselect();
     this.getList();
   },
+  computed: {
+    // 计算属性:是否显示显示器免按钮
+    shouldShowExemptDeviceButton() {
+      // 只有在显示器械编码输入框且不是III类器械时才显示按钮
+      return this.showMedicalDeviceCode &&
+             this.form.cateId &&
+             this.cateIdToNameMap[this.form.cateId] &&
+             !this.cateIdToNameMap[this.form.cateId].includes('III类器械');
+    },
+    // 判断当前分类是否为医疗器械分类
+    isMedicalDeviceCategory() {
+      const cateName = this.cateIdToNameMap[this.form.cateId];
+      return cateName !== undefined && cateName.includes('器械');
+    }
+  },
   watch: {
     licenseArr(val) {
       this.form.license = val.join(',');
@@ -1243,14 +1325,27 @@ export default {
       handler(newVal, oldVal) {
         // 分类变化时动态修改验证规则
         const cateName = this.cateIdToNameMap[newVal];
-
         // 判断是否包含"器械"
         if(cateName !== undefined && cateName.includes('器械')){
           this.displayDemo = true;
+          // 当分类包含"器械"时,默认设置为药品
+          if (cateName.includes('器械')) {
+            this.form.isDrug = "1";
+          }
         } else {
           this.displayDemo = false;
         }
 
+        // 判断是否为II类器械或III类器械,如果是则显示器械编码输入框
+        if (cateName !== undefined && (cateName.includes('II类器械') || cateName.includes('III类器械'))) {
+          this.showMedicalDeviceCode = true;
+          // 只有当商品分类为II类器械时才显示显示器免按钮
+          this.showExemptDeviceButton = cateName.includes('II类器械');
+        } else {
+          this.showMedicalDeviceCode = false;
+          this.showExemptDeviceButton = false;
+        }
+
         // 判断是否包含"处方药"
         const isPrescriptionDrug = cateName !== undefined && cateName.includes('处方药');
 
@@ -1313,6 +1408,20 @@ export default {
         if (newVal && this.form.storeId && this.isFormInitialized) {
           this.debounceCheckStoreLicense();
         }
+        // 动态调整批号的验证规则
+        this.$nextTick(() => {
+          if (this.isMedicalDeviceCategory) {
+            // 是器械时,批号为必填
+            if (!this.rules.batchNumber?.some(rule => rule.required)) {
+              this.rules.batchNumber = [{ required: true, message: "批号不能为空", trigger: "blur" }, ...(this.rules.batchNumber || [])];
+            }
+          } else {
+            // 非器械时,移除批号必填规则
+            if (this.rules.batchNumber) {
+              this.rules.batchNumber = this.rules.batchNumber.filter(rule => !rule.required);
+            }
+          }
+        });
       },
       immediate: true
     },
@@ -1340,6 +1449,13 @@ export default {
   },
   data() {
     return {
+      certificateValue:false,
+      licenseValue:false,
+      businessValue:false,
+      // 溯源码弹窗相关
+      titleVisible:'溯源管理:',
+      verifyDialogVisible: false, // 溯源码弹窗显示状态
+      currentProductId: null,     // 当前选中的商品ID
       storeLicenseErrorMessage: '', // 店铺许可证错误信息
       isFormInitialized: false, // 表单是否已初始化完成
       licenseCheckTimer: null,  // 防抖定时器
@@ -1349,6 +1465,8 @@ export default {
       ingredientError: '', // 成分禁止提示
       displayDemo: false,
       cateIdToNameMap: {},
+      showMedicalDeviceCode: false, // 是否显示器械编码输入框
+      showExemptDeviceButton: false, // 是否显示显示器免按钮
       businessArr: [],
       licenseArr: [],
       certificateArr: [],
@@ -1389,7 +1507,7 @@ export default {
         {dictValue: "1", dictLabel: "是"}
       ],
 
-      // 药品展示图
+      // 头图展示
       drugImageArr: [],
 
       //首营资质上传图
@@ -1444,6 +1562,17 @@ export default {
       // 企业列表
       companyOptions: [],
       storeOptions: [],
+      // 防抖定时器
+      categoryOrStoreChangeTimer: null,
+      // 免于经营备案的第二类医疗器械产品相关变量
+      exemptDeviceDialogVisible: false,
+      exemptDeviceList: [],
+      allExemptDeviceList: [], // 保存所有数据用于本地搜索
+      exemptDeviceLoading: false,
+      exemptDeviceTotal: 0,
+      exemptDeviceQueryParams: {
+        productName: null
+      },
       // 遮罩层
       loading: true,
       // 选中数组
@@ -1510,6 +1639,7 @@ export default {
         isCertificatePermanent:null,
         isLicensePermanent:null,
         isBusinessPermanent:null,
+        medicalDeviceCode: null, // 器械编码
       },
       // 表单校验
       rules: {
@@ -1547,6 +1677,9 @@ export default {
         cateId: [
           {required: true, message: "分类id不能为空", trigger: "blur"}
         ],
+        medicalDeviceCode: [
+          {required: true, message: "器械编码不能为空", trigger: "blur"}
+        ],
         price: [
           {required: true, message: "商品价格不能为空", trigger: "blur"}
         ],
@@ -1665,12 +1798,34 @@ export default {
         return;
       }
 
+      // 获取分类名称
+      const cateName = this.cateIdToNameMap[this.form.cateId];
+
+      // 判断是否为II类器械或III类器械
+      const isMedicalDevice = cateName !== undefined && (cateName.includes('II类器械') || cateName.includes('III类器械'));
+
+      // 如果是II类或III类器械,需要检查器械编码是否为空
+      if (isMedicalDevice && (!this.form.medicalDeviceCode || this.form.medicalDeviceCode.trim() === '')) {
+        this.$message.error('请选择II类器械或III类器械分类时,器械编码不能为空');
+        this.storeLicenseCheckFailed = true;
+        this.storeLicenseErrorMessage = '请选择II类器械或III类器械分类时,器械编码不能为空';
+        return;
+      }
       // 添加检查中标志,防止重复调用
       if (this.isCheckingLicense) {
         return;
       }
       this.isCheckingLicense = true;
-      checkStoreLicense(this.form.storeId, this.form.cateId).then(response => {
+      // 准备请求参数
+      let cateId = this.form.cateId;
+      let medicalDeviceCode = null;
+      let productType = null;
+      // 如果是II类或III类器械,传递器械编码
+      if (isMedicalDevice) {
+        medicalDeviceCode = this.form.medicalDeviceCode;
+        productType = this.form.productType; // 添加商品类型参数
+      }
+      checkStoreLicense(this.form.storeId, cateId, medicalDeviceCode, productType).then(response => {
         if (response.code === 200) {
           if (!response.data.flag) {
             // 权限检查失败
@@ -1747,22 +1902,90 @@ export default {
         });
       }
     },
+    // 当商品分类或所属店铺改变时触发
+    onCategoryOrStoreChange() {
+      // 使用防抖机制,避免频繁调用
+      clearTimeout(this.categoryOrStoreChangeTimer);
+      this.categoryOrStoreChangeTimer = setTimeout(() => {
+        this.checkStoreLicensePermission();
+      }, 500);
+    },
+
+    // 显示免于经营备案的第二类医疗器械产品弹窗
+    showExemptDeviceDialog() {
+      this.exemptDeviceDialogVisible = true;
+      // 重置搜索条件
+      this.exemptDeviceQueryParams = {
+        productName: null
+      };
+      // 只有在没有数据时才获取数据
+      if (this.allExemptDeviceList.length === 0) {
+        this.getExemptDeviceList();
+      } else {
+        // 如果已有数据,直接显示
+        this.exemptDeviceList = this.allExemptDeviceList;
+        this.exemptDeviceTotal = this.exemptDeviceList.length;
+      }
+    },
+    // 获取免于经营备案的第二类医疗器械产品列表
+    getExemptDeviceList() {
+      this.exemptDeviceLoading = true;
+      // 调用实际的API接口来获取数据
+      getExemptSecondMedicalDeviceList(this.exemptDeviceQueryParams).then(response => {
+        this.allExemptDeviceList = response.rows || response.data || [];
+        // 根据搜索条件过滤数据
+        if (this.exemptDeviceQueryParams.productName) {
+          const searchTerm = this.exemptDeviceQueryParams.productName.toLowerCase();
+          this.exemptDeviceList = this.allExemptDeviceList.filter(item =>
+            item.productName && item.productName.toLowerCase().includes(searchTerm)
+          );
+        } else {
+          this.exemptDeviceList = this.allExemptDeviceList;
+        }
+        this.exemptDeviceTotal = this.exemptDeviceList.length;
+        this.exemptDeviceLoading = false;
+      }).catch(error => {
+        console.error('获取免于经营备案的第二类医疗器械产品列表失败:', error);
+        this.$message.error('获取免于经营备案的第二类医疗器械产品列表失败');
+        this.exemptDeviceLoading = false;
+        this.exemptDeviceList = [];
+        this.allExemptDeviceList = [];
+        this.exemptDeviceTotal = 0;
+      });
+    },
+    // 搜索免于经营备案的第二类医疗器械产品
+    handleExemptDeviceQuery() {
+      // 在本地数据中搜索
+      if (this.exemptDeviceQueryParams.productName) {
+        const searchTerm = this.exemptDeviceQueryParams.productName.toLowerCase();
+        this.exemptDeviceList = this.allExemptDeviceList.filter(item =>
+          item.productName && item.productName.toLowerCase().includes(searchTerm)
+        );
+      } else {
+        this.exemptDeviceList = this.allExemptDeviceList;
+      }
+      this.exemptDeviceTotal = this.exemptDeviceList.length;
+    },
+    // 重置免于经营备案的第二类医疗器械产品搜索
+    resetExemptDeviceQuery() {
+      this.exemptDeviceQueryParams = {
+        productName: null
+      };
+      // 重置时显示所有数据
+      this.exemptDeviceList = this.allExemptDeviceList;
+      this.exemptDeviceTotal = this.exemptDeviceList.length;
+    },
     handleNoticeInfo() {
       qualifications()
         .then(response => {
-          console.log("noticeInfo接口完整响应:", response);
           if (response.code === 200) {
             this.promptList = response.data;
             if (this.promptList && this.promptList.length > 0) {
               this.dialogVisible = true;
             }
-            console.log("通知信息请求完成!", this.promptList);
-          } else {
-            console.warn("接口返回非成功状态:", response.code);
           }
         })
         .catch(err => {
-          console.error("获取通知信息失败:", err);
           this.$message.error("加载通知信息失败,请稍后重试");
         });
     },
@@ -1827,7 +2050,7 @@ export default {
       this.upload.open = false;
       this.upload.isUploading = false;
       this.$refs.upload.clearFiles();
-      this.$alert(response.msg, "导入结果", {dangerouslyUseHTMLString: true});
+      this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
       this.getList();
     },
     handleImport() {
@@ -1850,7 +2073,7 @@ export default {
     },
     //生成SKU
     generate() {
-      genFormatAttr(this.form.productId, {attrs: this.attrs}).then(res => {
+      genFormatAttr(this.form.productId, { attrs: this.attrs }).then(res => {
         if (this.form.specType === 0) {
           this.oneFormValidate = res.value;
           this.form.header = res.header;
@@ -1912,7 +2135,7 @@ export default {
         };
         this.attrs.push(data);
         var hash = {};
-        this.attrs = this.attrs.reduce(function (item, next) {
+        this.attrs = this.attrs.reduce(function(item, next) {
           hash[next.value] ? '' : hash[next.value] = true && item.push(next);
           return item
         }, [])
@@ -1928,7 +2151,7 @@ export default {
       if (num) {
         this.attrs[idx].detail.push(num);
         var hash = {};
-        this.attrs[idx].detail = this.attrs[idx].detail.reduce(function (item, next) {
+        this.attrs[idx].detail = this.attrs[idx].detail.reduce(function(item, next) {
           hash[next] ? '' : hash[next] = true && item.push(next);
           return item
         }, [])
@@ -1945,7 +2168,7 @@ export default {
           type: 'error'
         });
       }
-      that.ruleList.forEach(function (item, index) {
+      that.ruleList.forEach(function(item, index) {
         if (item.ruleName === that.form.selectRule) {
           that.attrs = JSON.parse(item.ruleValue);
 
@@ -2059,7 +2282,7 @@ export default {
         qualificationExpire: null,
         // companyIds:[],
         isDrug: "1", // 是否药品
-        drugImage: null, // 药品展示图
+        drugImage: null, // 头图展示
         drugRegCertNo: null, // 药品注册证书编号
         commonName: null, // 通用名称
         dosageForm: null, // 剂型
@@ -2215,12 +2438,34 @@ export default {
           this.qualificationArr = this.form.qualificationCertificate.split(",");
         }
 
+        if (this.form.isBusinessPermanent == 1) {
+          this.businessValue = true
+        } else {
+          this.businessValue = false
+        }
+
+        if (this.form.isLicensePermanent == 1) {
+          this.licenseValue = true
+        } else {
+          this.licenseValue = false
+        }
+
+        if (this.form.isCertificatePermanent == 1) {
+          this.certificateValue = true
+        } else {
+          this.certificateValue = false
+        }
+
         const expireFieldMap = [
           { expireKey: 'businessExpire', startKey: 'businessStart', endKey: 'businessEnd' },
           { expireKey: 'licenseExpire', startKey: 'licenseStart', endKey: 'licenseEnd' },
           { expireKey: 'certificateExpire', startKey: 'certificateStart', endKey: 'certificateEnd' },
           { expireKey: 'voucherExpire', startKey: 'voucherStart', endKey: 'voucherEnd' },
-          { expireKey: 'qualificationExpire', startKey: 'qualificationCertificateStart', endKey: 'qualificationCertificateEnd' }
+          {
+            expireKey: 'qualificationExpire',
+            startKey: 'qualificationCertificateStart',
+            endKey: 'qualificationCertificateEnd'
+          }
         ];
 
         expireFieldMap.forEach(item => {
@@ -2234,8 +2479,8 @@ export default {
         //组装attrs数据
         if (response.attrs != null) {
           this.attrs = [];
-          response.attrs.forEach(function (item, index) {
-            var data = {value: item.attrName, detail: item.attrValues.split(',')}
+          response.attrs.forEach(function(item, index) {
+            var data = { value: item.attrName, detail: item.attrValues.split(',') }
             that.attrs.push(data);
           });
         }
@@ -2351,10 +2596,24 @@ export default {
             this.form.qualificationCertificateEnd = this.form.qualificationExpire[1];
           }
 
-          // 删除长期有效标识,所有证书都需要填写有效期
-          this.form.isBusinessPermanent = 0;
-          this.form.isLicensePermanent = 0;
-          this.form.isCertificatePermanent = 0;
+          //无语,有的时候要删除,删除了又要加回来。
+          if (!!this.businessValue) {
+            this.form.isBusinessPermanent = 1;
+          } else {
+            this.form.isBusinessPermanent = 0;
+          }
+
+          if (!!this.licenseValue) {
+            this.form.isLicensePermanent = 1;
+          } else {
+            this.form.isLicensePermanent = 0;
+          }
+
+          if (!!this.certificateValue) {
+            this.form.isCertificatePermanent = 1;
+          } else {
+            this.form.isCertificatePermanent = 0;
+          }
 
           // // 组装companyIds
           // if (this.form.companyIds != null && this.form.companyIds != undefined) {
@@ -2377,12 +2636,12 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
-      }).then(function () {
+      }).then(function() {
         return delStoreProduct(productIds);
       }).then(() => {
         this.getList();
         this.msgSuccess("删除成功");
-      }).catch(function () {
+      }).catch(function() {
       });
     },
     /** 导出按钮操作 */
@@ -2392,14 +2651,14 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
-      }).then(function () {
+      }).then(function() {
         return exportStoreProduct(queryParams);
       }).then(response => {
         this.download(response.msg);
-      }).catch(function () {
+      }).catch(function() {
       });
     },
-    handleDrugExport(row){
+    handleDrugExport(row) {
       const productId = row.productId
       this.exportLoading = true;
       exportDrugProduct({ productId: productId }).then(response => {
@@ -2416,12 +2675,12 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
-      }).then(function () {
+      }).then(function() {
         return sync580(productIds);
       }).then(() => {
         this.getList();
         this.msgSuccess("同步成功");
-      }).catch(function () {
+      }).catch(function() {
       });
     },
     /** 批量下架按钮操作 */
@@ -2436,19 +2695,19 @@ export default {
       }).then(() => {
         this.getList();
         this.msgSuccess("下架成功");
-      }).catch(function () {
+      }).catch(function() {
       });
     },
-    handleReviewAudit(){
-      console.log("aaaaaaaaaaaaaaa->",this.form.reviewAudit);
+    handleReviewAudit() {
+      console.log("aaaaaaaaaaaaaaa->", this.form.reviewAudit);
     },
-    switchChange(){
+    switchChange() {
       console.log(this.form.isBusinessLicensePermanent);
     },
-    showOperLog(row){
+    showOperLog(row) {
       getAuthInfo(row.productId).then(response => {
         this.auditLogs = response.auditLog;
-        this.titleValue ="商品:" +"《" +row.productName+"》"+ "审核记录";
+        this.titleValue = "商品:" + "《" + row.productName + "》" + "审核记录";
         this.authVisible = true;
       })
     },
@@ -2457,19 +2716,20 @@ export default {
         .then(_ => {
           done();
         })
-        .catch(_ => {});
+        .catch(_ => {
+        });
     },
     /**
      * 复制商品
      * **/
-    productCopy(row){
-      this.$confirm('确认是否复制当前《'+row.productName+'》商品!', '复制商品', {
+    productCopy(row) {
+      this.$confirm('确认是否复制当前《' + row.productName + '》商品!', '复制商品', {
         confirmButtonText: '确 认',
         cancelButtonText: '取 消',
         type: 'warning'
       }).then(() => {
         copyProduct(row).then(response => {
-          if(response.code === 200){
+          if (response.code === 200) {
             this.$message.success("操作成功!")
             this.getList();
           }
@@ -2577,6 +2837,56 @@ export default {
         { required: true, message: "注意事项不能为空", trigger: "blur" }
       ]);
     },
+    // 组件销毁前清理定时器
+    beforeDestroy() {
+      if (this.categoryOrStoreChangeTimer) {
+        clearTimeout(this.categoryOrStoreChangeTimer);
+      }
+    },
+    //打开溯源码页面
+    openVerify(row) {
+      if (row) {
+        this.currentProductId = row.productId;
+      } else if (this.ids.length > 0) {
+        this.currentProductId = this.ids[0];
+        if (this.ids.length > 1) {
+          this.$message.warning('溯源码管理仅支持单个商品操作,已默认选择第一个商品');
+        }
+      } else {
+        this.$message.error('请先选择需要管理溯源码的商品');
+        return;
+      }
+      this.titleVisible = this.titleVisible + '《' + row.productName + '》';
+      this.verifyDialogVisible = true;
+    },
+    /**
+     * 关闭溯源码弹窗
+     */
+    handleVerifyDialogClose() {
+      if (this.$refs.verifyCodeRef) {
+        this.$refs.verifyCodeRef.fullReset();
+      }
+      setTimeout(() => {
+        this.currentProductId = null;
+      }, 100);
+      this.getList();
+      this.verifyDialogVisible = false;
+      this.titleVisible = "溯源管理";
+    },
   }
 };
 </script>
+
+<style scoped>
+.exempt-device-dialog {
+  z-index: 9999 !important;
+}
+
+.exempt-device-dialog .el-dialog {
+  z-index: 9999 !important;
+}
+
+.exempt-device-dialog .el-dialog__wrapper {
+  z-index: 9999 !important;
+}
+</style>

+ 13 - 93
src/views/hisStore/storeProductAudit/index.vue

@@ -37,16 +37,7 @@
               />
         </el-select>
       </el-form-item>
-<!--      <el-form-item label="所属公司">-->
-<!--        <el-select style="width: 240px" v-model="companyId" multiple placeholder="请选择企业" clearable size="small" >-->
-<!--          <el-option-->
-<!--            v-for="item in companyOptions"-->
-<!--            :key="item.companyId"-->
-<!--            :label="item.companyName"-->
-<!--            :value="item.companyId"-->
-<!--          />-->
-<!--        </el-select>-->
-<!--      </el-form-item>-->
+
       <el-form-item label="所属店铺">
         <el-select style="width: 240px" v-model="storeId" multiple placeholder="请选择企业" clearable size="small" >
           <el-option
@@ -57,16 +48,6 @@
           />
         </el-select>
       </el-form-item>
-      <!-- <el-form-item label="状态" prop="isShow">
-         <el-select style="width: 240px" v-model="queryParams.isShow" placeholder="请选择状态" clearable size="small" >
-         <el-option
-                v-for="item in isShowOptions"
-                :key="item.dictValue"
-                :label="item.dictLabel"
-                :value="item.dictValue"
-              />
-        </el-select>
-      </el-form-item> -->
 
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -98,11 +79,6 @@
 	    <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-<!--    <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
-      <el-tab-pane label="出售中" name="1"></el-tab-pane>
-      <el-tab-pane label="待上架" name="0"></el-tab-pane>
-    </el-tabs>-->
-
     <el-table  height="500" border v-loading="loading" :data="storeProductList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="ID" align="center" prop="productId" />
@@ -198,7 +174,7 @@
           </div>
         </div>
       </template>
-      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px" :disabled="isAuditMode">
         <el-row>
           <el-col :span="12">
             <el-form-item label="商品名称" prop="productName">
@@ -240,7 +216,7 @@
           </el-col>
         </el-row>
         <div v-if="form.isDrug === '1' ">
-          <el-form-item label="药品展示图" prop="drugImage">
+          <el-form-item label="头图展示" prop="drugImage">
             <Material v-model="drugImageArr" type="image" :num="1" :width="150" :height="150"/>
           </el-form-item>
           <div v-if="medicalMallConfig.isMedicalMall">
@@ -346,22 +322,7 @@
         <el-form-item label="商品图片" prop="image">
           <Material v-model="imageArr" type="image" :num="1" :width="150" :height="150"/>
         </el-form-item>
-        <!--        <el-form-item label="商品视频" prop="video">
-                  <div>
-                    <el-upload
-                      ref="upload"
-                      class="upload-demo"
-                      :action="uploadUrl"
-                      :on-success="handleSuccess"
-                      :before-upload="beforeUpload"
-                      :limit="1"
-                      :accept="videoAccept"
-                    >
-                      <el-button size="small" type="primary">点击上传视频</el-button>
-                    </el-upload>
-                    <video v-if="form.video" :src="form.video" controls style="max-width: 300px; max-height: 300px; margin-top: 10px"></video>
-                  </div>
-                </el-form-item>-->
+
         <el-form-item label="轮播图" prop="sliderImage">
           <Material v-model="photoArr" type="image" :num="10" :width="150" :height="150"/>
         </el-form-item>
@@ -641,16 +602,7 @@
             />
           </el-select>
         </el-form-item>
-        <!--        <el-form-item label="所属公司">-->
-        <!--          <el-select style="width: 240px" v-model="form.companyIds" multiple placeholder="请选择企业" clearable size="small" >-->
-        <!--            <el-option-->
-        <!--              v-for="item in companyOptions"-->
-        <!--              :key="item.companyId"-->
-        <!--              :label="item.companyName"-->
-        <!--              :value="item.companyId"-->
-        <!--            />-->
-        <!--          </el-select>-->
-        <!--        </el-form-item>-->
+
         <el-form-item label="所属店铺" prop="storeId" v-if="medicalMallConfig.isStores">
           <el-select style="width: 240px" v-model="form.storeId" placeholder="请选择店铺" clearable size="small">
             <el-option
@@ -747,43 +699,6 @@
           </el-date-picker>
         </el-form-item>
 
-        <!--        <el-form-item v-if="form.isShow === '1' && displayDemo" label="Ⅰ类Ⅱ类备案凭证" prop="voucher">-->
-        <!--          <Material v-model="voucherArr" type="image" :num="1" :width="150" :height="150"/>-->
-        <!--        </el-form-item>-->
-        <!--        <el-form-item v-if="form.isShow === '1' && voucherArr.length > 0 && displayDemo" prop="voucherExpire">-->
-        <!--          <el-date-picker-->
-        <!--            v-model="form.voucherExpire"-->
-        <!--            type="daterange"-->
-        <!--            value-format="yyyy-MM-dd"-->
-        <!--            range-separator="至"-->
-        <!--            start-placeholder="开始日期"-->
-        <!--            end-placeholder="结束日期">-->
-        <!--          </el-date-picker>-->
-        <!--        </el-form-item>-->
-
-        <el-form-item v-if="form.isShow === '1'" label="GMP/GSP认证证书" prop="gmpAuth">
-          <Material v-model="gmpAuthArr" type="image" :num="1" :width="150" :height="150"/>
-        </el-form-item>
-
-        <el-form-item v-if="form.isShow === '1' && businessArr.length > 0" label="GMP/GSP认证证书是否长期有效" prop="isGmpAuthPermanent">
-          <el-switch
-            @change="switchChange()"
-            v-model="gmpAuthValue"
-            active-color="#13ce66"
-            inactive-color="#ff4949">
-          </el-switch>
-        </el-form-item>
-
-        <el-form-item v-if="form.isShow === '1' && gmpAuthArr.length > 0 && !gmpAuthValue" prop="gmpAuthExpire">
-          <el-date-picker
-            v-model="form.gmpAuthExpire"
-            type="daterange"
-            value-format="yyyy-MM-dd"
-            range-separator="至"
-            start-placeholder="开始日期"
-            end-placeholder="结束日期">
-          </el-date-picker>
-        </el-form-item>
         <el-form-item label="国药准字" v-if="form.productType==2" prop="prescribeCode">
           <el-input v-model="form.prescribeCode" placeholder="请输入国药准字"/>
         </el-form-item>
@@ -929,7 +844,8 @@ export default {
   },
   data() {
     return {
-      activeValue: '0',
+      isAuditMode: false, // 添加此标志位控制是否为审核模式
+      activeValue: '1',
       gmpAuthValue:false,
       certificateValue:false,
       licenseValue:false,
@@ -970,7 +886,7 @@ export default {
         { dictValue: "1", dictLabel: "是" }
       ],
 
-      // 药品展示图
+      // 头图展示
       drugImageArr: [],
       //首营资质上传图
       qualificationArr: [],
@@ -1412,6 +1328,7 @@ export default {
     cancel() {
       this.open = false;
       this.reset();
+      this.isAuditMode = false; // 重置审核模式标志
     },
     // 表单重置
     reset() {
@@ -1460,7 +1377,7 @@ export default {
         isDisplay:"1",
         // companyIds:[],
         isDrug: "0", // 是否药品
-        drugImage: null, // 药品展示图
+        drugImage: null, // 头图展示
         drugRegCertNo: null, // 药品注册证书编号
         commonName: null, // 通用名称
         dosageForm: null, // 剂型
@@ -1673,6 +1590,8 @@ export default {
         }
         this.open = true;
         this.title = "修改商品";
+        // 设置为审核模式,禁用商品信息表单
+        this.isAuditMode = true;
       });
     },
     handleUpdate1(oper) {
@@ -1696,6 +1615,7 @@ export default {
           this.form1.auditReason = null;
           this.form1.attachment = null;
           this.getList();
+          this.isAuditMode = false; // 重置审核模式标志
         }else{
           this.$message.error("审核失败",res.msg);
         }

+ 542 - 0
src/views/hisStore/storeVerify/index.vue

@@ -0,0 +1,542 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="核销码" prop="verifyCode">
+        <el-input
+          v-model="queryParams.verifyCode"
+          placeholder="核销码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <!-- 出库状态筛选 -->
+      <el-form-item label="出库状态" prop="outboundStatus">
+        <el-select v-model="queryParams.outboundStatus" placeholder="请选择出库状态" clearable size="small">
+          <el-option label="未出库" value="0" />
+          <el-option label="已出库" value="1" />
+        </el-select>
+      </el-form-item>
+
+      <!-- 核销状态筛选 -->
+      <el-form-item label="核销状态" prop="verifyStatus">
+        <el-select v-model="queryParams.verifyStatus" placeholder="请选择核销状态" clearable size="small">
+          <el-option label="未核销" value="0" />
+          <el-option label="已核销" value="1" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['shop:scrm:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['shop:scrm:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['shop:scrm:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['shop:scrm:export']"
+        >导出</el-button>
+      </el-col>
+      <!-- 新增:批量核销按钮 -->
+      <el-col :span="1.8">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-check-circle"
+          size="mini"
+          :disabled="multiple || hasWriteOffAll"
+          @click="handleBatchWriteOff"
+          v-hasPermi="['shop:scrm:writeOff']"
+        >批量核销</el-button>
+      </el-col>
+      <el-col :span="1.8">
+        <el-button
+          icon="el-icon-s-order"
+          size="mini"
+          type="warning"
+          @click="openDeliveryNote"
+        >批量导入溯源码
+        </el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="scrmList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="主键ID" align="center" prop="id" />
+      <el-table-column label="核销码" align="center" prop="verifyCode" />
+      <el-table-column label="关联商品ID" align="center" prop="productId" />
+      <el-table-column
+        label="出库状态"
+        align="center"
+        prop="outboundStatus"
+        :formatter="formatOutboundStatus"
+      />
+      <el-table-column
+        label="核销状态"
+        align="center"
+        prop="verifyStatus"
+        :formatter="formatVerifyStatus"
+      />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['shop:scrm:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['shop:scrm:remove']"
+          >删除</el-button>
+          <!-- 新增:单个核销按钮 -->
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-check"
+            :disabled="scope.row.verifyStatus === 1"
+            @click="handleSingleWriteOff(scope.row)"
+            v-hasPermi="['shop:scrm:writeOff']"
+          >核销</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改核销码对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <!-- 用户自定义核销码 -->
+        <el-form-item label="核销码" prop="verifyCode">
+          <el-input v-model="form.verifyCode" placeholder="核销码" />
+        </el-form-item>
+        <el-form-item label="出库状态" prop="outboundStatus">
+          <el-radio-group v-model="form.outboundStatus">
+            <el-radio :label="0">未出库</el-radio>
+            <el-radio :label="1">已出库</el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <!-- 核销状态 -->
+        <el-form-item label="核销状态" prop="verifyStatus">
+          <el-radio-group v-model="form.verifyStatus">
+            <el-radio :label="0">未核销</el-radio>
+            <el-radio :label="1">已核销</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog
+      :before-close="handleClose"
+      :visible.sync="verifyNoteOpen"
+      center
+      title="批量导入溯源码"
+      width="35%"
+      :append-to-body="true"
+    >
+      <span slot="footer" class="dialog-footer">
+
+        <el-upload ref="upload" :action="getUploadUrl()" :auto-upload="false" :disabled="verifyUpload.isUploading"
+                   :headers="verifyUpload.headers"
+                   :limit="1" :on-progress="handleFileUploadProgress"
+                   :on-success="handleFileSuccess" accept=".xlsx, .xls" drag
+        >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">
+          将文件拖到此处,或
+          <em>点击上传</em>
+        </div>
+        <div slot="tip" class="el-upload__tip">
+          <el-link style="font-size:12px" type="info" @click="importVerifyNoteTemplate">下载模板</el-link>
+        </div>
+        <div slot="tip" class="el-upload__tip" style="color:red">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+      </el-upload>
+        <el-divider></el-divider>
+        <el-button @click="verifyNoteOpen = false">取 消</el-button>
+        <el-button type="primary" @click="submitDeliveryNote">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listScrm, getScrm, delScrm, addScrm, updateScrm, exportScrm ,importVerifyNoteTemplate,writeOff} from "@/api/hisStore/verify";
+import { getToken } from '@/utils/auth'
+
+export default {
+  name: "Scrm",
+  props: {
+    productId: {
+      type: [Number, String],
+      default: null,
+      required: false
+    }
+  },
+  data() {
+    return {
+      importMsgOpen: false,
+      importMsg: '',
+      verifyUpload: {
+        open: false,
+        title: '',
+        isUploading: false,
+        updateSupport: 0,
+        headers: {Authorization: 'Bearer ' + getToken()},
+        url: process.env.VUE_APP_BASE_API + '/shop/scrm/importExpress',
+      },
+      verifyNoteOpen: false,
+      loading: true,
+      exportLoading: false,
+      ids: [],
+      single: true,
+      multiple: true,
+      hasWriteOffAll: false,
+      showSearch: true,
+      total: 0,
+      scrmList: [],
+      title: "",
+      open: false,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        verifyCode: null,
+        productId: null,
+        outboundStatus: null,
+        verifyStatus: null,
+        status: null,
+        isDel: null,
+      },
+      form: {},
+      rules: {
+        verifyCode: [
+          { required: true, message: "用户自定义核销码不能为空", trigger: "blur" }
+        ],
+        productId: [
+          { required: true, message: "关联商品ID不能为空", trigger: "blur" }
+        ],
+        outboundStatus: [
+          { required: true, message: "出库状态不能为空", trigger: "blur" }
+        ],
+        verifyStatus: [
+          { required: true, message: "核销状态不能为空", trigger: "blur" }
+        ],
+        status: [
+          { required: true, message: "数据状态不能为空", trigger: "blur" }
+        ],
+        isDel: [
+          { required: true, message: "是否删除不能为空", trigger: "blur" }
+        ],
+        createTime: [
+          { required: true, message: "创建时间不能为空", trigger: "blur" }
+        ],
+        updateTime: [
+          { required: true, message: "更新时间不能为空", trigger: "blur" }
+        ]
+      },
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    fullReset() {
+      this.reset();
+      this.queryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        verifyCode: null,
+        productId: null,
+        outboundStatus: null,
+        verifyStatus: null,
+        status: null,
+        isDel: null,
+      };
+      this.scrmList = [];
+      this.total = 0;
+      this.ids = [];
+      this.single = true;
+      this.multiple = true;
+      this.hasWriteOffAll = false;
+      if (this.$refs.form) {
+        this.$refs.form.clearValidate();
+      }
+    },
+    // 出库状态翻译
+    formatOutboundStatus(row) {
+      return row.outboundStatus === 0 ? "未出库" : "已出库";
+    },
+    // 核销状态翻译
+    formatVerifyStatus(row) {
+      return row.verifyStatus === 0 ? "未核销" : "已核销";
+    },
+    // 是否删除翻译
+    formatIsDel(row) {
+      return row.isDel === 0 ? "未删除" : "已删除";
+    },
+    /** 查询核销码列表 */
+    getList() {
+      this.loading = true;
+      this.queryParams.productId = this.productId;
+      console.log("打印pp----------------->", this.productId);
+      listScrm(this.queryParams).then(response => {
+        this.scrmList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        verifyCode: null,
+        productId: this.productId,
+        outboundStatus: 0,
+        verifyStatus: 0,
+        status: 1,
+        isDel: 0
+      };
+      if (this.$refs.form) {
+        this.$refs.form.resetFields();
+      }
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据 - 新增:校验选中行的核销状态
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
+
+      // 校验选中的行是否全部已核销
+      this.hasWriteOffAll = selection.every(item => item.verifyStatus === 1);
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加核销码";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getScrm(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改核销码";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateScrm(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addScrm(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除核销码编号为"' + ids + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delScrm(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有核销码数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportScrm(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
+    },
+    openDeliveryNote() {
+      this.verifyNoteOpen = true
+      this.getAppList();
+    },
+    handleClose(done) {
+      this.$confirm('确认关闭?')
+        .then(_ => {
+          done()
+        })
+        .catch(_ => {
+        })
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.verifyUpload.isUploading = true
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.verifyUpload.open = false;
+      this.verifyUpload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      this.importMsgOpen = true;
+      this.importMsg = response.msg;
+      console.log("打印请求-----------》",response.msg);
+      if(response.code == 200) {
+        this.$message.success(response.msg || '全部数据导入成功');
+      }
+      this.getList();
+    },
+    //发货单模板下载
+    importVerifyNoteTemplate() {
+      importVerifyNoteTemplate().then((response) => {
+        this.download(response.msg);
+      });
+    },
+    // 提交发货单
+    submitDeliveryNote() {
+      const uploadFiles = this.$refs.upload.uploadFiles;
+      if (uploadFiles.length === 0) {
+        this.$message.error('请选择要上传的文件');
+        return;
+      }
+      this.$refs.upload.submit();
+    },
+    getUploadUrl() {
+      if (!this.productId) {
+        this.$message.warning('请先选择商品ID');
+        return '';
+      }
+      return `${this.verifyUpload.url}?productId=${this.productId}`;
+    },
+
+    /** 单个核销操作 */
+    handleSingleWriteOff(row) {
+      this.$confirm(
+        `是否确认核销溯源码【${row.verifyCode}】?`,
+        "核销确认",
+        {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "info"
+        }
+      ).then(() => {
+        return writeOff({ids:[row.id]});
+      }).then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("核销成功!");
+          this.getList(); // 刷新列表
+        }
+      })
+    },
+
+    /** 批量核销操作 */
+    handleBatchWriteOff() {
+      this.$confirm(
+        `是否确认核销选中的${this.ids.length}条溯源码数据?`,
+        "批量核销确认",
+        {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "info"
+        }
+      ).then(() => {
+        // 调用核销接口
+        return writeOff({ids:this.ids});
+      }).then(response => {
+        if (response.code === 200) {
+          this.msgSuccess(`批量核销成功!共核销${this.ids.length}条数据`);
+          this.getList();
+          this.ids = [];
+          this.hasWriteOffAll = false;
+        }
+      })
+    }
+  }
+};
+</script>

+ 8 - 0
src/views/system/config/config.vue

@@ -1505,6 +1505,14 @@
              </el-switch>
            </el-form-item>
 
+          <el-form-item label="是否开启企微二维码" prop="showQwCode">
+            <el-switch
+              v-model="form18.showQwCode"
+              active-color="#13ce66"
+              inactive-color="#ff4949">
+            </el-switch>
+          </el-form-item>
+
           <el-form-item label="登录小程序appId" prop="loginMiniAppId">
             <el-input style="width: 300px" v-model="form18.loginMiniAppId" label="登录小程序appId"></el-input>
           </el-form-item>