|
|
<template> <div class="customer-css"> <el-dialog :title="titleCon" :close-on-click-modal="false" :visible.sync="visible" :width="showPreview ? '1200px' : '600px'" class="customer-dialog" > <el-form label-position="top"> <el-row :gutter="16"> <el-col :span="12"> <el-form-item label="BU"> <el-select v-model="pageData.buNo" placeholder="请选择" style="width: 100%"> <el-option v-for="i in buList" :key="i.buNo" :label="i.buDesc" :value="i.buNo"></el-option> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label=" "> <el-button type="primary" @click="downloadFile()">下载文件模板</el-button> </el-form-item> </el-col> <el-col :span="24" style="margin-top: 10px"> <el-upload class="customer-upload" drag action="javascript:void(0);" ref="uploadFile" :limit="1" accept=".xlsx,.xls" :before-upload="beforeUploadHandle" :on-change="onChange" :auto-upload="false" style="text-align: left;"> <i class="el-icon-upload"></i> <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> </el-upload> </el-col> </el-row> </el-form>
<!-- 预览数据表格 --> <!-- 加载状态 --> <div v-if="previewLoading" style="margin-top: 20px; text-align: center; padding: 40px;"> <i class="el-icon-loading" style="font-size: 24px; color: #409EFF;"></i> <p style="margin-top: 10px; color: #666;">正在解析文件,请稍候...</p> </div>
<div v-if="showPreview" style="margin-top: 20px; margin-bottom: 30px;"> <h4>文件预览 - 按发票号汇总 (共{{ previewData.length }}个发票)</h4>
<el-table :data="previewData" border style="width: 100%" max-height="400" :show-overflow-tooltip="true" class="delClass"> <el-table-column label="操作" width="40" fixed="left"> <template slot-scope="scope"> <a type="text" size="small" style="color: red" @click="deleteRow(scope.$index, scope.row)">删除</a> </template> </el-table-column> <el-table-column prop="cmcInvoice" label="发票号" width="120" fixed="left"> <template slot-scope="scope"> <span :style="scope.row.exists ? 'color: red; font-weight: bold;' : ''"> {{ scope.row.cmcInvoice }} <el-tag v-if="scope.row.exists" type="danger" size="mini">已存在</el-tag> </span> </template> </el-table-column> <el-table-column prop="destination" label="目的地" width="100"></el-table-column> <el-table-column label="客户模板" width="150"> <template slot-scope="scope"> <el-input v-model="scope.row.selectedTemplate" placeholder="请选择客户模板" @dblclick.native="selectTemplateForRow(scope.row)" size="small" style="cursor: pointer;"> </el-input> </template> </el-table-column> <el-table-column label="客户" width="150"> <template slot-scope="scope"> <el-input v-model="scope.row.selectedCustomer" placeholder="请选择客户" @dblclick.native="selectCustomerForRow(scope.row)" size="small" style="cursor: pointer;" readonly> <i slot="suffix" class="el-icon-edit" style="cursor: pointer;" @click.stop="openEditDialog(scope.row, 'selectedCustomer', '客户', '编辑客户信息')"></i> </el-input> </template> </el-table-column> <el-table-column label="客户地址" width="160"> <template slot-scope="scope"> <el-input v-model="scope.row.selectedLocalAddress" placeholder="请选择客户地址" @dblclick.native="selectLocalAddressForRow(scope.row)" size="small" style="cursor: pointer;" readonly> <i slot="suffix" class="el-icon-edit" style="cursor: pointer;" @click.stop="openEditDialog(scope.row, 'selectedLocalAddress', '客户地址', '编辑客户地址')"></i> </el-input> </template> </el-table-column> <el-table-column label="收货单位" width="150"> <template slot-scope="scope"> <el-input v-model="scope.row.selectedOverseasShipper" placeholder="请选择收货单位" @dblclick.native="selectOverseasShipperForRow(scope.row)" size="small" style="cursor: pointer;" readonly> <i slot="suffix" class="el-icon-edit" style="cursor: pointer;" @click.stop="openEditDialog(scope.row, 'selectedOverseasShipper', '收货单位', '编辑收货单位')"></i> </el-input> </template> </el-table-column> <el-table-column label="收货单位地址" width="160"> <template slot-scope="scope"> <el-input v-model="scope.row.selectedOverseasAddress" placeholder="请选择收货单位地址" @dblclick.native="selectOverseasAddressForRow(scope.row)" size="small" style="cursor: pointer;" readonly> <i slot="suffix" class="el-icon-edit" style="cursor: pointer;" @click.stop="openEditDialog(scope.row, 'selectedOverseasAddress', '收货单位地址', '编辑收货单位地址')"></i> </el-input> </template> </el-table-column> <el-table-column label="运抵国" width="80"> <template slot-scope="scope"> <el-input v-model="scope.row.selectedCnative" placeholder="运抵国" size="small" style="cursor: pointer;" readonly> <i slot="suffix" class="el-icon-edit" style="cursor: pointer;" @click.stop="openEditDialog(scope.row, 'selectedCnative', '运抵国', '编辑运抵国')"></i> </el-input> </template> </el-table-column> <el-table-column label="贸易国" min-width="80"> <template slot-scope="scope"> <el-input v-model="scope.row.selectedSalesArea" placeholder="贸易国" size="small" style="cursor: pointer;" readonly> <i slot="suffix" class="el-icon-edit" style="cursor: pointer;" @click.stop="openEditDialog(scope.row, 'selectedSalesArea', '贸易国', '编辑贸易国')"></i> </el-input> </template> </el-table-column> </el-table> </div>
<span slot="footer" class="dialog-footer" style="margin-top: 10px"> <el-button v-if="!showPreview" type="primary" @click="saveUploadFile">保存</el-button> <el-button v-if="showPreview" type="primary" @click="saveFromPreview">确认保存</el-button> <el-button v-if="showPreview" @click="cancelPreview">取消预览</el-button> <el-button v-if="!showPreview" type="primary" @click="closeDialog">关闭</el-button> </span> </el-dialog>
<el-dialog :title="currentRow ? `为发票号 ${currentRow.cmcInvoice} 选择客户模板` : '客户模板'" @close="templateFlag = false; currentRow = null" :visible.sync="templateFlag" width="1200px" v-drag> <el-table :height="400" :data="customerTemplateList" stripe highlight-current-row border class="delClass" @row-dblclick="rowDblclickTemplate" style="width: 100%;"> <el-table-column prop="template_name" header-align="center" align="left" width="150" label="模板名称"> </el-table-column> <el-table-column prop="ccusname" header-align="center" align="left" width="200" label="客户名称"> </el-table-column> <el-table-column prop="localShipAddress" header-align="center" align="left" width="300" label="客户地址"> </el-table-column> <el-table-column prop="overseasShipper" header-align="center" align="left" width="200" label="收货单位"> </el-table-column> <el-table-column prop="overseasAddress" header-align="center" align="left" width="300" label="收货地址"> </el-table-column> <el-table-column prop="salesArea" header-align="center" align="left" width="80" label="贸易国"> </el-table-column> <el-table-column prop="cnative" header-align="center" align="left" width="80" label="运抵国"> </el-table-column> </el-table> <el-footer style="height:40px;margin-top: 10px;text-align:center"> <el-button @click="templateFlag = false; currentRow = null">关闭</el-button> </el-footer> </el-dialog>
<el-dialog :title="currentRow ? `为发票号 ${currentRow.cmcInvoice} 选择客户` : '客户'" @close="closeCustomDialog" :visible.sync="customFlag" width="500px" v-drag> <el-form inline="inline" label-position="top" :model="customSearchData" style="margin-left: 7px;margin-top: -5px;"> <el-form-item label="客户名称"> <el-input v-model="customSearchData.ccusname" clearable style="width: 150px"></el-input> </el-form-item> <el-form-item label=" "> <el-button type="primary" style="padding: 3px 12px" @click="getCustomerList()">查询</el-button> </el-form-item> </el-form> <el-table :height="400" :data="customerList" stripe highlight-current-row border @row-dblclick="rowDblclick" style="width: 100%;"> <el-table-column prop="ccusname" header-align="center" align="left" width="350" label="客户名称"> </el-table-column> <el-table-column prop="country" header-align="center" align="left" label="贸易国"> </el-table-column> </el-table> <el-footer style="height:40px;margin-top: 10px;text-align:center"> <el-button @click="customFlag = false">关闭</el-button> </el-footer> </el-dialog>
<el-dialog :title="currentRow ? `为发票号 ${currentRow.cmcInvoice} 选择客户地址` : '客户地址'" @close="localShipAddressFlag = false; currentRow = null" :visible.sync="localShipAddressFlag" width="500px" v-drag> <el-table :height="400" :data="customerAddrs" stripe highlight-current-row border @row-dblclick="rowDblclick2" style="width: 100%;"> <el-table-column prop="cDeliverAdd" header-align="center" align="left" label="客户地址"> </el-table-column> </el-table> <el-footer style="height:40px;margin-top: 10px;text-align:center"> <el-button @click="localShipAddressFlag = false; currentRow = null">关闭</el-button> </el-footer> </el-dialog>
<el-dialog :title="currentRow ? `为发票号 ${currentRow.cmcInvoice} 选择收货单位地址` : '收货单位地址'" @close="overseasAddressFlag = false; currentRow = null" :visible.sync="overseasAddressFlag" width="500px" v-drag> <el-table :height="400" :data="customerAddrs" stripe highlight-current-row border @row-dblclick="rowDblclick3" style="width: 100%;"> <el-table-column prop="cDeliverAdd" header-align="center" align="left" label="收货单位地址"> </el-table-column> </el-table> <el-footer style="height:40px;margin-top: 10px;text-align:center"> <el-button @click="overseasAddressFlag = false; currentRow = null">关闭</el-button> </el-footer> </el-dialog>
<el-dialog :title="currentRow ? `为发票号 ${currentRow.cmcInvoice} 选择收货单位` : '收货单位'" @close="overseasShipperFlag = false; currentRow = null" :visible.sync="overseasShipperFlag" width="500px" v-drag> <el-table :height="400" :data="customerAddrs" stripe highlight-current-row border @row-dblclick="rowDblclick4" style="width: 100%;"> <el-table-column prop="cDeliverUnit" header-align="left" align="left" width="350" label="收货单位"> </el-table-column> <el-table-column prop="deliverycountry" header-align="center" align="left" label="运抵国"> </el-table-column> </el-table> <el-footer style="height:40px;margin-top: 10px;text-align:center"> <el-button @click="overseasShipperFlag = false; currentRow = null">关闭</el-button> </el-footer> </el-dialog>
<!-- 大输入框编辑弹窗 --> <el-dialog :title="editDialog.title" :visible.sync="editDialog.visible" width="600px" class="edit-dialog" @close="closeEditDialog"> <div class="edit-dialog-tip"> <i class="el-icon-info"></i> 提示:您可以在此编辑较长的文本内容,支持多行输入 </div> <el-form label-position="top" style="margin-bottom: 120px"> <el-form-item :label="editDialog.label"> <el-input ref="editTextarea" v-model="editDialog.value" type="textarea" :rows="6" placeholder="请输入内容,支持多行文本..." maxlength="500" show-word-limit class="edit-textarea"> </el-input> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="closeEditDialog">取消</el-button> <el-button type="primary" @click="confirmEdit">保存</el-button> </span> </el-dialog> </div></template>
<script> import {queryFileId} from "@/api/qc/qc.js" import {previewExcel,saveEcssCoDelNotifyByExcel,getCustomerList,getCustomers,getCustomerAdd,getCustomerTemplateList} from '@/api/ecss/ecss.js' import {downLoadObjectFile} from '@/api/eam/eam_object_list.js' import {getBuList}from '@/api/factory/site.js' export default { name: 'bomComponentUpload', data() { return { buList: [], titleCon: '文件导入', visible: false, fileList: [], pageData: { site: '', buNo: '', createBy: this.$store.state.user.name, customerName:'', localShipAddress:'', overseasShipper:'', overseasAddress:'', cnative:'', salesArea:'', }, previewData: [], // 预览数据
showPreview: false, // 是否显示预览
selectedFile: null, // 选择的文件
previewLoading: false, // 预览加载状态
deletedInvoices: [], // 被删除的发票号列表
customSearchData: {}, customerList : [],//所有客户
customerAddrs : [],//地址
customerPersons : [],//联系人
customerMap:new Map, customFlag:false, localShipAddressFlag:false, overseasShipperFlag:false, overseasAddressFlag:false, templateFlag:false, customerTemplateList: [],//客户模板列表
cacheKey: '', // 缓存键
cacheTimer: null, // 缓存定时器
currentRow: null, // 当前编辑的行
cachedFileInfo: null, // 缓存的文件信息
cachedFileList: [], // 缓存的文件列表
// 大输入框编辑弹窗相关数据
editDialog: { visible: false, title: '', label: '', value: '', fieldName: '', // 要编辑的字段名
row: null // 当前编辑的行数据
} } }, watch: { // 深度监听pageData的变化,自动保存到缓存
pageData: { handler: function(newVal, oldVal) { // 只有在组件已初始化且对话框可见时才保存缓存
if (this.visible && this.cacheKey) { this.saveToCache(); } }, deep: true }, // 深度监听previewData的变化,保存用户的编辑
previewData: { handler: function(newVal, oldVal) { // 只有在组件已初始化且对话框可见时才保存缓存
if (this.visible && this.cacheKey && newVal && newVal.length > 0) { this.saveToCache(); } }, deep: true } }, beforeDestroy() { // 组件销毁前清理定时器
if (this.cacheTimer) { clearTimeout(this.cacheTimer); } }, methods: { // 生成缓存键
generateCacheKey() { const userId = this.$store.state.user.id || this.$store.state.user.name; return `ecss_del_upload_cache_${userId}`; },
// 保存数据到缓存(防抖处理)
saveToCache() { // 清除之前的定时器
if (this.cacheTimer) { clearTimeout(this.cacheTimer); }
// 设置新的定时器,500ms后执行保存
this.cacheTimer = setTimeout(() => { try { const cacheData = { pageData: { buNo: this.pageData.buNo, customerName: this.pageData.customerName, localShipAddress: this.pageData.localShipAddress, overseasShipper: this.pageData.overseasShipper, overseasAddress: this.pageData.overseasAddress, cnative: this.pageData.cnative, salesArea: this.pageData.salesArea, }, // 保存文件和预览相关数据
fileInfo: this.selectedFile ? { name: this.selectedFile.name, size: this.selectedFile.size, lastModified: this.selectedFile.lastModified } : null, showPreview: this.showPreview, previewData: this.previewData, deletedInvoices: this.deletedInvoices, fileList: this.fileList.map(file => ({ name: file.name, size: file.size, lastModified: file.lastModified, uid: file.uid })) }; localStorage.setItem(this.cacheKey, JSON.stringify(cacheData)); } catch (error) { console.warn('保存缓存失败:', error); } }, 500); },
// 从缓存加载数据
loadFromCache() { try { const cachedData = localStorage.getItem(this.cacheKey); if (cachedData) { const parsedData = JSON.parse(cachedData); if (parsedData.pageData) { // 恢复基础表单数据
Object.assign(this.pageData, parsedData.pageData);
// 恢复预览数据和文件状态
if (parsedData.previewData && parsedData.previewData.length > 0) { this.previewData = parsedData.previewData; this.showPreview = parsedData.showPreview || false; }
// 恢复删除的发票号列表
if (parsedData.deletedInvoices) { this.deletedInvoices = parsedData.deletedInvoices; }
// 恢复文件列表信息(用于界面显示)
if (parsedData.fileList && parsedData.fileList.length > 0) { // 记录缓存的文件信息,用于后续比对
this.cachedFileInfo = parsedData.fileInfo; this.cachedFileList = parsedData.fileList; }
return true; } } } catch (error) { console.warn('加载缓存失败:', error); } return false; },
// 清除缓存
clearCache() { try { localStorage.removeItem(this.cacheKey); } catch (error) { console.warn('清除缓存失败:', error); } },
// 检查并恢复文件状态
checkAndRestoreFileState() { // 检查上传组件中是否有文件
const uploadFiles = this.$refs.uploadFile.uploadFiles;
if (this.cachedFileInfo && this.cachedFileList.length > 0) { // 如果有缓存的文件信息,检查当前上传组件中的文件
if (uploadFiles && uploadFiles.length > 0) { const currentFile = uploadFiles[0]; const isSameFile = currentFile.name === this.cachedFileInfo.name && currentFile.size === this.cachedFileInfo.size && currentFile.lastModified === this.cachedFileInfo.lastModified;
if (isSameFile) { // 是同一个文件,恢复文件相关状态
this.selectedFile = currentFile; this.fileList = [currentFile]; console.log('恢复文件状态:', currentFile.name); } else { // 文件不匹配,清除预览状态但保留表单数据
this.showPreview = false; this.previewData = []; this.selectedFile = null; this.fileList = []; console.log('文件不匹配,清除预览状态'); } } else { // 没有文件但有缓存,说明文件可能被清除了
this.showPreview = false; this.previewData = []; this.selectedFile = null; this.fileList = []; console.log('没有找到文件,清除预览状态'); } }
// 保存当前状态
this.saveToCache(); },
// 初始化组件的参数
init () { // 初始化缓存键,但不清除任何现有数据
this.cacheKey = this.generateCacheKey(); this.previewLoading = false
let tempData = { username: this.$store.state.user.name, } getBuList(tempData).then(({data}) => { if (data.code === 0) { this.buList = data.row2 if(data.row2.length===1){ this.pageData.buNo=data.row2[0].buNo } } // 在获取BU列表后尝试加载缓存
this.loadFromCache();
// 检查并恢复文件状态
this.$nextTick(() => { this.checkAndRestoreFileState(); }); })
getCustomerList({}).then(({data}) => { //区分请求成功和失败的状况
if (data && data.code === 0) { this.customerList=data.rows } });
// 只有在完全没有缓存数据时才初始化为空
const hasCache = this.loadFromCache(); if (!hasCache) { this.fileList = [] this.previewData = [] this.showPreview = false this.selectedFile = null this.deletedInvoices = [] this.pageData.customerName='' this.pageData.cnative='' this.pageData.localShipAddress='', this.pageData.overseasShipper='', this.pageData.overseasAddress='', this.pageData.salesArea='' }
this.customerPersons=[] this.customerAddrs=[] // 打开页面
this.visible = true }, getCustomerList(){ getCustomerList(this.customSearchData).then(({data}) => { //区分请求成功和失败的状况
if (data && data.code === 0) { this.customerList=data.rows } }); }, getCusPersons(){ let cusData = {ccusname: this.pageData.customerName} getCustomers(cusData).then(({data}) => { //区分请求成功和失败的状况
if (data && data.code === 0) { this.customerPersons=data.rows this.customerPersons.forEach(o => { if (!this.customerMap.has(o.ccontactname)) { this.customerMap.set(o.ccontactname, o.cnative); } }); } }); getCustomerAdd(cusData).then(({data}) => { //区分请求成功和失败的状况
if (data && data.code === 0) { this.customerAddrs=data.rows } }); }, setCnative(){ this.pageData.cnative=this.customerMap.get(this.pageData.overseasShipper) }, closeCustomDialog () { this.customFlag = false this.currentRow = null }, rowDblclickTemplate(row) { console.log(row) if (this.currentRow) { // 使用模板设置当前行的所有信息
this.currentRow.selectedTemplate = row.template_name this.currentRow.selectedCustomer = row.ccusname || '' this.currentRow.selectedLocalAddress = row.localShipAddress || '' this.currentRow.selectedOverseasShipper = row.overseasShipper || '' this.currentRow.selectedOverseasAddress = row.overseasAddress || '' this.currentRow.selectedCnative = row.cnative || '' this.currentRow.selectedSalesArea = row.salesArea || ''
// 如果模板中有客户信息,自动获取该客户的地址和收货单位信息
if (row.ccusname) { this.getCusPersonsForRow(row.ccusname) } } this.templateFlag = false this.currentRow = null },
rowDblclick (row) { if (this.currentRow) { // 预览模式下,为当前行设置客户信息
this.currentRow.selectedCustomer = row.ccusname this.currentRow.selectedSalesArea = row.country this.currentRow.selectedLocalAddress = '' this.currentRow.selectedOverseasShipper = '' this.currentRow.selectedOverseasAddress = '' this.currentRow.selectedCnative = '' this.getCusPersonsForRow(row.ccusname) } else { // 普通模式下,设置全局信息
this.pageData.customerName=row.ccusname this.pageData.cnative='', this.pageData.localShipAddress='', this.pageData.overseasShipper='', this.pageData.overseasAddress='', this.pageData.salesArea = row.country this.getCusPersons() } this.customFlag = false }, rowDblclick2 (row) { if (this.currentRow) { this.currentRow.selectedLocalAddress = row.cDeliverAdd } else { this.pageData.localShipAddress = row.cDeliverAdd } this.localShipAddressFlag = false this.currentRow = null }, rowDblclick3 (row) { if (this.currentRow) { this.currentRow.selectedOverseasAddress = row.cDeliverAdd } else { this.pageData.overseasAddress = row.cDeliverAdd } this.overseasAddressFlag = false this.currentRow = null }, rowDblclick4 (row) { if (this.currentRow) { this.currentRow.selectedOverseasShipper = row.cDeliverUnit this.currentRow.selectedCnative = row.deliverycountry } else { this.pageData.overseasShipper = row.cDeliverUnit this.pageData.cnative = row.deliverycountry } this.overseasShipperFlag = false this.currentRow = null },
// 上传之前
beforeUploadHandle (file) { let extName = file[0].name.substring(file[0].name.lastIndexOf('.')).toLowerCase() if (!(extName === '.xlsx' || extName === '.xls')) { this.$message.error('数据导入失败,请选择正确的xlsx模板文件') return false } },
// 选择上传文件时
onChange (file) { this.fileList.push(file) this.selectedFile = file this.previewFile(file) // 保存文件信息到缓存
this.saveToCache() },
// 关闭modal
closeDialog () { // 保存当前状态到缓存
this.saveToCache() // 关闭当前的页面
this.visible = false this.$emit('refreshTable') }, deleteFile(){ // 只有在明确需要清除数据时才调用此方法
this.fileList = [] this.previewData = [] this.showPreview = false this.selectedFile = null this.deletedInvoices = [] this.cachedFileInfo = null this.cachedFileList = [] // 清空文件上传记录
this.$refs.uploadFile.clearFiles() // 清除缓存
this.clearCache() // 刷新报工的页面
this.$emit('refreshTable') },
// 保修当前的数据
saveUploadFile () { if (null == this.pageData.buNo || this.pageData.buNo=='') { this.$message.error("请先选择BU!") return false } if (null == this.pageData.customerName || this.pageData.customerName=='') { this.$message.error("请先选择客户!") return false } if (null == this.pageData.localShipAddress || this.pageData.localShipAddress=='') { this.$message.error("请先填写客户发货地址!") return false } if (null == this.pageData.overseasShipper || this.pageData.overseasShipper=='') { this.$message.error("请先填写收货单位!") return false } if (null == this.pageData.overseasAddress || this.pageData.overseasAddress=='') { this.$message.error("请先填写收货单位地址!") return false } if (null == this.pageData.cnative || this.pageData.cnative=='') { this.$message.error("请先填写收货单位运抵国!") return false } // 判断文件是否上传
if (null == this.fileList || 0 === this.fileList.length) { this.$message.error("请先上传文件!") return false } const formData = new FormData() formData.append("buNo",this.pageData.buNo) formData.append("username",this.$store.state.user.name) formData.append("file", this.fileList[0].raw) formData.append("customerName", this.pageData.customerName) formData.append("localShipAddress", this.pageData.localShipAddress) formData.append("overseasShipper", this.pageData.overseasShipper) formData.append("overseasAddress", this.pageData.overseasAddress) formData.append("cnative", this.pageData.cnative) formData.append("salesArea", this.pageData.salesArea) saveEcssCoDelNotifyByExcel(formData).then(({ data }) => { if (data.code === 0) { const { resultMap } = data; const successList = resultMap.success || []; const failList = resultMap.fail || [];
// 紧凑样式
let html = `
<div style="max-height:380px;overflow:auto;font-size:12px;line-height:1.4;"> `;
if (successList.length > 0) { html += `<div style="margin-bottom:6px;">
<div style="color:green;font-weight:bold;margin-bottom:3px;"> ✅ 成功(${successList.length}) </div> <table border="1" cellspacing="0" cellpadding="2" style="border-collapse:collapse;width:100%;"> `;
successList.forEach(item => { html += `<tr><td style="color:green;padding:2px 4px;">${item}</td></tr>`; }); html += `</table></div>`; }
if (failList.length > 0) { html += `<div>
<div style="color:red;font-weight:bold;margin-bottom:3px;"> ❌ 失败(${failList.length}) </div> <table border="1" cellspacing="0" cellpadding="2" style="border-collapse:collapse;width:100%;"> `;
failList.forEach(item => { html += `<tr><td style="color:red;padding:2px 4px;">${item}</td></tr>`; }); html += `</table></div>`; }
html += `</div>`;
this.$alert(html, '导入结果', { confirmButtonText: '确定', dangerouslyUseHTMLString: true, callback: () => { if (successList.length > 0){ this.clearCache(); this.clearPreviewData(); this.closeDialog(); } } }); } else { this.$alert(data.msg, '错误', { confirmButtonText: '确定' }); } });
},
// 预览文件
async previewFile(file) { if (!file || !file.raw) { return } if (!this.pageData.buNo) { this.$message.error('请先选择BU!') this.fileList = [] this.$refs.uploadFile.clearFiles() return }
this.previewLoading = true // 开始加载
const formData = new FormData() formData.append("file", file.raw) formData.append("buNo", this.pageData.buNo)
try { const { data } = await previewExcel(formData)
if (data.code === 0) { this.previewData = data.data || [] this.showPreview = true // 清空删除列表,因为这是新的文件预览
this.deletedInvoices = [] // 为每个发票号初始化客户信息
this.previewData.forEach(item => { this.$set(item, 'selectedTemplate', '') this.$set(item, 'selectedCustomer', '') this.$set(item, 'selectedLocalAddress', '') this.$set(item, 'selectedOverseasShipper', '') this.$set(item, 'selectedOverseasAddress', '') this.$set(item, 'selectedCnative', '') this.$set(item, 'selectedSalesArea','') }) // 预览成功后立即保存缓存
this.saveToCache() } else { this.$message.error(data.msg || '文件预览失败') } } catch (error) { this.$message.error('文件预览失败:' + error.message) } finally { this.previewLoading = false // 结束加载
} },
// 从预览数据保存
saveFromPreview() { // 验证每个发票的必填信息
for (let item of this.previewData) { if (!item.selectedCustomer) { this.$message.error(`发票号 ${item.cmcInvoice} 请选择客户`) return false } if (!item.selectedLocalAddress) { this.$message.error(`发票号 ${item.cmcInvoice} 请填写客户地址`) return false } if (!item.selectedOverseasShipper) { this.$message.error(`发票号 ${item.cmcInvoice} 请填写收货单位`) return false } if (!item.selectedOverseasAddress) { this.$message.error(`发票号 ${item.cmcInvoice} 请填写收货单位地址`) return false } if (!item.selectedCnative) { this.$message.error(`发票号 ${item.cmcInvoice} 请填写运抵国`) return false } }
// 发送保存请求
const formData = new FormData() formData.append("buNo", this.pageData.buNo) formData.append("username", this.$store.state.user.name) formData.append("file", this.fileList[0].raw) // 添加被删除的发票号列表
formData.append("deletedInvoices", JSON.stringify(this.deletedInvoices)) // 为每个发票设置客户信息
this.previewData.forEach((item, index) => { formData.append(`customerName_${item.cmcInvoice}`, item.selectedCustomer) formData.append(`localShipAddress_${item.cmcInvoice}`, item.selectedLocalAddress) formData.append(`overseasShipper_${item.cmcInvoice}`, item.selectedOverseasShipper) formData.append(`overseasAddress_${item.cmcInvoice}`, item.selectedOverseasAddress) formData.append(`cnative_${item.cmcInvoice}`, item.selectedCnative) formData.append(`salesArea_${item.cmcInvoice}`, item.selectedSalesArea) })
saveEcssCoDelNotifyByExcel(formData).then(({ data }) => { if (data.code === 0) { const { resultMap } = data; const successList = resultMap.success || []; const failList = resultMap.fail || [];
// 紧凑样式
let html = `
<div style="max-height:380px;overflow:auto;font-size:12px;line-height:1.4;"> `;
if (successList.length > 0) { html += `<div style="margin-bottom:6px;">
<div style="color:green;font-weight:bold;margin-bottom:3px;"> ✅ 成功(${successList.length}) </div> <table border="1" cellspacing="0" cellpadding="2" style="border-collapse:collapse;width:100%;"> `;
successList.forEach(item => { html += `<tr><td style="color:green;padding:2px 4px;">${item}</td></tr>`; }); html += `</table></div>`; }
if (failList.length > 0) { html += `<div>
<div style="color:red;font-weight:bold;margin-bottom:3px;"> ❌ 失败(${failList.length}) </div> <table border="1" cellspacing="0" cellpadding="2" style="border-collapse:collapse;width:100%;"> `;
failList.forEach(item => { html += `<tr><td style="color:red;padding:2px 4px;">${item}</td></tr>`; }); html += `</table></div>`; }
html += `</div>`;
this.$alert(html, '导入结果', { confirmButtonText: '确定', dangerouslyUseHTMLString: true, callback: () => { if (successList.length > 0){ this.clearCache(); this.clearPreviewData(); this.closeDialog(); } } }); } else { this.$alert(data.msg, '错误', { confirmButtonText: '确定' }); } }); },
// 取消预览
cancelPreview() { this.showPreview = false this.previewData = [] this.fileList = [] this.selectedFile = null this.deletedInvoices = [] this.cachedFileInfo = null this.cachedFileList = [] this.$refs.uploadFile.clearFiles() // 更新缓存
this.saveToCache() },
// 清除预览数据
clearPreviewData() { this.previewData = [] this.showPreview = false this.selectedFile = null this.fileList = [] this.deletedInvoices = [] this.previewLoading = false this.cachedFileInfo = null this.cachedFileList = [] this.$refs.uploadFile.clearFiles() // 更新缓存
this.saveToCache() },
// 为行选择客户模板
selectTemplateForRow(row) { this.currentRow = row this.getCustomerTemplateList() this.templateFlag = true },
// 为行选择客户
selectCustomerForRow(row) { this.currentRow = row this.customFlag = true },
// 为行选择客户地址
selectLocalAddressForRow(row) { if (!row.selectedCustomer) { this.$message.warning('请先选择客户') return } this.currentRow = row this.getCusPersonsForRow(row.selectedCustomer) this.localShipAddressFlag = true },
// 为行选择收货单位
selectOverseasShipperForRow(row) { if (!row.selectedCustomer) { this.$message.warning('请先选择客户') return } this.currentRow = row this.getCusPersonsForRow(row.selectedCustomer) this.overseasShipperFlag = true },
// 为行选择收货单位地址
selectOverseasAddressForRow(row) { if (!row.selectedCustomer) { this.$message.warning('请先选择客户') return } this.currentRow = row this.getCusPersonsForRow(row.selectedCustomer) this.overseasAddressFlag = true },
// 获取客户模板列表
async getCustomerTemplateList() { try { const { data } = await getCustomerTemplateList({}) if (data && data.code === 0) { this.customerTemplateList = data.rows || [] } } catch (error) { console.error('获取客户模板列表失败:', error) this.customerTemplateList = [] } },
// 获取特定客户的地址信息
getCusPersonsForRow(customerName) { let cusData = {ccusname: customerName} getCustomers(cusData).then(({data}) => { if (data && data.code === 0) { this.customerPersons = data.rows this.customerPersons.forEach(o => { if (!this.customerMap.has(o.ccontactname)) { this.customerMap.set(o.ccontactname, o.cnative); } }); } }); getCustomerAdd(cusData).then(({data}) => { if (data && data.code === 0) { this.customerAddrs = data.rows } }); },
// 打开大输入框编辑弹窗
openEditDialog(row, fieldName, label, title) { this.editDialog.visible = true this.editDialog.title = title this.editDialog.label = label this.editDialog.fieldName = fieldName this.editDialog.row = row this.editDialog.value = row[fieldName] || '' this.$nextTick(() => this.$refs.editTextarea.focus()); },
// 关闭大输入框编辑弹窗
closeEditDialog() { this.editDialog.visible = false this.editDialog.title = '' this.editDialog.label = '' this.editDialog.fieldName = '' this.editDialog.row = null this.editDialog.value = '' },
// 确认编辑
confirmEdit() { if (this.editDialog.row && this.editDialog.fieldName) { this.editDialog.row[this.editDialog.fieldName] = this.editDialog.value } this.closeEditDialog() },
// 删除行
deleteRow(index, row) { this.$confirm(`确定要删除发票号 "${row.cmcInvoice}" 吗?删除后将不会提交到后台。`, '删除确认', { confirmButtonText: '确定删除', cancelButtonText: '取消', type: 'warning' }).then(() => { // 记录被删除的发票号
if (!this.deletedInvoices.includes(row.cmcInvoice)) { this.deletedInvoices.push(row.cmcInvoice) } // 从预览数据中移除该行
this.previewData.splice(index, 1) this.$message.success(`发票号 "${row.cmcInvoice}" 已删除`) // 保存到缓存
this.saveToCache() }).catch(() => { // 用户取消删除
}) },
// 下载
async downloadFile () { let file = { id: 0, fileName: '' } let tempData = { orderRef1: 'ecss', orderRef2: 'upLoadDel' } await queryFileId(tempData).then(({data}) => { if (data && data.code === 0) { file.id = data.data.id file.fileName = data.data.fileName } else { this.$alert(data.msg, '错误', { confirmButtonText: '确定' }) } })
await downLoadObjectFile(file).then(({data}) => { // 不限制文件下载类型
const blob = new Blob([data], {type: "application/octet-stream"}) // 下载文件名称
const fileName = file.fileName // a标签下载
const linkNode = document.createElement('a') // a标签的download属性规定下载文件的名称
linkNode.download = fileName linkNode.style.display = 'none' // 生成一个Blob URL
linkNode.href = URL.createObjectURL(blob) document.body.appendChild(linkNode) // 模拟在按钮上的一次鼠标单击
linkNode.click() // 释放URL 对象
URL.revokeObjectURL(linkNode.href) document.body.removeChild(linkNode) }) }, } }</script><style scoped>/deep/ .delClass .cell { line-height: 24px !important; font-size: 12px !important; height: 24px !important;}
/deep/ .customer-upload .el-upload .el-upload-dragger { width: 580px;}
/* 输入框样式优化 */.el-input.is-readonly { cursor: pointer !important;}
.el-input.is-readonly .el-input__inner { cursor: pointer !important; background-color: #f8f9fa;}
.el-input.is-readonly .el-input__inner:hover { background-color: #e9ecef; border-color: #409EFF;}
/* 编辑图标样式 */.el-input__suffix .el-icon-edit { color: #409EFF; transition: all 0.3s; font-size: 14px; padding: 2px; border-radius: 3px;}
.el-input__suffix .el-icon-edit:hover { color: #ffffff; background-color: #409EFF; transform: scale(1.1);}
/* 编辑弹窗整体样式 */.edit-dialog .el-dialog__body { padding: 20px 20px 0;}
.edit-dialog-tip { margin-bottom: 15px; color: #909399; font-size: 12px; background-color: #f4f4f5; padding: 8px 12px; border-radius: 4px; border-left: 3px solid #409EFF;}
.edit-dialog-tip .el-icon-info { margin-right: 5px; color: #409EFF;}
/* 大输入框样式 */.edit-textarea .el-textarea__inner { resize: vertical !important; min-height: 120px !important; border: 1px solid #dcdfe6 !important; border-radius: 4px !important; padding: 8px 12px !important; font-size: 14px !important; line-height: 1.5 !important; color: #606266 !important; background-color: #fff !important; transition: border-color 0.2s cubic-bezier(.645,.045,.355,1) !important; box-sizing: border-box !important;}
.edit-textarea .el-textarea__inner:focus { outline: none !important; border-color: #409EFF !important; box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2) !important;}
.edit-textarea .el-input__count { color: #909399 !important; background: #fff !important; position: absolute !important; font-size: 12px !important; bottom: 5px !important; right: 10px !important;}
/* 修复弹窗中的表单项样式 */.edit-dialog .el-form-item { margin-bottom: 18px !important;}
.edit-dialog .el-form-item__label { color: #606266 !important; font-weight: 500 !important; line-height: 1.5 !important; padding: 0 0 8px 0 !important; box-sizing: border-box !important; font-size: 14px !important;}
/* 编辑弹窗按钮样式 */.edit-dialog .dialog-footer { text-align: right !important; padding: 15px 20px 20px !important;}
.edit-dialog .dialog-footer .el-button { margin-left: 10px !important;}
/* 确保弹窗内容不会溢出 */.edit-dialog .el-dialog__wrapper { overflow: hidden;}
.edit-dialog .el-dialog { margin-top: 5vh !important; margin-bottom: 50px !important;}
/* 表格输入框提示文字 */.el-table .el-input__inner::placeholder { font-size: 12px; color: #c0c4cc;}
</style>
|