|
|
@@ -0,0 +1,2800 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
|
|
|
+
|
|
|
+ <el-form-item label="商品分类" prop="cateId">
|
|
|
+ <treeselect v-model="queryParams.cateId" style="width:205.4px" :options="categoryOptions"
|
|
|
+ :normalizer="normalizer" placeholder="请选择分类"/>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="商品名称" prop="productName">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.productName"
|
|
|
+ placeholder="请输入商品名称"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ @keyup.enter.native="handleQuery"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="是否药品" prop="isDrug">
|
|
|
+ <el-select v-model="queryParams.isDrug" placeholder="请选择" clearable size="small">
|
|
|
+ <el-option
|
|
|
+ v-for="item in isDrugOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="商品类型" prop="productType">
|
|
|
+ <el-select v-model="queryParams.productType" placeholder="请选择商品类型" clearable size="small">
|
|
|
+ <el-option
|
|
|
+ v-for="item in productTypeOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <div v-if="medicalMallConfig.isAudit">
|
|
|
+ <el-form-item label="药品注册证书编号" prop="drugRegCertNo">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.drugRegCertNo"
|
|
|
+ placeholder="请输入药品注册证书编号"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="通用名称" prop="commonName">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.commonName"
|
|
|
+ placeholder="请输入通用名称"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="剂型" prop="dosageForm">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.dosageForm"
|
|
|
+ placeholder="请输入剂型"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="单价" prop="unitPrice">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.unitPrice"
|
|
|
+ placeholder="请输入单价"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="上市许可持有人" prop="mah">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.mah"
|
|
|
+ placeholder="请输入上市许可持有人"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="持有人地址" prop="mahAddress">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.mahAddress"
|
|
|
+ placeholder="请输入持有人地址"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="生产企业" prop="manufacturer">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.manufacturer"
|
|
|
+ placeholder="请输入生产企业"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="生产企业地址" prop="manufacturerAddress">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.manufacturerAddress"
|
|
|
+ placeholder="请输入生产企业地址"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="功能主治" prop="indications">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.indications"
|
|
|
+ placeholder="请输入功能主治"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="用法用量" prop="dosage">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.dosage"
|
|
|
+ placeholder="请输入用法用量"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="不良反应" prop="adverseReactions">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.adverseReactions"
|
|
|
+ placeholder="请输入不良反应"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="禁忌" prop="contraindications">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.contraindications"
|
|
|
+ placeholder="请输入禁忌"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="注意事项" prop="precautions">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.precautions"
|
|
|
+ placeholder="请输入注意事项"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="规格" prop="prescribeSpec">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.prescribeSpec"
|
|
|
+ placeholder="请输入规格"
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <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>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <el-row :gutter="10" class="mb8">
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ icon="el-icon-plus"
|
|
|
+ size="mini"
|
|
|
+ @click="handleAdd"
|
|
|
+ v-hasPermi="['store:storeProduct:add']"
|
|
|
+ >新增
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="success"
|
|
|
+ icon="el-icon-edit"
|
|
|
+ size="mini"
|
|
|
+ :disabled="multiple"
|
|
|
+ @click="handleUpdate"
|
|
|
+ v-hasPermi="['store:storeProduct:edit']"
|
|
|
+ >修改
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ size="mini"
|
|
|
+ :disabled="multiple"
|
|
|
+ @click="handleDelete"
|
|
|
+ v-hasPermi="['store:storeProduct:remove']"
|
|
|
+ >删除
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="info"
|
|
|
+ plain
|
|
|
+ icon="el-icon-upload2"
|
|
|
+ size="mini"
|
|
|
+ @click="handleImport"
|
|
|
+ v-hasPermi="['store:storeProduct:import']"
|
|
|
+ >导入
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="warning"
|
|
|
+ icon="el-icon-download"
|
|
|
+ size="mini"
|
|
|
+ @click="handleExport"
|
|
|
+ v-hasPermi="['store:storePayment:export']"
|
|
|
+ >导出
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+<!-- <el-col :span="1.5">-->
|
|
|
+<!-- <el-button-->
|
|
|
+<!-- type="primary"-->
|
|
|
+<!-- plain-->
|
|
|
+<!-- icon="el-icon-refresh"-->
|
|
|
+<!-- size="mini"-->
|
|
|
+<!-- :disabled="multiple"-->
|
|
|
+<!-- @click="handleSync"-->
|
|
|
+<!-- v-hasPermi="['store:storeProduct:sync']"-->
|
|
|
+<!-- >同步-->
|
|
|
+<!-- </el-button>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <el-col :span="1.5">-->
|
|
|
+<!-- <el-button-->
|
|
|
+<!-- type="danger"-->
|
|
|
+<!-- plain-->
|
|
|
+<!-- icon="el-icon-close"-->
|
|
|
+<!-- size="mini"-->
|
|
|
+<!-- :disabled="multiple"-->
|
|
|
+<!-- @click="handleBatchOff"-->
|
|
|
+<!-- v-hasPermi="['store:storeProduct:updateIsShow']"-->
|
|
|
+<!-- >批量下架-->
|
|
|
+<!-- </el-button>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+ <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="1"></el-tab-pane>-->
|
|
|
+<!-- <el-tab-pane label="待上架" name="0"></el-tab-pane>-->
|
|
|
+<!-- <el-tab-pane label="待审核" name="3"></el-tab-pane>-->
|
|
|
+<!-- <el-tab-pane label="已驳回" name="4"></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"/>
|
|
|
+ <el-table-column label="商品图片" align="center" width="120">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-popover
|
|
|
+ placement="right"
|
|
|
+ title=""
|
|
|
+ trigger="hover">
|
|
|
+ <img slot="reference" :src="scope.row.image" width="100">
|
|
|
+ <img :src="scope.row.image" style="max-width: 150px;">
|
|
|
+ </el-popover>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="商品名称" show-overflow-tooltip align="center" prop="productName"/>
|
|
|
+ <el-table-column label="分类" align="center" prop="cateName"/>
|
|
|
+ <el-table-column label="售价" align="center" prop="price">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span v-if="scope.row.price!=null">{{ scope.row.price.toFixed(2) }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="原价" align="center" prop="otPrice">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span v-if="scope.row.otPrice!=null">{{ scope.row.otPrice.toFixed(2) }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="销量" align="center" prop="sales"/>
|
|
|
+ <el-table-column label="库存" align="center" prop="stock"/>
|
|
|
+ <el-table-column label="类型" align="center" prop="productType">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag prop="productType" v-for="(item, index) in productTypeOptions"
|
|
|
+ v-if="scope.row.productType==item.dictValue">{{ item.dictLabel }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="状态" align="center" prop="isShow">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <dict-tag :options="isShowOptions" :value="scope.row.isShow"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+<!-- <el-table-column label="同步状态" align="center" prop="pushStatus">-->
|
|
|
+<!-- <template slot-scope="scope">-->
|
|
|
+<!-- <el-tag :type="scope.row.pushStatus === 1 ? 'success' : scope.row.pushStatus === 2 ? 'danger' : 'warning'">-->
|
|
|
+<!-- {{-->
|
|
|
+<!-- scope.row.pushStatus === 0 ? '推送中' : scope.row.pushStatus === 1 ? '成功' : scope.row.pushStatus === 2 ? '失败' : '未同步'-->
|
|
|
+<!-- }}-->
|
|
|
+<!-- </el-tag>-->
|
|
|
+<!-- </template>-->
|
|
|
+<!-- </el-table-column>-->
|
|
|
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200px">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-edit"
|
|
|
+ @click="handleUpdate(scope.row)"
|
|
|
+ v-hasPermi="['store:storeProduct:edit']"
|
|
|
+ >修改
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-postcard"
|
|
|
+ @click="showOperLog(scope.row)"
|
|
|
+ v-hasPermi="['his:storeProduct:auditLog']"
|
|
|
+ >审核记录
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ @click="handleDelete(scope.row)"
|
|
|
+ v-hasPermi="['store:storeProduct:remove']"
|
|
|
+ >删除
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-document-copy"
|
|
|
+ @click="productCopy(scope.row)"
|
|
|
+ v-hasPermi="['his:storeProduct:copyProduct']"
|
|
|
+ >一键复制
|
|
|
+ </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="open1" width="580px" append-to-body>
|
|
|
+ <el-form ref="form1" :model="form1" :rules="rules" label-width="80px">
|
|
|
+ <el-form-item label="商品状态" prop="status">
|
|
|
+ <el-radio-group v-model="form1.isShow">
|
|
|
+ <el-radio :label="item.dictValue" v-for="item in isShowOptions">{{ item.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="商城展示" prop="isDisplay">
|
|
|
+ <el-radio-group v-model="form1.isDisplay">
|
|
|
+ <el-radio :label="item.dictValue" v-for="item in isDisplayOptions">{{ item.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="submitForm1">确 定</el-button>
|
|
|
+ <el-button @click="cancel1">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 添加或修改商品对话框 -->
|
|
|
+ <el-dialog :title="title" v-if="open" :fullscreen="isFullscreen" :visible.sync="open" width="1000px" append-to-body
|
|
|
+ :show-close="false">
|
|
|
+ <template v-slot:title>
|
|
|
+ <div style="display: flex; justify-content: space-between; align-items: center;">
|
|
|
+ <span>{{ title }}</span>
|
|
|
+ <div>
|
|
|
+ <!-- 全屏按钮 -->
|
|
|
+ <el-button type="text" @click="handleFullScreen" size="middle">
|
|
|
+ <i class="el-icon-full-screen"></i>
|
|
|
+ </el-button>
|
|
|
+ <!--关闭按钮-->
|
|
|
+ <el-button type="text" @click="open = false">
|
|
|
+ <i class="el-icon-close"></i>
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="商品名称" prop="productName">
|
|
|
+ <el-input v-model="form.productName" @blur="handleProductNameBlur" placeholder="请输入商品名称" @input="onProductNameInput"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="商品分类" prop="cateId">
|
|
|
+ <treeselect v-model="form.cateId" :options="categoryOptions" :normalizer="normalizer"
|
|
|
+ placeholder="请选择上级分类" @input="onCategoryOrStoreChange"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="商品类型" prop="productType">
|
|
|
+ <el-select style="width: 240px" v-model="form.productType" placeholder="请选择商品类型" clearable
|
|
|
+ size="small">
|
|
|
+ <el-option
|
|
|
+ v-for="item in productTypeOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </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">
|
|
|
+ <el-input v-model="form.keyword" placeholder="请输入关键字"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="单位名" prop="unitName">
|
|
|
+ <el-input v-model="form.unitName" placeholder="请输入单位名"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="10">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="是否药品" prop="isDrug" v-if="!isMedicalDeviceCategory">
|
|
|
+ <el-radio-group v-model="form.isDrug">
|
|
|
+ <el-radio
|
|
|
+ v-for="item in isDrugOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictValue"
|
|
|
+ >{{ item.dictLabel }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <div v-if="form.isDrug === '1' ">
|
|
|
+ <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="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" v-if="!isMedicalDeviceCategory">
|
|
|
+ <el-input v-model="form.commonName" placeholder="请输入通用名称"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="剂型" prop="dosageForm" v-if="!isMedicalDeviceCategory">
|
|
|
+ <el-input v-model="form.dosageForm" placeholder="请输入剂型"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="单价" prop="unitPrice">
|
|
|
+ <el-input v-model="form.unitPrice" placeholder="请输入单价" type="number"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="规格" prop="prescribeSpec">
|
|
|
+ <el-input v-model="form.prescribeSpec" placeholder="请输入规格"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="上市许可持有人" prop="mah">
|
|
|
+ <el-input v-model="form.mah" placeholder="请输入上市许可持有人"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="持有人地址" prop="mahAddress">
|
|
|
+ <el-input v-model="form.mahAddress" placeholder="请输入上市许可持有人地址"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="生产企业" prop="manufacturer">
|
|
|
+ <el-input v-model="form.manufacturer" placeholder="请输入生产企业"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="企业地址" prop="manufacturerAddress">
|
|
|
+ <el-input v-model="form.manufacturerAddress" placeholder="请输入生产企业地址"/>
|
|
|
+ </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" v-if="!isMedicalDeviceCategory">
|
|
|
+ <el-input v-model="form.indications" type="textarea" placeholder="请输入功能主治"/>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="成分" prop="ingredient" v-if="!isMedicalDeviceCategory">
|
|
|
+ <el-input
|
|
|
+ v-model="form.ingredient"
|
|
|
+ type="textarea"
|
|
|
+ placeholder="请输入成分"
|
|
|
+ @blur="handleIngredientBlur"
|
|
|
+ @input="onIngredientInput"
|
|
|
+ />
|
|
|
+ <div v-if="ingredientError" class="el-form-item__error">{{ ingredientError }}</div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <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" v-if="!isMedicalDeviceCategory">
|
|
|
+ <el-input v-model="form.adverseReactions" type="textarea" placeholder="请输入不良反应"/>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <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" v-if="!isMedicalDeviceCategory">
|
|
|
+ <el-input v-model="form.precautions" type="textarea" placeholder="请输入注意事项"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-collapse-item>
|
|
|
+ </el-collapse>
|
|
|
+ </div>
|
|
|
+ <el-form-item label="说明书" prop="instructionManual">
|
|
|
+ <editor ref="instructionManualRef" @on-text-change="updateInstructionManualText"/>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="商品简介" prop="productInfo">
|
|
|
+ <el-input v-model="form.productInfo" type="textarea" :rows="2" placeholder="请输入商品简介"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <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="sliderImage">
|
|
|
+ <Material v-model="photoArr" type="image" :num="10" :width="150" :height="150"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="商品规格:" props="specType">
|
|
|
+ <el-radio-group v-model="form.specType">
|
|
|
+ <el-radio :label="0" class="radio">单规格</el-radio>
|
|
|
+ <el-radio :label="1">多规格</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <!-- 多规格添加-->
|
|
|
+ <el-col :span="24" v-if="form.specType === 1" class="noForm">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="选择规格:" prop="">
|
|
|
+ <div class="acea-row row-middle">
|
|
|
+ <el-select v-model="form.selectRule" style="width: 23%;">
|
|
|
+ <el-option v-for="(item, index) in ruleList" :value="item.ruleName" :key="index">{{
|
|
|
+ item.ruleName
|
|
|
+ }}
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ <el-button style="margin-left:10px;" type="primary" class="mr20" @click="confirm">确认</el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item v-if="attrs!=null&&attrs.length!==0">
|
|
|
+ <div v-for="(item, index) in attrs" :key="index">
|
|
|
+ <div class="acea-row row-middle"><span class="mr5">{{ item.value }}</span>
|
|
|
+ <i class="el-icon-circle-close" @click="handleRemoveRole(index)"></i>
|
|
|
+ </div>
|
|
|
+ <div class="rulesBox">
|
|
|
+ <el-tag type="dot" closable color="primary" v-for="(j, indexn) in item.detail" :key="indexn"
|
|
|
+ :name="j" class="mr20" @close="handleRemove2(item.detail,indexn)">{{ j }}
|
|
|
+ </el-tag>
|
|
|
+ <el-input placeholder="请输入属性名称" v-model="item.detail.attrsVal"
|
|
|
+ style="width: 200px">
|
|
|
+ <el-button slot="append" type="primary" @click="createAttr(item.detail.attrsVal,index)">添加
|
|
|
+ </el-button>
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <el-col :span="24" v-if="createBnt">
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" size="small" icon="md-add" @click="addBtn" class="mr15">添加新规格</el-button>
|
|
|
+ <el-button type="success" size="small" @click="generate">立即生成</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24" v-if="showIput">
|
|
|
+ <el-col :xl="6" :lg="9" :md="10" :sm="24" :xs="24">
|
|
|
+ <el-form-item label="规格:">
|
|
|
+ <el-input placeholder="请输入规格" v-model="formDynamic.attrsName"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xl="6" :lg="9" :md="10" :sm="24" :xs="24">
|
|
|
+ <el-form-item label="规格值:">
|
|
|
+ <el-input v-model="formDynamic.attrsVal" placeholder="请输入规格值"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xl="6" :lg="5" :md="10" :sm="24" :xs="24">
|
|
|
+ <el-button type="primary" @click="createAttrName">确定</el-button>
|
|
|
+ <el-button type="danger" @click="closeAttrName">取消</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-col>
|
|
|
+ <!-- 多规格设置-->
|
|
|
+ <el-col :xl="24" :lg="24" :md="24" :sm="24" :xs="24" v-if="manyFormValidate!=null&&manyFormValidate.length">
|
|
|
+ <!-- 多规格表格-->
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="商品属性:" class="labeltop">
|
|
|
+
|
|
|
+ <el-table :data="manyFormValidate" size="small" style="width: 90%;" border>
|
|
|
+ <el-table-column type="myindex" v-for="(item,index) in form.header" :key="index"
|
|
|
+ :width="item.minWidth" :label="item.title" :property="item.slot" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div v-if="scope.column.property == 'image'" align="center">
|
|
|
+ <single-img v-model="scope.row[scope.column.property]" type="image" :num="1" :width="60"
|
|
|
+ :height="60"/>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="scope.column.property.indexOf('value') != -1" align="center">
|
|
|
+ {{ scope.row[scope.column.property] }}
|
|
|
+ </div>
|
|
|
+ <div v-else-if="scope.column.property == 'action'" align="center">
|
|
|
+ <a @click="delAttrTable(scope.$index)" align="center">删除</a>
|
|
|
+ </div>
|
|
|
+ <div v-else align="center">
|
|
|
+ <el-input v-model="scope.row[scope.column.property]" align="center"/>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-col>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 单规格表格-->
|
|
|
+ <el-col :xl="23" :lg="24" :md="24" :sm="24" :xs="24" v-if="form.specType === 0" style="">
|
|
|
+ <el-form-item>
|
|
|
+ <el-table :data="oneFormValidate" size="small" border>
|
|
|
+ <el-table-column prop="image" label="图片" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <single-img v-model="scope.row.image" type="image" :num="1" :width="60" :height="60"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="price" label="售价" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.price"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="agentPrice" label="代理价" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.agentPrice"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="cost" label="成本价" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.cost"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="otPrice" label="原价" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.otPrice"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="stock" label="库存" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.stock" maxlength="7"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="barCode" label="商品条码" width="130px" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.barCode"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="barCode" label="组合编号" width="130px" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.groupBarCode"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="weight" label="重量(KG)" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.weight"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="volume" label="体积(m³)" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.volume"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="volume" label="所需积分" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.integral"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="volume" label="一级返佣" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.brokerage"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="volume" label="二级返佣" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.brokerageTwo"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="volume" label="三级返佣" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input type="text" v-model="scope.row.brokerageThree"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="运费模板:" prop="tempId">
|
|
|
+ <div class="acea-row">
|
|
|
+ <el-select v-model="form.tempId" class="mr20">
|
|
|
+ <el-option v-for="(item,index) in templateList" :value="item.id" :key="index" :label="item.name">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-form-item label="商品详情" prop="description">
|
|
|
+ <editor ref="myeditor" @on-text-change="updateText"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="商品状态" prop="isShow">
|
|
|
+ <el-radio-group v-model="form.isShow">
|
|
|
+ <el-radio
|
|
|
+ :label="item.dictValue"
|
|
|
+ v-for="item in isShowOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ v-if="item.dictValue === '0' || item.dictValue === '1'">
|
|
|
+ {{ item.dictLabel }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="是否热卖" prop="isHot">
|
|
|
+ <el-radio-group v-model="form.isHot">
|
|
|
+ <el-radio :label="item.dictValue" v-for="item in isHotOptions">{{ item.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="猜你喜欢" prop="isGood">
|
|
|
+ <el-radio-group v-model="form.isGood">
|
|
|
+ <el-radio :label="item.dictValue" v-for="item in isGoodOptions">{{ item.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="精品推荐" prop="isBest">
|
|
|
+ <el-radio-group v-model="form.isBest">
|
|
|
+ <el-radio :label="item.dictValue" v-for="item in isBestOptions">{{ item.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="新品首发" prop="isNew">
|
|
|
+ <el-radio-group v-model="form.isNew">
|
|
|
+ <el-radio :label="item.dictValue" v-for="item in isNewOptions">{{ item.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="返还积分">
|
|
|
+ <el-input-number v-model="form.giveIntegral" :min="0" placeholder="请输入积分"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="商城展示" prop="isDisplay">
|
|
|
+ <el-radio-group v-model="form.isDisplay">
|
|
|
+ <el-radio :label="item.dictValue" v-for="item in isDisplayOptions">{{ item.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+
|
|
|
+ <el-form-item label="排序" prop="sort">
|
|
|
+ <el-input-number :min="0" v-model="form.sort" placeholder="请输入排序"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="销量" prop="sales">
|
|
|
+ <el-input-number :min="0" v-model="form.sales" placeholder="请输入销量"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ </el-row>
|
|
|
+ <el-form-item label="推广分类" prop="tuiCateId">
|
|
|
+ <el-select style="width: 240px" v-model="form.tuiCateId" placeholder="请选择推广分类" clearable size="small">
|
|
|
+ <el-option
|
|
|
+ v-for="item in productTuiCateOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <div v-if="form.isDrug === '1'">
|
|
|
+ <el-form-item v-if="form.isShow==='1'" label="审核说明" prop="reviewAudit">
|
|
|
+ <el-select style="width: 240px" v-model="form.reviewAudit" placeholder="请选择审核说明" clearable
|
|
|
+ size="small">
|
|
|
+ <el-option
|
|
|
+ v-for="item in reviewAuditOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="非首营链接" prop="businessLink" v-if="form.reviewAudit === '1'">
|
|
|
+ <el-input :min="0" v-model="form.businessLink" placeholder="请输入非首营链接"/>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 生产企业营业执照 -->
|
|
|
+ <el-form-item v-if="form.isShow === '1'" label="生产企业营业执照" prop="business">
|
|
|
+ <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="isBusinessPermanent">
|
|
|
+ <el-switch 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="isLicensePermanent">
|
|
|
+ <el-switch 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' && licenseArr.length > 0" label="商品注册证/备案凭证是否长期有效" prop="isCertificatePermanent">
|
|
|
+ <el-switch 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="结束日期">
|
|
|
+ </el-date-picker>
|
|
|
+ </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>
|
|
|
+ <el-form-item label="规格" v-if="form.productType==2" prop="prescribeSpec">
|
|
|
+ <el-input v-model="form.prescribeSpec" placeholder="请输入规格"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="生产厂家" v-if="form.productType==2" prop="prescribeFactory">
|
|
|
+ <el-input v-model="form.prescribeFactory" placeholder="请输入生产厂家"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="处方名" v-if="form.productType==2" prop="prescribeName">
|
|
|
+ <el-input v-model="form.prescribeName" 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>
|
|
|
+ <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
|
|
|
+ <el-upload
|
|
|
+ ref="upload"
|
|
|
+ :limit="1"
|
|
|
+ accept=".xlsx, .xls"
|
|
|
+ :headers="upload.headers"
|
|
|
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
|
|
|
+ :disabled="upload.isUploading"
|
|
|
+ :on-progress="handleFileUploadProgress"
|
|
|
+ :on-success="handleFileSuccess"
|
|
|
+ :auto-upload="false"
|
|
|
+ drag
|
|
|
+ >
|
|
|
+ <i class="el-icon-upload"></i>
|
|
|
+ <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
|
|
+ <div class="el-upload__tip text-center" slot="tip">
|
|
|
+ <div class="el-upload__tip" slot="tip">
|
|
|
+ <!-- <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的数据 -->
|
|
|
+ </div>
|
|
|
+ <span>仅允许导入xls、xlsx格式文件。</span>
|
|
|
+ <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
|
|
|
+ @click="importTemplate">下载模板
|
|
|
+ </el-link>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="submitFileForm">确 定</el-button>
|
|
|
+ <el-button @click="upload.open = false">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ title="首营资质消息提示"
|
|
|
+ :visible.sync="dialogVisible"
|
|
|
+ width="40%"
|
|
|
+ center>
|
|
|
+ <div v-for="(item,index) in promptList">({{ index + 1 }})、{{ item }}</div>
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="dialogVisible = false">已 知 晓</el-button>
|
|
|
+ </span>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ :title=titleValue
|
|
|
+ :visible.sync="authVisible"
|
|
|
+ width="50%"
|
|
|
+ :before-close="handleClose"
|
|
|
+ center>
|
|
|
+ <el-table :data="auditLogs" border>
|
|
|
+ <el-table-column label="描述" align="center" prop="des" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="操作人员" align="center" prop="operName" width="100" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
|
|
|
+ <el-table-column label="操作日期" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span>{{ parseTime(scope.row.operTime) }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="审核理由" align="center" prop="reason" ></el-table-column>
|
|
|
+ <el-table-column label="图片" align="center" prop="attachImage" width="100" >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-image
|
|
|
+ style="width: 100px"
|
|
|
+ :src="scope.row.attachImage"
|
|
|
+ :preview-src-list="[scope.row.attachImage]"
|
|
|
+ v-if="scope.row.attachImage">
|
|
|
+ </el-image>
|
|
|
+ <span v-else >无图片</span >
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
+ <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>
|
|
|
+
|
|
|
+ <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>
|
|
|
+
|
|
|
+<script>
|
|
|
+import {
|
|
|
+ genFormatAttr,
|
|
|
+ listStoreProduct,
|
|
|
+ getStoreProduct,
|
|
|
+ delStoreProduct,
|
|
|
+ addOrEdit,
|
|
|
+ exportStoreProduct,
|
|
|
+ importTemplate,
|
|
|
+ batchModify,
|
|
|
+ sync580,
|
|
|
+ updateIsShow, exportDrugProduct,getAuthInfo,copyProduct,selectForbiddenKeywords,checkStoreLicense,getExemptSecondMedicalDeviceList
|
|
|
+} from "@/api/hisStore/platformProduct";
|
|
|
+import {qualifications} from "@/api/hisStore/platformProduct";
|
|
|
+import {getAllStoreProductCategory} from "@/api/hisStore/storeProductCategory";
|
|
|
+import {getAllStoreProductRule} from "@/api/hisStore/storeProductRule";
|
|
|
+import {getAllShippingTemplates} from "@/api/hisStore/shippingTemplates";
|
|
|
+import {getToken} from "@/utils/auth";
|
|
|
+import Treeselect from "@riophae/vue-treeselect";
|
|
|
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
|
|
+import Editor from '@/components/Editor/wang';
|
|
|
+import Material from '@/components/Material'
|
|
|
+import singleImg from '@/components/Material/single'
|
|
|
+import {getCompanyList} from "@/api/company/company";
|
|
|
+import {listStore} from '@/api/hisStore/store'
|
|
|
+import {getConfigByKey} from '@/api/system/config'
|
|
|
+import VerifyCode from '@/views/hisStore/storeVerify/index.vue';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "PlatFormProduct",
|
|
|
+ components: {
|
|
|
+ Treeselect,
|
|
|
+ Editor,
|
|
|
+ Material,
|
|
|
+ VerifyCode,
|
|
|
+ singleImg
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.handleNoticeInfo();
|
|
|
+ });
|
|
|
+ this.getDicts("sys_order_status").then(response => {
|
|
|
+ this.orderOptions = response.data;
|
|
|
+ });
|
|
|
+ this.getDicts("store_product_tui_cate").then((response) => {
|
|
|
+ this.productTuiCateOptions = response.data;
|
|
|
+ });
|
|
|
+ getConfigByKey("medicalMall.func.switch").then(response => {
|
|
|
+ if (response.data && response.data.configValue) {
|
|
|
+ this.medicalMallConfig = JSON.parse(response.data.configValue);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.getDicts("store_product_enable").then((response) => {
|
|
|
+ this.isNewOptions = response.data;
|
|
|
+ this.isBestOptions = response.data;
|
|
|
+ this.isHotOptions = response.data;
|
|
|
+ this.isGoodOptions = response.data;
|
|
|
+ this.isDisplayOptions = response.data;
|
|
|
+ });
|
|
|
+ this.getDicts("store_product_type").then((response) => {
|
|
|
+ this.productTypeOptions = response.data;
|
|
|
+ // if (!this.medicalMallConfig.isMedicalMall &&
|
|
|
+ // this.productTypeOptions.length === 4) {
|
|
|
+ // //删除后两项
|
|
|
+ // this.productTypeOptions.splice(2, 2);
|
|
|
+ // }
|
|
|
+ });
|
|
|
+ this.getDicts("store_product_is_show").then((response) => {
|
|
|
+ this.isShowOptions = response.data;
|
|
|
+ });
|
|
|
+ getAllShippingTemplates().then(response => {
|
|
|
+ this.templateList = response.data;
|
|
|
+ });
|
|
|
+ getAllStoreProductRule().then(response => {
|
|
|
+ this.ruleList = response.data;
|
|
|
+ });
|
|
|
+ getCompanyList().then(response => {
|
|
|
+ this.companyOptions = response.data;
|
|
|
+ });
|
|
|
+ listStore().then(response => {
|
|
|
+ this.storeOptions = response.rows;
|
|
|
+ });
|
|
|
+
|
|
|
+ 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: {
|
|
|
+ businessArr(val) {
|
|
|
+ this.form.business = val.join(',');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 1. 组件层面清除校验
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate('business');
|
|
|
+ }
|
|
|
+ // 2. DOM层面强制移除错误提示
|
|
|
+ const errorDom = document.querySelector('.el-form-item__error[style*="business"]');
|
|
|
+ if (errorDom) {
|
|
|
+ errorDom.style.display = 'none'; // 隐藏提示
|
|
|
+ // 或彻底移除:errorDom.remove();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 生产许可证
|
|
|
+ licenseArr(val) {
|
|
|
+ this.form.license = val.join(',');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 1. 组件层面清除校验
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate('license');
|
|
|
+ }
|
|
|
+ // 2. DOM层面强制移除错误提示
|
|
|
+ const errorDom = document.querySelector('.el-form-item__error[style*="license"]');
|
|
|
+ if (errorDom) {
|
|
|
+ errorDom.style.display = 'none'; // 隐藏提示
|
|
|
+ // 或彻底移除:errorDom.remove();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 注册证书
|
|
|
+ certificateArr(val) {
|
|
|
+ this.form.certificate = val.join(',');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 1. 组件层面清除校验
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate('certificate');
|
|
|
+ }
|
|
|
+ // 2. DOM层面强制移除错误提示
|
|
|
+ const errorDom = document.querySelector('.el-form-item__error[style*="certificate"]');
|
|
|
+ if (errorDom) {
|
|
|
+ errorDom.style.display = 'none'; // 隐藏提示
|
|
|
+ // 或彻底移除:errorDom.remove();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 其他字段(如drugImageArr等)按相同逻辑补充
|
|
|
+ drugImageArr(val) {
|
|
|
+ this.form.drugImage = val.join(',');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate('drugImage');
|
|
|
+ this.$refs.form.validateField('drugImage');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ voucherArr(val) {
|
|
|
+ this.form.voucher = val.length > 0 ? val.join(',') : '';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs.form && this.$refs.form.validateField('voucher');
|
|
|
+ this.$refs.form && this.$refs.form.validateField('voucherExpire');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ gmpAuthArr(val) {
|
|
|
+ this.form.gmpAuth = val.length > 0 ? val.join(',') : '';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs.form && this.$refs.form.validateField('gmpAuth');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ imageArr(val) {
|
|
|
+ this.form.image = val.length > 0 ? val.join(',') : '';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs.form && this.$refs.form.validateField('image');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ photoArr(val) {
|
|
|
+ this.form.sliderImage = val.length > 0 ? val.join(',') : '';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs.form && this.$refs.form.validateField('sliderImage');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ qualificationArr(val) {
|
|
|
+ this.form.qualificationCertificate = val.length > 0 ? val.join(',') : '';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs.form && this.$refs.form.validateField('qualificationCertificate');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 监听商品分类变化
|
|
|
+ 'form.cateId': {
|
|
|
+ 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('处方药');
|
|
|
+
|
|
|
+ // 如果是处方药,则移除相关字段的必填校验
|
|
|
+ if (isPrescriptionDrug) {
|
|
|
+ // 移除必填校验规则
|
|
|
+ const fieldsToRemoveRequired = ['indications', 'ingredient', 'dosage', 'adverseReactions', 'contraindications', 'precautions'];
|
|
|
+ fieldsToRemoveRequired.forEach(field => {
|
|
|
+ if (this.rules[field]) {
|
|
|
+ // 过滤掉 required 规则
|
|
|
+ this.rules[field] = this.rules[field].filter(rule => rule.required !== true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果不是处方药,恢复默认的必填校验规则
|
|
|
+ // 恢复 ingredient 字段的必填规则
|
|
|
+ if (!this.rules.ingredient) {
|
|
|
+ this.rules.ingredient = [];
|
|
|
+ }
|
|
|
+ if (!this.rules.ingredient.some(rule => rule.required)) {
|
|
|
+ this.rules.ingredient.unshift({ required: true, message: "成分不能为空", trigger: "blur" });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复其他字段的必填规则
|
|
|
+ const requiredRules = {
|
|
|
+ indications: [{ required: true, message: "功能主治不能为空", trigger: "blur" }],
|
|
|
+ dosage: [{ required: true, message: "用法用量不能为空", trigger: "blur" }],
|
|
|
+ adverseReactions: [{ required: true, message: "不良反应不能为空", trigger: "blur" }],
|
|
|
+ contraindications: [{ required: true, message: "禁忌不能为空", trigger: "blur" }],
|
|
|
+ precautions: [{ required: true, message: "注意事项不能为空", trigger: "blur" }]
|
|
|
+ };
|
|
|
+
|
|
|
+ Object.keys(requiredRules).forEach(field => {
|
|
|
+ if (!this.rules[field]) {
|
|
|
+ this.rules[field] = [];
|
|
|
+ }
|
|
|
+ // 检查是否已有 required 规则,如果没有就添加
|
|
|
+ if (!this.rules[field].some(rule => rule.required)) {
|
|
|
+ this.rules[field] = [...requiredRules[field], ...this.rules[field]];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ this.ingredientError = '';
|
|
|
+ // 清除验证状态
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate([
|
|
|
+ 'indications',
|
|
|
+ 'ingredient',
|
|
|
+ 'dosage',
|
|
|
+ 'adverseReactions',
|
|
|
+ 'contraindications',
|
|
|
+ 'precautions'
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 只有当两个值都存在时才进行检查(排除初始化情况)
|
|
|
+ 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
|
|
|
+ },
|
|
|
+ 'form.isDrug': {
|
|
|
+ handler(newVal) {
|
|
|
+ if (newVal === '1') {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.instructionManualRef) {
|
|
|
+ this.$refs.instructionManualRef.setText(this.form.instructionManual || "");
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ },
|
|
|
+ // 监听所属店铺变化
|
|
|
+ 'form.storeId': {
|
|
|
+ handler(newVal, oldVal) {
|
|
|
+ // 只有当两个值都存在时才进行检查(排除初始化情况)
|
|
|
+ if (newVal && this.form.cateId && this.isFormInitialized) {
|
|
|
+ this.debounceCheckStoreLicense();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ ingredientError: '', // 成分禁止提示
|
|
|
+ productNameError: '', // 商品名称禁止提示
|
|
|
+ certificateValue:false,
|
|
|
+ licenseValue:false,
|
|
|
+ businessValue:false,
|
|
|
+ // 溯源码弹窗相关
|
|
|
+ titleVisible:'溯源管理:',
|
|
|
+ verifyDialogVisible: false, // 溯源码弹窗显示状态
|
|
|
+ currentProductId: null, // 当前选中的商品ID
|
|
|
+ storeLicenseErrorMessage: '', // 店铺许可证错误信息
|
|
|
+ isFormInitialized: false, // 表单是否已初始化完成
|
|
|
+ licenseCheckTimer: null, // 防抖定时器
|
|
|
+ storeLicenseCheckFailed: false, // 店铺许可证接口检查是否失败
|
|
|
+ auditLogs:[],
|
|
|
+ titleValue:null,
|
|
|
+ displayDemo: false,
|
|
|
+ cateIdToNameMap: {},
|
|
|
+ showMedicalDeviceCode: false, // 是否显示器械编码输入框
|
|
|
+ showExemptDeviceButton: false, // 是否显示显示器免按钮
|
|
|
+ businessArr: [],
|
|
|
+ licenseArr: [],
|
|
|
+ certificateArr: [],
|
|
|
+ voucherArr: [],
|
|
|
+ gmpAuthArr: [],
|
|
|
+ // 证书过期错误提示
|
|
|
+ businessExpireError: '',
|
|
|
+ licenseExpireError: '',
|
|
|
+ certificateExpireError: '',
|
|
|
+ activeValue: '1',
|
|
|
+ orderOptions: [],
|
|
|
+ medicalMallConfig: {},
|
|
|
+ promptList: [],
|
|
|
+ dialogVisible: false,
|
|
|
+ authVisible:false,
|
|
|
+ companyId: null,
|
|
|
+ storeId: null,
|
|
|
+ isAudit: null,
|
|
|
+ uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS",
|
|
|
+ //videoAccept:"video/*",
|
|
|
+ upload: {
|
|
|
+ // 是否显示弹出层
|
|
|
+ open: false,
|
|
|
+ // 弹出层标题
|
|
|
+ title: "",
|
|
|
+ // 是否禁用上传
|
|
|
+ isUploading: false,
|
|
|
+ // 是否更新已经存在的用户数据
|
|
|
+ updateSupport: 0,
|
|
|
+ // 设置上传的请求头部
|
|
|
+ headers: {Authorization: "Bearer " + getToken()},
|
|
|
+ // 上传的地址
|
|
|
+ url: process.env.VUE_APP_BASE_API + "/store/storeProduct/importData"
|
|
|
+ },
|
|
|
+ // 添加药品相关字段
|
|
|
+ isDrugOptions: [
|
|
|
+ {dictValue: "0", dictLabel: "否"},
|
|
|
+ {dictValue: "1", dictLabel: "是"}
|
|
|
+ ],
|
|
|
+
|
|
|
+ // 头图展示
|
|
|
+ drugImageArr: [],
|
|
|
+
|
|
|
+ //首营资质上传图
|
|
|
+ qualificationArr: [],
|
|
|
+ productTuiCateOptions: [],
|
|
|
+ reviewAuditOptions: [
|
|
|
+ {dictValue: "0", dictLabel: "首营"},
|
|
|
+ {dictValue: "1", dictLabel: "非首营"}
|
|
|
+ ],
|
|
|
+ showIput: false,
|
|
|
+ createBnt: true,
|
|
|
+ // 规格数据
|
|
|
+ formDynamic: {
|
|
|
+ attrsName: '',
|
|
|
+ attrsVal: ''
|
|
|
+ },
|
|
|
+ open1: false,
|
|
|
+ form1: {},
|
|
|
+ isBtn: false,
|
|
|
+ columns: [],
|
|
|
+ attrs: [],
|
|
|
+ templateList: [],
|
|
|
+ ruleList: [],
|
|
|
+ // 多规格表格data
|
|
|
+ manyFormValidate: [],
|
|
|
+ // 单规格表格data
|
|
|
+ oneFormValidate: [
|
|
|
+ {
|
|
|
+ image: '',
|
|
|
+ price: 0,
|
|
|
+ cost: 0,
|
|
|
+ agentPrice: 0,
|
|
|
+ otPrice: 0,
|
|
|
+ stock: 0,
|
|
|
+ barCode: '',
|
|
|
+ weight: 0,
|
|
|
+ volume: 0,
|
|
|
+ integral: 0
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ photoArr: [],
|
|
|
+ imageArr: [],
|
|
|
+ activeName: "-1",
|
|
|
+ productTypeOptions: [],
|
|
|
+ isDisplayOptions: [],
|
|
|
+ isGoodOptions: [],
|
|
|
+ isNewOptions: [],
|
|
|
+ isBestOptions: [],
|
|
|
+ isHotOptions: [],
|
|
|
+ isShowOptions: [],
|
|
|
+ categoryOptions: [],
|
|
|
+ // 企业列表
|
|
|
+ companyOptions: [],
|
|
|
+ storeOptions: [],
|
|
|
+ // 防抖定时器
|
|
|
+ categoryOrStoreChangeTimer: null,
|
|
|
+ // 免于经营备案的第二类医疗器械产品相关变量
|
|
|
+ exemptDeviceDialogVisible: false,
|
|
|
+ exemptDeviceList: [],
|
|
|
+ allExemptDeviceList: [], // 保存所有数据用于本地搜索
|
|
|
+ exemptDeviceLoading: false,
|
|
|
+ exemptDeviceTotal: 0,
|
|
|
+ exemptDeviceQueryParams: {
|
|
|
+ productName: null
|
|
|
+ },
|
|
|
+ // 遮罩层
|
|
|
+ loading: true,
|
|
|
+ // 选中数组
|
|
|
+ ids: [],
|
|
|
+ // 非单个禁用
|
|
|
+ single: false,
|
|
|
+ // 非多个禁用
|
|
|
+ multiple: true,
|
|
|
+ // 显示搜索条件
|
|
|
+ showSearch: true,
|
|
|
+ isFullscreen: false,
|
|
|
+ // 总条数
|
|
|
+ total: 0,
|
|
|
+ // 商品表格数据
|
|
|
+ storeProductList: [],
|
|
|
+ // 弹出层标题
|
|
|
+ title: "",
|
|
|
+ // 是否显示弹出层
|
|
|
+ open: false,
|
|
|
+
|
|
|
+ // 查询参数
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ productName: null,
|
|
|
+ productType: null,
|
|
|
+ isShow: "-1",
|
|
|
+ barCode: null,
|
|
|
+ // companyIds: null,
|
|
|
+ storeIds: null,
|
|
|
+ drugRegCertNo: null,
|
|
|
+ commonName: null,
|
|
|
+ dosageForm: null,
|
|
|
+ unitPrice: null,
|
|
|
+ batchNumber: null,
|
|
|
+ mah: null,
|
|
|
+ mahAddress: null,
|
|
|
+ manufacturer: null,
|
|
|
+ manufacturerAddress: null,
|
|
|
+ indications: null,
|
|
|
+ dosage: null,
|
|
|
+ adverseReactions: null,
|
|
|
+ contraindications: null,
|
|
|
+ precautions: null
|
|
|
+ },
|
|
|
+ // 表单参数
|
|
|
+ form: {
|
|
|
+ ingredient: null,
|
|
|
+ cateId: null,
|
|
|
+ businessExpire: null,
|
|
|
+ indications: '',
|
|
|
+ dosage: '',
|
|
|
+ instructionManual: null,
|
|
|
+ business:null,
|
|
|
+ licenseExpire:null,
|
|
|
+ license:null,
|
|
|
+ certificate:null,
|
|
|
+ certificateExpire:null,
|
|
|
+ voucher:null,
|
|
|
+ voucherExpire:null,
|
|
|
+ gmpAuth:null,
|
|
|
+ businessLink:null,
|
|
|
+ isGmpAuthPermanent:null,
|
|
|
+ isCertificatePermanent:null,
|
|
|
+ isLicensePermanent:null,
|
|
|
+ isBusinessPermanent:null,
|
|
|
+ medicalDeviceCode: null, // 器械编码
|
|
|
+ },
|
|
|
+ // 表单校验
|
|
|
+ rules: {
|
|
|
+ ingredient: [
|
|
|
+ { required: true, message: "成分不能为空", trigger: "blur" },
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (this.ingredientError) {
|
|
|
+ callback(new Error(this.ingredientError));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: "blur"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ image: [
|
|
|
+ {required: true, message: "商品图片不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ sliderImage: [
|
|
|
+ {required: true, message: "轮播图不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ productName: [
|
|
|
+ {required: true, message: "商品名称不能为空", trigger: "blur"},
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (this.productNameError) {
|
|
|
+ callback(new Error(this.productNameError));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: "blur"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ productInfo: [
|
|
|
+ {required: true, message: "商品简介不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ unitName: [
|
|
|
+ {required: true, message: "单位名不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ keyword: [
|
|
|
+ {required: true, message: "关键字不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ cateId: [
|
|
|
+ {required: true, message: "分类id不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ medicalDeviceCode: [
|
|
|
+ {required: true, message: "器械编码不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ price: [
|
|
|
+ {required: true, message: "商品价格不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ prescribeCode: [
|
|
|
+ {required: true, message: "国药准字不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ prescribeSpec: [
|
|
|
+ {required: true, message: "规格不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ prescribeFactory: [
|
|
|
+ {required: true, message: "生产厂家不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ prescribeName: [
|
|
|
+ {required: true, message: "处方药不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ // companyIds: [
|
|
|
+ // { required: true, message: "销售公司不能为空", trigger: "blur" }
|
|
|
+ // ],
|
|
|
+ // 药品相关字段校验(仅在是药品时必填)
|
|
|
+ drugImage: [
|
|
|
+ {required: true, message: "药品展示图不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ drugRegCertNo: [
|
|
|
+ {required: true, message: "药品注册证书编号不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ commonName: [
|
|
|
+ {required: true, message: "通用名称不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ dosageForm: [
|
|
|
+ {required: true, message: "剂型不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ unitPrice: [
|
|
|
+ {required: true, message: "单价不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ // batchNumber: [
|
|
|
+ // {required: true, message: "批号不能为空", trigger: "blur"}
|
|
|
+ // ],
|
|
|
+ mah: [
|
|
|
+ {required: true, message: "上市许可持有人不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ mahAddress: [
|
|
|
+ {required: true, message: "上市许可持有人地址不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ manufacturer: [
|
|
|
+ {required: true, message: "生产企业不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ manufacturerAddress: [
|
|
|
+ {required: true, message: "生产企业地址不能为空", trigger: "blur"}
|
|
|
+ ],
|
|
|
+ // reviewAudit: [
|
|
|
+ // {required: true, message: "审核资质不能为空!", trigger: "blur"}
|
|
|
+ // ],
|
|
|
+ // businessLink: [
|
|
|
+ // { required: true, message: "非首营链接不能为空!", trigger: "change" }
|
|
|
+ // ],
|
|
|
+ business: [
|
|
|
+ { required: true, message: "生产企业营业执照不能为空!", trigger: ["blur", "change"] },
|
|
|
+ { whitespace: true, message: "生产企业营业执照不能为空白!", trigger: ["blur", "change"] }
|
|
|
+ ],
|
|
|
+ license: [
|
|
|
+ { required: true, message: "生产企业的生产许可证/备案凭证不能为空!", trigger: ["blur", "change"] },
|
|
|
+ { whitespace: true, message: "生产企业的生产许可证/备案凭证不能为空白!", trigger: ["blur", "change"]}
|
|
|
+ ],
|
|
|
+ certificate: [
|
|
|
+ { required: true, message: "商品注册证/备案凭证不能为空!", trigger: ["blur", "change"] },
|
|
|
+ { whitespace: true, message: "商品注册证/备案凭证不能为空白!", trigger: ["blur", "change"]}
|
|
|
+ ],
|
|
|
+ businessExpire: [
|
|
|
+ { required: true, message: "生产企业营业执照有效期不能为空!", trigger: "change" }
|
|
|
+ ],
|
|
|
+ licenseExpire: [
|
|
|
+ { required: true, message: "生产企业的生产许可证/备案凭证有效期不能为空!", trigger: "change" }
|
|
|
+ ],
|
|
|
+ certificateExpire: [
|
|
|
+ { required: true, message: "商品注册证/备案凭证有效期不能为空!", trigger: "change" }
|
|
|
+ ],
|
|
|
+ voucher: [
|
|
|
+ { required: true, message: "Ⅰ类Ⅱ类备案凭证不能为空!", trigger: "change" }
|
|
|
+ ],
|
|
|
+ voucherExpire: [
|
|
|
+ { required: true, message: "Ⅰ类Ⅱ类备案凭证有效期不能为空!", trigger: "change" }
|
|
|
+ ],
|
|
|
+ // gmpAuth: [
|
|
|
+ // { required: true, message: "GMP认证不能为空!", trigger: "blur" }
|
|
|
+ // ],
|
|
|
+ indications: [
|
|
|
+ { required: true, message: "功能主治不能为空", trigger: "blur" }
|
|
|
+ ],
|
|
|
+ dosage: [
|
|
|
+ { required: true, message: "用法用量不能为空", trigger: "blur" }
|
|
|
+ ],
|
|
|
+ adverseReactions: [
|
|
|
+ { required: true, message: "不良反应不能为空", trigger: "blur" }
|
|
|
+ ],
|
|
|
+ contraindications: [
|
|
|
+ { required: true, message: "禁忌不能为空", trigger: "blur" }
|
|
|
+ ],
|
|
|
+ precautions: [
|
|
|
+ { required: true, message: "注意事项不能为空", trigger: "blur" }
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 防抖检查店铺许可证权限
|
|
|
+ debounceCheckStoreLicense() {
|
|
|
+ clearTimeout(this.licenseCheckTimer);
|
|
|
+ this.licenseCheckTimer = setTimeout(() => {
|
|
|
+ this.checkStoreLicensePermission();
|
|
|
+ }, 300);
|
|
|
+ },
|
|
|
+ // 检查店铺许可证权限
|
|
|
+ checkStoreLicensePermission() {
|
|
|
+ // 确保分类ID和店铺ID都存在
|
|
|
+ if (!this.form.cateId || !this.form.storeId) {
|
|
|
+ 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;
|
|
|
+ // 准备请求参数
|
|
|
+ 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) {
|
|
|
+ // 权限检查失败
|
|
|
+ const errorMessage = response.data.message || '当前店铺无权限经营该类商品';
|
|
|
+ this.$message.error(errorMessage);
|
|
|
+ this.storeLicenseCheckFailed = true;
|
|
|
+ this.storeLicenseErrorMessage = errorMessage;
|
|
|
+ } else {
|
|
|
+ // 权限检查通过,清除之前的错误提示
|
|
|
+ this.storeLicenseCheckFailed = false;
|
|
|
+ this.storeLicenseErrorMessage = ''; // 清除错误信息
|
|
|
+ // 如果之前有显示错误信息的地方,也会被清除
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ const errorMessage = '店铺许可证检查接口调用失败';
|
|
|
+ this.$message.error(errorMessage);
|
|
|
+ this.storeLicenseCheckFailed = true;
|
|
|
+ this.storeLicenseErrorMessage = errorMessage;
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ console.error('店铺许可证检查失败:', error);
|
|
|
+ const errorMessage = '店铺许可证检查失败';
|
|
|
+ this.$message.error(errorMessage);
|
|
|
+ this.storeLicenseCheckFailed = true;
|
|
|
+ this.storeLicenseErrorMessage = errorMessage;
|
|
|
+ }).finally(() => {
|
|
|
+ this.isCheckingLicense = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 成分输入框失焦时的处理方法
|
|
|
+ handleIngredientBlur() {
|
|
|
+ this.checkForbiddenKeywords('ingredient', this.form.ingredient);
|
|
|
+ },
|
|
|
+ // 商品名称输入框失焦时的处理方法
|
|
|
+ handleProductNameBlur() {
|
|
|
+ this.checkForbiddenKeywords('productName', this.form.productName);
|
|
|
+ },
|
|
|
+ // 通用关键字检查方法 - 根据字段类型分别处理错误提示
|
|
|
+ checkForbiddenKeywords(fieldName, fieldValue) {
|
|
|
+ // 检查内容是否包含禁用关键字
|
|
|
+ if (fieldValue && fieldValue.trim() !== '') {
|
|
|
+ // 统一使用 keywords 参数传递当前失去焦点的值
|
|
|
+ selectForbiddenKeywords(fieldName,fieldValue).then(response => {
|
|
|
+ if (response.code === 200 && !response.data) {
|
|
|
+ // 包含禁用词
|
|
|
+ const errorMsg = response.msg || '内容包含禁用关键字';
|
|
|
+
|
|
|
+ // 根据字段类型设置不同的错误提示变量
|
|
|
+ if (fieldName === 'ingredient') {
|
|
|
+ this.ingredientError = errorMsg;
|
|
|
+ } else if (fieldName === 'productName') {
|
|
|
+ this.productNameError = errorMsg;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置表单验证错误状态
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.validateField(fieldName);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 清除对应字段的错误提示
|
|
|
+ if (fieldName === 'ingredient') {
|
|
|
+ this.ingredientError = '';
|
|
|
+ } else if (fieldName === 'productName') {
|
|
|
+ this.productNameError = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除验证状态
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate(fieldName);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ console.error('检查禁用关键字失败:', error);
|
|
|
+ this.$message.error('检查禁用关键字失败');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 用来清除验证信息
|
|
|
+ onIngredientInput() {
|
|
|
+ if (this.ingredientError) {
|
|
|
+ this.ingredientError = '';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate('ingredient');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 添加清除商品名称验证信息的方法
|
|
|
+ onProductNameInput() {
|
|
|
+ if (this.productNameError) {
|
|
|
+ this.productNameError = '';
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate('productName');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 当商品分类或所属店铺改变时触发
|
|
|
+ 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 => {
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.promptList = response.data;
|
|
|
+ if (this.promptList && this.promptList.length > 0) {
|
|
|
+ this.dialogVisible = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ this.$message.error("加载通知信息失败,请稍后重试");
|
|
|
+ });
|
|
|
+ },
|
|
|
+ cancel1() {
|
|
|
+ this.open1 = false;
|
|
|
+ },
|
|
|
+ submitForm1() {
|
|
|
+ let param = {}
|
|
|
+ param.productId = this.ids;
|
|
|
+ param.goodsStatus = this.form1.isShow;
|
|
|
+ param.goodsIsShow = this.form1.isDisplay;
|
|
|
+ // param.companyIds = this.companyId+''
|
|
|
+ batchModify(param).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success("批量修改成功");
|
|
|
+ this.getList();
|
|
|
+ }
|
|
|
+ }).finally(() => {
|
|
|
+ this.open1 = false;
|
|
|
+ this.form1.isShow = null;
|
|
|
+ this.form1.isDisplay = null;
|
|
|
+ this.form1.companyId = null;
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleFullScreen() {
|
|
|
+ this.isFullscreen = !this.isFullscreen;
|
|
|
+ },
|
|
|
+ handleSuccess(response, file) {
|
|
|
+ // 上传成功后的回调函数
|
|
|
+ this.myloading.close();
|
|
|
+ //this.form.video = response.url;
|
|
|
+ this.$refs.upload.clearFiles();
|
|
|
+ },
|
|
|
+ beforeUpload(file) {
|
|
|
+ // 上传前的钩子函数,可以在这里对文件进行处理
|
|
|
+ // 返回 false 则取消上传
|
|
|
+
|
|
|
+ // 例如限制文件大小
|
|
|
+ const isLt2M = file.size / 1024 / 1024 < 200;
|
|
|
+ if (!isLt2M) {
|
|
|
+ this.$message.error('上传视频文件大小不能超过 200MB!');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ this.myloading = this.$loading({
|
|
|
+ lock: true,
|
|
|
+ text: '上传中',
|
|
|
+ spinner: 'el-icon-loading',
|
|
|
+ background: 'rgba(0, 0, 0, 0.7)'
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+ // 提交上传文件
|
|
|
+ submitFileForm() {
|
|
|
+ this.$refs.upload.submit();
|
|
|
+ },
|
|
|
+ // 文件上传中处理
|
|
|
+ handleFileUploadProgress(event, file, fileList) {
|
|
|
+ this.upload.isUploading = true;
|
|
|
+ },
|
|
|
+ // 文件上传成功处理
|
|
|
+ handleFileSuccess(response, file, fileList) {
|
|
|
+ this.upload.open = false;
|
|
|
+ this.upload.isUploading = false;
|
|
|
+ this.$refs.upload.clearFiles();
|
|
|
+ this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ handleImport() {
|
|
|
+ this.upload.title = "商品导入";
|
|
|
+ this.upload.open = true;
|
|
|
+ },
|
|
|
+ importTemplate() {
|
|
|
+ importTemplate().then(response => {
|
|
|
+ this.download(response.msg);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 删除表格中的属性
|
|
|
+ delAttrTable(index) {
|
|
|
+ this.manyFormValidate.splice(index, 1);
|
|
|
+ },
|
|
|
+ addBtn() {
|
|
|
+ this.clearAttr();
|
|
|
+ this.createBnt = false;
|
|
|
+ this.showIput = true;
|
|
|
+ },
|
|
|
+ //生成SKU
|
|
|
+ generate() {
|
|
|
+ genFormatAttr(this.form.productId, { attrs: this.attrs }).then(res => {
|
|
|
+ if (this.form.specType === 0) {
|
|
|
+ this.oneFormValidate = res.value;
|
|
|
+ this.form.header = res.header;
|
|
|
+ let header = res.header;
|
|
|
+ header.pop();
|
|
|
+ this.oneFormValidate.map((item) => {
|
|
|
+ if (this.imageArr.length > 0) {
|
|
|
+ item.image = this.imageArr[0]
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else if (this.form.specType === 1) {
|
|
|
+ this.manyFormValidate = res.value;
|
|
|
+ let headerdel = {
|
|
|
+ title: '操作',
|
|
|
+ slot: 'action',
|
|
|
+ fixed: 'right',
|
|
|
+ width: 220
|
|
|
+ };
|
|
|
+ res.header.push(headerdel);
|
|
|
+ this.form.header = res.header;
|
|
|
+ let header = res.header;
|
|
|
+ header.pop();
|
|
|
+ // this.manyFormValidate.map((item) => {
|
|
|
+ // if(this.imageArr.length>0){
|
|
|
+ // item.image = this.imageArr[0]
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ }
|
|
|
+
|
|
|
+ }).catch(res => {
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 取消添加新规格
|
|
|
+ closeAttrName() {
|
|
|
+ this.showIput = false;
|
|
|
+ this.createBnt = true;
|
|
|
+ },
|
|
|
+ clearAttr() {
|
|
|
+ this.formDynamic.attrsName = '';
|
|
|
+ this.formDynamic.attrsVal = '';
|
|
|
+ },
|
|
|
+ // 删除规格
|
|
|
+ handleRemoveRole(index) {
|
|
|
+ this.attrs.splice(index, 1);
|
|
|
+ this.manyFormValidate.splice(index, 1);
|
|
|
+ },
|
|
|
+ // 删除属性
|
|
|
+ handleRemove2(item, index) {
|
|
|
+ item.splice(index, 1);
|
|
|
+ },
|
|
|
+ // 添加规则名称
|
|
|
+ createAttrName() {
|
|
|
+ if (this.formDynamic.attrsName && this.formDynamic.attrsVal) {
|
|
|
+ let data = {
|
|
|
+ value: this.formDynamic.attrsName,
|
|
|
+ detail: [
|
|
|
+ this.formDynamic.attrsVal
|
|
|
+ ]
|
|
|
+ };
|
|
|
+ this.attrs.push(data);
|
|
|
+ var hash = {};
|
|
|
+ this.attrs = this.attrs.reduce(function(item, next) {
|
|
|
+ hash[next.value] ? '' : hash[next.value] = true && item.push(next);
|
|
|
+ return item
|
|
|
+ }, [])
|
|
|
+ this.clearAttr();
|
|
|
+ this.showIput = false;
|
|
|
+ this.createBnt = true;
|
|
|
+ } else {
|
|
|
+ this.$message.warning('请添加完整的规格!');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 添加属性
|
|
|
+ createAttr(num, idx) {
|
|
|
+ if (num) {
|
|
|
+ this.attrs[idx].detail.push(num);
|
|
|
+ var hash = {};
|
|
|
+ this.attrs[idx].detail = this.attrs[idx].detail.reduce(function(item, next) {
|
|
|
+ hash[next] ? '' : hash[next] = true && item.push(next);
|
|
|
+ return item
|
|
|
+ }, [])
|
|
|
+ } else {
|
|
|
+ this.$message.warning('请添加属性!');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ confirm() {
|
|
|
+ let that = this;
|
|
|
+ that.createBnt = true;
|
|
|
+ if (that.form.selectRule == null || that.form.selectRule.trim().length <= 0) {
|
|
|
+ return this.$message({
|
|
|
+ message: '请选择属性',
|
|
|
+ type: 'error'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ that.ruleList.forEach(function(item, index) {
|
|
|
+ if (item.ruleName === that.form.selectRule) {
|
|
|
+ that.attrs = JSON.parse(item.ruleValue);
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+ updateText(text) {
|
|
|
+ this.form.description = text
|
|
|
+ },
|
|
|
+ updateInstructionManualText(text) {
|
|
|
+ this.form.instructionManual = text
|
|
|
+ },
|
|
|
+ handleClick(tab, event) {
|
|
|
+ this.queryParams.isShow = tab.name;
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ /** 转换商品分类数据结构 */
|
|
|
+ normalizer(node) {
|
|
|
+ if (node.children && !node.children.length) {
|
|
|
+ delete node.children;
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ id: node.cateId,
|
|
|
+ label: node.cateName,
|
|
|
+ children: node.children
|
|
|
+ };
|
|
|
+ },
|
|
|
+ getTreeselect() {
|
|
|
+ getAllStoreProductCategory().then(response => {
|
|
|
+ this.categoryOptions = [];
|
|
|
+ const data = this.handleTree(response.data, "cateId", "pid");
|
|
|
+ this.categoryOptions = data;
|
|
|
+ this.buildCateMap(data);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ buildCateMap(nodes) {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ this.cateIdToNameMap[node.cateId] = node.cateName;
|
|
|
+ if (node.children && node.children.length) {
|
|
|
+ this.buildCateMap(node.children); // 递归处理子节点
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 查询商品列表 */
|
|
|
+ getList() {
|
|
|
+ this.loading = true;
|
|
|
+ if (this.queryParams.storeIds !== null && this.queryParams.storeIds.length === 0) {
|
|
|
+ this.queryParams.storeIds = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ listStoreProduct(this.queryParams).then(response => {
|
|
|
+ this.storeProductList = response.rows;
|
|
|
+ this.total = response.total;
|
|
|
+ this.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 取消按钮
|
|
|
+ cancel() {
|
|
|
+ this.open = false;
|
|
|
+ this.reset();
|
|
|
+ },
|
|
|
+ // 表单重置
|
|
|
+ reset() {
|
|
|
+ this.initPrescriptionDrugRules(); // 重置处方药相关的校验规则
|
|
|
+ this.isFormInitialized = false; // 重置初始化标志
|
|
|
+ this.ingredientError = '';
|
|
|
+ this.form = {
|
|
|
+ ingredient: null,
|
|
|
+ productId: null,
|
|
|
+ image: null,
|
|
|
+ video: null,
|
|
|
+ sliderImage: null,
|
|
|
+ productName: null,
|
|
|
+ productInfo: null,
|
|
|
+ keyword: null,
|
|
|
+ barCode: null,
|
|
|
+ cateId: null,
|
|
|
+ price: null,
|
|
|
+ vipPrice: null,
|
|
|
+ otPrice: null,
|
|
|
+ postage: null,
|
|
|
+ unitName: null,
|
|
|
+ sort: null,
|
|
|
+ sales: null,
|
|
|
+ stock: null,
|
|
|
+ isShow: "0",
|
|
|
+ isHot: "0",
|
|
|
+ isBenefit: "0",
|
|
|
+ isBest: "0",
|
|
|
+ isNew: "0",
|
|
|
+ description: null,
|
|
|
+ instructionManual: null,
|
|
|
+ createTime: null,
|
|
|
+ updateTime: null,
|
|
|
+ isPostage: null,
|
|
|
+ isDel: null,
|
|
|
+ giveIntegral: null,
|
|
|
+ cost: null,
|
|
|
+ isGood: "0",
|
|
|
+ browse: null,
|
|
|
+ codePath: null,
|
|
|
+ tempId: "",
|
|
|
+ specType: 0,
|
|
|
+ isIntegral: null,
|
|
|
+ integral: null,
|
|
|
+ productType: "1",
|
|
|
+ prescribeCode: null,
|
|
|
+ prescribeSpec: null,
|
|
|
+ prescribeFactory: null,
|
|
|
+ prescribeName: null,
|
|
|
+ isDisplay: "1",
|
|
|
+ qualificationExpire: null,
|
|
|
+ // companyIds:[],
|
|
|
+ isDrug: "1", // 是否药品
|
|
|
+ drugImage: null, // 头图展示
|
|
|
+ drugRegCertNo: null, // 药品注册证书编号
|
|
|
+ commonName: null, // 通用名称
|
|
|
+ dosageForm: null, // 剂型
|
|
|
+ unitPrice: null, // 单价
|
|
|
+ batchNumber: null, // 批号
|
|
|
+ mah: null, // 上市许可持有人
|
|
|
+ mahAddress: null, // 上市许可持有人地址
|
|
|
+ manufacturer: null, // 生产企业
|
|
|
+ manufacturerAddress: null, // 生产企业地址
|
|
|
+ indications: null, // 功能主治
|
|
|
+ dosage: null, // 用法用量
|
|
|
+ adverseReactions: null, // 不良反应
|
|
|
+ contraindications: null, // 禁忌
|
|
|
+ precautions: null // 注意事项
|
|
|
+ };
|
|
|
+ // 重置药品展示图
|
|
|
+ this.drugImageArr = [];
|
|
|
+ this.resetForm("form");
|
|
|
+ this.oneFormValidate = [
|
|
|
+ {
|
|
|
+ image: '',
|
|
|
+ price: 0,
|
|
|
+ agentPrice: 0,
|
|
|
+ cost: 0,
|
|
|
+ otPrice: 0,
|
|
|
+ stock: 0,
|
|
|
+ barCode: '',
|
|
|
+ weight: 0,
|
|
|
+ volume: 0,
|
|
|
+ integral: 0,
|
|
|
+ brokerage: 0,
|
|
|
+ brokerageTwo: 0
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ this.attrs = [];
|
|
|
+ this.photoArr = [];
|
|
|
+ this.imageArr = [];
|
|
|
+ this.qualificationArr = [];
|
|
|
+ this.businessArr = [];
|
|
|
+ this.licenseArr = [];
|
|
|
+ this.certificateArr = [];
|
|
|
+ this.voucherArr = [];
|
|
|
+ this.gmpAuthArr = [];
|
|
|
+ },
|
|
|
+ /** 搜索按钮操作 */
|
|
|
+ handleQuery() {
|
|
|
+ this.queryParams.pageNum = 1;
|
|
|
+ // this.queryParams.companyIds = this.companyId +''
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ /** 重置按钮操作 */
|
|
|
+ resetQuery() {
|
|
|
+ this.resetForm("queryForm");
|
|
|
+ // 查询参数
|
|
|
+ this.queryParams = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ productName: null,
|
|
|
+ productType: null,
|
|
|
+ isShow: "1",
|
|
|
+ barCode: null,
|
|
|
+ // companyIds: null,
|
|
|
+ storeIds: null,
|
|
|
+ drugRegCertNo: null,
|
|
|
+ commonName: null,
|
|
|
+ dosageForm: null,
|
|
|
+ unitPrice: null,
|
|
|
+ batchNumber: null,
|
|
|
+ mah: null,
|
|
|
+ mahAddress: null,
|
|
|
+ manufacturer: null,
|
|
|
+ manufacturerAddress: null,
|
|
|
+ indications: null,
|
|
|
+ dosage: null,
|
|
|
+ adverseReactions: null,
|
|
|
+ contraindications: null,
|
|
|
+ precautions: null
|
|
|
+ }
|
|
|
+ this.handleQuery();
|
|
|
+ },
|
|
|
+ // 多选框选中数据
|
|
|
+ handleSelectionChange(selection) {
|
|
|
+ this.ids = selection.map(item => item.productId)
|
|
|
+ this.single = selection.length !== 1
|
|
|
+ this.multiple = !selection.length
|
|
|
+ },
|
|
|
+ /** 新增按钮操作 */
|
|
|
+ handleAdd() {
|
|
|
+ this.reset();
|
|
|
+ this.clearExpireErrors(); // 清空过期错误提示
|
|
|
+ this.isFormInitialized = true; // 新增时直接设置为已初始化
|
|
|
+ this.open = true;
|
|
|
+ this.title = "添加商品";
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$refs.myeditor.setText("");
|
|
|
+ this.$refs.instructionManualRef.setText("");
|
|
|
+ }, 500);
|
|
|
+ },
|
|
|
+ /** 修改按钮操作 */
|
|
|
+ handleUpdate(row) {
|
|
|
+ this.reset();
|
|
|
+ if (this.ids.length > 1) {
|
|
|
+ this.title = "批量修改商品";
|
|
|
+ this.open1 = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var that = this;
|
|
|
+ this.clearExpireErrors(); // 清空过期错误提示
|
|
|
+ const productId = row.productId || this.ids
|
|
|
+ getStoreProduct(productId).then(response => {
|
|
|
+ this.open = true;
|
|
|
+ this.title = "修改商品";
|
|
|
+ this.form = response.data;
|
|
|
+ this.form.isShow = response.data.isShow.toString();
|
|
|
+ this.form.isHot = response.data.isHot.toString();
|
|
|
+ this.form.isGood = response.data.isGood.toString();
|
|
|
+ this.form.isBest = response.data.isBest.toString();
|
|
|
+ this.form.isNew = response.data.isNew.toString();
|
|
|
+ this.form.productType = response.data.productType.toString();
|
|
|
+ this.form.isDisplay = response.data.isDisplay.toString();
|
|
|
+
|
|
|
+ if (this.form.business) {
|
|
|
+ this.businessArr = this.form.business.split(',');
|
|
|
+ }
|
|
|
+ if (this.form.license) {
|
|
|
+ this.licenseArr = this.form.license.split(',');
|
|
|
+ }
|
|
|
+ if (this.form.certificate) {
|
|
|
+ this.certificateArr = this.form.certificate.split(',');
|
|
|
+ }
|
|
|
+ if (this.form.voucher) {
|
|
|
+ this.voucherArr = this.form.voucher.split(',');
|
|
|
+ }
|
|
|
+ if (this.form.gmpAuth) {
|
|
|
+ this.gmpAuthArr = this.form.gmpAuth.split(',');
|
|
|
+ }
|
|
|
+ if (this.form.image != null) {
|
|
|
+ this.imageArr = this.form.image.split(",");
|
|
|
+ }
|
|
|
+ if (this.form.sliderImage != null) {
|
|
|
+ this.photoArr = this.form.sliderImage.split(",");
|
|
|
+ }
|
|
|
+ if (this.form.drugImage != null) {
|
|
|
+ this.drugImageArr = this.form.drugImage.split(",");
|
|
|
+ }
|
|
|
+ if (this.form.qualificationCertificate != null) {
|
|
|
+ this.qualificationArr = this.form.qualificationCertificate.split(",");
|
|
|
+ }
|
|
|
+ if (this.form.tuiCateId != null) {
|
|
|
+ this.form.tuiCateId = response.data.tuiCateId.toString();
|
|
|
+ }
|
|
|
+ if (this.form.reviewAudit != null) {
|
|
|
+ this.form.reviewAudit = response.data.reviewAudit.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ // this.form.isDrug = response.data.isDrug ? response.data.isDrug.toString() : "1";
|
|
|
+ this.form.isDrug = response.data.isDrug === 0 ? "0" :
|
|
|
+ (response.data.isDrug ? response.data.isDrug.toString() : "1");
|
|
|
+
|
|
|
+ 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'
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ expireFieldMap.forEach(item => {
|
|
|
+ const startVal = response.data[item.startKey];
|
|
|
+ const endVal = response.data[item.endKey];
|
|
|
+ if (startVal && endVal) {
|
|
|
+ this.$set(this.form, item.expireKey, [startVal, endVal]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ //组装attrs数据
|
|
|
+ if (response.attrs != null) {
|
|
|
+ this.attrs = [];
|
|
|
+ response.attrs.forEach(function(item, index) {
|
|
|
+ var data = { value: item.attrName, detail: item.attrValues.split(',') }
|
|
|
+ that.attrs.push(data);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ const dateFields = [
|
|
|
+ 'qualificationExpire'
|
|
|
+ ];
|
|
|
+ dateFields.forEach(field => {
|
|
|
+ const startField = field.replace('Expire', 'CertificateStart'); // qualificationCertificateStart
|
|
|
+ const endField = field.replace('Expire', 'CertificateEnd'); // qualificationCertificateEnd
|
|
|
+ if (this.form[startField] && this.form[endField]) {
|
|
|
+ this.$set(this.form, field, [this.form[startField], this.form[endField]]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // // 组装companyIds
|
|
|
+ // if (response.data.companyIds != null && response.data.companyIds != undefined && response.data.companyIds.length > 0) {
|
|
|
+ // this.form.companyIds = response.data.companyIds.split(',').map(Number);
|
|
|
+ // }
|
|
|
+ setTimeout(() => {
|
|
|
+ that.generate();
|
|
|
+ }, 200);
|
|
|
+ if (this.form.specType === 0) {
|
|
|
+ that.manyFormValidate = [];
|
|
|
+ } else {
|
|
|
+ that.createBnt = true;
|
|
|
+ that.oneFormValidate = [
|
|
|
+ {
|
|
|
+ image: '',
|
|
|
+ price: 0,
|
|
|
+ agentPrice: 0,
|
|
|
+ cost: 0,
|
|
|
+ otPrice: 0,
|
|
|
+ stock: 0,
|
|
|
+ barCode: '',
|
|
|
+ weight: 0,
|
|
|
+ volume: 0,
|
|
|
+ integral: 0,
|
|
|
+ brokerage: 0,
|
|
|
+ brokerageTwo: 0
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$refs.myeditor.setText(this.form.description==null?"":this.form.description);
|
|
|
+ this.$refs.instructionManualRef.setText(this.form.instructionManual == null?""
|
|
|
+ :this.form.instructionManual);
|
|
|
+ }, 200);
|
|
|
+
|
|
|
+ // 加载数据后立即校验过期状态
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.isFormInitialized = true;
|
|
|
+ // 首次加载后检查一次
|
|
|
+ if (this.form.storeId && this.form.cateId) {
|
|
|
+ this.checkStoreLicensePermission();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 提交按钮 */
|
|
|
+ submitForm() {
|
|
|
+ // 1. 先执行 Element UI 的表单验证
|
|
|
+ this.$refs["form"].validate(valid => {
|
|
|
+ if (valid) {
|
|
|
+ // 4. 检查店铺许可证权限
|
|
|
+ if (this.storeLicenseCheckFailed) {
|
|
|
+ this.$message.error('当前店铺无权限经营该类商品,请重新选择分类或店铺');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 5. 统一校验所有证书是否过期
|
|
|
+ const expireError = this.checkAllCertificatesExpire();
|
|
|
+ if (expireError) {
|
|
|
+ this.$message.error(expireError);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 6. 执行提交逻辑
|
|
|
+ this.executeSubmit();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ //具体的提交逻辑
|
|
|
+ executeSubmit() {
|
|
|
+ let checkBoolean = false;
|
|
|
+ let itemErrMsg = "";
|
|
|
+
|
|
|
+ if (this.form.specType === 0) {
|
|
|
+ this.form.items = [];
|
|
|
+ this.form.values = this.oneFormValidate;
|
|
|
+ } else {
|
|
|
+ this.form.items = this.attrs;
|
|
|
+ this.form.values = this.manyFormValidate;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证规格数据
|
|
|
+ const validateItem = (item) => {
|
|
|
+ if (item.barCode == null || item.barCode === '') {
|
|
|
+ return "规格/型号,商品条码不能为空!";
|
|
|
+ }
|
|
|
+ if (item.price == null || item.price === '' || item.price === 0) {
|
|
|
+ return "规格/型号,商品售价不能为空且不能为0!";
|
|
|
+ }
|
|
|
+ if (item.cost == null || item.cost === '') {
|
|
|
+ return "规格/型号,商品成本价不能为空!";
|
|
|
+ }
|
|
|
+ if (item.otPrice == null || item.otPrice === '') {
|
|
|
+ return "规格/型号,商品原价不能为空!";
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 遍历检查每个规格项
|
|
|
+ for (let i = 0; i < this.form.values.length; i++) {
|
|
|
+ const item = this.form.values[i];
|
|
|
+ const errorMsg = validateItem(item);
|
|
|
+ if (errorMsg) {
|
|
|
+ itemErrMsg = errorMsg;
|
|
|
+ checkBoolean = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (checkBoolean) {
|
|
|
+ this.$message.warning(itemErrMsg);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.form.specType === 1 && this.manyFormValidate.length === 0) {
|
|
|
+ this.$message.warning('请点击生成规格!');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理其他业务逻辑...
|
|
|
+ // 设置永久有效标识
|
|
|
+ this.form.isBusinessPermanent = this.businessValue ? 1 : 0;
|
|
|
+ this.form.isLicensePermanent = this.licenseValue ? 1 : 0;
|
|
|
+ this.form.isCertificatePermanent = this.certificateValue ? 1 : 0;
|
|
|
+
|
|
|
+ // 调用API提交数据
|
|
|
+ addOrEdit(this.form).then(response => {
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.msgSuccess("操作成功!");
|
|
|
+ this.open = false;
|
|
|
+ this.getList();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 删除按钮操作 */
|
|
|
+ handleDelete(row) {
|
|
|
+ const productIds = row.productId || this.ids;
|
|
|
+ this.$confirm('是否确认删除商品编号为"' + productIds + '"的数据项?', "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(function() {
|
|
|
+ return delStoreProduct(productIds);
|
|
|
+ }).then(() => {
|
|
|
+ this.getList();
|
|
|
+ this.msgSuccess("删除成功");
|
|
|
+ }).catch(function() {
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 导出按钮操作 */
|
|
|
+ handleExport() {
|
|
|
+ const queryParams = this.queryParams;
|
|
|
+ this.$confirm('是否确认导出所有商品数据项?', "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(function() {
|
|
|
+ return exportStoreProduct(queryParams);
|
|
|
+ }).then(response => {
|
|
|
+ this.download(response.msg);
|
|
|
+ }).catch(function() {
|
|
|
+ });
|
|
|
+ },
|
|
|
+ showOperLog(row) {
|
|
|
+ getAuthInfo(row.productId).then(response => {
|
|
|
+ this.auditLogs = response.auditLog;
|
|
|
+ this.titleValue = "商品:" + "《" + row.productName + "》" + "审核记录";
|
|
|
+ this.authVisible = true;
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleClose(done) {
|
|
|
+ this.$confirm('确认关闭?')
|
|
|
+ .then(_ => {
|
|
|
+ done();
|
|
|
+ })
|
|
|
+ .catch(_ => {
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 复制商品
|
|
|
+ * **/
|
|
|
+ productCopy(row) {
|
|
|
+ this.$confirm('确认是否复制当前《' + row.productName + '》商品!', '复制商品', {
|
|
|
+ confirmButtonText: '确 认',
|
|
|
+ cancelButtonText: '取 消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ copyProduct(row).then(response => {
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.$message.success("操作成功!")
|
|
|
+ this.getList();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }).catch(() => {
|
|
|
+
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 清空所有证书过期错误提示
|
|
|
+ clearExpireErrors() {
|
|
|
+ this.businessExpireError = '';
|
|
|
+ this.licenseExpireError = '';
|
|
|
+ this.certificateExpireError = '';
|
|
|
+ },
|
|
|
+ // 统一校验证书有效期(返回错误信息或null),新增如果选择长期按钮打开,验证就会跳过
|
|
|
+ checkCertificateExpire(dates, flag, certName) {
|
|
|
+ if(!flag) {
|
|
|
+ // 检查是否为空
|
|
|
+ if (!dates || !Array.isArray(dates) || dates.length !== 2) {
|
|
|
+ return `${certName}有效期不能为空`;
|
|
|
+ }
|
|
|
+ if (dates && dates.length === 2) {
|
|
|
+ const endDate = new Date(dates[1]);
|
|
|
+ const today = new Date();
|
|
|
+ today.setHours(0, 0, 0, 0);
|
|
|
+ if (endDate < today) {
|
|
|
+ return `${certName}已过期,请更新证书`;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+ // 检查所有证书是否过期(提交时使用)
|
|
|
+ checkAllCertificatesExpire() {
|
|
|
+ // 按顺序检查,返回第一个过期的证书错误信息
|
|
|
+ let error = null;
|
|
|
+ error = this.checkCertificateExpire(this.form.businessExpire, this.businessValue,'生产企业营业执照');
|
|
|
+ if (error) return error + '后再提交!';
|
|
|
+ error = this.checkCertificateExpire(this.form.licenseExpire, this.licenseValue,'生产企业的生产许可证/备案凭证');
|
|
|
+ if (error) return error + '后再提交!';
|
|
|
+ error = this.checkCertificateExpire(this.form.certificateExpire, this.certificateValue,'商品注册证/备案凭证');
|
|
|
+ if (error) return error + '后再提交!';
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加一个新的方法用于初始化处方药相关规则
|
|
|
+ initPrescriptionDrugRules() {
|
|
|
+ // 初始化处方药相关字段的校验规则
|
|
|
+ this.$set(this.rules, 'indications', [
|
|
|
+ { required: true, message: "功能主治不能为空", trigger: "blur" }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ this.$set(this.rules, 'ingredient', [
|
|
|
+ { required: true, message: "成分不能为空", trigger: "blur" },
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (this.ingredientError) {
|
|
|
+ callback(new Error(this.ingredientError));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: "blur"
|
|
|
+ }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ this.$set(this.rules, 'dosage', [
|
|
|
+ { required: true, message: "用法用量不能为空", trigger: "blur" }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ this.$set(this.rules, 'adverseReactions', [
|
|
|
+ { required: true, message: "不良反应不能为空", trigger: "blur" }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ this.$set(this.rules, 'contraindications', [
|
|
|
+ { required: true, message: "禁忌不能为空", trigger: "blur" }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ this.$set(this.rules, 'precautions', [
|
|
|
+ { 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>
|