<template> <div class="app-startUnloading"> <el-row class="number-area"> <p class="label-font"><span style="color: red">*</span>{{ $t("卸柜时间") }}:</p> <el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="ulWarehouseTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker> </el-row> <!-- 自编号 --> <el-row class="number-area"> <p class="label-font">{{ $t("自编号") }}:</p> <p class="label-font">{{ selfNo }}</p> <el-input v-model="labelNo" :placeholder="$t('请输入')"></el-input> <div> <el-button type="primary" :disabled="isSuccessReview" @click="modifyUnload">{{ $t("提交") }}</el-button> <el-button type="primary" :disabled="isSuccessReview" @click="modifyBatchUnload">{{ $t("批量输入") }}</el-button> <el-button type="primary" :disabled="isSuccessReview" @click="modifyAllUnload">{{ $t("一键卸柜") }}</el-button> </div> </el-row> <!-- 当前部分 --> <el-row class="number-area"> <p class="label-font">{{ $t("当前部分") }}:</p> <el-select :placeholder="$t('请选择')" v-model="sectionId" @change="sectionChange"> <el-option key="0" :label="$t('全部')" value="0"></el-option> <el-option v-for="item in sectionList" :key="item.id" :label="item.title" :value="item.id"></el-option> </el-select> <p> {{ getSectionInfo }} </p> </el-row> <el-row> <el-form inline> <el-form-item :label="$t('订单号')"> <el-input v-model="queryParams.orderNo" :placeholder="$t('请输入订单号')" clearable></el-input> </el-form-item> <el-form-item :label="$t('始发仓')"> <el-select v-model="queryParams.startWarehouseIds" :placeholder="$t('请选择始发仓')" clearable multiple> <el-option v-for="item in exportWarehouseList" :label="$l(item, 'title')" :value="$l(item, 'title')" :key="item.id"></el-option> </el-select> </el-form-item> <el-form-item :label="$t('目的仓')"> <el-select v-model="queryParams.destWarehouseIds" :placeholder="$t('请选择目的仓')" clearable multiple> <el-option v-for="item in importWarehouseList" :label="$l(item, 'title')" :value="$l(item, 'title')" :key="item.id"></el-option> </el-select> </el-form-item> <el-form-item :label="$t('订单状态')"> <dict-selector :type="DICT_TYPE.ORDER_STATUS" v-model="queryParams.status" :filter="statusDictFilter" clearable /> </el-form-item> <el-form-item> <el-button @click="batchUnLoad" :disabled="!multipleSelection.length">{{ $t("选中订单一键卸柜") }}</el-button> </el-form-item> </el-form> </el-row> <!-- 表格 --> <el-row class="table-area"> <el-table v-loading="loading" :data="filteredOrderList" border max-height="500px" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column :label="$t('序号')" align="center" width="50" prop="tidanNum" /> <el-table-column :label="$t('订单号')" align="center" prop="orderNo"> <template slot-scope="scope"> <div> <a href="javascript:void(0);" class="order-href" @click="orderClick(scope.row)">{{ scope.row.orderNo }}</a> </div> <div style="color: blue; fontweight: bold"> {{ scope.row.isExternalWarehouse === 1 ? "(" + $t("外部仓") + ")" : "" }} </div> </template> </el-table-column> <el-table-column :label="$t('商品信息')" align="center" prop="goodsList" width="200px"> <template slot-scope="scope"> <section class="table-goodList"> <div v-for="(item, index) in scope.row.goodsList" :key="index" class="goodList-div"> <p>{{ $t("品名") }}:{{ $l(item, "prodTitle") }}</p> <p> {{ $t("品牌") }}:【<template v-if="item.brandName">{{ item.brandName }}</template> <dict-tag v-else :type="DICT_TYPE.ECW_IS_BRAND" :value="item.feeType" />{{ $t("】") }} </p> </div> </section> </template> </el-table-column> <el-table-column :label="$t('报关方式')" align="center" prop="customsType"> <template slot-scope="scope"> <div :class="scope.row.customsType !== 1 ? 'custom_type_red' : ''"> <dict-tag :type="DICT_TYPE.ECW_CUSTOMS_TYPE" :value="scope.row.customsType" /> </div> </template> </el-table-column> <el-table-column :label="$t('实装箱数')" align="center" prop="installNum"> <template slot-scope="scope"> <div> <a href="javascript:void(0);" class="order-href" @click="orderClick(scope.row)">{{ scope.row.installNum }}</a> </div> <div style="color: blue; fontweight: bold"> {{ scope.row.isExternalWarehouse === 1 ? "(" + $t("外部仓") + ")" : "" }} </div> </template> </el-table-column> <el-table-column :label="$t('卸柜箱数')" align="center" prop="unloadNum"> <template slot-scope="scope"> <div> <a href="javascript:void(0);" class="order-href" @click="orderClick(scope.row)">{{ scope.row.unloadNum }}</a> </div> <div style="color: blue; fontweight: bold"> {{ scope.row.isExternalWarehouse === 1 ? "(" + $t("外部仓") + ")" : "" }} </div> </template> </el-table-column> <el-table-column :label="$t('清关状态')" align="center" prop=""> <template slot-scope="scope">{{ clearStatus(scope.row) }}</template> </el-table-column> <el-table-column :label="$t('卸柜/到仓时间')" align="center" prop=""> <template slot-scope="scope">{{ scope.row.unloadTime }}</template> </el-table-column> <el-table-column :label="$t('始发仓')" align="center" prop="startWarehouseName" /> <el-table-column :label="$t('目的仓')" align="center" prop="destWarehouseName" /> <el-table-column :label="$t('体积')" align="center" prop="volume" /> <el-table-column :label="$t('重量')" align="center" prop="weight" /> <el-table-column :label="$t('订单状态')" align="center" prop=""> <template slot-scope="scope"> {{ scope.row.statusMsg }} </template> </el-table-column> <el-table-column :label="$t('异常状态')" align="center" prop=""> <template slot-scope="scope"> <el-button v-if="scope.row.exceptionList" type="text" size="small" @click="handleError(scope.row)" icon="el-icon-edit">{{ getOrderError(scope.row, "errorStatus") }}</el-button> </template> </el-table-column> <el-table-column :label="$t('异常类型')" align="center" prop=""> <template slot-scope="scope"> {{ getUnloadError(scope.row.exceptionList) }} </template> </el-table-column> <el-table-column :label="$t('操作')" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <div class="btns"> <el-button type="danger" size="small" @click="openError(scope.row)">{{ $t("异常") }}</el-button> <el-button type="primary" size="small" @click="order_warehouse_check_revoke(scope.row.orderId)" v-if="scope.row.inWarehouseState == 218 && !isSuccessReview && !isUnderReview">{{ $t("撤销到仓") }}</el-button> <el-button type="primary" size="small" @click="order_warehouse_check_force(scope.row.orderId)" v-if="scope.row.inWarehouseState == 0 && scope.row.unloadNum > 0 && scope.row.installNum > scope.row.unloadNum">{{ $t("强制到仓") }}</el-button> <el-button type="primary" size="small" @click="$router.push('/order/warehousingTo-update?id=' + scope.row.orderId)" v-if="scope.row.inWarehouseState == 218">{{ $t("到仓修改") }}</el-button> </div> </template> </el-table-column> </el-table> </el-row> <!-- 总计 --> <el-row> <div class="label-font"> <p> <span>{{ $t("总计") }}:</span> <span>{{ getTotlContent(pageData.totalStatistics) }}</span> </p> </div> <div class="label-font"> <p> <span>{{ $t("已卸") }}:</span> <span>{{ getUnLoadNumCount }}</span> </p> </div> </el-row> <!-- 审核流程 --> <el-row class="process-area"> <div class="process"> <div>{{ $t("审批流程") }}</div> <work-flow xmlkey="unload_container" v-model="selectedUsers"></work-flow> </div> <!-- 操作 --> <div v-if="!isUnderReview"> <el-button type="success" :disabled="isSuccessReview" @click="onSubmit">{{ $t("卸柜完成") }}</el-button> <el-button plain type="primary" @click="$emit('closeStart')">{{ $t("返回") }}</el-button> </div> <div v-if="isUnderReview"> <el-button type="primary" @click="jumpReviewDetail">{{ $t("卸柜审核中") }}</el-button> <el-button plain type="primary" @click="canclAudit">{{ $t("取消审核") }}</el-button> <el-button plain type="primary" @click="$emit('closeStart')">{{ $t("返回") }}</el-button> </div> </el-row> <!-- 对话框 --> <el-dialog custom-class="shipping-dialog" :title="dialogConfig.title" :visible.sync="dialogConfig.dialogVisible" :fullscreen="dialogConfig.fullscreen" :width="dialogConfig.width" :modal-append-to-body="false" append-to-body> <template v-if="dialogConfig.type === 'orderTable'"> <el-table :data="orderList" height="500px" border> <el-table-column :label="$t('实装')" align="center" prop="loadTag" /> <el-table-column :label="$t('已卸')" align="center" prop="unloadTag" /> </el-table> </template> </el-dialog> <!-- 对话框 --> <el-dialog custom-class="shipping-dialog" :title="$t('异常')" :visible.sync="dialogVisible" width="600px" :modal-append-to-body="false" append-to-body> <unloadingError v-if="dialogVisible" @closeDialog="closeDialog" v-bind="$attrs" :currRow="currRow" /> </el-dialog> <el-dialog :title="$t('批量卸柜选中订单')" :visible="batchUnloading" :before-close="handleCloseBatchUnloading" append-to-body> <template v-for="item in batchLogs"> <div>{{ item }}</div> </template> </el-dialog> </div> </template> <script> import unloadingError from "./unloadingError.vue" import { loadGoodsList, batchUnload, orderTagList, allUnload, approvalCreate, approvalCancel, getSectionList, singleUnload } from "@/api/ecw/boxSea" import { serviceMsg, getTotlContent, toReviewDetail } from "../../utils" import WorkFlow from "@/components/WorkFlow" import Decimal from "decimal.js" import { getWarehouseList } from "@/api/ecw/warehouse" import Template from "@/views/cms/template/index.vue" import { order_warehouse_check_revoke, order_warehouse_check_force } from "@/api/ecw/order" /** * 开始卸柜 */ export default { name: "startUnloading", inheritAttrs: false, components: { Template, unloadingError, WorkFlow }, data() { return { // 标签号 labelNo: "", // 当前部分 currPart: "", // loading loading: false, // 页面数据 pageData: {}, // 弹窗配置 dialogVisible: false, // 自编号 selfNo: this.$attrs.shipmentObj.selfNo, // 当前行 currRow: {}, // 部分 sectionList: [], // 已选部分 sectionId: "0", // 已卸/未卸 orderList: [], // 弹窗配置 dialogConfig: { title: "", dialogVisible: false, width: "30%", type: "", fullscreen: false }, // 部分订单商品 sectionObj: { secStatistics: {}, sectionOrderList: [], totalStatistics: {} }, selectedUsers: [], ulWarehouseTime: null, warehouseList: [], // 筛选参数 queryParams: { orderNo: "", startWarehouseIds: [], destWarehouseIds: [], status: null }, // 表格选中的 multipleSelection: [], // 是否正在批量卸柜 batchUnloading: false, // 批量操作的日志 batchLogs: [] } }, created() { getWarehouseList().then((res) => (this.warehouseList = res.data)) this.getLoadGoodsList() // 部分 getSectionList({ shipmentId: this.$attrs.shipmentObj.id }).then((res) => { this.sectionList = res.data.map((item, index) => { return { ...item, title: this.$t("第{index}部分", { index: index + 1 }) } }) }) }, methods: { order_warehouse_check_revoke(orderId) { this.$confirm(this.$t("确定要撤销到仓么?")).then(async () => { let r = await order_warehouse_check_revoke({ orderId }) this.getLoadGoodsList() }) }, order_warehouse_check_force(orderId) { if (!this.ulWarehouseTime) { this.$message.error(this.$t("请选择到仓时间")) return } this.$confirm(this.$t("确定要强制到仓么?")).then(async () => { let params = {} params.orderId = orderId params.unloadTime = this.ulWarehouseTime await order_warehouse_check_force(params).then((res) => { if (res.data){ this.$router.push('/order/warehousingTo-update?id=' + orderId) } }) }) }, getTotlContent, /* 获取卸柜数据 */ getLoadGoodsList() { this.loading = true let params = { secId: this.sectionId, shipmentId: this.$attrs.shipmentObj.id } loadGoodsList(params).then((res) => { const { data } = res this.pageData = data this.loading = false }) }, /* 单个卸柜 */ modifyUnload() { if (!this.labelNo) { this.$message.error(this.$t("请输入箱号标签")) return } singleUnload({ orderNumCode: this.labelNo, shipmentId: this.$attrs.shipmentObj.id }).then((res) => { serviceMsg(res, this).then((res) => { this.labelNo = "" this.getLoadGoodsList() }) }) }, /* 批量输入 */ modifyBatchUnload() { if (!this.labelNo) { this.$message.error(this.$t("请输入订单号")) return } if (!this.ulWarehouseTime) { this.$message.error(this.$t("请选择卸柜时间")) return } batchUnload({ orderNo: this.labelNo, shipmentId: this.$attrs.shipmentObj.id, unloadTime: this.ulWarehouseTime }).then((res) => { serviceMsg(res, this).then((res) => { this.labelNo = "" this.getLoadGoodsList() }) }) }, /* 一键卸柜 */ modifyAllUnload() { if (!this.ulWarehouseTime) { this.$message.error(this.$t("请选择卸柜时间")) return } this.$confirm(this.$t("确认卸柜?"), this.$t("提示"), { type: "warning" }) .then((_) => { allUnload({ shipmentId: this.$attrs.shipmentObj.id, unloadTime: this.ulWarehouseTime }).then((res) => { serviceMsg(res, this).then((res) => { this.getLoadGoodsList() }) }) }) .catch((_) => {}) }, /** 提交 */ onSubmit() { approvalCreate({ shipmentId: this.$attrs.shipmentObj.id, approvalStatus: 0, approvalType: 3, // 卸柜 copyUserId: this.selectedUsers }).then((res) => { serviceMsg(res, this).then(() => { this.cancel() }) }) }, /** 表格订单号点击 */ orderClick(row) { orderTagList({ orderId: row.orderId }).then((res) => { const { data = {} } = res this.orderList = [] // 取最长的list let dataLength = data.loadList.length if (data.unLoadList.length > dataLength) { dataLength = data.unLoadList.length } // 组装数据,用一个table组件渲染 for (let index = 0; index < dataLength; index++) { this.orderList.push({ loadTag: data.loadList[index], unloadTag: data.unloadCabinetList[index] }) } }) this.shwoDialog({ type: "orderTable", title: row.selfNo }) }, /** 取消 */ cancel() { this.$emit("closeStart", "submit") }, /** 弹窗事件 */ shwoDialog(config) { this.$set(this.dialogConfig, "title", config.title) this.$set(this.dialogConfig, "type", config.type) switch (config.type) { case "orderTable": this.$set(this.dialogConfig, "fullscreen", false) break case "supplementOrder": this.$set(this.dialogConfig, "fullscreen", true) break case "batchInput": this.$set(this.dialogConfig, "fullscreen", false) this.batchObj = { boxNum: 0 } this.boxOrderInfo = {} break case "correction": this.$set(this.dialogConfig, "fullscreen", false) this.correctionObj = {} break case "correctionOrder": this.$set(this.dialogConfig, "fullscreen", false) this.orderObj = {} break case "modifyCabinet": this.$set(this.dialogConfig, "fullscreen", false) this.modifyCabinetObj = {} this.$set(this.modifyCabinetObj, "cabinetId", this.shipmentObj.cabinetId) this.$set(this.modifyCabinetObj, "cubNo", this.shipmentObj.cubNo) break case "splitOrder": this.$set(this.dialogConfig, "fullscreen", true) break } this.$set(this.dialogConfig, "dialogVisible", true) }, /* 关闭弹窗 */ closeDialog(type) { this.dialogVisible = false if (type === "query") this.getLoadGoodsList() }, /* 打开异常 */ openError(row) { this.currRow = row this.dialogVisible = true }, /* 清关状态 */ clearStatus(row) { const { installNum, unloadNum } = row if (installNum === unloadNum) { return this.$t("全部清关") } if (installNum >= unloadNum) { return this.$t("部分清关") } if (unloadNum === 0) { return this.$t("未清关") } }, // 部分切换 sectionChange() { this.getLoadGoodsList() }, /* 取消审核 */ canclAudit() { const { shipmentObj } = this.$attrs approvalCancel({ applyReason: this.$t("取消审核"), id: shipmentObj["cabinetUnloadApprovalInfo"].id, shipmentId: shipmentObj.id }).then((res) => { serviceMsg(res, this).then(() => { this.cancel() }) }) }, // 获取异常类型 getUnloadError(exceptionList) { if (!exceptionList) return exceptionList const codes = this.getDictDatas(this.DICT_TYPE.ORDER_ERROR_TYPE) let errorLabels = [] exceptionList.forEach((item) => { const errObj = codes.find((cItem) => cItem.value === item.orderExceptionType) if (errObj) errorLabels.push(errObj.label) }) return errorLabels.join(",") }, // 订单异常 getOrderError(row, type) { if (row.exceptionList && row.exceptionList.length) { return type === "orderStatus" ? this.$t("卸柜异常") : this.$t("待处理") } return type === "orderStatus" ? this.$t("已到港") : "" }, // 处理异常 handleError(row) { this.$emit("closeStart", "close") this.$router.push({ path: `/order/pending?id=${row.orderId}` }) }, jumpReviewDetail() { const { cabinetUnloadApprovalInfo } = this.$attrs.shipmentObj toReviewDetail.apply(this, [cabinetUnloadApprovalInfo.bpmProcessId]) this.$emit("closeStart", "close") }, // 表格多选 handleSelectionChange(selection) { console.log({ selection }) this.multipleSelection = selection }, async batchUnLoad() { if (!this.multipleSelection?.length) { return this.$message(this.$t("请先选择订单")) } if (!this.ulWarehouseTime) { return this.$message(this.$t("请选择卸柜时间")) } console.log("批量卸柜") this.batchUnloading = true this.batchLogs = [] for (const item of this.multipleSelection) { if (!this.batchUnloading) break const time = new Date() const timeStr = [time.getHours(), time.getMinutes(), time.getSeconds()].map((item) => item.toString().padStart(2, "0")).join(":") await batchUnload({ orderNo: item.orderNo, shipmentId: this.$attrs.shipmentObj.id, unloadTime: this.ulWarehouseTime }) .then((res) => { this.batchLogs.push(`${timeStr} 订单号:${item.orderNo}卸柜成功`) }) .catch((err) => { this.batchLogs.push(`${timeStr} 订单号:${item.orderNo}卸柜失败` + JSON.stringify(err)) }) } this.batchLogs.push("批量卸柜完成") this.getLoadGoodsList() }, handleCloseBatchUnloading() { this.batchUnloading = false }, // 过滤订单状态筛选字典内容 statusDictFilter(item) { if (item.cssClass && item.cssClass != "sea") { return false } return true } }, computed: { exportWarehouseList() { /* tradeType 1 进口,2出口,3进出口 */ return this.warehouseList.filter((item) => item.tradeType == 2 || item.tradeType == 3) }, importWarehouseList() { return this.warehouseList.filter((item) => item.tradeType == 1 || item.tradeType == 3) }, filteredOrderList() { if (!this.pageData?.sectionOrderList?.length) return [] return this.pageData.sectionOrderList.filter((item) => { if (this.queryParams.orderNo && item.orderNo.indexOf(this.queryParams.orderNo) == -1) return false if (this.queryParams.startWarehouseIds?.length && this.queryParams.startWarehouseIds.indexOf(item.startWarehouseName) === -1) { return false } if (this.queryParams.destWarehouseIds?.length && this.queryParams.destWarehouseIds.indexOf(item.destWarehouseName) === -1) { return false } if (this.queryParams.status && this.queryParams.status != item.status) { return false } return true }) }, /* 是否审核中 */ isUnderReview() { const { currNode, shipmentObj } = this.$attrs return shipmentObj[currNode.keyName] === 183 ? true : false }, /* 是否卸柜审核成功 */ isSuccessReview() { const { currNode, shipmentObj } = this.$attrs return shipmentObj[currNode.keyName] === 185 ? true : false }, // 部分信息 getSectionInfo() { const { totalStatistics, secStatistics } = this.pageData if (!this.sectionId) { return getTotlContent(totalStatistics) } else { return getTotlContent(secStatistics) } }, /* 已卸总数 */ getUnLoadNumCount() { let count = 0 if (this.pageData.sectionOrderList) { this.pageData.sectionOrderList.forEach((item) => { count = Decimal.add(count, item.unloadNum).toNumber() }) } return count } } } </script> <style lang="scss" scoped> .btns { & > * { &:nth-child(n + 1) { margin: 0 auto; margin-top: 6px; display: block; } } } .app-startUnloading { p { margin: 0; > span { margin-right: 5px; } } .el-row { margin-bottom: 15px; } .label-font { font-size: 16px; font-weight: bolder; } .number-area { display: flex; align-items: center; > * { margin-right: 10px; } > .el-input { width: 200px; } } .table-area { .table-goodList { .goodList-div { border-bottom: 1px solid #e6ebf5; > p { text-align: left; > span { margin-right: 0px; } } } > div:last-child { border-bottom: none; } } } } </style>