|
|
@@ -161,6 +161,17 @@
|
|
|
v-hasPermi="['his:store:export']"
|
|
|
>导出</el-button>
|
|
|
</el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="success"
|
|
|
+ icon="el-icon-video-play"
|
|
|
+ size="mini"
|
|
|
+ :loading="enableLoading"
|
|
|
+ :disabled="multiple"
|
|
|
+ @click="handleEnable"
|
|
|
+ v-hasPermi="['his:store:edit']"
|
|
|
+ >一键启用</el-button>
|
|
|
+ </el-col>
|
|
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
|
</el-row>
|
|
|
|
|
|
@@ -201,6 +212,17 @@
|
|
|
<el-table-column label="登录帐号" align="center" prop="account" width="150px" />
|
|
|
|
|
|
<el-table-column label="上次审核日期" align="center" prop="qualificationUpdateTime" width="150px" />
|
|
|
+ <el-table-column label="网销报告" align="center" width="100px">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button
|
|
|
+ v-if="scope.row.reportUrl"
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-view"
|
|
|
+ @click="viewReportFileByUrl(scope.row.reportUrl)">查看</el-button>
|
|
|
+ <span v-else>-</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column label="下次到期日" align="center" prop="nextQualificationUpdateTime" width="150px" />
|
|
|
<el-table-column label="剩余天数" align="center" prop="daysDiff" width="150px" />
|
|
|
<el-table-column label="提醒状态(标签)" align="center" prop="daysDiff" width="150px">
|
|
|
@@ -754,8 +776,9 @@
|
|
|
:src="form.settlementAgreement"
|
|
|
class="uploaded-img"
|
|
|
width="100px"
|
|
|
+ @click="viewAgreementFile('settlementAgreement')"
|
|
|
/>
|
|
|
- <div v-else class="document-icon">
|
|
|
+ <div v-else class="document-icon" @click="viewAgreementFile('settlementAgreement')">
|
|
|
<i :class="getDocumentIconClass(form.settlementAgreement, 'settlementAgreement')" class="icon"></i>
|
|
|
<span class="file-name">{{ form.settlementAgreementFileName || getFileName(form.settlementAgreement) }}</span>
|
|
|
</div>
|
|
|
@@ -827,8 +850,9 @@
|
|
|
:src="form.qualityAssuranceAgreement"
|
|
|
class="uploaded-img"
|
|
|
width="100px"
|
|
|
+ @click="viewAgreementFile('qualityAssuranceAgreement')"
|
|
|
/>
|
|
|
- <div v-else class="document-icon">
|
|
|
+ <div v-else class="document-icon" @click="viewAgreementFile('qualityAssuranceAgreement')">
|
|
|
<i :class="getDocumentIconClass(form.qualityAssuranceAgreement, 'qualityAssuranceAgreement')" class="icon"></i>
|
|
|
<span class="file-name">{{ form.qualityAssuranceAgreementFileName || getFileName(form.qualityAssuranceAgreement) }}</span>
|
|
|
</div>
|
|
|
@@ -900,8 +924,9 @@
|
|
|
:src="form.otherSpecialQualification"
|
|
|
class="uploaded-img"
|
|
|
width="100px"
|
|
|
+ @click="viewAgreementFile('otherSpecialQualification')"
|
|
|
/>
|
|
|
- <div v-else class="document-icon">
|
|
|
+ <div v-else class="document-icon" @click="viewAgreementFile('otherSpecialQualification')">
|
|
|
<i :class="getDocumentIconClass(form.otherSpecialQualification, 'otherSpecialQualification')" class="icon"></i>
|
|
|
<span class="file-name">{{ form.otherSpecialQualificationFileName || getFileName(form.otherSpecialQualification) }}</span>
|
|
|
</div>
|
|
|
@@ -956,15 +981,35 @@
|
|
|
<el-upload
|
|
|
class="upload-demo"
|
|
|
:action="uploadUrl"
|
|
|
- :on-preview="handlePreview"
|
|
|
:on-remove="handleRemove"
|
|
|
:before-remove="beforeRemove"
|
|
|
- multiple
|
|
|
:limit="1"
|
|
|
:on-exceed="handleExceed"
|
|
|
- :on-success="(response, file) => handleFileSuccess(response, file, 'reportUrl')"
|
|
|
- :file-list="reportFileList">
|
|
|
- <el-button size="small" type="primary">点击上传</el-button>
|
|
|
+ :on-success="(response, file) => handleReportUploadSuccess(response, file, 'reportUrl')"
|
|
|
+ :before-upload="beforeReportUpload"
|
|
|
+ :disabled="!!form.reportUrl"
|
|
|
+ accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf"
|
|
|
+ >
|
|
|
+ <div class="report-file-wrapper" v-if="form.reportUrl">
|
|
|
+ <img
|
|
|
+ v-if="isImageFile(form.reportUrl)"
|
|
|
+ :src="form.reportUrl"
|
|
|
+ class="uploaded-file-thumb"
|
|
|
+ width="100px"
|
|
|
+ @click="viewReportFile('reportUrl')"
|
|
|
+ />
|
|
|
+ <div v-else class="document-file-icon" @click="viewReportFile('reportUrl')">
|
|
|
+ <i class="el-icon-document"></i>
|
|
|
+ <span class="file-name">{{ getFileName(form.reportUrl) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-else class="upload-btn-wrapper">
|
|
|
+ <el-button size="small" type="primary">点击上传</el-button>
|
|
|
+ </div>
|
|
|
+ <div v-if="form.reportUrl" class="report-preview-btn">
|
|
|
+ <el-button size="mini" type="success" @click.stop="viewReportFile('reportUrl')">查看已上传文件</el-button>
|
|
|
+ <el-button size="mini" type="danger" @click.stop="handleReportRemove('reportUrl')">删除</el-button>
|
|
|
+ </div>
|
|
|
</el-upload>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
@@ -973,15 +1018,35 @@
|
|
|
<el-upload
|
|
|
class="upload-demo"
|
|
|
:action="uploadUrl"
|
|
|
- :on-preview="handlePreview"
|
|
|
:on-remove="handleRemove"
|
|
|
:before-remove="beforeRemove"
|
|
|
- :on-success="(response, file) => handleFileSuccess(response, file, 'filingUrl')"
|
|
|
- multiple
|
|
|
:limit="1"
|
|
|
:on-exceed="handleExceed"
|
|
|
- :file-list="fileList">
|
|
|
- <el-button size="small" type="primary">点击上传</el-button>
|
|
|
+ :on-success="(response, file) => handleReportUploadSuccess(response, file, 'filingUrl')"
|
|
|
+ :before-upload="beforeReportUpload"
|
|
|
+ :disabled="!!form.filingUrl"
|
|
|
+ accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf"
|
|
|
+ >
|
|
|
+ <div class="report-file-wrapper" v-if="form.filingUrl">
|
|
|
+ <img
|
|
|
+ v-if="isImageFile(form.filingUrl)"
|
|
|
+ :src="form.filingUrl"
|
|
|
+ class="uploaded-file-thumb"
|
|
|
+ width="100px"
|
|
|
+ @click="viewReportFile('filingUrl')"
|
|
|
+ />
|
|
|
+ <div v-else class="document-file-icon" @click="viewReportFile('filingUrl')">
|
|
|
+ <i class="el-icon-document"></i>
|
|
|
+ <span class="file-name">{{ getFileName(form.filingUrl) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-else class="upload-btn-wrapper">
|
|
|
+ <el-button size="small" type="primary">点击上传</el-button>
|
|
|
+ </div>
|
|
|
+ <div v-if="form.filingUrl" class="report-preview-btn">
|
|
|
+ <el-button size="mini" type="success" @click.stop="viewReportFile('filingUrl')">查看已上传文件</el-button>
|
|
|
+ <el-button size="mini" type="danger" @click.stop="handleReportRemove('filingUrl')">删除</el-button>
|
|
|
+ </div>
|
|
|
</el-upload>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
@@ -1025,7 +1090,7 @@
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
<el-row>
|
|
|
- <el-col :span="12">
|
|
|
+ <el-col :span="12" v-if="false">
|
|
|
<el-form-item label="状态">
|
|
|
<el-radio-group v-model="form.status">
|
|
|
<el-radio
|
|
|
@@ -1037,7 +1102,7 @@
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
|
|
|
- <el-col :span="12">
|
|
|
+ <el-col :span="12" v-if="false">
|
|
|
<el-form-item label="分佣方式" prop="brokerageType">
|
|
|
<el-radio-group v-model="form.brokerageType" disabled>
|
|
|
<el-radio label="1" >每盒</el-radio>
|
|
|
@@ -1047,7 +1112,7 @@
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
- <el-form-item label="配送方式" prop="shippingType">
|
|
|
+ <el-form-item label="配送方式" prop="shippingType" v-if="false">
|
|
|
<el-checkbox-group v-model="form.shippingType" size="medium">
|
|
|
<el-checkbox v-for="(item, index) in shippingTypeOptions" :key="index" :label="item.value"
|
|
|
:disabled="item.disabled">{{item.label}}</el-checkbox>
|
|
|
@@ -1067,9 +1132,40 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
|
|
|
- <!-- 修改图片预览对话框,增加更大的预览尺寸 -->
|
|
|
- <el-dialog :visible.sync="imagePreviewVisible" width="1100px" append-to-body :modal-append-to-body="false" @close="imagePreviewVisible = false">
|
|
|
- <img :src="previewImageUrl" style="width: 100%; height: auto; max-height: 700px; object-fit: contain;" />
|
|
|
+ <!-- 图片预览对话框,支持放大缩小 -->
|
|
|
+ <el-dialog :visible.sync="imagePreviewVisible" width="1100px" append-to-body :modal-append-to-body="false" @close="onImagePreviewClose">
|
|
|
+ <div slot="title">
|
|
|
+ <span>图片预览</span>
|
|
|
+ <span style="margin-left: 16px; font-size: 13px; color: #909399;">{{ previewScale }}%</span>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="img-preview-body"
|
|
|
+ @wheel.prevent="onPreviewWheel"
|
|
|
+ @mousedown="onImgMouseDown"
|
|
|
+ @mousemove="onImgMouseMove"
|
|
|
+ @mouseup="onImgMouseUp"
|
|
|
+ @mouseleave="onImgMouseUp"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ :src="previewImageUrl"
|
|
|
+ :style="{
|
|
|
+ transform: `translate(${dragOffset.x}px, ${dragOffset.y}px) scale(${previewScale / 100})`,
|
|
|
+ transition: isDragging ? 'none' : 'transform .15s',
|
|
|
+ cursor: isDragging ? 'grabbing' : (previewScale > 100 ? 'grab' : 'default')
|
|
|
+ }"
|
|
|
+ style="max-width: 100%; max-height: 65vh; user-select: none;"
|
|
|
+ ref="previewImg"
|
|
|
+ @dragstart.prevent
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div slot="footer" class="dialog-footer" style="text-align: left;">
|
|
|
+ <el-button-group>
|
|
|
+ <el-button size="small" icon="el-icon-zoom-out" :disabled="previewScale <= 25" @click="zoomOut">缩小</el-button>
|
|
|
+ <el-button size="small" icon="el-icon-refresh" @click="resetZoom">复位</el-button>
|
|
|
+ <el-button size="small" icon="el-icon-zoom-in" :disabled="previewScale >= 300" @click="zoomIn">放大</el-button>
|
|
|
+ </el-button-group>
|
|
|
+ <el-button size="small" style="float: right;" @click="imagePreviewVisible = false">关 闭</el-button>
|
|
|
+ </div>
|
|
|
</el-dialog>
|
|
|
|
|
|
<!-- 设置ERP店铺信息对话框 -->
|
|
|
@@ -1116,7 +1212,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { listStore, getStore, delStore, addStore, updateStore, exportStore, refreshPasWod,exportFsStream, businessLicenseCheck, getStoreErpInfo, saveStoreErpInfo} from '@/api/hisStore/store'
|
|
|
+import { listStore, getStore, delStore, addStore, updateStore, exportStore, refreshPasWod,exportFsStream, businessLicenseCheck, getStoreErpInfo, saveStoreErpInfo, enableStore} from '@/api/hisStore/store'
|
|
|
import storeDetails from '../components/storeDetails.vue';
|
|
|
import StoreDialog from '../components/StoreDialog.vue';
|
|
|
import {getCitys} from "@/api/store/city";
|
|
|
@@ -1131,6 +1227,10 @@ export default {
|
|
|
fileList:[],
|
|
|
previewImageUrl: '', // 添加预览图片URL
|
|
|
imagePreviewVisible: false,// 添加图片预览对话框可见性控制
|
|
|
+ previewScale: 100, // 图片预览缩放比例
|
|
|
+ dragOffset: { x: 0, y: 0 }, // 拖动偏移
|
|
|
+ isDragging: false, // 是否正在拖动
|
|
|
+ dragStart: { x: 0, y: 0 }, // 拖动起始坐标
|
|
|
// 新增:控制LOGO上传组件禁用状态
|
|
|
isDeleting: false,
|
|
|
promptList:[],
|
|
|
@@ -1196,6 +1296,27 @@ export default {
|
|
|
loading: true,
|
|
|
// 导出遮罩层
|
|
|
exportLoading: false,
|
|
|
+ enableLoading: false,
|
|
|
+ originalForm: null,
|
|
|
+ excludedFields: [
|
|
|
+ 'storeId', 'createTime', 'updateTime',
|
|
|
+ 'balance', 'totalMoney', 'salesCount', 'productCount',
|
|
|
+ 'qualificationUpdateTime', 'nextQualificationUpdateTime', 'daysDiff', 'remainDays',
|
|
|
+ 'permStatus', 'storeSeq', 'merchantId', 'selectableProductTypes',
|
|
|
+ 'doctorList', 'queryStoreId', 'hasErpInfo',
|
|
|
+ 'shippingType', 'brokerageType', 'brokerageRate', 'status',
|
|
|
+ 'password', 'licenseImages'
|
|
|
+ ],
|
|
|
+ agreementFields: [
|
|
|
+ 'settlementAgreement', 'settlementAgreementFileName', 'settlementAgreementCode',
|
|
|
+ 'settlementAgreementStart', 'settlementAgreementEnd', 'settlementAgreementExpiry', 'settlementAgreementFileType',
|
|
|
+ 'qualityAssuranceAgreement', 'qualityAssuranceAgreementFileName', 'qualityAssuranceAgreementCode',
|
|
|
+ 'qualityAssuranceAgreementStart', 'qualityAssuranceAgreementEnd', 'qualityAssuranceAgreementExpiry', 'qualityAssuranceAgreementFileType',
|
|
|
+ 'otherSpecialQualification', 'otherSpecialQualificationFileName', 'otherSpecialQualificationCode',
|
|
|
+ 'otherSpecialQualificationStart', 'otherSpecialQualificationEnd', 'otherSpecialQualificationExpiry', 'otherSpecialQualificationFileType',
|
|
|
+ 'titleNameOne', 'titleNameTwo', 'titleNameThree',
|
|
|
+ 'isEffectivePermanent1', 'isEffectivePermanent2', 'isEffectivePermanent3'
|
|
|
+ ],
|
|
|
// 选中数组
|
|
|
ids: [],
|
|
|
// 非单个禁用
|
|
|
@@ -1319,15 +1440,9 @@ export default {
|
|
|
licenseImages: [
|
|
|
{ required: true, message: "资质证书不能为空", trigger: "blur" }
|
|
|
],
|
|
|
- shippingType: [
|
|
|
- { required: true, message: "配送方式不能为空", trigger: "blur" }
|
|
|
- ],
|
|
|
account: [
|
|
|
{ required: true, message: "登录账号不能为空", trigger: "blur" }
|
|
|
],
|
|
|
- brokerageType: [
|
|
|
- { required: true, message: "分佣方式不能为空", trigger: "blur" }
|
|
|
- ],
|
|
|
refundPhone: [
|
|
|
{ required: true, message: "退货电话不能为空", trigger: "blur" }
|
|
|
],
|
|
|
@@ -1457,8 +1572,9 @@ export default {
|
|
|
},
|
|
|
// 添加图片预览方法
|
|
|
previewImage(url) {
|
|
|
- this.previewImageUrl = url;
|
|
|
- this.imagePreviewVisible = true;
|
|
|
+ this.previewImageUrl = url
|
|
|
+ this.previewScale = 100
|
|
|
+ this.imagePreviewVisible = true
|
|
|
},
|
|
|
handleNoticeInfo() {
|
|
|
qualifications()
|
|
|
@@ -1582,8 +1698,10 @@ export default {
|
|
|
reset() {
|
|
|
this.switchValue = false;
|
|
|
this.switchMedicalValue=false;
|
|
|
- // 重置时确保isDeleting为false
|
|
|
this.isDeleting = false;
|
|
|
+ this.reportFileList = [];
|
|
|
+ this.fileList = [];
|
|
|
+ this.originalForm = null;
|
|
|
this.form = {
|
|
|
storeId: null,
|
|
|
cityIds: null,
|
|
|
@@ -1824,6 +1942,7 @@ export default {
|
|
|
// 如果为空,则初始化为空数组
|
|
|
this.form.foodLicense = [];
|
|
|
}
|
|
|
+ this.originalForm = JSON.parse(JSON.stringify(this.form));
|
|
|
});
|
|
|
},
|
|
|
// 验证所有执照有效性验证方法
|
|
|
@@ -1892,6 +2011,17 @@ export default {
|
|
|
if (!this.validateLicenses()) {
|
|
|
return; // 验证失败,停止提交
|
|
|
}
|
|
|
+ const isEdit = this.form.storeId != null;
|
|
|
+ let isAgreementOnlySave = false;
|
|
|
+ if (isEdit && this.originalForm) {
|
|
|
+ const changedFields = this.getChangedFields(this.originalForm, this.form);
|
|
|
+ if (changedFields.length === 0) {
|
|
|
+ this.$message.warning("未检测到任何修改,无需提交");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const agreementFieldSet = this.getAgreementFieldSet();
|
|
|
+ isAgreementOnlySave = changedFields.every(f => agreementFieldSet.has(f));
|
|
|
+ }
|
|
|
// 处理表单数据
|
|
|
const formData = Object.assign({}, this.form);
|
|
|
//清空非必填日期控件
|
|
|
@@ -1938,23 +2068,27 @@ export default {
|
|
|
expiryField: 'settlementAgreementExpiry',
|
|
|
startField: 'settlementAgreementStart',
|
|
|
endField: 'settlementAgreementEnd',
|
|
|
+ permanentFlag: this.medicalLicenseExpiryValue1,
|
|
|
message: '其它资质-入驻协议,有效期开始日期或结束日期不能为空!'
|
|
|
},
|
|
|
{
|
|
|
expiryField: 'qualityAssuranceAgreementExpiry',
|
|
|
startField: 'qualityAssuranceAgreementStart',
|
|
|
endField: 'qualityAssuranceAgreementEnd',
|
|
|
+ permanentFlag: this.medicalLicenseExpiryValue2,
|
|
|
message: '质量保证协议,有效期开始日期或结束日期不能为空!'
|
|
|
},
|
|
|
{
|
|
|
expiryField: 'otherSpecialQualificationExpiry',
|
|
|
startField: 'otherSpecialQualificationStart',
|
|
|
endField: 'otherSpecialQualificationEnd',
|
|
|
+ permanentFlag: this.medicalLicenseExpiryValue3,
|
|
|
message: '其它特殊资质,有效期开始日期或结束日期不能为空!'
|
|
|
}
|
|
|
];
|
|
|
|
|
|
for (const field of agreementFields) {
|
|
|
+ if (field.permanentFlag) continue;
|
|
|
if (formData[field.expiryField] && formData[field.expiryField].length === 2) {
|
|
|
formData[field.startField] = formData[field.expiryField][0];
|
|
|
formData[field.endField] = formData[field.expiryField][1];
|
|
|
@@ -1980,9 +2114,16 @@ export default {
|
|
|
formData.foodLicense = formData.foodLicense.join(',');
|
|
|
}
|
|
|
|
|
|
- if (formData.storeId != null) {
|
|
|
+ if (isAgreementOnlySave) {
|
|
|
+ delete formData.isAudit;
|
|
|
updateStore(formData).then(response => {
|
|
|
- this.msgSuccess("修改成功");
|
|
|
+ this.msgSuccess("直接保存成功(未触发审核)");
|
|
|
+ this.open = false;
|
|
|
+ this.getList();
|
|
|
+ });
|
|
|
+ } else if (isEdit) {
|
|
|
+ updateStore(formData).then(response => {
|
|
|
+ this.msgSuccess("提交审核成功");
|
|
|
this.open = false;
|
|
|
this.getList();
|
|
|
});
|
|
|
@@ -2052,6 +2193,40 @@ export default {
|
|
|
});
|
|
|
|
|
|
},
|
|
|
+ handleEnable() {
|
|
|
+ const storeIds = this.ids
|
|
|
+ if (storeIds.length === 0) {
|
|
|
+ this.$message.warning('请选择要启用的店铺')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const storeNames = this.storeList
|
|
|
+ .filter(s => storeIds.includes(s.storeId))
|
|
|
+ .map(s => s.storeName)
|
|
|
+ .join('、')
|
|
|
+ this.$confirm(`确认一键启用以下店铺吗?<br/>${storeNames}`, '一键启用', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ dangerouslyUseHTMLString: true
|
|
|
+ }).then(() => {
|
|
|
+ this.enableLoading = true
|
|
|
+ const promises = storeIds.map(id => enableStore(id))
|
|
|
+ Promise.all(promises).then(responses => {
|
|
|
+ this.enableLoading = false
|
|
|
+ const failures = responses.filter(r => r.code !== 200)
|
|
|
+ if (failures.length > 0) {
|
|
|
+ const msgs = failures.map(f => f.msg).join('<br/>')
|
|
|
+ this.$message({ dangerouslyUseHTMLString: true, message: msgs, type: 'error', duration: 5000 })
|
|
|
+ } else {
|
|
|
+ this.$message.success('全部启用成功')
|
|
|
+ }
|
|
|
+ this.getList()
|
|
|
+ }).catch(() => {
|
|
|
+ this.enableLoading = false
|
|
|
+ this.getList()
|
|
|
+ })
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
/** 设置ERP店铺信息按钮 */
|
|
|
handleErpInfo(row) {
|
|
|
this.erpForm = {
|
|
|
@@ -2198,6 +2373,130 @@ export default {
|
|
|
handlePreview(file) {
|
|
|
console.log(file);
|
|
|
},
|
|
|
+ handleReportRemove(field) {
|
|
|
+ this.$set(this.form, field, '');
|
|
|
+ this.$message.info('文件已移除');
|
|
|
+ },
|
|
|
+ handleReportUploadSuccess(response, file, field) {
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.$set(this.form, field, response.url);
|
|
|
+ this.$message.success(`文件:${file.name}上传成功`);
|
|
|
+ this.$forceUpdate();
|
|
|
+ } else {
|
|
|
+ this.msgError(response.msg);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ beforeReportUpload(file) {
|
|
|
+ const isValid = file.type.startsWith('image/') || file.type === 'application/pdf'
|
|
|
+ if (!isValid) {
|
|
|
+ this.$message.error('仅支持 jpg/png/gif/bmp 图片或 PDF 文件')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ const isLt10M = file.size / 1024 / 1024 < 10
|
|
|
+ if (!isLt10M) {
|
|
|
+ this.$message.error('文件大小不能超过 10MB')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ isImageFile(url) {
|
|
|
+ if (!url) return false
|
|
|
+ return /\.(jpg|jpeg|png|gif|bmp|webp)(\?|$)/i.test(url)
|
|
|
+ },
|
|
|
+ viewReportFile(field) {
|
|
|
+ const url = this.form[field]
|
|
|
+ if (!url) {
|
|
|
+ this.$message.warning('暂无文件')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.viewReportFileByUrl(url)
|
|
|
+ },
|
|
|
+ viewReportFileByUrl(url) {
|
|
|
+ if (this.isImageFile(url)) {
|
|
|
+ this.previewImageUrl = url
|
|
|
+ this.previewScale = 100
|
|
|
+ this.imagePreviewVisible = true
|
|
|
+ } else {
|
|
|
+ window.open(url, '_blank')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ viewAgreementFile(field) {
|
|
|
+ const url = this.form[field]
|
|
|
+ if (!url) return
|
|
|
+ if (this.isImageFile(url, field)) {
|
|
|
+ this.previewImageUrl = url
|
|
|
+ this.previewScale = 100
|
|
|
+ this.imagePreviewVisible = true
|
|
|
+ } else {
|
|
|
+ window.open(url, '_blank')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onImagePreviewClose() {
|
|
|
+ this.previewScale = 100
|
|
|
+ this.dragOffset = { x: 0, y: 0 }
|
|
|
+ this.isDragging = false
|
|
|
+ this.imagePreviewVisible = false
|
|
|
+ },
|
|
|
+ zoomOut() {
|
|
|
+ if (this.previewScale > 25) {
|
|
|
+ this.previewScale = Math.max(25, this.previewScale - 25)
|
|
|
+ this.dragOffset = { x: 0, y: 0 }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ zoomIn() {
|
|
|
+ if (this.previewScale < 300) {
|
|
|
+ this.previewScale = Math.min(300, this.previewScale + 25)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ resetZoom() {
|
|
|
+ this.previewScale = 100
|
|
|
+ this.dragOffset = { x: 0, y: 0 }
|
|
|
+ },
|
|
|
+ onPreviewWheel(e) {
|
|
|
+ if (e.deltaY < 0) {
|
|
|
+ this.zoomIn()
|
|
|
+ } else {
|
|
|
+ this.zoomOut()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onImgMouseDown(e) {
|
|
|
+ this.isDragging = true
|
|
|
+ this.dragStart = { x: e.clientX - this.dragOffset.x, y: e.clientY - this.dragOffset.y }
|
|
|
+ },
|
|
|
+ onImgMouseMove(e) {
|
|
|
+ if (!this.isDragging) return
|
|
|
+ this.dragOffset = {
|
|
|
+ x: e.clientX - this.dragStart.x,
|
|
|
+ y: e.clientY - this.dragStart.y
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onImgMouseUp() {
|
|
|
+ this.isDragging = false
|
|
|
+ },
|
|
|
+ fieldsEqual(a, b) {
|
|
|
+ if (a === b) return true;
|
|
|
+ if (a == null && b == null) return true;
|
|
|
+ if (a == null || b == null) return false;
|
|
|
+ if (Array.isArray(a) && Array.isArray(b)) {
|
|
|
+ if (a.length !== b.length) return false;
|
|
|
+ return a.every((v, i) => this.fieldsEqual(v, b[i]));
|
|
|
+ }
|
|
|
+ if ((a === '' && b === null) || (a === null && b === '')) return true;
|
|
|
+ return String(a) === String(b);
|
|
|
+ },
|
|
|
+ getChangedFields(original, current) {
|
|
|
+ const changed = [];
|
|
|
+ for (const key of Object.keys(original)) {
|
|
|
+ if (this.excludedFields.indexOf(key) !== -1) continue;
|
|
|
+ if (!this.fieldsEqual(original[key], current[key])) {
|
|
|
+ changed.push(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return changed;
|
|
|
+ },
|
|
|
+ getAgreementFieldSet() {
|
|
|
+ return new Set(this.agreementFields);
|
|
|
+ },
|
|
|
handleExceed(files, fileList) {
|
|
|
this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
|
|
|
},
|
|
|
@@ -2238,6 +2537,7 @@ export default {
|
|
|
border-radius: 4px;
|
|
|
border: 1px solid #e4e7ed;
|
|
|
vertical-align: middle;
|
|
|
+ cursor: pointer;
|
|
|
}
|
|
|
|
|
|
/* 文档图标容器 */
|
|
|
@@ -2253,6 +2553,7 @@ export default {
|
|
|
justify-content: center;
|
|
|
background-color: #f5f7fa;
|
|
|
vertical-align: middle;
|
|
|
+ cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.document-icon .icon {
|
|
|
@@ -2531,5 +2832,63 @@ export default {
|
|
|
background-color: #f0f7ff;
|
|
|
}
|
|
|
|
|
|
+.img-preview-body {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-height: 300px;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.report-file-wrapper {
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+
|
|
|
+.uploaded-file-thumb {
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ border-radius: 4px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ cursor: pointer;
|
|
|
+ vertical-align: middle;
|
|
|
+}
|
|
|
+
|
|
|
+.document-file-icon {
|
|
|
+ width: 150px;
|
|
|
+ height: 100px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 4px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ cursor: pointer;
|
|
|
+ vertical-align: middle;
|
|
|
+}
|
|
|
+
|
|
|
+.document-file-icon .el-icon-document {
|
|
|
+ font-size: 32px;
|
|
|
+ color: #409eff;
|
|
|
+ margin-bottom: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.document-file-icon .file-name {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #606266;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ max-width: 120px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-btn-wrapper {
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+
|
|
|
+.report-preview-btn {
|
|
|
+ margin-top: 8px;
|
|
|
+}
|
|
|
|
|
|
</style>
|