diff --git a/package.json b/package.json index 7603eb8b..763e1097 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "crypto-js": "^4.1.1", "dayjs": "^1.10.6", "element-plus": "^2.3.1", + "file-saver": "^2.0.5", "html2canvas": "^1.4.1", "js-base64": "^3.7.4", "js-cookie": "^3.0.0", @@ -34,7 +35,8 @@ "vue-i18n": "^9.1.9", "vue-qr": "^4.0.9", "vue-router": "^4.2.4", - "vuex": "^4.0.2" + "vuex": "^4.0.2", + "xlsx-style-vite": "^0.0.2" }, "devDependencies": { "@vitejs/plugin-vue": "^1.3.0", @@ -46,6 +48,6 @@ "vite": "^5.4.2", "vite-plugin-compression": "^0.5.1", "vite-plugin-vue-setup-extend": "^0.4.0", - "xlsx": "0.18.5" + "xlsx": "^0.18.5" } } diff --git a/src/components/ArteryPrintTemplate/ArteryPrintTemplate.vue b/src/components/ArteryPrintTemplate/ArteryPrintTemplate.vue index 6d8b9659..fe1c5a41 100644 --- a/src/components/ArteryPrintTemplate/ArteryPrintTemplate.vue +++ b/src/components/ArteryPrintTemplate/ArteryPrintTemplate.vue @@ -226,22 +226,12 @@ <td style="border-bottom: 1px solid #000; border-left: 1px solid #000"></td> <td style="border-bottom: 1px solid #000; border-left: 1px solid #000"></td> </tr> - <tr> - <td - style="border-bottom: 1px solid #000; border-left: 1px solid #000" - :colspan="17 + goodsTitleList.length" - contenteditable - > - <span style="display: inline-block; margin-right: 20px; min-width: 200px"> - 投诉电话:4000184668 - </span> - <span style="display: inline-block; margin-right: 20px; min-width: 200px"> - 营业部电话: - </span> - <span style="display: inline-block; margin-right: 20px; min-width: 200px"> - 系统单调度: - </span> - </td> + <tr style="border-bottom: 1px solid #000; border-left: 1px solid #000"> + <td :colspan="6" contenteditable>投诉电话:4000184668</td> + + <td :colspan="6" contenteditable>营业部电话:</td> + + <td :colspan="5 + goodsTitleList.length" contenteditable>系统单调度:</td> </tr> </table> </div> diff --git a/src/components/Tableexportcomponent/Tableexportcomponent.vue b/src/components/Tableexportcomponent/Tableexportcomponent.vue index 6fbee0b1..9eaf7fc2 100644 --- a/src/components/Tableexportcomponent/Tableexportcomponent.vue +++ b/src/components/Tableexportcomponent/Tableexportcomponent.vue @@ -56,6 +56,9 @@ removeColumn('复选框'); const exportFileName = ref(''); // 已选择的列 const checkedColumns = ref([]); +const initializeCheckedColumns = () => { + checkedColumns.value = transferData.value.map(item => item.key); +}; // 构建 el-transfer 所需的数据格式,并添加类型检查 const transferData = computed(() => { @@ -69,7 +72,7 @@ const transferData = computed(() => { return []; } }); - +initializeCheckedColumns(); // 设置 el-transfer 的 props const transferProps = { key: 'key', diff --git a/src/components/TripartiteTransferPrintTemplate/TripartiteTransferPrintTemplate.vue b/src/components/TripartiteTransferPrintTemplate/TripartiteTransferPrintTemplate.vue index ce42e2f9..a42c7e42 100644 --- a/src/components/TripartiteTransferPrintTemplate/TripartiteTransferPrintTemplate.vue +++ b/src/components/TripartiteTransferPrintTemplate/TripartiteTransferPrintTemplate.vue @@ -7,11 +7,11 @@ <thead> <tr> <th colspan="4"> - <img src="" alt="暂无图片" /> + <img style="height: 40px" src="../../../public/img/htlogo.png" alt="暂无图片" /> </th> - <th colspan="6">干线装载清单</th> + <th colspan="6" style="font-size: 20px">中转装载清单</th> <th :colspan="3 + goodsTitleList.length + 1"> - <img id="imgcode" /> + <img id="imgcode" :src="renderInfo.carsNoBase64" /> <div>{{ renderInfo.carsNo }}</div> </th> </tr> @@ -106,11 +106,11 @@ <td></td> </tr> <tr> - <td :colspan="14 + goodsTitleList.length"> - <span style="display: inline-block; margin-right: 20px"> 投诉电话:4000184668 </span> - <span style="display: inline-block; margin-right: 20px"> 营业部售后电话: </span> - <span style="display: inline-block; margin-right: 20px"> 系统单调度: </span> - </td> + <td :colspan="5">投诉电话:4000184668</td> + + <td :colspan="5">营业部售后电话:</td> + + <td :colspan="4 + goodsTitleList.length">系统单调度:</td> </tr> </tbody> </table> diff --git a/src/components/tablecmt/tablecmt.vue b/src/components/tablecmt/tablecmt.vue index e0ef44b4..0a0a0107 100644 --- a/src/components/tablecmt/tablecmt.vue +++ b/src/components/tablecmt/tablecmt.vue @@ -30,95 +30,97 @@ <!-- <template #header> <el-text class="mx-1">{{ column.label }}</el-text> </template> --> - <el-table-column - :type="column.type == 12 ? 'index' : ''" - :min-width="column.width" - :prop="column.prop" - :label="column.label" - v-if="column.type != 0" - flexible - show-overflow-tooltip - class="el_boxsa" - > - <template #header> - <el-text class="el_placeholder" v-if="column.type == 1"> </el-text> - <el-text - v-if="column.type == 1 || column.type == 0 || column.type == 12 || column.type == 6" - class="mx-1" - ></el-text> - - <el-icon v-if="column.type == 12 && props.isShowRefresh === true" @click="handleRefresh" - ><RefreshRight - /></el-icon> - - <el-input - v-if="column.type == 2 || column.type == 13" - v-model.trim="column.values" - clearable - :placeholder="`请输入${column.label}`" - @change="inputchange($event, column)" - @keyup.enter="handleInput" - /> - <el-select - v-else-if="column.type == 3 || column.type == 14" - v-model="column.values" - filterable - class="m-2 selectbr" - clearable - :placeholder="`请选择${column.label}`" - @change="selectchange($event, column)" - > - <el-option - v-for="item in column.checkarr" - :key="item.value" - :label="item.label" - :value="item.value" + <template v-if="column.type != 0 && column.type !== 30"> + <el-table-column + :type="column.type == 12 ? 'index' : ''" + :min-width="column.width" + :prop="column.prop" + :label="column.label" + flexible + show-overflow-tooltip + class="el_boxsa" + > + <template #header> + <el-text class="el_placeholder" v-if="column.type == 1"> </el-text> + <el-text + v-if="column.type == 1 || column.type == 0 || column.type == 12 || column.type == 6" + class="mx-1" + ></el-text> + + <el-icon + v-if="column.type == 12 && props.isShowRefresh === true" + @click="handleRefresh" + ><RefreshRight + /></el-icon> + + <el-input + v-if="column.type == 2 || column.type == 13" + v-model.trim="column.values" + clearable + :placeholder="`请输入${column.label}`" + @change="inputchange($event, column)" + @keyup.enter="handleInput" /> - </el-select> - <el-date-picker - v-model="column.values" - v-else-if="column.type == 4" - type="date" - clearable - style="width: auto; height: 23px !important" - :placeholder="`请选择${column.label}`" - @change="timechange($event, column)" - /> - <el-date-picker - v-model="column.values" - v-else-if="column.type == 5" - type="datetime" - clearable - style="width: auto" - size="default" - :placeholder="`请选择${column.label}`" - format="YYYY/MM/DD HH:mm:ss" - @change="timechange($event, column)" - /> - <span v-else></span> - </template> - - <template #default="scope"> - <el-text - @click.stop - @dblclick.stop="Copytxt(scope.row[column.prop])" - class="mx-2 tabculconte" - :class=" - scope.row[column.prop] == props.searchInput && scope.row[column.prop] - ? 'static-class' - : '' - " - :id="scope.row[column.prop]" - v-if="Number(column.type) < 6 && Number(column.type) > 0" - >{{ scope.row[column.prop] }}</el-text - > - <el-switch - @change="makeCargo(scope.row, column)" - v-else-if="column.type == 11" - v-model="scope.row[column.prop]" - /> - - <!-- <el-text + <el-select + v-else-if="column.type == 3 || column.type == 14" + v-model="column.values" + filterable + class="m-2 selectbr" + clearable + :placeholder="`请选择${column.label}`" + @change="selectchange($event, column)" + > + <el-option + v-for="item in column.checkarr" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + <el-date-picker + v-model="column.values" + v-else-if="column.type == 4" + type="date" + clearable + style="width: auto; height: 23px !important" + :placeholder="`请选择${column.label}`" + @change="timechange($event, column)" + /> + <el-date-picker + v-model="column.values" + v-else-if="column.type == 5" + type="datetime" + clearable + style="width: auto" + size="default" + :placeholder="`请选择${column.label}`" + format="YYYY/MM/DD HH:mm:ss" + @change="timechange($event, column)" + /> + <span v-else></span> + </template> + + <template #default="scope"> + <el-text + @click.stop + @dblclick.stop="Copytxt(scope.row[column.prop])" + class="mx-2 tabculconte" + :class=" + scope.row[column.prop] == props.searchInput && scope.row[column.prop] + ? 'static-class' + : '' + " + :id="scope.row[column.prop]" + v-if="Number(column.type) < 6 && Number(column.type) > 0" + >{{ scope.row[column.prop] }}</el-text + > + <el-switch + @change="makeCargo(scope.row, column)" + v-else-if="column.type == 11" + v-model="scope.row[column.prop]" + /> + + <!-- <el-text class="mx-2 tabculconte" v-for="item in column.checkarr" v-if="Number(column.type) < 6 && Number(column.type) > 0" @@ -126,37 +128,37 @@ <span v-if="item.value==scope.row[column.prop]">{{ item.label }}</span> </el-text > --> - <el-text - style="" - class="mx-2 tabculconte colors" - v-else-if="column.type == 9" - @click="godowns(scope.row[column.downprop])" - >{{ scope.row[column.prop] }}</el-text - > - <el-input - @blur="handleNumberRange(column, scope.row)" - v-else-if="column.type == 10" - v-model.trim="scope.row[column.prop]" - type="number" - :min="0" - :max="scope.row.residueNumber" - ></el-input> - <div - class="slotbuts" - v-else-if="column.type == 6 || column.type == 13 || column.type == 14" - > - <slot :scope="scope"> </slot> - </div> - - <el-input - v-else-if="column.type == 15" - v-model.trim="scope.row[column.prop]" - style="width: 100%" - :placeholder="'请输入' + column.label" - :disabled="!scope.row.disabled" - clearable - /> - <!-- <el-image + <el-text + style="" + class="mx-2 tabculconte colors" + v-else-if="column.type == 9" + @click="godowns(scope.row[column.downprop])" + >{{ scope.row[column.prop] }}</el-text + > + <el-input + @blur="handleNumberRange(column, scope.row)" + v-else-if="column.type == 10" + v-model.trim="scope.row[column.prop]" + type="number" + :min="0" + :max="scope.row.residueNumber" + ></el-input> + <div + class="slotbuts" + v-else-if="column.type == 6 || column.type == 13 || column.type == 14" + > + <slot :scope="scope"> </slot> + </div> + + <el-input + v-else-if="column.type == 15" + v-model.trim="scope.row[column.prop]" + style="width: 100%" + :placeholder="'请输入' + column.label" + :disabled="!scope.row.disabled" + clearable + /> + <!-- <el-image preview-teleported v-else-if="column.type == 7" style="width: 60px; height: 60px; margin-left: 10px" @@ -166,19 +168,19 @@ :src="item" :preview-src-list="scope.row[column.prop].split(',')" /> --> - <el-image - preview-teleported - v-else-if="column.type == 7" - style="width: 60px; height: 60px; margin-left: 10px" - :initial-index="index" - :z-index="100" - v-for="(item, index) in scope.row[column.prop]?.split(',')" - :src="item" - :preview-src-list="scope.row[column.prop]?.split(',')" - /> - </template> - </el-table-column> - + <el-image + preview-teleported + v-else-if="column.type == 7" + style="width: 60px; height: 60px; margin-left: 10px" + :initial-index="index" + :z-index="100" + v-for="(item, index) in scope.row[column.prop]?.split(',')" + :src="item" + :preview-src-list="scope.row[column.prop]?.split(',')" + /> + </template> + </el-table-column> + </template> <template #header> <div style="display: inline-block"> <div class="tilbox"> diff --git a/src/option/aftersales/vueTvemp.js b/src/option/aftersales/vueTvemp.js index 7b67802d..0532734a 100644 --- a/src/option/aftersales/vueTvemp.js +++ b/src/option/aftersales/vueTvemp.js @@ -317,7 +317,17 @@ export const columnList = [ sortable: true, head: false, }, - + { + prop: 'createTime', + label: '录入时间', + type: 1, + values: '', + width: '150', + checkarr: [], + fixed: false, + sortable: true, + head: false, + }, { prop: 'remarks', diff --git a/src/utils/export.js b/src/utils/export.js new file mode 100644 index 00000000..c5390f0e --- /dev/null +++ b/src/utils/export.js @@ -0,0 +1,180 @@ +import * as XLSX from 'xlsx'; +import FileSaver from 'file-saver'; +import XLSXS from 'xlsx-style-vite'; +import { getObjType, isNumber } from '@/utils/util'; + +/** + * 根据DOM进行导出 + * @param {Element} dom + * @param {String} fileName + */ +export function exportExcelByDom(dom, fileName) { + const book = XLSX.utils.book_new(); + const sheet = XLSX.utils.table_to_sheet(dom); + + XLSX.utils.book_append_sheet(book, sheet, 'Sheet1'); + addRangeBorder(sheet['!merges'], sheet); // 给合并行列赋值样式 + setExcelStyle(sheet); // 设置样式 + let wbout = XLSXS.write(book, { + bookType: 'xlsx', + bookSST: false, + type: 'binary', + }); + try { + FileSaver.saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), fileName); + } catch (e) { + console.error(e, wbout, '----->>>'); + } +} + +// 设置导出Excel样式(统一样式) +function setExcelStyle(data, wpx = 80) { + data['!cols'] = []; + const excludes = ['!cols', '!fullref', '!merges', '!ref', '!rows']; + console.log('data :>> ', data); + for (let key in data) { + if (data.hasOwnProperty(key)) { + if (!excludes.includes(key)) { + data[key].s = { + alignment: { + horizontal: 'center', //水平居中对齐 + vertical: 'center', // 垂直居中 + wrapText: true, + }, + border: { + top: { + style: 'thin', + color: { rgb: '000000' }, + }, + bottom: { + style: 'thin', + color: { rgb: '000000' }, + }, + left: { + style: 'thin', + color: { rgb: '000000' }, + }, + right: { + style: 'thin', + color: { rgb: '000000' }, + }, + }, + // fill: { + // fgColor: { rgb: "00a2ff" }, + // }, + font: { + sz: 11, + color: { + rgb: '000000', + }, + }, + bold: true, + numFmt: 0, + }; + const _text = data[key].v; + getObjType(_text) === 'string' && (data[key].v = _text.replace('-->', '')); + // 单元格宽度 + data['!cols'].push({ wpx }); + // 根据不同行添加单元格背景颜色 + let color = 'ffffff'; + // 文字颜色 + let textColor = '000000'; + let num = Number(key.slice(1)); + num = isNumber(num) ? num : Number(key.slice(2)); + if (num === 1) { + color = '172e60'; + textColor = 'ffffff'; + data[key].s.font.sz = 16; + } else { + } + data[key].s.fill = { + fgColor: { rgb: color, patternType: 'solid' }, + }; + + data[key].s.font.color.rgb = textColor; + } + } + } +} + +//给合并行列赋值样式 +function addRangeBorder(range, ws) { + let cols = [ + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'AA', + 'AB', + 'AC', + 'AD', + 'AE', + 'AF', + 'AG', + ]; + console.log('range :>> ', range); + range.forEach(item => { + console.log('item :>> ', item); + let style = { + s: { + border: { + top: { + style: 'thin', + color: { rgb: '000000' }, + }, + bottom: { + style: 'thin', + color: { rgb: '000000' }, + }, + left: { + style: 'thin', + color: { rgb: '000000' }, + }, + right: { + style: 'thin', + color: { rgb: '000000' }, + }, + }, + }, + }; + // 处理合并行 + for (let i = item.s.c; i <= item.e.c; i++) { + ws[`${cols[i]}${Number(item.e.r) + 1}`] = ws[`${cols[i]}${Number(item.e.r) + 1}`] || style; + // 处理合并列 + for (let k = item.s.r + 2; k <= item.e.r + 1; k++) { + // console.log(' ws[cols[k] + item.e.r] :>> ', ws[cols[k] + item.e.r]); + ws[cols[i] + k] = ws[cols[i] + k] || style; + } + } + }); + return ws; +} + +function s2ab(s) { + var buf = new ArrayBuffer(s.length); + var view = new Uint8Array(buf); + for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff; + return buf; +} diff --git a/src/views/aftersales/aftersalesWorkOrder.vue b/src/views/aftersales/aftersalesWorkOrder.vue index 9022cff2..64bf9867 100644 --- a/src/views/aftersales/aftersalesWorkOrder.vue +++ b/src/views/aftersales/aftersalesWorkOrder.vue @@ -1816,6 +1816,8 @@ const IndexTable = (val, Refresh) => { } else { TabList.value.find(res => res.name == '9').state = false; } + }else{ + TabList.value.find(res => res.name == '9').state = false; } console.log(UserPermissions.value, '当前角色权限'); let data = { diff --git a/src/views/aftersales/aftersalesWorkOrderAdd.vue b/src/views/aftersales/aftersalesWorkOrderAdd.vue index 0a597cf3..9fb464c1 100644 --- a/src/views/aftersales/aftersalesWorkOrderAdd.vue +++ b/src/views/aftersales/aftersalesWorkOrderAdd.vue @@ -807,41 +807,41 @@ const form = ref({ const myData = ref({}); //用户信息记录 const ruleForm = reactive({ basis: { - workOrderType: [{ required: true, message: '请选择异常类型', trigger: ['bulr', 'change'] }], - discoveryNode: [{ required: true, message: '请选择发现节点', trigger: ['bulr', 'change'] }], - trainNumber: [{ required: true, message: '请选择车次号', trigger: ['bulr', 'change'] }], - deliveryTime: [{ required: true, message: '请输入配送时间', trigger: ['bulr', 'change'] }], - deliveryDriver: [{ required: true, message: '请输入配送司机', trigger: ['bulr', 'change'] }], - vehicleRoute: [{ required: true, message: '请输入车辆线路', trigger: ['bulr', 'change'] }], - deliverGoodsTime: [{ required: true, message: '请输入发货时间', trigger: ['bulr', 'change'] }], - warehousingTime: [{ required: true, message: '请选择入库时间', trigger: ['bulr', 'change'] }], - discoveryTime: [{ required: true, message: '请选择发现时间', trigger: ['bulr', 'change'] }], - waybillMall: [{ required: true, message: '请输入运单商场', trigger: ['bulr'] }], - typeServiceName: [{ required: false, message: '请输入合作模式', trigger: ['bulr', 'change'] }], + workOrderType: [{ required: true, message: '请选择异常类型', trigger: ['blur', 'change'] }], + discoveryNode: [{ required: true, message: '请选择发现节点', trigger: ['blur', 'change'] }], + trainNumber: [{ required: true, message: '请选择车次号', trigger: ['blur', 'change'] }], + deliveryTime: [{ required: true, message: '请输入配送时间', trigger: ['blur', 'change'] }], + deliveryDriver: [{ required: true, message: '请输入配送司机', trigger: ['blur', 'change'] }], + vehicleRoute: [{ required: true, message: '请输入车辆线路', trigger: ['blur', 'change'] }], + deliverGoodsTime: [{ required: true, message: '请输入发货时间', trigger: ['blur', 'change'] }], + warehousingTime: [{ required: true, message: '请选择入库时间', trigger: ['blur', 'change'] }], + discoveryTime: [{ required: true, message: '请选择发现时间', trigger: ['blur', 'change'] }], + waybillMall: [{ required: true, message: '请输入运单商场', trigger: ['blur'] }], + typeServiceName: [{ required: false, message: '请输入合作模式', trigger: ['blur', 'change'] }], investigationProcess: [ - { required: true, message: '请输入调查经过', trigger: ['bulr', 'change'] }, + { required: true, message: '请输入调查经过', trigger: ['blur', 'change'] }, ], - result: [{ required: false, message: '请输选择处理结果', trigger: ['bulr'] }], - processor: [{ required: true, message: '请选择处理方', trigger: ['bulr'] }], - processorEntityList: [{ required: true, message: '请选择责任方', trigger: ['bulr'] }], + result: [{ required: false, message: '请输选择处理结果', trigger: ['blur'] }], + processor: [{ required: true, message: '请选择处理方', trigger: ['blur'] }], + processorEntityList: [{ required: true, message: '请选择责任方', trigger: ['blur'] }], }, - packageCode: [{ required: true, message: '请输入包条码', trigger: ['bulr', 'change'] }], - waybillNumber: [{ required: true, message: '请输入运单号', trigger: ['bulr', 'change'] }], - orderCode: [{ required: true, message: '请输入订单自编号', trigger: ['bulr', 'change'] }], - first: [{ required: false, message: '请输入一级品', trigger: ['bulr', 'change'] }], - secondary: [{ required: false, message: '请输入二级品', trigger: ['bulr', 'change'] }], - brandName: [{ required: false, message: '请输入品牌', trigger: ['bulr', 'change'] }], - businessId: [{ required: true, message: '请选择责任方', trigger: ['bulr', 'change'] }], - personResponsibleId: [{ required: true, message: '请输入责任人', trigger: ['bulr', 'change'] }], - responsibilityRatio: [{ required: false, message: '请输入占比', trigger: ['bulr', 'change'] }], - tripartite: [{ required: false, message: '请输入三方责任人', trigger: ['bulr', 'change'] }], - description: [{ required: true, message: '请输入说明', trigger: ['bulr', 'change'] }], - money: [{ required: true, message: '请输入金额', trigger: ['bulr', 'change'] }], - paymentUnit: [{ required: false, message: '请输入支付单位', trigger: ['bulr', 'change'] }], + packageCode: [{ required: true, message: '请输入包条码', trigger: ['blur', 'change'] }], + waybillNumber: [{ required: true, message: '请输入运单号', trigger: ['blur', 'change'] }], + orderCode: [{ required: true, message: '请输入订单自编号', trigger: ['blur', 'change'] }], + first: [{ required: false, message: '请输入一级品', trigger: ['blur', 'change'] }], + secondary: [{ required: false, message: '请输入二级品', trigger: ['blur', 'change'] }], + brandName: [{ required: false, message: '请输入品牌', trigger: ['blur', 'change'] }], + businessId: [{ required: true, message: '请选择责任方', trigger: ['blur', 'change'] }], + personResponsibleId: [{ required: true, message: '请输入责任人', trigger: ['blur', 'change'] }], + responsibilityRatio: [{ required: false, message: '请输入占比', trigger: ['blur', 'change'] }], + tripartite: [{ required: false, message: '请输入三方责任人', trigger: ['blur', 'change'] }], + description: [{ required: true, message: '请输入说明', trigger: ['blur', 'change'] }], + money: [{ required: true, message: '请输入金额', trigger: ['blur', 'change'] }], + paymentUnit: [{ required: false, message: '请输入支付单位', trigger: ['blur', 'change'] }], compensationTime: [ - { required: false, message: '请选择理赔支付时间', trigger: ['bulr', 'change'] }, + { required: false, message: '请选择理赔支付时间', trigger: ['blur', 'change'] }, ], - compensationMethod: [{ required: false, message: '请选择支付方式', trigger: ['bulr', 'change'] }], + compensationMethod: [{ required: false, message: '请选择支付方式', trigger: ['blur', 'change'] }], }); const ResponsibleParty = ref([]); //提货责任方 const ruleFormRef = ref(); //表单示例 diff --git a/src/views/aftersales/aftersalesWorkOrderInfo.vue b/src/views/aftersales/aftersalesWorkOrderInfo.vue index 503a7e43..ed708daf 100644 --- a/src/views/aftersales/aftersalesWorkOrderInfo.vue +++ b/src/views/aftersales/aftersalesWorkOrderInfo.vue @@ -567,6 +567,9 @@ <el-button type="primary" v-if="PermissionButton.Processing_results" @click="addingRecord" >处理结果 </el-button> + <el-button type="primary" v-if="PermissionButton.Processing_resultsSub" @click="addingRecord" + >处理结果提交 + </el-button> <!-- <el-button type="primary" v-if="PermissionButton.Confirm_review" @click="ConfirmReview" >确定审核 </el-button> --> @@ -1336,6 +1339,12 @@ const isProcessingResults = () => { } return false; }; +const isProcessingResultssub=()=>{ + if (workOrderStatus == '90') { + return true; + } + return false; +} //完结工单权限 const isWorkOrderCompletion = () => { @@ -1438,6 +1447,7 @@ const Appealrejection = () => { const PermissionButton = computed(() => ({ reply: true, // 回复 Processing_results: isProcessingResults(), //处理结果 + Processing_resultsSub: isProcessingResultssub(), //处理结果提交 work_order_completion: isWorkOrderCompletion(), //完结工单 repulse: isRepulse(), //打回 result_returned: Resultreturned(), //处理结果打回 diff --git a/src/views/aftersales/aftersalesWorkOrderend.vue b/src/views/aftersales/aftersalesWorkOrderend.vue index 594a0dd4..197a1b81 100644 --- a/src/views/aftersales/aftersalesWorkOrderend.vue +++ b/src/views/aftersales/aftersalesWorkOrderend.vue @@ -7,7 +7,7 @@ <el-tab-pane label="零担信息" :name="2"></el-tab-pane> </el-tabs> - <el-form :model="endFrom"> + <el-form :model="endFrom" :rules="ruleForm" ref="ruleFormRef"> <div class="el_top"> <el-form-item label="异常类型" class="el_inputTop"> <el-select v-model="endFrom.workOrderType" disabled style="width: 240px"> @@ -445,11 +445,13 @@ <span>{{ PayeeNum }}</span> </div> </div> - <div class="payanindemnity" v-for="(item, index) in CompensationParty" :key="index"> <div style="display: flex"> <el-form-item - :class="{ payanindemnity_title: item.state == 0 }" + :class="{ + payanindemnity_title: item.state == 0, + payanindemnity_titlecheck: item.warehouseIdcheck, + }" :label="item.state == 0 ? '赔款方' : '受款方'" > <el-select @@ -457,6 +459,7 @@ v-model="item.warehouseId" filterable placeholder="请选择仓库" + @change="warehouseChange(item, index)" > <el-option v-for="item in warehouseData" @@ -475,8 +478,18 @@ /> </el-form-item> - <el-form-item label="原 . 因"> - <el-input v-model="item.reason" placeholder="请填写原因" /> + <el-form-item + label="原 . 因" + :class="{ + payanindemnity_reason: item.state == 0, + payanindemnity_reasoncheck: item.reasoncheck, + }" + > + <el-input + v-model="item.reason" + placeholder="请填写原因" + @blur="reasonChange(item, index)" + /> </el-form-item> <el-form-item label="金额(元)"> @@ -520,7 +533,13 @@ <!-- 仲裁原因说明 --> <div class="arbitrate" v-if="routerState == 'end'"> - <el-tabs type="border-card" class="demo-tabs"> + <el-tabs + type="border-card" + :class="{ + 'Reason_arbitration_tip': ReasonarbClass, + 'demo-tabs Reason_arbitration': true, + }" + > <el-tab-pane> <template #label> <span class="custom-tabs-label"> @@ -623,10 +642,10 @@ >处理结果修改保存</el-button > <el-button - type="primary" - v-if="PermissionButton.information_editing" - @click="EditInformation" - >修改内部责任划分</el-button + type="primary" + v-if="PermissionButton.information_editing" + @click="EditInformation" + >修改内部责任划分</el-button > <!-- <el-button @click="DetermineStorage" @@ -939,6 +958,7 @@ const HistoricalPackageList = ref([]); //历史包件数组 const dialogHistoricalPackage = ref(false); //包件弹窗 const HistoricalPackageinput = ref(''); //历史包件选择 const UserPermissions = ref(''); //操作权限 +const ReasonarbClass = ref(false); const accountingLodading = ref(false); //财务是否处理 const accountingValue = ref(''); //财务处理结果 const accountingID = ref(); //财务处理当id前值 @@ -953,6 +973,18 @@ const Pageloading = ref(false); //页面加载load const TotalClaimAmount = ref(0); //理赔总金额 const TotalamountReceived = ref(0); //收款金额合计 const userInfo = ref({}); //用户信息 +const ruleForm = reactive({ + reason: [{ required: true, message: '请填写原因', trigger: ['blur', 'change'] }], + warehouseId: [{ required: true, message: '请选择仓库', trigger: ['blur', 'change'] }], +}); +const getRuleswarehouse = item => { + return item.state == 0 ? ruleForm.warehouseId : []; +}; + +const getRulesreason = item => { + // 根据 item.state 动态返回规则 + return item.state == 0 ? ruleForm.reason : []; +}; const PackageInfo = ref([ //包件信息 { packageCode: '', orderCode: '', waybillNumber: '' }, @@ -984,9 +1016,7 @@ const videoUrl = ref(null); //视频预览 const VideoPreviewStatus = ref(false); //视频预览状态 const Paymentmethodoptions = ref([]); //支付方式下拉菜单 const warehouseData = ref([]); //处理方 -const getClass = computed(item => { - return item.state === 0 ? 'class-for-state-0' : 'class-for-other-state'; -}); + const MessageContent = ref([]); const CompensationParty = ref([ { @@ -998,6 +1028,8 @@ const CompensationParty = ref([ warehouseId: '', compensationPersonnel: '', button: false, + warehouseIdcheck: false, //仓库校验 + reasoncheck: false, //原因校验 }, //赔款方 // explains: '' { @@ -1111,6 +1143,7 @@ const details = reactive({ const TransportChange = val => { console.log(val, '运损触发事件'); }; + const warehouseIdState = ref(false); //当前订单仓库状态 // 字典公共函数 async function updateDictionary(targetArray, dictionaryType) { @@ -1147,7 +1180,7 @@ const Saveresults = () => { }; // 处理结果编辑提交 const Processingresultmodification = () => { - if (['90','21'].includes($route.query.workOrderStatus)) { + if (['90', '21'].includes($route.query.workOrderStatus)) { return true; } }; @@ -1185,7 +1218,7 @@ const PermissionButton = computed(() => ({ Arbitration_completed: Arbitrationcompleted(), //客服仲裁完结 Processing_result_modification: Processingresultmodification(), //处理结果编辑提交 Processing_result_disabled: Processingresultdisabled(), //处理结果是否可以填写 - information_editing:isInformationEditing(), //修改提交 + information_editing: isInformationEditing(), //修改提交 })); // 页面初始化数据 @@ -1202,7 +1235,7 @@ const onLoad = async () => { }); //处理结果 // 获取角色权限 getDictionaryBiz('after_sales_visits') - .then( async res => { + .then(async res => { console.log(res, '角色字典'); // 获取用户角色信息,并拆分为数组 const roleNames = JSON.parse(localStorage.getItem('TWMS-userInfo')).content.role_name.split( @@ -1231,11 +1264,11 @@ const onLoad = async () => { endFrom.value.processor = []; endFrom.value.packageImage = []; if (res.data.data.createUser == userInfo.content.user_id) { - // 判断订单是否是当前登陆人发起的,用于修改订单信息(必须是待处理) - warehouseIdState.value = true; - } else { - warehouseIdState.value = false; - } + // 判断订单是否是当前登陆人发起的,用于修改订单信息(必须是待处理) + warehouseIdState.value = true; + } else { + warehouseIdState.value = false; + } //图片处理回显 if (res.data.data.discoveryNode == '1') { groundlineType.value = '1'; @@ -1663,6 +1696,8 @@ const AddCompensation = () => { num: 0, //金额 compensationPersonnel: '', //责任人 button: true, //按钮可移除 + warehouseIdcheck: false, + reasoncheck: false, }; CompensationParty.value.splice( CompensationParty.value.map(item => item.state).lastIndexOf(0) + 1, @@ -1968,22 +2003,56 @@ const submitresults = async value => { console.log(error, 'error'); }); }; - +const warehouseChange = (item, index) => { + if (item.warehouseId) { + item.warehouseIdcheck = false; + } +}; +const reasonChange = (item, index) => { + if (item.reasoncheck) { + item.reasoncheck = false; + } +}; // 完结信息提交() -const submitCompletion = () => { - console.log(CompensationParty.value, '完结填写的参数'); - // state:0赔款方 - // state:1受款方 - let _warehouseId = CompensationParty.value - .filter(item => item.state === 0) - .find(res => !res.warehouseId); - if (_warehouseId) { +const submitCompletion = async () => { + console.log(CompensationParty.value, 'CompensationParty'); + let _flag = CompensationParty.value.filter(item => item.state == 0); + console.log(_flag, '_flag'); + _flag.forEach(item => { + if (!item.warehouseId) { + item.warehouseIdcheck = true; + } + if (!item.reason) { + item.reasoncheck = true; + } + }); + let _result = _flag.every(item => item.warehouseId && item.reason); + console.log(_result, '_result'); + if (!endFrom.value.arbitrate) { + ReasonarbClass.value = true; + } else { + ReasonarbClass.value = false; + } + if (!_result || !endFrom.value.arbitrate) { ElMessage({ - message: `有赔款方未选择仓库`, + message: '完结信息必填项未填写完整!', type: 'warning', }); return; } + + // state:0赔款方 + // state:1受款方 + // let _warehouseId = CompensationParty.value + // .filter(item => item.state === 0) + // .find(res => !res.warehouseId); + // if (_warehouseId) { + // ElMessage({ + // message: `有赔款方未选择仓库`, + // type: 'warning', + // }); + // return; + // } ElMessageBox.confirm('是否提交完结信息?', '完结', { confirmButtonText: '确定', cancelButtonText: '取消', @@ -2465,6 +2534,60 @@ const CustomerServiceCompleted = () => { :deep(.el-form-item) { margin-right: 8px; } + .payanindemnity_title::before { + content: '*'; + color: #f00; + margin-top: 4px; + position: absolute; + left: 4px; + } + .payanindemnity_reason { + position: relative; + } + .payanindemnity_reason::before { + content: '*'; + color: #f00; + margin-right: 6px; + margin-top: 4px; + position: absolute; + left: -7px; + } + :deep(.payanindemnity_titlecheck) { + .el-select__wrapper { + border: 1px solid #f00; + border-radius: 2px; + box-shadow: none !important; + } + .el-select__wrapper::before { + content: '请选择仓库'; + color: #f00; + position: absolute; + bottom: -19px; + font-size: 11px; + font-family: '黑体'; + left: 0; + } + .is-focused { + box-shadow: none !important; + border: 1px solid #f00; + } + } + :deep(.payanindemnity_reasoncheck) { + position: relative; + .el-input__wrapper { + border: 1px solid #f00; + box-shadow: none !important; + } + .el-input__wrapper::before { + content: '请填写原因'; + color: #f00; + position: absolute; + bottom: -25px; + font-size: 11px; + font-family: '黑体'; + left: 0; + } + } } .arbitrate { width: 100%; @@ -3051,4 +3174,16 @@ const CustomerServiceCompleted = () => { } } } +:deep(.Reason_arbitration) { + .el-tabs__item::before { + content: '*'; + color: #f00; + } +} +:deep(.Reason_arbitration_tip) { + .el-textarea__inner { + box-shadow: none; + border: 1px solid #f00; + } +} </style> diff --git a/src/views/distribution/artery/TripartiteTransfer.vue b/src/views/distribution/artery/TripartiteTransfer.vue index ea3cdfc5..e4011a9e 100644 --- a/src/views/distribution/artery/TripartiteTransfer.vue +++ b/src/views/distribution/artery/TripartiteTransfer.vue @@ -116,14 +116,14 @@ </el-button> <!-- 装载卸车清单(财务) --> - <el-button + <!-- <el-button v-if="permissionObj.TripartiteTransfer_LoadingAndUnloadingList" type="primary" icon="Printer" @click="searchReset()" > 装载卸车清单(财务) - </el-button> + </el-button> --> <!-- 发车 --> <el-button @@ -425,6 +425,7 @@ }" > <TripartiteTransferPrintTemplate + ref="truckLoadingDetailNodeRef" v-if="details.popUpShow.listOfLoadedWagons" :waybillInfo="details.listOfLoadedWagonsData" /> @@ -433,6 +434,9 @@ <el-button icon="el-icon-circle-close" @click="details.popUpShow.listOfLoadedWagons = false"> 取 消 </el-button> + <el-button type="primary" icon="Download" @click="handleExportTruckLoadingDetail"> + 导 出 + </el-button> <el-button type="primary" icon="Printer" @click="handlePrint"> 打 印 </el-button> </div> </el-dialog> @@ -535,6 +539,8 @@ import { useRouter } from 'vue-router'; import type { UploadProps } from 'element-plus'; import { getToken } from '@/utils/auth'; import { compressImageBlob } from '@/components/IMGcompressor/imgcompressor.js'; +import { dateNow } from '@/utils/date'; +import { exportExcelByDom } from '@/utils/export'; import print from '@/utils/print'; // 获取路由实例 @@ -692,6 +698,7 @@ const details = reactive<any>({ /** 表格实例 */ const tableNode = ref(); +const truckLoadingDetailNodeRef = ref(); // details.columnList.payMethodName.checkArr = details.payMethodOptions; const { search, query, shortcuts, data, loadingObj, selectionList, drawerShow, page, popUpShow } = @@ -1486,6 +1493,14 @@ const handlePrint = () => { print(nodeList); }; + +/** 装车清单导出 */ +const handleExportTruckLoadingDetail = () => { + exportExcelByDom( + truckLoadingDetailNodeRef.value.$el, + details.selectionList[0].carsNo + '' + dateNow() + '.xlsx' + ); +}; </script> <style scoped lang="scss"> diff --git a/src/views/distribution/artery/VehicleArrivalManagement.vue b/src/views/distribution/artery/VehicleArrivalManagement.vue index 8cc3d6c1..9b71ac40 100644 --- a/src/views/distribution/artery/VehicleArrivalManagement.vue +++ b/src/views/distribution/artery/VehicleArrivalManagement.vue @@ -575,14 +575,21 @@ }" > <ArteryPrintTemplate + ref="truckLoadingDetailNodeRef" v-if="details.popUpShow.listOfLoadedWagons" :waybillInfo="details.listOfLoadedWagonsData" /> </div> + <div class="flex-c-c mt10"> <el-button icon="el-icon-circle-close" @click="details.popUpShow.listOfLoadedWagons = false"> 取 消 </el-button> + + <el-button type="primary" icon="Download" @click="handleExportTruckLoadingDetail"> + 导 出 + </el-button> + <el-button type="primary" icon="Printer" @click="handlePrint"> 打 印 </el-button> </div> </el-dialog> @@ -673,6 +680,8 @@ import { getListName } from '@/api/basicdata/basicdataVehicle'; import { useRouter, useRoute } from 'vue-router'; import { ElMessage, ElMessageBox } from 'element-plus'; import print from '@/utils/print'; +import { exportExcelByDom } from '@/utils/export'; +import { dateNow } from '@/utils/date'; // 获取路由实例 const $router = useRouter(); @@ -684,6 +693,8 @@ const Mydata = ref<any>({}); Mydata.value = JSON.parse(localStorage.getItem('my_data')); //获取本地仓库信息 +const truckLoadingDetailNodeRef = ref(); + const details = reactive({ /** 是否开启搜索 */ search: false, @@ -1658,6 +1669,14 @@ const handlePrint = () => { print(nodeList); }; +/** 装车清单导出 */ +const handleExportTruckLoadingDetail = () => { + exportExcelByDom( + truckLoadingDetailNodeRef.value.$el, + details.selectionList[0].carsNo + ' - ' + dateNow() + '.xlsx' + ); +}; + /** 配载图片显示 */ const handleShowVehicleImgs = async ({ row }) => {}; </script> diff --git a/src/views/distribution/artery/VehicleStowage.vue b/src/views/distribution/artery/VehicleStowage.vue index a05e29be..eb60493f 100644 --- a/src/views/distribution/artery/VehicleStowage.vue +++ b/src/views/distribution/artery/VehicleStowage.vue @@ -570,6 +570,7 @@ <ArteryPrintTemplate v-if="details.popUpShow.listOfLoadedWagons" :waybillInfo="details.listOfLoadedWagonsData" + ref="truckLoadingDetailNodeRef" /> </div> <div class="dialog-footer"> @@ -579,6 +580,11 @@ > 取 消 </el-button> + + <el-button type="primary" icon="Download" @click="handleExportTruckLoadingDetail"> + 导 出 + </el-button> + <el-button type="primary" icon="Printer" @click="handlePrint"> 打 印 </el-button> </div> </div> @@ -629,6 +635,9 @@ import { useStore } from 'vuex'; import { useRouter, useRoute } from 'vue-router'; import { ElMessage, ElMessageBox } from 'element-plus'; import print from '@/utils/print'; +import { dateNow } from '@/utils/date'; +import { exportExcelByDom } from '@/utils/export'; +// import * as XLSX from 'xlsx'; // 获取路由实例 const $router = useRouter(); @@ -644,6 +653,7 @@ Mydata.value = JSON.parse(localStorage.getItem('my_data')); //获取本地仓库 console.log('Mydata :>> ', Mydata); const tableNodeRef = ref(); +const truckLoadingDetailNodeRef = ref(); const details = reactive<any>({ /** 是否开启搜索 */ @@ -1515,6 +1525,14 @@ const handlePrint = () => { print(nodeList); }; +/** 装车清单导出 */ +const handleExportTruckLoadingDetail = () => { + exportExcelByDom( + truckLoadingDetailNodeRef.value.$el, + details.selectionList[0].carsNo + ' - ' + dateNow() + '.xlsx' + ); +}; + /** 配载图片显示 */ const handleShowVehicleImgs = async ({ row }) => { $router.push({ diff --git a/src/views/distribution/artery/VehicleStowageDetails.vue b/src/views/distribution/artery/VehicleStowageDetails.vue index c3b315c3..064214da 100644 --- a/src/views/distribution/artery/VehicleStowageDetails.vue +++ b/src/views/distribution/artery/VehicleStowageDetails.vue @@ -181,9 +181,11 @@ > 成本分摊确认 </el-button> - <el-button type="primary" icon="Download" @click="tcTableexport = true"> + <!-- <el-button type="primary" icon="Download" @click="tcTableexport = true"> 导出 - </el-button> + </el-button> --> + + <el-button type="primary" icon="Download" @click="handleExport"> 导出 </el-button> </div> <div class="avue-crud__right"> <el-button icon="el-icon-refresh" @click="searchChange" circle></el-button> @@ -213,41 +215,20 @@ </template> </tablecmt> - <!-- <div class="flex"> - <el-tabs - v-model="details.type" - tab-position="left" - style="height: 100%; width: fit-content; flex: none" - @tab-click="initOriginWarehouseOrder" - class="demo-tabs" + <div style="overflow: hidden; width: 0; height: 0"> + <tablecmt + ref="exportColumnListNode" + :columnList="tableColumnList" + :tableData="detailsRenderData" + :arraySpanMethod="row => arraySpanMethod(row)" > - <el-tab-pane label="实际数据" name="real"></el-tab-pane> - <el-tab-pane label="计划数据" name="plan"></el-tab-pane> - </el-tabs> - - <div class="overflow"> - <tablecmt - class="w100" - ref="oldColumnListNode" - :columnList="details.detailsColumnList" - :tableData="detailsRenderData" - :loading="loadingObj.oldListLoading" - @inputTxt="inputsc" - @timeCheck="timesc" - @selectCheck="selectsc" - @selection="selectionChange" - :arraySpanMethod="row => arraySpanMethod(row)" - > - <template #default="slotProps"> - <template v-if="slotProps.scope.column.label === '运单号'"> - <el-text @click="() => handleGoWayBillDetail(slotProps.scope)">{{ - slotProps.scope.row.waybillNo - }}</el-text> - </template> + <template #default="slotProps"> + <template v-if="slotProps.scope.column.label === '运单号'"> + {{ slotProps.scope.row.waybillNo }} </template> - </tablecmt> - </div> - </div> --> + </template> + </tablecmt> + </div> </el-tab-pane> <el-tab-pane label="日 志 跟 踪" name="tab2"> @@ -508,6 +489,8 @@ import { postRemoveCarsLoadScan } from '@/api/distribution/truckLoadingDetails'; import { useRouter, useRoute } from 'vue-router'; import { useStore } from 'vuex'; import { ElMessage, ElMessageBox } from 'element-plus'; +import { exportExcelByDom } from '@/utils/export'; +import { dateNow } from '@/utils/date'; /** 被合并的列 */ const mergeColumn = []; @@ -533,6 +516,7 @@ const oldColumnListNode = ref(); const abnormalTableRef = ref(); const tcTableexport = ref(false); +const exportColumnListNode = ref(); // 节点信息 const nodeInfoRef = ref(); @@ -663,6 +647,22 @@ const details = reactive<any>({ abnormalSelectionList: [], }); +const tableColumnList = computed(() => { + const _arr = []; + + for (let i = 0; i < details.detailsColumnList.length; i++) { + const val = details.detailsColumnList[i]; + let _obj = { ...val }; + _obj.type = 30; + + if (val.label === '序号' || val.label === '操作') continue; + _arr.push(_obj); + } + + console.log('_arr :>> ', _arr); + return _arr; +}); + const detailsRenderData = shallowRef([]); const { search, query, shortcuts, data, loadingObj, selectionList, drawerShow, popUpShow, form } = @@ -1156,6 +1156,13 @@ const handleBatchDelete = () => { }); }; +/** 导出 */ +const handleExport = () => { + console.log('exportColumnListNode.value.$el :>> ', exportColumnListNode.value.$el); + console.log('detailsRenderData.value :>> ', detailsRenderData.value); + exportExcelByDom(exportColumnListNode.value.$el, `${details.form.carsNo} - ${dateNow()}.xlsx`); +}; + watch( () => $route.query, () => {