<template> <div> <el-form ref="cusDeclarationForm" :rules="rules" :model="cusDeclarationObj" label-width="120px"> <el-form-item :label="$t('单证要求')"> <template v-for="(item, index) in cusDeclarationObj.documentInfo"> {{ (index === 0 || index === cusDeclarationObj.documentInfo.length) ? "" :"/" }} <dict-tag :type="DICT_TYPE.ECW_CUSTOMS_TYPE" :value="item" :key="index" /> </template> <el-button type="primary" style="margin-left:10px;" @click="downloadVGM">{{getButtonLabel(cusDeclarationObj.documentInfo)}}</el-button> </el-form-item> <el-form-item :label="$t('柜重')" prop="dcBoxWgt"> <el-input v-model="cusDeclarationObj.dcBoxWgt" :placeholder="$t('请输入柜重')" clearable /> </el-form-item> <el-form-item :label="$t('货重')" prop="dcGoodsWgt"> <el-input v-model="cusDeclarationObj.dcGoodsWgt" :placeholder="$t('请输入货重')" clearable /> </el-form-item> <el-form-item :label="$t('VGM重量')"> <el-input v-model="cusDeclarationObj.dcVgmWgt" :placeholder="$t('请输入VGM重量')" clearable /> </el-form-item> <el-form-item :label="$t('报关方式')" prop="dcCustomsType"> <el-select v-model="cusDeclarationObj.dcCustomsType" :placeholder="$t('请选择报关方式')"> <el-option v-for="type in this.getDictDatas(DICT_TYPE.BOX_SHIPPING_CUSTOMS_TYPE)" :key="type.value" :label="$l(type, 'label')" :value="type.value"></el-option> </el-select> </el-form-item> <el-form-item :label="$t('正常报关订单')" v-show="isShowNormal"> <div v-for="item in normalOrderList" :key="item.orderId"> <a href="javascript:void(0)" @click="jumpOrderDetail(item)">{{ item.orderNo }}</a> </div> </el-form-item> <el-form-item :label="$t('报关公司名称')"> <supplierSelect v-model="cusDeclarationObj.dcCompanyId" :companyType="'2'" :placeholder="$t('请选择报关公司名称')" :allSupplier="this.$attrs.allSupplier" /> </el-form-item> <el-form-item :label="$t('截关时间')"> <el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cusDeclarationObj.dcCutOffTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker> </el-form-item> <el-form-item :label="$t('报关时间')" prop="dcDecTime"> <el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cusDeclarationObj.dcDecTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker> </el-form-item> <el-form-item :label="$t('状态')" prop="dcCustomsStatus"> <el-radio-group v-model="cusDeclarationObj.dcCustomsStatus" :disabled="inReview || isCheckDeal('status')"> <el-radio v-for="item in this.getDictDatas(DICT_TYPE.BOX_SHIPPING_DCCUSTOMS_STATUS)" :key="item.value" :label="item.value">{{$l(item, 'label')}}</el-radio> </el-radio-group> </el-form-item> <!-- 查验 --> <div v-show="cusDeclarationObj.dcCustomsStatus === '3'"> <el-form-item :label="$t('查验')"> <el-radio-group v-model="cusDeclarationObj.dcCheckStatus" :disabled="inReview || isCheckDeal('check')"> <el-radio v-for="item in this.getDictDatas(DICT_TYPE.BOX_SHIPPING_CHECK_STATUS)" :key="item.value" :label="item.value" :disabled="disabledRadio(item)">{{$l(item, 'label')}}</el-radio> </el-radio-group> </el-form-item> </div> <!-- 退场 --> <div v-show="['1','2','3'].includes(cusDeclarationObj.dcCheckStatus)"> <el-form-item :label="$t('查验时间')"> <el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cusDeclarationObj.dcCheckTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker> </el-form-item> <el-form-item :label="$t('查验前图片')"> <ImageUpload :limit="1" :isShowTip=false v-model="cusDeclarationObj.dcCheckPreImg" /> </el-form-item> <el-form-item :label="$t('新封条')"> <el-input v-model="cusDeclarationObj.dcStripSeal" :placeholder="$t('请输入新封条')" clearable /> </el-form-item> <el-form-item :label="$t('退场状态')" v-if="cusDeclarationObj.dcCheckStatus === '1' || cusDeclarationObj.dcCheckStatus === '2'"> {{getCheckExamineStatus}} </el-form-item> </div> <!-- 放行 --> <el-form-item :label="$t('放行时间')" v-show="cusDeclarationObj.dcCustomsStatus === '2' || cusDeclarationObj.dcCheckStatus === '3'"> <el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cusDeclarationObj.dcPassTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker> </el-form-item> <!-- <el-form-item :label="$t('装箱单')"> <el-button type="primary">{{$t('下载装箱单')}}</el-button> </el-form-item> --> <el-form-item :label="$t('报关单')" v-show="isDownload"> <el-button type="primary" @click="downloadCusFile">{{$t('下载所有报关单')}}</el-button> </el-form-item> </el-form> <el-row class="operate-button" v-if="inReview"> <el-button type="primary" @click="jumpReviewDetail">{{cusDeclarationObj.dcCheckStatus === '1' ? $t('全部退场审核中') : $t('部分退场审核中')}}</el-button> <el-button type="primary" plain @click="canclAudit">{{cusDeclarationObj.dcCheckStatus === '1' ? $t('取消全部退场审核') : $t('取消部分退场审核')}}</el-button> </el-row> <el-row class="operate-button"> <el-button type="primary" @click="onSubmit(1)" :disabled="isCheckDeal('submit')">{{$t('保存')}}</el-button> <el-button type="success" v-if="!inReview" @click="onSubmit(2)" :disabled="isCheckDeal('submit')">{{$t('提交')}}</el-button> <el-button @click="cancel">{{$t('关闭')}}</el-button> <el-button type="primary" @click="extraCost" v-show="cusDeclarationObj.dcCustomsStatus === '2' || cusDeclarationObj.dcCustomsStatus === '3'">{{$t('额外费用')}}</el-button> <el-button type="primary" @click="exceptionReg" :disabled="!isShowError">{{$t('异常登记')}}</el-button> </el-row> <!-- 对话框 --> <el-dialog custom-class="shipping-dialog customsClearance" :title="dialogConfig.title" :visible.sync="dialogConfig.dialogVisible" width="700px" :modal-append-to-body=false append-to-body> <el-row> <el-row> <el-form label-width="100px"> <el-form-item :label="$t('订单号')" class="two-element"> <el-input v-model="orderNo" :placeholder="$t('请输入订单号')" clearable /> <el-button type="primary" icon="el-icon-search" @click="searchOrder"></el-button> </el-form-item> </el-form> </el-row> <el-row> <el-table :data="costOrderList" border class="table-inputNumber"> <el-table-column :label="$t('订单号')" align="center" prop="orderNo" /> <el-table-column :label="$t('报关费用')" align="center" prop="fee" width="220"> <template slot-scope="scope"> <el-input-number v-model="scope.row.fee" controls-position="right" :min="1"></el-input-number> </template> </el-table-column> <el-table-column :label="$t('操作')" align="center"> <template slot-scope="scope"> <el-button type="primary" size="small" @click="createExtraCost(scope.row)">{{$t('确定')}}</el-button> </template> </el-table-column> </el-table> </el-row> <el-row class="cost-title"> <div>{{$t('额外费用订单')}}</div> <div> <el-button size="small" @click="restCostList()">{{$t('重置')}}</el-button> </div> </el-row> <el-row> <el-table :data="costList" border height="300px" class="table-inputNumber"> <el-table-column type="selection" width="55" align="center" /> <el-table-column :label="$t('订单号')" align="center" prop="orderNo" /> <el-table-column :label="$t('报关费用')" align="center" prop="fee" width="220"> <template slot-scope="scope"> <el-input-number v-model="scope.row.fee" controls-position="right" :min="1"></el-input-number> </template> </el-table-column> <el-table-column :label="$t('操作')" align="center"> <template slot-scope="scope"> <el-button type="primary" size="small" @click="updateExtraCost(scope.row)">{{$t('修改')}}</el-button> <el-button size="small" @click="restCostList(scope.row)">{{$t('重置')}}</el-button> </template> </el-table-column> </el-table> </el-row> </el-row> </el-dialog> <!-- 对话框 --> <el-dialog custom-class="shipping-dialog" :title="$t('票异常')" :visible.sync="regDialogVisible" width="700px" :modal-append-to-body=false append-to-body destroy-on-close> <regError @closeDialog="regCloseDialog" v-bind="$attrs" :shipmentObj="shipmentObj" /> </el-dialog> </div> </template> <script> import supplierSelect from "./common/supplierSelect.vue"; import { customsCreate, extraCostList, extraCostOrder, extraCostCreate, extraCostUpdate, approvalCancel, resetById, resetByShipmentId, customsOrderList, } from "@/api/ecw/boxSea"; import { formatNumberString, formatDateStr, serviceMsg, toReviewDetail, downloadFileByUrl, } from "../utils"; import ImageUpload from "@/components/ImageUpload"; import Decimal from "decimal.js"; import regError from "../../regError"; import dayjs from "dayjs"; /** * 报关 */ export default { name: "cusDeclaration", inheritAttrs: false, components: { supplierSelect, ImageUpload, regError }, props: { shipmentObj: Object, }, data() { return { // 报关对象 cusDeclarationObj: {}, // 校验 rules: { dcBoxWgt: [ { required: true, message: this.$t("必填"), trigger: "change" }, ], dcGoodsWgt: [ { required: true, message: this.$t("必填"), trigger: "change" }, ], dcCustomsType: [ { required: true, message: this.$t("必填"), trigger: "change" }, ], dcCustomsStatus: [ { required: true, message: this.$t("必填"), trigger: "change" }, ], dcDecTime: [ { required: true, message: this.$t("必填"), trigger: "change" }, ], }, // 弹窗配置 dialogConfig: { title: "", dialogVisible: false, }, // 订单号 orderNo: "", // 订单列表 costOrderList: [], // 额外费用列表 costList: [], // 是否审核中 inReview: false, // 异常登记 regDialogVisible: false, isShowError: false, inspectionTimecustoms: this.getDictDatas( this.DICT_TYPE.BOX_INSPECTION_TIME_CUSTOMS )[0].value, isDownload: false, normalOrderList: [], isShowNormal: false, }; }, created() { const { currNode } = this.$attrs; const { voName } = currNode; let oldData = { ...this.shipmentObj[voName], documentInfo: this.shipmentObj.documentInfo?.split(",") ?? [], }; if (!this.shipmentObj[voName]) { oldData.dcCustomsType = oldData.dcCustomsType ? oldData.dcCustomsType : this.getDcCustomsType(oldData.documentInfo); } oldData = formatDateStr(oldData, [ "dcCutOffTime", "dcCheckTime", "dcPassTime", "dcDecTime", ]); oldData = formatNumberString(oldData, [ "dcCustomsType", "dcCustomsStatus", "dcCheckStatus", ]); this.cusDeclarationObj = oldData; }, methods: { getCustomsOrderList(dcCustomsType) { if(!dcCustomsType) dcCustomsType = '1' customsOrderList({ shipmentId: this.shipmentObj.id, customsTypes: dcCustomsType === "3" ? "2,3" : dcCustomsType, }).then((res) => { this.normalOrderList = res.data ?? []; if (dcCustomsType === "1") { this.isShowNormal = false; } else { this.isShowNormal = true; } }); }, regCloseDialog(type) { this.regDialogVisible = false; if (type === "error") { this.$emit("getBoxInfo"); } }, // 时间比较 compareDate(dcDecTime, dcPassTime) { this.isShowError = false; let date1 = null, date2 = null; if (dcDecTime) date1 = dayjs(dcDecTime); if (dcPassTime) date2 = dayjs(dcPassTime); if (date1 && date2) { const delayDay = date2.diff(date1, "day"); if (delayDay >= this.inspectionTimecustoms) this.isShowError = true; } }, // 异常登记 exceptionReg() { this.regDialogVisible = true; }, /* 跳转订单详情 */ jumpOrderDetail(row) { this.$router.push({ path: "/order/detail", query: { orderId: row.orderId }, }); }, getDcCustomsType(documentInfo = []) { const newList = Array.from(new Set(documentInfo)); if (newList.length > 1) { return "3"; } if (newList.length === 1) { return newList[0] === "1" ? "1" : "2"; } }, getButtonLabel(documentInfo = []) { const newList = Array.from(new Set(documentInfo)); return newList.length >= 2 ? this.$t("混合报关") : this.$t("VGM声明"); }, submitCustomsCreate(operateType) { customsCreate({ ...this.cusDeclarationObj, shipmentId: this.shipmentObj.id, operateType, }).then((res) => { serviceMsg(res, this).then(() => { this.cancel("submit"); }); }); }, /** 提交 */ onSubmit(operateType) { this.$refs["cusDeclarationForm"].validate((valid) => { if (valid) { if (operateType === 1) { this.submitCustomsCreate(operateType); return; // 保存 } // 提交 const { dcCustomsStatus, dcCheckStatus } = this.cusDeclarationObj; // 1.状态 报关中/放行 直接提交 if (dcCustomsStatus !== "3") { this.submitCustomsCreate(operateType); return; } // 2.查验状态,空 直接提交 if (!dcCheckStatus) { this.submitCustomsCreate(operateType); return; } // 3.查验状态,查验后放行 直接提交 if (dcCheckStatus === "3") { const { checkExamineStatus } = this.shipmentObj; // 没有退场审核中的状态 if (checkExamineStatus !== 1) { this.submitCustomsCreate(operateType); return; } } // 4.查验状态,退场/部分退场 提示 if (["1", "2"].includes(dcCheckStatus)) { const { checkExamineStatus } = this.shipmentObj; // 退场审核状态,1-审核中,2-审核成功,3-审核失败,4-取消 if ([0, 2, 3, 4].includes(checkExamineStatus)) { this.$modal .confirm(this.$t( `您确认提交${ dcCheckStatus === "1" ? this.$t("全部退场") : this.$t("部分退场") }审核吗?`) ) .then(() => { customsCreate({ ...this.cusDeclarationObj, shipmentId: this.shipmentObj.id, operateType, }).then((res) => { serviceMsg(res, this).then(() => { // 触发外层重新查询出货信息 this.$emit("getBoxInfo"); }); }); }); } else { this.submitCustomsCreate(operateType); } } } }); }, /* 查询订单号 */ searchOrder() { if (!this.orderNo) { this.$message.error(this.$t("请输入订单号")); return; } extraCostOrder({ shipmentId: this.shipmentObj.id, orderNo: this.orderNo, }).then((res) => { serviceMsg(res, this).then(() => { this.costOrderList = [ { orderNo: this.orderNo, orderId: res.data, }, ]; this.searchCostList(); }); }); }, /* 查询额外费用订单 */ searchCostList() { extraCostList({ shipmentId: this.shipmentObj.id, }).then((res) => { this.costList = res.data; }); }, /* 创建额外费用 */ createExtraCost(row) { if (!row.fee) { this.$message.error(this.$t("请输入费用")); return; } extraCostCreate({ fee: row.fee, orderId: row.orderId, orderNo: row.orderNo, shipmentId: this.shipmentObj.id, }).then((res) => { serviceMsg(res, this).then(() => { this.searchCostList(); }); }); }, /* 修改额外费用 */ updateExtraCost(row) { if (!row.fee) { this.$message.error(this.$t("请输入费用")); return; } extraCostUpdate(row).then((res) => { serviceMsg(res, this).then(() => { this.searchCostList(); }); }); }, /* 重置 */ restCostList(row) { if (row) { resetById({ id: row.id }).then((res) => { serviceMsg(res, this).then(() => { this.searchCostList(); }); }); } else { resetByShipmentId({ id: this.shipmentObj.id }).then((res) => { serviceMsg(res, this).then(() => { this.searchCostList(); }); }); } }, /** 取消 */ cancel(type) { this.$emit("closeDialog", type); }, // 下载VGM downloadVGM() { window.open( "http://pdatest.groupage.cn//apivue/boxTrack/vgmExport?token=930b11a41d9ca06f306d157f336a5dcb&id=1752" ); }, // 额外费用 extraCost() { // 清空额外费用 this.orderNo = ""; this.costOrderList = []; this.costList = []; this.$set( this.dialogConfig, "title", `${this.shipmentObj.selfNo} ` + this.$t("报关费用") ); this.$set(this.dialogConfig, "dialogVisible", true); this.searchCostList(); }, // 计算VGM重量 calcVGM(dcBoxWgt, dcGoodsWgt) { let dcBoxWgtTmp = 0, dcGoodsWgtTmp = 0; if (!Number.isNaN(Number(dcBoxWgt))) { dcBoxWgtTmp = Number(dcBoxWgt); } if (!Number.isNaN(Number(dcGoodsWgt))) { dcGoodsWgtTmp = Number(dcGoodsWgt); } this.$set( this.cusDeclarationObj, "dcVgmWgt", Decimal.add(dcBoxWgtTmp, dcGoodsWgtTmp).toFixed(2) ); }, // 审核详情 jumpReviewDetail() { const { customsApprovalInfo } = this.shipmentObj; toReviewDetail.apply(this, [customsApprovalInfo.bpmProcessId]); this.cancel("close"); }, /* 取消审核 */ canclAudit() { approvalCancel({ applyReason: this.$t("取消审核"), id: this.shipmentObj["customsApprovalInfo"].id, shipmentId: this.shipmentObj.id, }).then((res) => { serviceMsg(res, this).then(() => { // 触发外层重新查询出货信息 this.cancel("close"); this.$emit("getBoxInfo"); }); }); }, /* 判断查验选择是否禁用 */ disabledRadio(item) { const { checkExamineStatus, checkDealStatus, customsInfo } = this.shipmentObj; const { dcCheckStatus } = customsInfo ?? {}; // 部分退场状态并且审核通过,退场不可选择 if ( checkExamineStatus === 2 && dcCheckStatus === 2 && checkDealStatus === 0 && item.value === "1" ) { return true; } return false; }, /* 下载报关单 */ downloadCusFile() { downloadFileByUrl("downloadCustomFiles", { shipmentId: this.shipmentObj.id, }); }, }, watch: { "cusDeclarationObj.dcCustomsType"(val) { console.log(val,'val') this.getCustomsOrderList(val); }, "cusDeclarationObj.documentInfo"(val) { this.isDownload = false; if (val.includes("2")) { this.isDownload = true; } }, "cusDeclarationObj.dcBoxWgt"(dcBoxWgt) { this.calcVGM(dcBoxWgt, this.cusDeclarationObj.dcGoodsWgt); }, "cusDeclarationObj.dcGoodsWgt"(dcGoodsWgt) { this.calcVGM(this.cusDeclarationObj.dcBoxWgt, dcGoodsWgt); }, "cusDeclarationObj.dcCustomsStatus"(val) { if (val !== "3") { this.$set(this.cusDeclarationObj, "dcCheckStatus", ""); // this.$set(this.cusDeclarationObj, "dcPassTime", ""); } else { const { customsInfo } = this.shipmentObj; this.$set( this.cusDeclarationObj, "dcCheckStatus", (customsInfo?.dcCheckStatus && String(customsInfo?.dcCheckStatus)) || "3" ); } }, shipmentObj: { deep: true, immediate: true, handler: function (val) { // 监听查验状态变化 let { checkExamineStatus } = val; if (checkExamineStatus === 1) { // 按钮变成审核中 this.inReview = true; } }, }, // 报关时间 "cusDeclarationObj.dcDecTime"(val) { this.compareDate(val, this.cusDeclarationObj.dcPassTime); }, // 放行时间 "cusDeclarationObj.dcPassTime"(val) { this.compareDate(this.cusDeclarationObj.dcDecTime, val); }, // 查验状态 "cusDeclarationObj.dcCheckStatus"(val) { const { customsInfo } = this.shipmentObj; if (val != customsInfo?.dcCheckStatus) { this.$set(this.cusDeclarationObj, "dcPassTime", ""); } }, }, computed: { /* 获取报关审核退场状态文字 */ getCheckExamineStatus() { const { checkExamineStatus, checkDealStatus, customsInfo } = this.shipmentObj; const { dcCheckStatus } = customsInfo ?? {}; if (checkExamineStatus === 1) { return dcCheckStatus === 1 ? this.$t("退场审核中") : this.$t("部分退场审核中"); } if (checkExamineStatus === 2 && checkDealStatus === 0) { return dcCheckStatus === 1 ? this.$t("审核通过,退场中") : this.$t("审核通过,部分退场中"); } return this.$t("未审核"); }, /* 判断是否已处理 */ isCheckDeal() { return (type) => { const { checkExamineStatus, checkDealStatus, customsInfo } = this.shipmentObj; const { dcCheckStatus } = customsInfo ?? {}; // 状态 if (type === "status") { // 退场/部分退场 审核通过未处理,禁用 if ( checkExamineStatus === 2 && [1, 2].includes(dcCheckStatus) && checkDealStatus === 0 ) { return true; } } // 查验 if (type === "check") { // 退场 审核通过未处理,禁用 // 部分退场 审核通过未处理,由 disabledRadio 方法判断 if ( checkExamineStatus === 2 && [1].includes(dcCheckStatus) && checkDealStatus === 0 ) { return true; } } // 提交/保存 if (type === "submit") { const { dcCheckStatus: newCheckStatus } = this.cusDeclarationObj; // 退场/部分退场 审核通过未处理 if (checkExamineStatus === 2 && checkDealStatus === 0) { // 退场,禁用 if (dcCheckStatus === 1) return true; // 部分退场 if (dcCheckStatus === 2) { // 修改为查验后放行,可用,其他禁用 if (newCheckStatus === "3") return false; return true; } } } return false; }; }, }, }; </script> <style lang="scss"> .customsClearance { .cost-title { display: flex; align-items: center; margin: 20px 0; border-left: 5px solid gray; > div:first-child { margin-left: 10px; } > div:last-child { flex: 1; text-align: right; } } .el-table.table-inputNumber { .cell { overflow: visible; } } } </style>