Commit 33211bf4 authored by zhoutong's avatar zhoutong

空运暂存

parent b6692430
......@@ -16,4 +16,27 @@ export function updatebox(data) {
method: "put",
data: data,
});
}
/**
* 订舱
*
* @export
* @param {*} data
* @return {*}
*/
export function booking(data) {
if (data.id) {
return request({
url: "/shipment/box-book-air/update",
method: "put",
data,
});
}
return request({
url: "/shipment/box-book-air/create",
method: "post",
data,
});
}
\ No newline at end of file
......@@ -466,6 +466,28 @@ export const constantRoutes = [
}
]
},
{
path: '/boxAir',
component: Layout,
hidden: true,
redirect: 'noredirect',
children: [
{
path: 'query/:shipmentId(\\d+)',
component: (resolve) => import('@/views/ecw/box/query'),
props: true,
name: 'shippingDetail',
meta: {titleZh: '出货详情', titleEn: "Shipping Details", icon: '', activeMenu: '/shipment/boxDetail'}
},
{
path: 'shippingAir/:shipmentId(\\d+)',
component: (resolve) => import('@/views/ecw/box/shippingAir/shippingAir'),
props: true,
name: 'shippingAir',
meta: {titleZh: '空运出货操作', titleEn: "Ocean shipment operation", icon: '', activeMenu: '/shipment/boxAir'}
}
]
},
]
// 防止连续点击多次路由报错
......
......@@ -101,8 +101,6 @@ export default {
return
}
this.form.transportType = 4
// 修改的提交
if (this.form.id != null) {
updatebox(this.form).then((response) => {
......
......@@ -341,45 +341,21 @@ export default {
this.$set(this.dialogCfg, 'fullscreen', false)
this.$set(this.dialogCfg, 'open', true)
this.currRow = {
transportType: '1'
transportType: '3'
}
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id
const id = row.id;
getbox(id).then((response) => {
this.form = response.data
this.open = true
this.title = this.$t('修改出货')
})
this.currRow = response.data;
this.$set(this.dialogCfg, "title", this.$t("修改出货"));
this.$set(this.dialogCfg, "dialogType", "edit");
this.$set(this.dialogCfg, "width", "600px");
this.$set(this.dialogCfg, "open", true);
});
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (!valid) {
return
}
this.form.transportType = 3
// 修改的提交
if (this.form.id != null) {
updatebox(this.form).then((response) => {
this.$modal.msgSuccess(this.$t('修改成功'))
this.open = false
this.getList()
})
return
}
// 添加的提交
createbox(this.form).then((response) => {
this.$modal.msgSuccess(this.$t('新增成功'))
this.open = false
this.getList()
})
})
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id
......@@ -397,7 +373,7 @@ export default {
/** 导出按钮操作 */
handleExport() {
// 处理查询参数
let params = { ...this.queryParams }
let params = { ...this.queryParams }
params.pageNo = undefined
params.pageSize = undefined
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime')
......@@ -417,8 +393,8 @@ export default {
/** 查看按钮操作 */
handleCommand(row, command) {
switch (command) {
case 'sea':
this.$router.push('/box/shippingSea/' + row.id)
case 'air':
this.$router.push('/boxAir/shippingAir/' + row.id)
break
case 'edit':
......
<template>
<div>
<el-form ref="agentForm" :model="agentObj" :rules="rules" label-width="120px">
<el-form-item :label="$t('代理商Agent')" prop="agentId">
<supplierSelect v-model="agentObj.agentId" :companyType="'1'" :areaType="1" :placeholder="$t('请选择代理商')" :allSupplier="this.$attrs.allSupplier" />
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="success" @click="onSubmit">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { agentSet } from "@/api/ecw/boxSea";
import supplierSelect from "./common/supplierSelect.vue";
import { formatStringNumber, serviceMsg } from "../utils";
/**
* agent
*/
export default {
name: "agent",
inheritAttrs: false,
components: { supplierSelect },
data() {
return {
// agent对象
agentObj: {},
// 校验
rules: {
agentId: [{ required: true, message: this.$t("必填"), trigger: "change" }],
},
};
},
created() {
const { currNode, shipmentObj } = this.$attrs;
const voName = currNode.voName;
let oldData = { ...shipmentObj[voName] };
oldData = formatStringNumber(oldData, ["agentId"]);
this.agentObj = oldData;
},
methods: {
/** 提交 */
onSubmit() {
this.$refs["agentForm"].validate((valid) => {
if (valid) {
agentSet({
shipmentId: this.$attrs.shipmentObj.id,
...this.agentObj,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-form ref="arrivalForm" :rules="rules" :model="arrivalObj" label-width="120px">
<el-form-item :label="$t('预计到港时间')">{{getExpectedTime()}}</el-form-item>
<el-form-item :label="$t('实际到港时间')" prop="apRealTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="arrivalObj.apRealTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('确认到港')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="arrivalObj.apConfirmTime" value-format="yyyy-MM-dd HH:mm:ss">
</el-date-picker>
<p class="message-area" v-show="showMsg">{{$t('请确认是否有异常,如有异常请进行异常登记')}}</p>
</el-form-item>
<el-form-item :label="$t('卸港时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="arrivalObj.apUnloadPortTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button type="primary" @click="exceptionReg" :disabled="!showMsg">{{$t('异常登记')}}</el-button>
</el-row>
<!-- 对话框 -->
<el-dialog custom-class="shipping-dialog" :title="$t('票异常')" :visible.sync="dialogVisible" width="700px" :modal-append-to-body=false append-to-body destroy-on-close>
<regError @closeDialog="regCloseDialog" v-bind="$attrs" />
</el-dialog>
</div>
</template>
<script>
import regError from "../../regError";
import dayjs from "dayjs";
import { arrivalCreate } from "@/api/ecw/boxSea";
import { formatDateStr, serviceMsg } from "../utils";
/**
* 到港
*/
export default {
name: "arrival",
inheritAttrs: false,
components: {
regError,
},
data() {
return {
// 到港对象
arrivalObj: {},
// 校验
rules: {
apRealTime: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
},
// 弹窗配置
dialogVisible: false,
// 提示消息
showMsg: false,
inspectionTimeArrival: this.getDictDatas(
this.DICT_TYPE.BOX_INSPECTION_TIME_ARRIVAL
)[0].value,
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(
oldData,
["apRealTime", "apConfirmTime"],
"YYYY-MM-DD HH:mm:ss"
);
oldData = formatDateStr(oldData, ["apUnloadPortTime"]);
this.arrivalObj = oldData;
},
watch: {
// 确认到港时间
"arrivalObj.apConfirmTime"(val) {
this.compareDate(this.getExpectedTime(), val);
},
},
methods: {
regCloseDialog(type) {
this.dialogVisible = false;
if (type === "error") {
this.$emit("getBoxInfo");
}
},
// 获取预计到港时间
getExpectedTime() {
const { shippingInfo } = this.$attrs.shipmentObj;
if (shippingInfo) {
return dayjs(shippingInfo.dtEstArrivalTime).format(
"YYYY-MM-DD HH:mm:ss"
);
}
return null;
},
// 时间比较
compareDate(expectedTime, apConfirmTime) {
this.showMsg = false;
let date1 = null,
date2 = null;
if (expectedTime) date1 = dayjs(expectedTime);
if (apConfirmTime) date2 = dayjs(apConfirmTime);
if (date1 && date2) {
const days = date2.diff(date1, "day");
if (days > this.inspectionTimeArrival) {
this.showMsg = true;
}
}
},
// 异常登记
exceptionReg() {
this.dialogVisible = true;
},
/** 提交 */
onSubmit(operateType) {
this.$refs["arrivalForm"].validate((valid) => {
if (valid) {
arrivalCreate({
...this.arrivalObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
.message-area {
margin: 0;
color: red;
}
</style>
<template>
<div>
<el-form ref="bargeForm" :model="bargeObj" :rules="rules" label-width="80px">
<el-form-item :label="$t('驳船')" prop="bgExmtStatus">
<el-radio-group v-model="bargeObj.bgExmtStatus">
<el-radio v-for="item in bargeStatus" :key="item.value" :label="item.value">{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
<div v-show="bargeObj.bgExmtStatus === '2'">
<el-row>
<el-col :span="12">
<el-form-item :label="$t('驳船预计开船时间')" label-width="130px">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="bargeObj.bgEstShipTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('通知人')" label-width="80px">
<userSelect v-model="bargeObj.notifyUser" :placeholder="$t('请选择通知人')" :allUsers="this.$attrs.allUsers" />
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('驳船实际开船时间')" label-width="130px">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="bargeObj.bgRealShipTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</div>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { bargeCreate } from "@/api/ecw/boxSea";
import userSelect from "./common/userSelect.vue";
import { constantDict, formatDateStr, formatNumberString, serviceMsg } from "../utils";
/**
* 驳船
*/
export default {
name: "barge",
inheritAttrs: false,
components: { userSelect },
data() {
return {
// 驳船对象
bargeObj: {},
// 驳船状态
bargeStatus: constantDict.bgExmtStatus,
// 校验
rules: {
bgExmtStatus: [{ required: true, message: this.$t("必填"), trigger: "change" }],
},
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, ["bgEstShipTime", "bgRealShipTime"]);
oldData = formatNumberString(oldData, ["bgExmtStatus"]);
this.bargeObj = oldData;
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["bargeForm"].validate((valid) => {
if (valid) {
bargeCreate({
...this.bargeObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-form ref="blCopyForm" :model="blCopyObj" label-width="120px">
<el-form-item :label="$t('提单Copy')">
<FileUpload :limit="1" :isShowTip=false v-model="blCopyObj.copyUrl" :fileType="fileType" />
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { ladingCopyCreate } from "@/api/ecw/boxSea";
import FileUpload from "@/components/FileUpload";
import { fileTypes, serviceMsg } from "../utils";
/**
* 提单copy
*/
export default {
name: "blCopy",
inheritAttrs: false,
components: { FileUpload },
data() {
return {
// 提单copy对象
blCopyObj: {},
// 文件格式
fileType: fileTypes,
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
this.blCopyObj = oldData;
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["blCopyForm"].validate((valid) => {
if (valid) {
ladingCopyCreate({
...this.blCopyObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-form ref="bookingForm" :rules="rules" :model="bookingObj" label-width="140px">
<el-form-item :label="$t('提单号')">
<el-input v-model="bookingObj.blNo" :placeholder="$t('请输入提单号')"></el-input>
</el-form-item>
<el-form-item :label="$t('起运港')">
<dockSelect v-model="bookingObj.departurePortId" :placeholder="$t('请选择起运港')" portType="2" :allDocks="this.$attrs.allDocks" />
</el-form-item>
<el-form-item :label="$t('目的港')">
<dockSelect v-model="bookingObj.destPortId" :placeholder="$t('请选择目的港')" portType="2" :allDocks="this.$attrs.allDocks" />
</el-form-item>
<el-form-item :label="$t('Shipper')">
<supplierSelect v-model="bookingObj.shipperId" :companyType="'5'" :placeholder="$t('请选择Shipper')" :allSupplier="this.$attrs.allSupplier" />
</el-form-item>
<el-form-item :label="$t('航空公司')">
<supplierSelect v-model="bookingObj.airlineCompanyId" :companyType="'7'" :placeholder="$t('请选择航空公司')" :allSupplier="this.$attrs.allSupplier" />
</el-form-item>
<el-form-item :label="$t('预计起飞时间')" prop="flyTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" value-format="yyyy-MM-dd HH:mm:ss" v-model="bookingObj.flyTime"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('截关时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" value-format="yyyy-MM-dd HH:mm:ss" v-model="bookingObj.closingTime"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('截补料时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" value-format="yyyy-MM-dd HH:mm:ss" v-model="bookingObj.replenishmentTime"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('航程')" prop="voyage">
<el-radio-group v-model="bookingObj.voyage">
<el-radio v-for="item in voyageData" :key="item.value" :label="item.value">{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('截止送货时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" value-format="yyyy-MM-dd HH:mm:ss" v-model="bookingObj.deliveryTime"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('出货渠道')">
<el-select v-model="bookingObj.airlineTypeId" :placeholder="$t('请选择出货渠道')">
<el-option v-for="item in channelList" :label="$l(item, 'name')" :value="item.channelId" :key="item.channelId"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { booking } from "@/api/ecw/boxAir";
import supplierSelect from "./common/supplierSelect.vue";
import dockSelect from "./common/dockSelect.vue";
import userSelect from "./common/userSelect.vue";
import { formatStringNumber, formatDateStr, serviceMsg, constantDict } from "../utils";
import { getChannelList } from '@/api/ecw/channel'
/**
* 订舱
*/
export default {
name: "booking",
inheritAttrs: false,
components: {
supplierSelect,
dockSelect,
userSelect,
},
props: {
shipmentObj: Object,
},
data() {
return {
// 订舱对象
bookingObj: {},
channelList: [],
voyageData: constantDict.voyageData,
// 校验
rules: {
flyTime: [{ required: true, message: this.$t("必填"), trigger: "change" }],
voyage: [{ required: true, message: this.$t("必填"), trigger: "change" }],
},
};
},
created() {
getChannelList().then((res) => (this.channelList = res.data))
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.shipmentObj[voName] };
oldData = formatStringNumber(oldData, ["shipCompanyType", "spaceCompany"]);
oldData = formatDateStr(oldData, [
"flyTime",
"closingTime",
"replenishmentTime",
"deliveryTime"
]);
this.bookingObj = oldData;
},
methods: {
/** 提交 */
onSubmit() {
this.$refs["bookingForm"].validate((valid) => {
if (valid) {
booking({
shipmentId: this.shipmentObj.id,
...this.bookingObj,
operateType: 2,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<template>
<div>
<el-form ref="cabinetForm" :rules="rules" :model="cabinetObj" label-width="80px">
<el-form-item :label="$t('到仓时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cabinetObj.ldInWarehouseTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('仓库')">
<el-select v-model="cabinetObj.ldWarehouseType" :placeholder="$t('请选择仓库')" filterable>
<el-option v-for="warehouse in $attrs.warehouseList" :key="warehouse.id" :label="$l(warehouse,'title')" :value="warehouse.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('装柜时间')" prop="ldBoxTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cabinetObj.ldBoxTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('出仓时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cabinetObj.ldOutWarehouseTime" 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="cabinetObj.ldPictures" />
</el-form-item>
</el-form>
<!-- 开始装柜 -->
<el-dialog :title="$t('开始装柜')" :visible.sync="dialogVisible" fullscreen :modal-append-to-body=false append-to-body>
<startPacking v-bind="$attrs" v-if="dialogVisible" v-on="$listeners" @closeDialog1="closeDialog1" />
</el-dialog>
<!-- 操作 -->
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)" :disabled="isSeal">{{$t('封柜')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button type="danger" @click="startCabinet" :disabled="isStartCabinet">{{$t('开始装柜')}}</el-button>
</el-row>
</div>
</template>
<script>
import startPacking from "./startPacking.vue";
import { cabinetCreate } from "@/api/ecw/boxSea";
import { formatDateStr, serviceMsg } from "../../utils";
import ImageUpload from "@/components/ImageUpload";
/**
* 装柜
*/
export default {
name: "cabinet",
inheritAttrs: false,
components: { startPacking, ImageUpload },
data() {
return {
// 弹窗
dialogVisible: false,
// 装柜对象
cabinetObj: {},
// 校验
rules: {
ldBoxTime: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
},
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, [
"ldInWarehouseTime",
"ldBoxTime",
"ldOutWarehouseTime",
]);
let pictures = oldData.ldPictures;
if (oldData.ldPictures) {
pictures = JSON.parse(oldData.ldPictures);
if (Array.isArray(pictures)) {
pictures = pictures.map((item) => item.url).join(",");
}
}
this.cabinetObj = {
...oldData,
ldWarehouseType:
oldData.ldWarehouseType === 0 ? undefined : oldData.ldWarehouseType,
ldPictures: pictures,
};
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["cabinetForm"].validate((valid) => {
if (valid) {
if (operateType === 2) {
const { currNode, shipmentObj } = this.$attrs;
const status = shipmentObj[currNode.keyName];
if (status !== 46) {
this.$message.error(this.$t("请先进行装柜->审批->确认封柜"));
return;
}
}
const { ldPictures } = this.cabinetObj;
let pictures = ldPictures?.split(",") ?? [];
let newPictures = [];
for (const item of pictures) {
if (item) {
newPictures.push({
type: "image",
url: item,
});
}
}
cabinetCreate({
shipmentId: this.$attrs.shipmentObj.id,
...this.cabinetObj,
ldPictures: newPictures.length ? JSON.stringify(newPictures) : "",
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
closeDialog1(type) {
this.dialogVisible = false;
if (type) this.cancel(type);
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
/** 开始装柜 */
startCabinet() {
this.dialogVisible = true;
},
},
computed: {
isStartCabinet() {
const { currNode, shipmentObj } = this.$attrs;
const status = shipmentObj[currNode.keyName];
return [46, 47].includes(status) ? true : false;
},
isSeal() {
const { currNode, shipmentObj } = this.$attrs;
const status = shipmentObj[currNode.keyName];
return status === 47 ? true : false;
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div class="app-container shipping-split-order">
<el-card>
<div slot="header" class="card-title">{{$t('拆单申请')}}-{{orderData.orderNo||''}}</div>
<div class="btn-header">
<span class="card-title">{{$t('原单信息')}}</span>
</div>
<el-descriptions :column="4">
<el-descriptions-item :label="$t('唛头')">
{{orderData.marks?orderData.marks:$t('')}}
</el-descriptions-item>
<el-descriptions-item :label="$t('已实装箱数/总箱数')">
<span>{{currRow.installNum||0}}/{{currRow.num||0}}</span>
</el-descriptions-item>
<el-descriptions-item :label="$t('订单状态')">
{{orderData.status==99? $t('异常'):$t('正常')}}
</el-descriptions-item>
<el-descriptions-item :label="$t('送货日期')">
{{orderData.deliveryDate}}
</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="4">
<el-descriptions-item :label="$t('运输方式')">
<dict-tag :type="DICT_TYPE.ECW_TRANSPORT_TYPE" :value="orderData.transportId" />
</el-descriptions-item>
<el-descriptions-item :label="$t('始发地')">
{{orderData.logisticsInfoDto?$l(orderData.logisticsInfoDto, 'startTitle'):$t('')}}
</el-descriptions-item>
<el-descriptions-item :label="$t('目的地')">
{{orderData.logisticsInfoDto?$l(orderData.logisticsInfoDto, 'destTitle'):$t('')}}
</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="4">
<el-descriptions-item :label="$t('发货人姓名')">
{{orderData.consignorVO?orderData.consignorVO.name||$t(''):$t('')}}
</el-descriptions-item>
<el-descriptions-item :label="$t('发货公司')">
{{orderData.consignorVO?orderData.consignorVO.company||$t(''):$t('')}}
</el-descriptions-item>
<el-descriptions-item :label="$t('发货电话')">
{{orderData.consignorVO?(orderData.consignorVO.phone?("+"+orderData.consignorVO.countryCode+orderData.consignorVO.phone):$t('')):$t('')}}
</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="4">
<el-descriptions-item :label="$t('收货人姓名')">
{{orderData.consigneeVO?orderData.consigneeVO.name||$t(''):$t('')}}
</el-descriptions-item>
<el-descriptions-item :label="$t('收货公司')">
{{orderData.consigneeVO?orderData.consigneeVO.company||$t(''):$t('')}}
</el-descriptions-item>
<el-descriptions-item :label="$t('收货电话')">
{{orderData.consigneeVO?orderData.consigneeVO.phone?"+"+orderData.consigneeVO.countryCode+orderData.consigneeVO.phone :$t(''):$t('')}}
</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card class="card">
<!-- 列表 -->
<div slot="header" class="card-title">{{$t('货物信息')}}</div>
<el-table id='table' v-loading="loading" border :data="orderData.orderItemVOList" :summary-method="getSummaries" show-summary>
<el-table-column :label="$t('序号')" align="center" prop="id" type="index" width="60">
<template slot-scope="scope">
<span>{{scope.$index + 1}}</span>
</template>
</el-table-column>
<el-table-column :label="$t('品名')" align="center">
<template slot-scope="scope">
<el-row>{{scope.row.prodTitleZh}}</el-row>
<el-row>{{scope.row.prodTitleEn}}</el-row>
</template>
</el-table-column>
<el-table-column :label="$t('装柜货物属性')" align="center" width="600">
<template slot-scope="scope">
<el-row style="text-align:left;">
<el-row>
<span>{{$t('规格')}}{{scope.row.warehouseInInfoVO ? scope.row.warehouseInInfoVO.boxGauge : ''}}</span>
</el-row>
<el-row>
<span>{{$t('品牌')}}
<template v-if="scope.row.brandName">{{scope.row.brandName}}</template>
<dict-tag v-else :type="DICT_TYPE.ECW_IS_BRAND" :value="scope.row.brandType" />
</span>
<span style="margin-left: 10px;">{{$t('箱数')}}:{{scope.row.warehouseInInfoVO ? scope.row.warehouseInInfoVO.cartonsNum : 0 }}</span>
<span style="margin-left: 10px;">{{$t('体积')}}:{{scope.row.warehouseInInfoVO ? scope.row.warehouseInInfoVO.volume : 0 }}m³</span>
<span style="margin-left: 10px;">{{$t('重量')}}:{{scope.row.warehouseInInfoVO ? scope.row.warehouseInInfoVO.weight : 0 }}kg</span>
</el-row>
<el-row>
<span>{{$t('计划装柜')}}:{{planCabinet}}</span>
</el-row>
</el-row>
</template>
</el-table-column>
<el-table-column :label="$t('最后操作时间')" align="center">
<template slot-scope="scope">
<span>{{parseTime(scope.row.updateTime)}}</span>
</template>
</el-table-column>
<el-table-column :label="$t('状态')" align="center">
{{orderData.abnormalState!=0?$t('异常'):$t('正常')}}
<!-- <template slot-scope="scope">
<dict-tag :type="DICT_TYPE.ORDER_STATUS" :value="scope.row.status" />
</template> -->
</el-table-column>
</el-table>
</el-card>
<el-card class="card" v-if="splitData.id">
<!-- 列表 -->
<div slot="header" class="card-title">{{$t('拆单信息')}}</div>
<div>
<div class="btn-header">
<div>
<p class="card-info">
<span class="card-title">
{{splitData.orderNo}}
</span>
<span>{{orderData.logisticsInfoDto?$l(orderData.logisticsInfoDto, 'startTitle'):$t('无')}}</span>
<span>{{$t('发往')}}:{{splitData.dstWarehouseName}}</span>
</p>
</div>
<div>
<el-button type="primary" :disabled="isAudit" @click="addShop">{{$t('放入')}}</el-button>
</div>
</div>
<el-table border :data="splitData.orderSplitItemBackVOList">
<el-table-column :label="$t('序号')" align="center" prop="id" type="index">
<template slot-scope="scope">
<span>{{scope.$index + 1}}</span>
</template>
</el-table-column>
<el-table-column :label="$t('品名')" align="center">
<template slot-scope="scope">
<el-row>{{scope.row.prodTitleZh}}</el-row>
<el-row>{{scope.row.prodTitleEn}}</el-row>
</template>
</el-table-column>
<el-table-column :label="$t('品牌')" align="center">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.ECW_IS_BRAND" :value="scope.row.brandType" />
</template>
</el-table-column>
<el-table-column :label="$t('入仓体积')" align="center" >
<template slot-scope="scope">
<el-input v-model="scope.row.volume" @change="updateField(scope.row, 'volume')" size="mini" :disabled="index === 0">
<span slot="append"></span>
</el-input>
</template>
</el-table-column>
<el-table-column :label="$t('收费体积')" align="center" >
<template slot-scope="scope">
<el-input v-model="scope.row.chargeVolume" @change="updateField(scope.row, 'chargeVolume')" size="mini" :disabled="index === 0">
<span slot="append"></span>
</el-input>
</template>
</el-table-column>
<el-table-column :label="$t('入仓重量')" align="center">
<template slot-scope="scope">
<el-input v-model="scope.row.weight" @change="updateField(scope.row, 'weight')" size="mini" :disabled="index === 0">
<span slot="append">kg</span>
</el-input>
</template>
</el-table-column>
<el-table-column :label="$t('收费重量')" align="center">
<template slot-scope="scope">
<el-input v-model="scope.row.chargeWeight" @change="updateField(scope.row, 'chargeWeight')" size="mini" :disabled="index === 0">
<span slot="append">kg</span>
</el-input>
</template>
</el-table-column>
<el-table-column :label="$t('货值')" align="center">
<template slot-scope="scope">
<el-input v-model="scope.row.worth" @change="updateField(scope.row, 'worth')" size="mini" :disabled="index === 0">
<span slot="append">{{ $t('美元') }}</span>
</el-input>
</template>
</el-table-column>
<el-table-column :label="$t('箱数')" align="center">
<template slot-scope="scope">
<span>{{scope.row.num}}</span>
</template>
</el-table-column>
<el-table-column :label="$t('计划装柜')" align="center">
{{planCabinet}}
</el-table-column>
<el-table-column :label="$t('操作')" align="center">
<template slot-scope="scope">
<el-button size="mini" :disabled="isAudit" type="text" icon="el-icon-delete" @click="removeShop(scope.row.id)">{{$t('移出')}}</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
<el-row style="marginTop:15px;">
<work-flow xmlkey="split_order" v-model="selectedUsers"></work-flow>
</el-row>
<div slot="footer" class="card footer_btn">
<el-button v-if="!isAudit" type="primary" @click="submitForm">{{$t('提交申请')}}</el-button>
<el-button v-if="!isAudit" plain type="primary" @click="$emit('closeDialog2')">{{$t('取消')}}</el-button>
<el-button v-if="isAudit" type="primary" @click="jumpReviewDetail">{{$t('审核中')}}</el-button>
<el-button v-if="isAudit" plain type="primary" @click="cancelSplit">{{$t('取消审核')}}</el-button>
<el-button v-if="isAudit" plain type="primary" @click="$emit('closeDialog2')">{{$t('返回')}}</el-button>
</div>
<!-- 对话框(添加 / 修改) -->
<el-dialog :title="$t('放入品名')" :visible.sync="shopOpen" width="500px" append-to-body>
<el-form ref="shopForm" :model="shopForm" :rules="shopRules" label-width="150px">
<el-row>
<el-form-item :label="$t('中文品名')+':'" prop="orderItemId">
<el-select v-model="shopForm.orderItemId" :placeholder="$t('请选择中文品名')" @change="onProdChange">
<el-option v-for="item in orderItems" :label="item.prodTitleZh" :value="item.orderItemId" :key="item.id" :disabled="itemDisabled(item)"></el-option>
</el-select>
</el-form-item>
</el-row>
<el-row>
<el-form-item :label="$t('英文品名')+':'" prop="orderItemId">
<el-select v-model="shopForm.orderItemId" :placeholder="$t('请选择英文品名')" @change="onProdChange">
<el-option v-for="item in orderItems" :label="item.prodTitleEn" :value="item.orderItemId" :key="item.id" :disabled="itemDisabled(item)"></el-option>
</el-select>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('剩余箱数')+':'">
{{shopForm.leftNum||0}}
</el-form-item>
</el-col>
<!--剩余数量计算不出来,显示没意义-->
<!--<el-col :span="12" v-show="isQuantity">
<el-form-item :label="$t('剩余数量(个)')+':'">
{{shopForm.leftQuantity||0}}
</el-form-item>
</el-col>-->
</el-row>
<el-form-item :label="$t('放入箱数')+':'">
<el-input-number v-model="shopForm.num" controls-position="right" :min="0" :max="+shopForm.leftNum" @change="calcAverg"></el-input-number>
</el-form-item>
<el-form-item v-if="mainOrderItem.orderItemId" label-width="0">
{{ $t('剩余入仓方数') }}:{{ mainOrderItem.volume || 0 }}m³,
{{$t('剩余收费方数')}}:{{ mainOrderItem.chargeVolume || 0 }}m³
</el-form-item>
<el-form-item :label="$t('入仓体积')">
<el-input-number v-model="shopForm.volume" controls-position="right" :min="0" :max="mainOrderItem.volume"></el-input-number>
</el-form-item>
<el-form-item :label="$t('收费体积')">
<el-input-number v-model="shopForm.chargeVolume" controls-position="right" :min="0" :max="mainOrderItem.chargeVolume"></el-input-number>
</el-form-item>
<el-form-item v-if="mainOrderItem.orderItemId" label-width="0">
{{ $t('剩余入仓重量') }}:{{ mainOrderItem.weight || 0 }}kg,
{{$t('剩余收费重量')}}:{{ mainOrderItem.chargeWeight || 0 }}kg
</el-form-item>
<el-form-item :label="$t('入仓重量')">
<el-input-number v-model="shopForm.weight" controls-position="right" :min="0" :max="mainOrderItem.weight"></el-input-number>
</el-form-item>
<el-form-item :label="$t('收费重量')">
<el-input-number v-model="shopForm.chargeWeight" controls-position="right" :min="0" :max="mainOrderItem.chargeWeight"></el-input-number>
</el-form-item>
<el-form-item v-if="mainOrderItem.orderItemId" label-width="0">
{{ $t('剩余货值') }}:{{ mainOrderItem.worth || 0 }}{{ $t('美元') }}
</el-form-item>
<el-form-item :label="$t('放入货值')">
<el-input-number v-model="shopForm.worth" controls-position="right" :min="0" :max="mainOrderItem.worth"></el-input-number>
</el-form-item>
<!--按照原型这里需要显示剩余数量,但是事实无法计算剩余数量,因为已装数量是未知的-->
<el-form-item :label="$t('放入数量(个)')+':'" prop="quantity" v-if="isQuantity">
<el-input-number v-model="shopForm.quantity" controls-position="right" :min="0" :max="mainOrderItem.quantity || undefined"></el-input-number>
</el-form-item>
<el-form-item :label="$t('备注信息')+':'">
<el-input v-model="shopForm.remarks"></el-input>
</el-form-item>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="shopAdd">{{$t('确定')}}</el-button>
<el-button @click="shopCancel">{{$t('取消')}}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
getSplitList,
// quantitycheck,
createSplitItem,
deleteSplitItem,
} from "@/api/ecw/orderHandle";
import {quantityRequired} from "@/api/ecw/warehouse";
import { getTradeCityList } from "@/api/ecw/region";
import WorkFlow from "@/components/WorkFlow";
import {getOrder, splitItemUpdate} from "@/api/ecw/order";
import { serviceMsg, toReviewDetail } from "../../utils";
import { createApproval, approvalCancel, splitList } from "@/api/ecw/boxSea";
import Decimal from "decimal.js";
export default {
name: "splitOrder",
inheritAttrs: false,
components: {
WorkFlow
},
props: {
currRow: Object,
},
data() {
return {
orderData: {},
splitData: {},
detail: {},
loading: false,
selectedUsers: [],
tradeCityList: [],
planCabinet: "",
shopOpen: false,
orderItems: [],
shopForm: {},
// 表单校验
shopRules: {
zhId: [
{
required: true,
message: this.$t("请选择中文品名"),
trigger: "change",
},
],
enId: [
{
required: true,
message: this.$t("请选择英文品名"),
trigger: "change",
},
],
},
queryParams: {
orderId: 0,
lang: 0,
},
isQuantity: false,
// 主单数据
mainOrder: {orderSplitItemBackVOList: {}}
};
},
created() {
const { shipmentObj } = this.$attrs;
this.planCabinet = `${shipmentObj.selfNo}-${this.currRow.sectionName}`;
getTradeCityList().then((res) => (this.tradeCityList = res.data));
this.queryParams.orderId = this.currRow.orderId;
this.getOrderDetail();
this.getSplit();
},
watch: {
//监听table这个对象
tableData: {
// 立即监听
immediate: true,
handler() {
this.$nextTick(() => {
const tds = document.querySelectorAll(
"#table .el-table__footer-wrapper tr>td"
);
// colSpan合并列
tds[1].colSpan = 5;
tds[1].style.textAlign = "left";
tds[2].style.display = "none";
tds[3].style.display = "none";
tds[4].style.display = "none";
});
},
},
},
computed: {
isAudit() {
const { shipmentObj } = this.$attrs;
const { cabinetSplitInfo } = shipmentObj;
if (cabinetSplitInfo) {
/**
* PROCESS(1, "处理中"),
* APPROVE(2, "通过"),
* REJECT(3, "不通过"),
* CANCEL(4, "已取消");
*/
const { approvalStatus } = cabinetSplitInfo;
if (approvalStatus === 1) return true;
}
return false;
},
// 订单项数据,默认要返回一个如下的空json结构体,避免报错
// 装柜拆单只能拆一个出来,所以直接用原单数据作为放入品名的最大值限制即可,跟订单操作中的拆单有所区别
mainOrderItem(){
if(!this.shopForm.orderItemId || !this.mainOrder.orderSplitItemBackVOList.length) return {}
return this.mainOrder.orderSplitItemBackVOList.find(item => item.orderItemId == this.shopForm.orderItemId) || {}
}
},
methods: {
/*检查并提交字段(体积,重量)修改*/
updateField(row, field){
let val = parseFloat(row[field])
if(!val || val < 0){
this.$message.error(this.$t('数据无效'))
return this.getList()
}
splitItemUpdate(row).then(() => {
this.$message.success(this.$t('修改成功'))
}).catch(() => {
this.getList()
})
},
/* 拆箱总数,默认计算箱数,传递quantity可计算个数 */
totalSplit(field = 'num') {
let _total = 0;
const { orderSplitItemBackVOList = [] } = this.splitData;
orderSplitItemBackVOList.forEach((v) => {
_total = Decimal.add(_total, Number(v[field])).toNumber();
});
return _total;
},
/* 打开拆单 */
getSplit() {
this.orderItems = this.currRow.goodsList ?? [];
const { shipmentObj } = this.$attrs;
splitList({
orderId: this.currRow.orderId,
shipmentId: shipmentObj.id,
}).then((res) => {
const data = res.data;
// 取拆单项
this.splitData = data.filter((item) => !item.isMaster)?.[0] ?? {};
// 取主单,用语判断放入品名的数据上限
this.mainOrder = data.find(item => item.isMaster)
});
},
itemDisabled(data) {
const { orderSplitItemBackVOList = [] } = this.splitData;
const isExist = orderSplitItemBackVOList.find(
(item) => item.orderItemId === data.orderItemId
);
return isExist ? true : false;
},
/* 查询拆单项 */
querySplitGoods() {
getSplitList({
lang: 0,
orderId: this.currRow.orderId,
shipmentType: 1,
}).then((res) => {
const { orderSplitBackVOList } = res.data; // 取拆单项
const list =
orderSplitBackVOList.filter((item) => !item.isMaster)?.[0] ?? {};
this.splitData.orderSplitItemBackVOList =
list.orderSplitItemBackVOList ?? [];
});
},
getOrderDetail() {
this.loading = true;
getOrder(this.queryParams.orderId).then((response) => {
this.orderData = response.data;
this.loading = false;
});
},
getSummaries() {
const sums = [];
sums[0] = this.$t("小计");
if (
!this.orderData ||
!this.orderData.orderItemVOList ||
this.orderData.length == 0
) {
return sums;
}
let orderSum = 0;
let orderV = 0;
let orderW = 0;
let leviteSum = 0;
let leviteV = 0;
let leviteW = 0;
this.orderData.orderItemVOList.forEach((column, index) => {
orderSum = Decimal.add(orderSum, column.num ?? 0).toNumber();
orderV = Decimal.add(orderV, column.volume ?? 0).toFixed(2);
orderW = Decimal.add(orderW, column.weight ?? 0).toFixed(2);
leviteSum = Decimal.add(
leviteSum,
column.warehouseInInfoVO?.cartonsNum ?? 0
).toNumber();
leviteV = Decimal.add(
leviteV,
column.warehouseInInfoVO?.volume ?? 0
).toFixed(2);
leviteW = Decimal.add(
leviteW,
column.warehouseInInfoVO?.weight ?? 0
).toFixed(2);
});
sums[1] = this.$t(
"下单统计:{orderSum} 箱 {orderV} m³ {orderW} kg 入仓统计:{leviteSum} 箱 {leviteV} m³ {leviteW} kg",
{
orderSum,
orderV,
orderW,
leviteSum,
leviteV,
leviteW,
}
);
return sums;
},
importCityName(id) {
let arr = this.tradeCityList.filter((item) => item.id == id);
return arr.length > 0 ? this.$l(arr[0], "title") : this.$t("");
},
submitForm() {
const { shipmentObj } = this.$attrs;
// 创建拆单审核
createApproval({
applyReason: this.$t("拆单审核"),
approvalStatus: 0,
approvalType: 8,
copyUserId: this.selectedUsers,
orderId: this.currRow.orderId,
shipmentId: shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then((res) => {
this.$emit("getBoxInfo");
this.querySplitGoods();
});
});
},
addShop() {
this.shopForm = {};
this.shopOpen = true;
this.isQuantity = false;
},
// 更改放入品名后触发,计算重量体积等默认值
onProdChange(){
// 根据键值(中文名或者英文名)来获取对应商品的信息,注:这里应该可以采用orderItemId来获取更优,而不是商品名称,同名可能导致异常
let orderItem = this.orderData.orderItemVOList.find(item => item.orderItemId == this.shopForm.orderItemId)
console.log({orderItem})
// 剩余可装箱数,订单入仓箱数 - 订单已装箱数 - 已拆箱数
let leftNum = Decimal(this.currRow.num).minus(this.currRow.installNum).minus(this.totalSplit('num'))
// 剩余箱数
this.$set(this.shopForm, 'leftNum', leftNum)
// 如果主单商品项的入仓箱数小于可装箱数,则取商品项数据
leftNum = Math.min(leftNum, this.mainOrderItem.num)
// 放入箱数
this.$set(this.shopForm, 'num', leftNum)
this.calcAverg()
},
// 按比例计算体积重量的默认值
calcAverg(){
// 装箱比例
const rate = this.shopForm.num / this.mainOrderItem.num
// 放入个数,剩余个数是算不出来的,因为不知道已装数量,所以放入数量只能按照总数的比例计算
this.$set(this.shopForm, 'quantity', Math.ceil(this.mainOrderItem.quantity*rate|| 0 * rate))
// 数量,体积,重量等按照比例给默认值
this.$set(this.shopForm, 'volume', (this.mainOrderItem.volume * rate).toFixed(2))
this.$set(this.shopForm, 'chargeVolume', (this.mainOrderItem.chargeVolume * rate).toFixed(2))
this.$set(this.shopForm, 'weight', (this.mainOrderItem.weight * rate).toFixed(2))
this.$set(this.shopForm, 'chargeWeight', (this.mainOrderItem.chargeWeight * rate).toFixed(2))
this.$set(this.shopForm, 'worth', (this.mainOrderItem.worth * rate).toFixed(2))
},
/*async getSelectData(item) {
await quantityRequired(this.orderData.lineId).then((res) => {
if (res.data) {
this.isQuantity = true;
this.shopRules.putQuantity = [
{
required: true,
message: this.$t("请输入数量(个)"),
trigger: "change",
},
];
} else {
this.isQuantity = false;
delete this.shopRules.putQuantity;
}
});
},*/
shopAdd() {
this.$refs["shopForm"].validate((valid) => {
if (valid) {
// 放入箱数自动计算出来的,所以不需要在做判断了
/*
// 输入箱数大于实装箱数
const total = this.totalSplitNum();
const canSplitNum = Decimal.sub(
this.currRow.num,
this.currRow.installNum
).toNumber();
const remain = Decimal.sub(canSplitNum, total).toNumber();
if (this.shopForm.num > remain) {
this.$message.error(this.$t("放入箱数不能大于总箱数"));
return;
}*/
if (this.shopForm.num === 0) {
this.$message.error(this.$t("放入箱数不能为0"));
return;
}
if (this.shopForm.quantity === 0 && this.isQuantity) {
this.$message.error(this.$t("放入数量(个)不能为0"));
return;
}
let params = {
num: this.shopForm.num,
// quantity: this.shopForm.quantity,
orderItemId: this.shopForm.orderItemId,
orderSplitId: this.splitData.id,
remarks: this.shopForm.remarks,
volume: this.shopForm.volume,
weight: this.shopForm.weight,
chargeWeight: this.shopForm.chargeWeight,
chargeVolume: this.shopForm.chargeVolume,
worth: this.shopForm.worth
};
// 按数量计费的才需要传递数量
if(this.isQuantity){
params.quantity = this.shopForm.quantity
}
createSplitItem(params).then((res) => {
this.$message.success(this.$t("放入成功"));
this.querySplitGoods();
this.$refs["shopForm"].resetFields();
});
this.shopOpen = false;
}
});
},
removeShop(id) {
let that = this;
that.$confirm(this.$t("是否移除货物吗?")).then(function () {
deleteSplitItem(id).then((res) => {
that.$message.success(that.$t("移除成功"));
that.querySplitGoods();
});
});
},
cancelSplit() {
const { shipmentObj } = this.$attrs;
approvalCancel({
applyReason: this.$t("取消审核"),
id: shipmentObj["cabinetSplitInfo"].id,
shipmentId: shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("getBoxInfo");
this.querySplitGoods();
});
});
},
shopCancel() {
this.$refs["shopForm"].resetFields();
this.shopOpen = false;
this.shopForm = {};
},
jumpReviewDetail() {
const { cabinetSplitInfo } = this.$attrs.shipmentObj;
toReviewDetail.apply(this, [cabinetSplitInfo.bpmProcessId]);
this.$emit("closeDialog2", "close");
},
},
};
</script>
<style lang="scss">
.shipping-split-order {
.card-title {
font-size: 18px;
font-weight: bold;
margin-top: 10px;
}
.card-info {
font-size: 16px;
> span {
margin-right: 10px;
}
}
.card {
margin-top: 20px;
}
.btn-header {
width: 90%;
display: flex;
align-items: center;
justify-content: space-between;
margin: 20px 0;
}
.red {
color: #ff3430;
font-size: 15px;
}
.footer_btn {
padding-bottom: 60px;
}
}
</style>
<template>
<div class="startPacking">
<el-card>
<el-row class="content-area">
<!-- 左侧 -->
<el-col :span="6" class="left-area">
<el-row v-for="item in listData" :key="item.id" class="title-info" :class="item.id === tableData.id ? 'selected' : ''">
<div @click="partClick(item)">
<p>{{item.title}}</p>
</div>
<div>
<template v-if="item.secStatistics">
{{getTotlContent(item.secStatistics)}}
</template>
</div>
</el-row>
</el-col>
<!-- 右侧 -->
<el-col :span="18" class="right-area">
<!-- 操作 -->
<el-row class="table-title">
<div>{{$t('当前装柜')}}:{{tableData.title}}</div>
<div>
<template v-if="!isUnderReview">
<el-input v-model="qrCode" :placeholder="$t('请输入二维码/条码编号')" clearable></el-input>
<el-button type="primary" @click="handlerBatchCreate('single')">{{$t('确定')}}</el-button>
<el-button type="primary" @click="handlerClick('batchInput',$t('批量输入'))">{{$t('批量输入')}}</el-button>
<el-button type="primary" @click="handlerClick('correction',$t('装柜纠错'))">{{$t('装柜纠错')}}</el-button>
<el-button type="primary" @click="handlerClick('correctionOrder',$t('批量装柜纠错'))">{{$t('批量装柜纠错')}}</el-button>
</template>
</div>
</el-row>
<!-- 表格 -->
<el-row class="table-content">
<el-table :data="tableData.sectionOrderList" border max-height="500px">
<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">
<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>
<p>{{$t('其他')}}:{{getTotlContent(item)}}</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="num">
<template slot-scope="scope">
{{getTotlContent(scope.row,['num'])}}
</template>
</el-table-column>
<el-table-column :label="$t('实装箱数')" align="center" prop="installNum">
<template slot-scope="scope">
{{ scope.row.installNum }}{{$t('')}}
</template>
</el-table-column>
<el-table-column :label="$t('体积')" align="center" prop="volume">
<template slot-scope="scope">
{{getTotlContent(scope.row,['volume'])}}
</template>
</el-table-column>
<el-table-column :label="$t('重量')" align="center" prop="weight">
<template slot-scope="scope">
{{getTotlContent(scope.row,['weight'])}}
</template>
</el-table-column>
<el-table-column :label="$t('操作')" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="text" size="small" @click="moveOut(scope.row)" v-if="!isUnderReview && scope.row.installNum === 0">{{$t('移出')}}</el-button>
<el-button type="text" size="small" v-if="isShowSplitOrder(scope.row)" @click="handlerSplitOrder(scope.row, 'splitOrder', $t('拆单'))">{{$t('拆单')}}</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-col>
</el-row>
</el-card>
<!-- 统计 -->
<el-row>
<el-col :span="6" class="totle-info">
<div class="count-info">
<p>{{$t('总计')}}:{{getSumData}}</p>
</div>
<div>
<p>{{$t('容量')}}:</p>
<p>{{calcCapacity}}</p>
</div>
<div>{{$t('已装')}} {{getInstallNumCount}} {{$t('箱')}}</div>
</el-col>
</el-row>
<!-- 审核流程 -->
<el-row class="process-area">
<div class="process">
<div>{{$t('审批流程')}}</div>
<work-flow xmlkey="close_container" v-model="selectedUsers"></work-flow>
</div>
<!-- 操作 -->
<div v-if="!isUnderReview">
<el-button type="primary" @click="handlerClick('supplementOrder',$t('补单'))">{{$t('补单')}}</el-button>
<el-button type="primary" @click="applyCloseCabinet">{{$t('封柜申请')}}</el-button>
<el-button type="primary" @click="handlerClick('modifyCabinet',$t('修改柜信息'))">{{$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('closeDialog1')">{{$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>
<!-- 补单 -->
<supplementOrder v-if="dialogConfig.type === 'supplementOrder' && dialogConfig.dialogVisible" v-bind="$attrs" :shipmentObj="shipmentObj" @supplementFinish="supplementFinish" />
<!-- 修改柜信息 -->
<template v-if="dialogConfig.type === 'modifyCabinet' && dialogConfig.dialogVisible">
<el-form ref="modifyForm" :rules="rules" :model="modifyCabinetObj" label-width="80px">
<el-form-item v-if="false" :label="$t('起运仓库')" prop="startWarehouseId">
<el-select v-model="modifyCabinetObj.startWarehouseId" :placeholder="$t('请选择仓库')" filterable>
<el-option v-for="warehouse in $attrs.warehouseList" :key="warehouse.id" :label="$l(warehouse, 'title')" :value="warehouse.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('预装日期')">{{preinstallDate}}</el-form-item>
<el-form-item :label="$t('选择柜型')" prop="cabinetId">
<el-select v-model="modifyCabinetObj.cabinetId" :placeholder="$t('请选择柜型')">
<el-option v-for="item in cabinetList" :label="item.name" :value="item.id" :key="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('柜号')">
<el-input v-model="modifyCabinetObj.cubNo" :placeholder="$t('请输入柜号')" clearable />
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit('modifyForm')">{{$t('下一步')}}</el-button>
<el-button @click="closeDialog2">{{$t('取消')}}</el-button>
</el-row>
</template>
<!-- 装柜纠错 -->
<template v-if="dialogConfig.type === 'correction' && dialogConfig.dialogVisible">
<el-form ref="correctionForm" :rules="rules" :model="correctionObj" label-position="top">
<el-form-item :label="$t('装柜纠错(二维码/条形码编号)')" prop="qrCode">
<el-input v-model="correctionObj.qrCode" :placeholder="$t('请输入二维码/条形码编号')" clearable />
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit('correctionForm')">{{$t('提交')}}</el-button>
<el-button @click="closeDialog2">{{$t('取消')}}</el-button>
</el-row>
</template>
<!-- 批量装柜纠错(订单号) -->
<template v-if="dialogConfig.type === 'correctionOrder' && dialogConfig.dialogVisible">
<el-form ref="orderForm" :rules="rules" :model="orderObj" label-position="top">
<el-form-item :label="$t('装柜纠错') +'(' + $t('订单号') + ')'" prop="orderNo">
<el-input type="textarea" :rows="3" v-model="orderObj.orderNo" :placeholder="$t('请输入,多个以逗号分隔')" clearable />
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit('orderForm')">{{$t('提交')}}</el-button>
<el-button @click="closeDialog2">{{$t('取消')}}</el-button>
</el-row>
</template>
<!-- 装柜批量输入 -->
<template v-if="dialogConfig.type === 'batchInput' && dialogConfig.dialogVisible">
<el-form ref="batchForm" :rules="rules" :model="batchObj">
<el-form-item label="" prop="qrCode" class="two-element">
<el-input v-model="batchObj.qrCode" :placeholder="$t('请输入订单号')" clearable />
<el-button style="marginLeft:10px;" type="primary" @click="queryOrderInfo">{{$t('确定')}}</el-button>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('订单号')">
{{boxOrderInfo.orderNo}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('箱数')">
<el-input-number v-if="boxOrderInfo.isExternalWarehouse === 1" v-model="batchObj.boxNum" :min="0" :max="boxOrderInfo.num" />
<template v-else>
{{boxOrderInfo.num}}
</template>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('方数')">
{{getTotlContent(boxOrderInfo, ['volume'])}}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('重量')">
{{getTotlContent(boxOrderInfo, ['weight'])}}
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row class="operate-button">
<el-button type="primary" :disabled="boxOrderInfo.orderId ? false : true" @click="batchLoad">{{$t('提交')}}</el-button>
<el-button @click="closeDialog2">{{$t('取消')}}</el-button>
</el-row>
</template>
<!-- 拆单 -->
<splitOrder v-bind="$attrs" v-on="$listeners" :shipmentObj="shipmentObj" v-if="dialogConfig.type === 'splitOrder' && dialogConfig.dialogVisible" :currRow="currRow" @closeDialog2="closeDialog2" />
</el-dialog>
</div>
</template>
<script>
import dayjs from "dayjs";
import supplementOrder from "./supplementOrder.vue";
import { getCabinetPage } from "@/api/ecw/cabinet";
import { getbox } from "@/api/ecw/box";
import {
loadSecGoodsList,
orderTagList,
singleCreate,
batchCreate,
singleDelete,
batchDelete,
remove,
boxUpdate,
approvalCreate,
approvalCancel,
getOrderDetailByBoxNo,
externalLoad,
} from "@/api/ecw/boxSea";
import {
getTotlContent,
serviceMsg,
getCapacity,
sumStatistics,
toReviewDetail,
} from "../../utils";
import splitOrder from "./splitOrder.vue";
import WorkFlow from "@/components/WorkFlow";
import Decimal from "decimal.js";
/**
* 开始装柜
*/
export default {
name: "startPacking",
inheritAttrs: false,
components: {
supplementOrder,
splitOrder,
WorkFlow,
},
props: {
shipmentObj: Object,
},
data() {
return {
// 表格数据
listData: [],
// 表格数据
tableData: {},
// 弹窗配置
dialogConfig: {
title: "",
dialogVisible: false,
width: "30%",
type: "",
fullscreen: false,
},
// 已装/未装
orderList: [],
// 柜型
cabinetList: [],
// 二维码/条码编号
qrCode: "",
// 批量输入
batchObj: {
boxNum: 0,
},
// 批量纠错(订单号)
orderObj: {},
// 纠错
correctionObj: {},
// 修改柜信息
modifyCabinetObj: {},
// 修改柜信息校验
rules: {
startWarehouseId: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
cabinetId: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
qrCode: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
orderNo: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
},
// 当前行
currRow: {},
selectedUsers: [],
// 订单信息
boxOrderInfo: {},
newshipmentObj: {}
};
},
created() {
this.getLoadSecGoodsList();
// 柜型
getCabinetPage(null).then((response) => {
this.cabinetList = response.data.list;
});
// this.getBoxInfo()
},
methods: {
getTotlContent,
getBoxInfo() {
getbox(this.shipmentObj.id).then((res) => {
const { data } = res;
this.newshipmentObj = data ?? {};
});
},
/* 装柜部分列表 */
getLoadSecGoodsList() {
loadSecGoodsList({ shipmentId: this.shipmentObj.id }).then((res) => {
const { data = [] } = res;
this.listData = data.map((item, index) => {
return {
...item,
title: this.$t("第{index}部分", { index: 1 + index }),
};
});
if (this.listData.length) {
this.tableData = this.listData[0];
}
});
},
/** 点击事件统一入口 */
handlerClick(type, title) {
this.shwoDialog({ type, title });
},
/* 拆单 */
handlerSplitOrder(row, type, title) {
this.currRow = row;
this.shwoDialog({ type, title });
},
/** 表格订单号点击 */
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.unLoadList[index],
});
}
});
this.shwoDialog({
type: "orderTable",
title: row.selfNo,
});
},
/** 弹窗事件 */
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);
},
/** 关闭弹窗 */
closeDialog2() {
this.$set(this.dialogConfig, "dialogVisible", false);
},
/** 修改提交 */
onSubmit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
if (formName === "batchForm") {
this.handlerBatchCreate("batch");
}
if (formName === "correctionForm") {
this.handlerBatchDelete(
{
orderNumCode: this.correctionObj.qrCode,
},
"single"
);
}
if (formName === "orderForm") {
this.handlerBatchDelete(
{ orderNo: this.orderObj.orderNo },
"batch"
);
}
if (formName === "modifyForm") {
this.modifyBoxUpdate();
}
}
});
},
/* 部分点击 */
partClick(item) {
this.tableData = item;
},
/* 装柜 */
handlerBatchCreate(type) {
let params = {
shipmentId: this.shipmentObj.id,
secId: this.tableData.id,
};
if (type === "single") {
if (!this.qrCode) {
this.$message.error(this.$t("请输入二维码/条码编号"));
return;
}
params.orderNumCode = this.qrCode;
singleCreate(params).then((res) => {
serviceMsg(res, this).then(() => {
this.qrCode = "";
this.getLoadSecGoodsList();
});
});
} else {
params.orderNo = this.batchObj.qrCode;
batchCreate(params).then((res) => {
serviceMsg(res, this).then(() => {
this.closeDialog2();
this.getLoadSecGoodsList();
});
});
}
},
/* 删除已装柜 */
handlerBatchDelete(params, type) {
params = {
shipmentId: this.shipmentObj.id,
secId: this.tableData.id,
...params,
};
if (type === "single") {
singleDelete(params).then((res) => {
serviceMsg(res, this).then(() => {
this.closeDialog2();
this.getLoadSecGoodsList();
});
});
} else {
batchDelete(params).then((res) => {
serviceMsg(res, this).then(() => {
this.closeDialog2();
this.getLoadSecGoodsList();
});
});
}
},
/* 移出 */
moveOut(row) {
let params = {
shipmentId: this.shipmentObj.id,
secId: this.tableData.id,
orderId: row.orderId,
};
remove(params).then((res) => {
serviceMsg(res, this).then(() => {
this.getLoadSecGoodsList();
});
}).catch((res) => {
if (res.code === 666) {
this.$confirm("<div style='max-height:500px;overflow:auto'>"+res.msg+this.$t('是否需要一起移出?')+"</div>", this.$t("提示"), {
dangerouslyUseHTMLString: true,
distinguishCancelAndClose: true,
confirmButtonText: '确定移出',
cancelButtonText: '仅移出当前订单'
})
.then((_) => {
remove({ ...params, deleteType: 2 }).then((res) => {
serviceMsg(res, this).then(() => {
this.getLoadSecGoodsList();
});
});
})
.catch(action => {
if(action =='cancel'){
remove({ ...params, deleteType: 1 }).then((res) => {
serviceMsg(res, this).then(() => {
this.getLoadSecGoodsList();
});
});
}
});
}
});
},
/* 修改柜信息 */
modifyBoxUpdate() {
let params = {
shipmentId: this.shipmentObj.id,
...this.modifyCabinetObj,
};
boxUpdate(params).then((res) => {
serviceMsg(res, this);
// this.getBoxInfo()
this.$emit('getBoxInfo')
this.closeDialog2();
});
},
/* 补单完成 */
supplementFinish() {
this.closeDialog2();
this.getLoadSecGoodsList();
},
/* 申请封柜 */
applyCloseCabinet() {
approvalCreate({
applyReason: this.$t("封柜审核"),
approvalStatus: 0,
approvalType: 2, // 封柜
copyUserId: this.selectedUsers,
shipmentId: this.shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("closeDialog1", "submit");
});
});
},
/* 是否显示拆单 */
isShowSplitOrder(row) {
if (row.num > row.installNum && row.installNum !== 0) {
return true;
}
return false;
},
/* 取消审核 */
canclAudit() {
approvalCancel({
applyReason: this.$t("取消审核"),
id: this.shipmentObj["cabinetApprovalInfo"].id,
shipmentId: this.shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("closeDialog1", "submit");
});
});
},
/* 跳转详情 */
jumpReviewDetail() {
const { cabinetApprovalInfo } = this.shipmentObj;
toReviewDetail.apply(this, [cabinetApprovalInfo.bpmProcessId]);
this.$emit("closeDialog1", "close");
},
queryOrderInfo() {
this.$refs["batchForm"].validate((valid) => {
if (valid) {
getOrderDetailByBoxNo({
orderNumCode: this.batchObj.qrCode,
shipmentId: this.shipmentObj.id,
}).then((res) => {
const { data } = res;
this.boxOrderInfo = data;
this.batchObj.boxNum = Number(data.num);
});
}
});
},
batchLoad() {
if (!this.boxOrderInfo.orderId) {
this.$message.error(this.$t("请输入订单号"));
return;
}
if (this.batchObj.boxNum === 0) {
this.$message.error(this.$t("箱数不能为0"));
return;
}
let params = {
boxNum: this.boxOrderInfo.num,
orderId: this.boxOrderInfo.orderId,
orderNo: this.boxOrderInfo.orderNo,
shipmentId: this.shipmentObj.id,
};
if (this.boxOrderInfo.isExternalWarehouse === 1) {
params.boxNum = this.batchObj.boxNum;
}
externalLoad(params).then((res) => {
serviceMsg(res, this).then(() => {
this.closeDialog2();
this.boxOrderInfo = {};
this.getLoadSecGoodsList();
});
});
},
},
computed: {
/* 是否审核中 */
isUnderReview() {
const { currNode } = this.$attrs;
return this.shipmentObj[currNode.keyName] === 44 ? true : false;
},
/* 预计时间 */
preinstallDate() {
if (this.shipmentObj.preInstallInfo.createTime) {
return dayjs(this.shipmentObj.preInstallInfo.createTime).format(
"YYYY-MM-DD HH:mm:ss"
);
}
return null;
},
/* 容量 */
calcCapacity() {
const { cabinetRespVO } = this.shipmentObj;
return getCapacity(cabinetRespVO);
},
/* 总计 */
getSumData() {
return sumStatistics(this.listData);
},
/* 已装总数 */
getInstallNumCount() {
let count = 0;
if (Array.isArray(this.listData)) {
this.listData.forEach((item) => {
const { sectionOrderList = [] } = item;
sectionOrderList.forEach((item) => {
count = Decimal.add(count, item.installNum).toNumber();
});
});
}
return count;
},
},
};
</script>
<style lang="scss" scoped>
.startPacking {
display: flex;
flex-direction: column;
p {
margin: 0;
}
.content-area {
display: flex;
.left-area {
border-right: 3px solid #e6ebf5;
padding-right: 10px;
.title-info {
height: 80px;
&.selected {
> div:first-child {
background-color: #4f9cdd;
color: #fff;
}
}
> div:first-child {
font-size: 16px;
background-color: #f2f2f2;
line-height: 30px;
text-align: center;
cursor: pointer;
}
> :last-child {
display: flex;
> p {
margin-right: 10px;
color: #4f9cdd;
}
}
}
}
.right-area {
padding-left: 10px;
.table-title {
display: flex;
align-items: center;
margin-bottom: 10px;
> div:first-child {
flex: 1;
font-size: 16px;
}
> div:last-child {
display: flex;
> .el-input {
margin-right: 10px;
}
}
}
.table-content {
.table-goodList {
.goodList-div {
border-bottom: 1px solid #e6ebf5;
> p {
text-align: left;
}
> p:last-child {
> span {
margin-right: 5px;
}
}
}
> div:last-child {
border-bottom: none;
}
}
.el-table {
color: red;
}
}
}
}
.totle-info {
font-size: 20px;
margin-top: 15px;
> div {
display: flex;
margin-bottom: 5px;
}
.count-info {
> p > span {
margin-right: 5px;
}
}
}
.process-area {
margin-top: 15px;
padding-bottom: 30px;
.process {
display: flex;
flex-direction: column;
> :first-child {
color: #606266;
font-weight: bolder;
font-size: 16px;
}
}
}
}
</style>
<template>
<div class="supplementOrder">
<el-card>
<!-- 内容区 -->
<el-row class="content-area">
<!-- 左侧 -->
<el-col :span="6" class="left-area">
<el-row>
<el-button type="primary" @click="addPart">{{$t('新增')}}</el-button>
<el-button type="danger" @click="deletePart">{{$t('删除')}}</el-button>
</el-row>
<el-scrollbar style="height:calc(100% - 40px)">
<el-row v-for="item in partList" :key="item.id" class="title-info" :class="item.id === partData.id ? 'selected' : ''">
<div @click="partClick(item)">
<p>{{item.title}}</p>
</div>
<el-collapse-transition>
<div v-if="item.fold === false ? true : false">
<div v-for="(secGoog, index) in item.sectionOrderList" :key="index" class="part-secGoog">
<p>{{secGoog.orderNo}}</p>
<p>{{secGoog.prodTitleZh}}</p>
<div>
<i class="el-icon-delete" @click="deleteOrder(secGoog)"></i>
</div>
</div>
</div>
</el-collapse-transition>
<div class="part-secGoog">
<template>
{{getTotlContent(item.secStatistics)}}
</template>
</div>
</el-row>
</el-scrollbar>
</el-col>
<!-- 右侧 -->
<el-col :span="18" class="right-area">
<el-row class="right-title">
<div>{{$t('货物筛选')}}</div>
<div>{{$t('当前装柜')}}:{{partData.title}}</div>
<div>{{$t('可预装方数')}}:{{unloadStatistics.volume}}m³,{{$t('重量')}}:{{unloadStatistics.weight}}Kg</div>
</el-row>
<!-- 搜索工作栏 -->
<el-row>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px">
<el-form-item :label="$t('始发地')">
<p>{{importCityName(queryParams.startWarehouseId)}}</p>
</el-form-item>
<el-form-item :label="$t('目的地')" prop="destination">
<el-select v-model="queryParams.destWarehouseIdList" :placeholder="$t('请选择目的地')" multiple>
<el-option v-for="item in importWarehouseList" :label="item.titleZh" :value="item.id" :key="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('订单号')" prop="orderNo">
<el-input v-model="queryParams.orderNo" :placeholder="$t('请输入订单号')" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="queryAllData">{{$t('搜索')}}</el-button>
</el-form-item>
</el-form>
</el-row>
<!-- 表格 -->
<el-scrollbar style="height:calc(100% - 164px)">
<el-row v-for="(item, index) in toBePreList" :key="index" class="toBePre-table">
<el-row class="table-title">
<div>{{item.orderNo}}</div>
<div>{{$t('发往')}}:{{item.destWarehouseName}}</div>
<div :class="item.customsType !== 1 ? 'custom_type_red' : ''">
<dict-tag :type="DICT_TYPE.ECW_CUSTOMS_TYPE" :value="item.customsType" />
</div>
<div>{{$t('入仓时间')}}:{{formatDate(item.rucangTime)}}</div>
<div>
<el-button type="text" @click="handleGoods('all', item)">[{{$t('全部预装')}}]</el-button>
<el-button type="text" @click="foldTable(index, item)">[{{item.fold ? $t('展开') : $t('收起')}}]</el-button>
</div>
</el-row>
<el-collapse-transition>
<div v-show="!item.fold">
<el-table v-loading="loading" :data="item.boxOrderItemList" border>
<el-table-column :label="$t('序号')" type="index" align="center" width="50" />
<el-table-column :label="$t('品名')" align="center" prop="" min-width="500">
<template slot-scope="{row}">
{{$l(row,'prodTitle')}}
</template>
</el-table-column>
<el-table-column :label="$t('品牌')" align="center" prop="brandType" width="120">
<template slot-scope="scope">
<template v-if="scope.row.brandName">{{scope.row.brandName}}</template>
<dict-tag v-else :type="DICT_TYPE.ECW_IS_BRAND" :value="scope.row.feeType" />
</template>
</el-table-column>
<el-table-column :label="$t('箱数')" align="center" prop="num" width="120" />
<el-table-column :label="$t('体积')" align="center" prop="volume" width="120">
<template slot-scope="scope">
<p v-if="scope.row.volume">{{getTotlContent(scope.row,['volume'])}}</p>
</template>
</el-table-column>
<el-table-column :label="$t('重量')" align="center" prop="weight" width="120">
<template slot-scope="scope">
<p v-if="scope.row.weight">{{getTotlContent(scope.row,['weight'])}}</p>
</template>
</el-table-column>
<!-- <el-table-column :label="$t('预装柜')"
align="center"
prop=""
width="120">{{ $t('无返回') }}</el-table-column> -->
<el-table-column :label="$t('操作')" align="center" class-name="small-padding fixed-width" width="100">
<template slot-scope="scope">
<el-button type="text" size="small" @click="handleGoods('singele',scope.row)">{{$t('预装')}}</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-collapse-transition>
</el-row>
</el-scrollbar>
<!-- 分页 -->
<el-pagination background layout="prev, pager, next" :page-size="pageParam.pageSize" :total="total" @current-change="pageChange" v-show="total > 0"></el-pagination>
</el-col>
</el-row>
</el-card>
<el-row>
<el-col :span="6" class="totle-info">
<div>
<p>{{$t('总计')}}:</p>
<p>{{sumStatistics(partList)}}</p>
</div>
<div>
<p>{{$t('容量')}}:</p>
<p>{{calcCapacity}}</p>
</div>
</el-col>
</el-row>
<el-row class="button-area">
<el-button type="primary" @click="handlerFinish">{{$t('完成')}}</el-button>
</el-row>
</div>
</template>
<script>
import {
loadSecGoodsList,
preloadPage,
createSection,
deleteSection,
createGoods,
remove,
} from "@/api/ecw/boxSea";
import {
formatDate,
getTotlContent,
serviceMsg,
getCapacity,
sumStatistics,
} from "../../utils";
/**
* 补单
*/
export default {
name: "supplementOrder",
inheritAttrs: false,
data() {
return {
// 二维码/条码编号
cabinetNo: "",
// 表格数据
listData: [],
// 选中部分
partData: {},
// 部分列表
partList: [],
// 部分统计
loadStatistics: {},
// 查询参数
queryParams: {
startWarehouseId: this.$attrs.shipmentObj.startWarehouseId,
},
pageParam: { pageNo: 1, pageSize: 10 },
// 待预装
toBePreList: [],
total: 0,
loading: false,
unloadStatistics: {},
};
},
created() {
this.queryAllData();
},
methods: {
/* 查询已预装 */
getSecGoods() {
loadSecGoodsList({ shipmentId: this.$attrs.shipmentObj.id }).then(
(res) => {
this.partList = res.data.map((item, index) => {
item.fold = true;
if (
Object.keys(this.partData).length &&
this.partData.id === item.id
) {
item.fold = false;
}
return {
...item,
title: this.$t("第{index}部分", { index: index + 1 }),
};
});
if (this.partList.length && !Object.keys(this.partData).length) {
this.partList[0].fold = false;
this.partData = this.partList[0];
}
}
);
},
/* 查询待预装 */
getPreLoad() {
this.loading = true;
// 处理查询参数
let params = {
...this.queryParams,
};
preloadPage({ ...params, ...this.pageParam }).then((res) => {
const { data } = res;
this.toBePreList = data.dataList?.list ?? [];
this.total = data.dataList?.total ?? 0;
this.unloadStatistics = data.unloadStatistics ?? {};
this.loading = false;
});
},
/* 删除订单 */
deleteOrder(data) {
let params = {
secId: this.partData.id,
shipmentId: this.$attrs.shipmentObj.id,
orderId: data.orderId,
};
remove(params).then((res) => {
serviceMsg(res, this).then(() => {
this.getSecGoods();
});
}).catch((res) => {
if (res.code === 666) {
this.$confirm(res.msg+this.$t('是否需要一起移出?'), this.$t("提示"), {
dangerouslyUseHTMLString: true,
distinguishCancelAndClose: true,
confirmButtonText: '确定移出',
cancelButtonText: '仅移出当前订单'
})
.then((_) => {
remove({ ...params, deleteType: 2 }).then((res) => {
serviceMsg(res, this).then(() => {
this.getSecGoods();
});
});
})
.catch(action => {
if(action =='cancel'){
remove({ ...params, deleteType: 1 }).then((res) => {
serviceMsg(res, this).then(() => {
this.getSecGoods();
});
});
}
});
}
});
},
/** 预装 */
handleGoods(type, item) {
let params = {
secId: this.partData.id,
shipmentId: this.$attrs.shipmentObj.id,
orderId: item.orderId,
};
if (type === "all") {
params.orderItemIdList = item.boxOrderItemList.map(
(data) => data.orderItemId
);
} else {
params.orderItemIdList = [item.orderItemId];
}
createGoods(params)
.then((res) => {
const { data } = res;
if (data.relationMsg) {
const msg = data.relationMsg.replaceAll(",", "");
this.$confirm(msg, this.$t("提示"), {
dangerouslyUseHTMLString: true,
type: "warning",
})
.then((_) => {
loadRelationOrder(data).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch((_) => {
this.queryAllData();
});
} else {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
}
})
.catch((res) => {
if (res.code === 555) {
const msg = res.msg && res.msg.replaceAll(",", "");
this.$confirm(msg, this.$t("提示"), {
dangerouslyUseHTMLString: true,
type: "warning",
})
.then((_) => {
createGoods({ ...params, relationStatus: 1 }).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch((_) => {
this.queryAllData();
});
}
if (res.code === 566) {
this.$confirm(res.msg+this.$t('是否需要一起预装?'), this.$t("提示"), {
dangerouslyUseHTMLString: true,
type: "warning",
})
.then((_) => {
createGoods({ ...params, relationStatus: 2 }).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch((_) => {
this.queryAllData();
});
}
});
},
/* 增加部分 */
addPart() {
createSection({
shipmentId: this.$attrs.shipmentObj.id,
isCover: 1,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.getSecGoods();
});
});
},
/* 删除部分 */
deletePart() {
this.$confirm(
this.$t("确认删除该部分及其已预装订单?"),
this.$t("提示"),
{
type: "warning",
}
)
.then((_) => {
let params = {
id: this.partData.id,
deleteType: 2
};
deleteSection(params).then((res) => {
serviceMsg(res, this).then(() => {
this.partData = {};
this.getSecGoods();
});
});
})
.catch((_) => {});
},
/* 部分点击 */
partClick(item) {
item.fold = !item.fold;
this.partData = item;
let copyList = [...this.partList];
copyList = copyList.map((cItem) => {
cItem.fold = true;
if (item.id === cItem.id) {
cItem.fold = false;
return cItem;
}
});
this.$set(this.partList, copyList);
},
/* 获取城市 */
importCityName(id) {
var arr = this.$attrs.warehouseList.filter((item) => item.id == id);
return arr.length > 0 ? this.$l(arr[0], "title") : this.$t("");
},
/* 待预装订单分页 */
pageChange(page) {
this.pageParam.pageNo = page;
this.getPreLoad();
},
/* 折叠 */
foldTable(index, item) {
item.fold = !item.fold;
this.$set(this.toBePreList, index, item);
},
/* 查询所有数据 */
queryAllData() {
this.getSecGoods();
this.pageParam.pageNo = 1;
this.getPreLoad();
},
/* 完成 */
handlerFinish() {
this.$confirm(this.$t("确定执行操作?"), this.$t("提示"), {
type: "warning",
})
.then((_) => {
this.$emit("supplementFinish");
})
.catch((_) => {});
},
formatDate,
getTotlContent,
sumStatistics,
},
computed: {
/** 目的地 */
importWarehouseList() {
return this.$attrs.warehouseList.filter(
(item) => item.tradeType == "1" || item.type == "3"
);
},
/* 容量 */
calcCapacity() {
const { cabinetRespVO } = this.$attrs.shipmentObj;
return getCapacity(cabinetRespVO);
},
},
};
</script>
<style lang="scss">
.supplementOrder {
display: flex;
flex-direction: column;
p {
margin: 0;
}
.el-card__body {
height: 100%;
}
.content-area {
display: flex;
height: 100%;
.left-area {
border-right: 3px solid #e6ebf5;
.el-scrollbar__view {
padding-right: 10px;
}
.title-info {
margin-top: 10px;
height: auto;
&.selected {
> div:first-child {
background-color: #4f9cdd;
color: #fff;
}
}
> div:first-child {
font-size: 16px;
background-color: #f2f2f2;
line-height: 30px;
text-align: center;
cursor: pointer;
}
.part-secGoog {
margin-top: 5px;
display: flex;
align-items: center;
> p {
margin-right: 10px;
color: #4f9cdd;
}
> div {
flex: 1;
text-align: right;
> i {
cursor: pointer;
color: red;
}
}
}
}
}
.right-area {
padding-left: 10px;
.right-title {
display: flex;
align-items: center;
margin-bottom: 10px;
font-size: 16px;
> div:first-child {
font-size: 18px;
}
> div:first-child + div {
margin-left: 20px;
}
> div:last-child {
flex: 1;
text-align: right;
font-size: 18px;
color: red;
}
}
.table-title {
display: flex;
align-items: center;
line-height: 30px;
background-color: #4f9cdd;
color: #fff;
> div {
margin-left: 10px;
}
> div:last-child {
flex: 1;
display: flex;
justify-content: flex-end;
> .el-button--text {
color: #fff;
}
> .el-button--text:last-child {
margin-right: 10px;
}
}
}
.el-pagination {
margin-top: 10px;
padding: 0;
text-align: right;
}
.toBePre-table {
margin-bottom: 10px;
}
}
}
.totle-info {
font-size: 20px;
margin-top: 15px;
> div {
display: flex;
margin-bottom: 5px;
}
}
.button-area {
text-align: center;
}
}
</style>
<template>
<div>
<el-form ref="cDocForm" :model="cDocObj" label-width="100px">
<el-form-item :label="$t('出单方式')">
<el-select v-model="cDocObj.cdOutBillType" :placeholder="$t('请选择出单方式')">
<el-option v-for="item in method" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<template v-if="cDocObj.cdOutBillType === '1'">
<el-form-item :label="$t('电放时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cDocObj.cdElectricTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('电放凭证附件')">
<FileUpload :limit="1" :isShowTip=false v-model="cDocObj.cdElectricVoucher" :fileType="fileType" />
</el-form-item>
</template>
<template v-if="cDocObj.cdOutBillType === '2'">
<el-form-item :label="$t('寄送时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cDocObj.cdSendTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('快递单号')">
<el-input v-model="cDocObj.cdBillNo" :placeholder="$t('请输入快递单号')"></el-input>
</el-form-item>
</template>
<el-form-item label="agent list">
<el-radio-group v-model="cDocObj.cdAgentlistType">
<el-radio v-for="item in status" :key="item.value" :label="item.value">{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cDocObj.cdAgentlistTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item>
<FileUpload :limit="1" :isShowTip=false v-model="cDocObj.cdAgentlistFile" :fileType="fileType" />
</el-form-item>
<el-form-item label="soncap">
<el-radio-group v-model="cDocObj.cdSoncapType">
<el-radio v-for="item in status" :key="item.value" :label="item.value">{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cDocObj.cdSoncapTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item>
<FileUpload :limit="1" :isShowTip=false v-model="cDocObj.cdSoncapFile" :fileType="fileType" />
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { clearanceDocCreate } from "@/api/ecw/boxSea";
import {
constantDict,
formatDateStr,
formatNumberString,
fileTypes,
serviceMsg,
} from "../utils";
import FileUpload from "@/components/FileUpload";
/**
* 清关文件
*/
export default {
name: "clrDocument",
inheritAttrs: false,
components: { FileUpload },
data() {
return {
// 清关文件对象
cDocObj: {},
// 出单方式
method: constantDict.billingMethod,
// 选项
status: constantDict.isFile,
// 文件类型
fileType: fileTypes,
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, [
"cdElectricTime",
"cdSendTime",
"cdAgentlistTime",
"cdSoncapTime",
]);
oldData = formatNumberString(oldData, [
"cdOutBillType",
"cdAgentlistType",
"cdSoncapType",
]);
this.cDocObj = {
...oldData,
cdOutBillType:
oldData.cdOutBillType === 0 ? undefined : oldData.cdOutBillType,
};
if(!this.$attrs.shipmentObj.clearanceDocInfo){
this.$set(this.cDocObj,'cdOutBillType',this.$attrs.shipmentObj.clearanceDocInfo?.cdOutBillType||undefined)
}
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["cDocForm"].validate((valid) => {
if (valid) {
clearanceDocCreate({
...this.cDocObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<el-select filterable :value="value === 0 ? undefined : value" @change="change" v-bind="$attrs" clearable>
<el-option v-for="dock in getDock" :key="dock.id" :label="$l(dock, 'title')" :value="dock.id"></el-option>
</el-select>
</template>
<script>
/**
* 码头
*/
export default {
name: "dockSelect",
inheritAttrs: false,
props: {
value: Number,
allDocks: Array,
portType: String
},
model: {
prop: "value",
event: "change",
},
data() {
return {};
},
computed: {
getDock() {
if(!this.portType) return this.allDocks;
return this.allDocks.filter(item=>item.portType==this.portType)
},
},
methods: {
change(val) {
this.$emit("change", val);
},
},
};
</script>
<template>
<el-select filterable :value="company === 0 ? undefined : company" @change="change" v-bind="$attrs" clearable>
<el-option v-for="user in getUser" :key="user.id" :value="user.id" :label="$l(user, 'company')"></el-option>
</el-select>
</template>
<script>
/**
* 用户
*/
export default {
name: "userSelect",
inheritAttrs: false,
props: {
value: Number | Array,
allUsers: Array,
},
model: {
prop: "value",
event: "change",
},
data() {
return {};
},
computed: {
getUser() {
this.allUsers.forEach(element => {
if(!element.companyEn) {
element.companyEn = element.companyZh
}
});
return this.allUsers;
},
company: {
get() {
return this.value
},
set(val) {
this.$emit("change", val);
}
}
},
created() {
this.company = this.value
let com = this.getUser.findIndex(item=>item.id==this.company)
if(com == -1){
this.company = 0
}
},
methods: {
change(val) {
this.$emit("change", val);
},
},
};
</script>
<template>
<el-select
filterable
:value="value === 0 ? undefined : value"
@change="change"
v-bind="$attrs"
clearable
>
<el-option
v-for="supplier in getSuppliers"
:key="supplier.id"
:label="$l(supplier, 'company')"
:value="supplier.id"
></el-option>
</el-select>
</template>
<script>
/**
* 供应商
*/
export default {
name: "supplierSelect",
props: {
companyType: String,
value: Number,
allSupplier: Array,
areaType: {
type: Number,
default: 0
},
},
model: {
prop: "value",
event: "change",
},
data() {
return {};
},
computed: {
getSuppliers() {
let allSupplier = this.allSupplier.filter(
(item) => item.areaType == this.areaType
);
if(this.areaType == 1 || !this.companyType) return allSupplier;
return allSupplier.filter((item) =>
item.companyTypes.includes(this.companyType)
);
},
},
methods: {
change(val) {
this.$emit("change", val);
},
},
};
</script>
<template>
<el-select filterable :value="value === 0 ? undefined : value" @change="change" v-bind="$attrs" clearable>
<el-option v-for="user in getUser" :key="user.id" :value="user.id" :label="user.nickname"></el-option>
</el-select>
</template>
<script>
/**
* 用户
*/
export default {
name: "userSelect",
inheritAttrs: false,
props: {
value: Number | Array,
allUsers: Array,
},
model: {
prop: "value",
event: "change",
},
data() {
return {};
},
computed: {
getUser() {
return this.allUsers;
},
},
methods: {
change(val) {
this.$emit("change", val);
},
},
};
</script>
<template>
<div>
<el-form ref="cusClearanceForm" :rules="rules" :model="cusClearanceObj" label-width="120px">
<el-form-item :label="$t('清关代理')">{{getClAgent('label')}}</el-form-item>
<el-form-item :label="$t('预计清关时间')" prop="clEstTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cusClearanceObj.clEstTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('清关时间')" prop="clClearTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="cusClearanceObj.clClearTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
<p class="message-area" v-show="showMsg">{{$t('清关时间与预计时间不符,如有异常请登记')}}</p>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button type="primary" @click="exceptionReg" :disabled="!showMsg">{{$t('异常登记')}}</el-button>
</el-row>
<!-- 对话框 -->
<el-dialog custom-class="shipping-dialog" :title="$t('票异常')" :visible.sync="dialogVisible" width="700px" :modal-append-to-body=false append-to-body destroy-on-close>
<regError @closeDialog="dialogVisible = false" v-bind="$attrs" />
</el-dialog>
</div>
</template>
<script>
import regError from "../../regError";
import dayjs from "dayjs";
import { clearanceCreate } from "@/api/ecw/boxSea";
import { formatDateStr, serviceMsg } from "../utils";
/**
* 清关
*/
export default {
name: "cusClearance",
inheritAttrs: false,
components: {
regError,
},
data() {
return {
// 清关对象
cusClearanceObj: {},
// 校验
rules: {
clEstTime: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
clClearTime: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
},
// 弹窗配置
dialogVisible: false,
// 提示消息
showMsg: false,
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, ["clEstTime"]);
oldData = formatDateStr(oldData, ["clClearTime"], "YYYY-MM-DD HH:mm:ss");
this.cusClearanceObj = oldData;
},
watch: {
// 预计清关时间
"cusClearanceObj.clEstTime"(val) {
this.compareDate(val, this.cusClearanceObj.clClearTime);
},
// 清关时间
"cusClearanceObj.clClearTime"(val) {
this.compareDate(this.cusClearanceObj.clEstTime, val);
},
},
methods: {
getClAgent(type) {
const agentId = this.$attrs.shipmentObj.agentInfo.agentId;
if (type === "label") {
const selected = this.$attrs.allSupplier.find(
(item) => item.id === agentId
);
return this.$l(selected, "company") ?? agentId;
}
return agentId;
},
// 时间比较
compareDate(clEstTime, clClearTime) {
this.showMsg = false;
let date1 = null,
date2 = null;
if (clEstTime) date1 = dayjs(clEstTime);
if (clClearTime) date2 = dayjs(clClearTime);
if (date1 && date2 && !date2.isSame(date1)) {
this.showMsg = true;
}
},
// 异常登记
exceptionReg() {
this.dialogVisible = true;
},
/** 提交 */
onSubmit(operateType) {
this.$refs["cusClearanceForm"].validate((valid) => {
if (valid) {
clearanceCreate({
...this.cusClearanceObj,
shipmentId: this.$attrs.shipmentObj.id,
clAgentId: this.getClAgent(),
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
.message-area {
margin: 0;
color: red;
}
</style>
<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) {
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) {
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>
<template>
<div class="app-departure">
<el-form ref="departureForm" :rules="rules" :model="departureObj" label-width="120px">
<el-form-item :label="$t('预计开船时间')">
{{getSailingTime()}}
</el-form-item>
<el-form-item :label="$t('实际开船时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="departureObj.dtRealShipTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
<p class="message-area">{{$t('订单状态与短信通知,将到指定时间更新与发送')}}</p>
<p class="message-area" v-show="showMsg">{{$t('实际开船实际与预计时间不符')}}</p>
</el-form-item>
<el-form-item :label="$t('预期到港时间')" prop="dtEstArrivalTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="departureObj.dtEstArrivalTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button type="primary" @click="exceptionReg" :disabled="!isShowError">{{$t('异常登记')}}</el-button>
</el-row>
<!-- 对话框 -->
<el-dialog custom-class="shipping-dialog" :title="$t('票异常')" :visible.sync="dialogVisible" width="700px" :modal-append-to-body=false append-to-body destroy-on-close>
<regError @closeDialog="regCloseDialog" v-bind="$attrs" />
</el-dialog>
</div>
</template>
<script>
import regError from "../../regError";
import { shippingCreate } from "@/api/ecw/boxSea";
import dayjs from "dayjs";
import { formatDateStr, serviceMsg } from "../utils";
/**
* 起运
*/
export default {
name: "departure",
inheritAttrs: false,
components: { regError },
data() {
return {
// 起运对象
departureObj: {},
// 校验
rules: {
dtEstArrivalTime: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
},
// 弹窗配置
dialogVisible: false,
// 提示消息
showMsg: false,
// 异常登记
isShowError: false,
inspectionTimeShipping: this.getDictDatas(
this.DICT_TYPE.BOX_INSPECTION_TIME_SHIPPING
)[0].value,
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, ["dtRealShipTime"], "YYYY-MM-DD HH:mm:ss");
oldData = formatDateStr(oldData, ["dtEstArrivalTime"]);
this.departureObj = oldData;
},
watch: {
// 实际开船时间
"departureObj.dtRealShipTime"(val) {
this.compareDate(val, this.getSailingTime());
this.compareDate1(val, this.getSailingTime());
},
},
methods: {
regCloseDialog(type) {
this.dialogVisible = false;
if (type === "error") {
this.$emit("getBoxInfo");
}
},
// 时间比较
compareDate(dtRealShipTime, sailTime) {
this.showMsg = false;
let date1 = null,
date2 = null;
if (dtRealShipTime) date1 = dayjs(dtRealShipTime);
if (sailTime) date2 = dayjs(sailTime);
if (date1 && date2 && date1.isAfter(date2)) {
this.showMsg = true;
}
},
compareDate1(dtRealShipTime, sailTime) {
this.isShowError = false;
let date1 = null,
date2 = null;
if (dtRealShipTime) date1 = dayjs(dtRealShipTime);
if (sailTime) date2 = dayjs(sailTime);
if (date1 && date2) {
const delayDay = date1.diff(date2, "day");
if (delayDay >= this.inspectionTimeShipping) this.isShowError = true;
}
},
// 异常登记
exceptionReg() {
this.dialogVisible = true;
},
/** 提交 */
onSubmit(operateType) {
this.$refs["departureForm"].validate((valid) => {
if (valid) {
shippingCreate({
...this.departureObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
// 预计开船时间
getSailingTime() {
return dayjs(this.$attrs.shipmentObj.bookSeaInfo.sailTime).format(
"YYYY-MM-DD HH:mm:ss"
);
},
},
};
</script>
<style lang="scss" scoped>
.app-departure {
.message-area {
margin: 0;
color: red;
}
}
</style>
<template>
<div class="preinstall">
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="90px">
<el-form-item :label="$t('入仓时间')" prop="rucangtime">
<el-date-picker v-model="queryParams.rucangtime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange" range-separator="-" start-:placeholder="$t('开始日期')" end-:placeholder="$t('结束日期')" />
</el-form-item>
<el-form-item :label="$t('始发地')" prop="startWarehouseId">
<el-select v-model="queryParams.startWarehouseId" :placeholder="$t('请选择始发地')" clearable size="small">
<el-option v-for="item in exportWarehouseList" :label="$l(item, 'title')" :value="item.id" :key="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('目的地')" prop="destWarehouseIdList">
<el-select v-model="queryParams.destWarehouseIdList" :placeholder="$t('请选择目的地')" multiple clearable>
<el-option v-for="item in importWarehouseList" :label="$l(item, 'title')" :value="item.id" :key="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('状态')" prop="orderStatus">
<el-select v-model="queryParams.orderStatus" :placeholder="$t('请选择状态')" clearable size="small">
<el-option v-for="item in stateOps" :label="$l(item, 'label')" :value="item.value" :key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('备案')" prop="productRecord">
<el-select v-model="queryParams.productRecord" :placeholder="$t('请选择备案')" clearable size="small">
<el-option v-for="item in filingOps" :label="$l(item, 'label')" :value="item.value" :key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('报关方式')" prop="customsType">
<el-select v-model="queryParams.customsType" :placeholder="$t('请选择报关方式')" clearable size="small">
<el-option v-for="item in declarationMethodOps" :label="$l(item, 'label')" :value="item.value" :key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('待预装订单')" prop="toBePreOrderNo">
<el-input v-model="queryParams.toBePreOrderNo" :placeholder="$t('请输入待预装订单')" clearable />
</el-form-item>
<el-form-item :label="$t('已预装单号')" prop="preOrderNo">
<el-input v-model="queryParams.preOrderNo" :placeholder="$t('请输入已预装单号')" clearable />
</el-form-item>
<el-form-item :label="$t('品名')" prop="itemName">
<el-input v-model="queryParams.itemName" :placeholder="$t('请输入品名')" clearable />
</el-form-item>
<el-form-item :label="$t('重货比')" prop="weightRatioMax">
<el-input v-model="queryParams.weightRatioMax" :placeholder="$t('请输入 大')" clearable />
</el-form-item>
<el-form-item label="" prop="weightRatioMin">
<el-input v-model="queryParams.weightRatioMin" :placeholder="$t('请输入 小')" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery('pre')">{{$t('搜索已预装订单')}}</el-button>
<el-button type="primary" icon="el-icon-search" @click="handleQuery('toBePre')">{{$t('搜索待预装订单')}}</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">{{$t('重置')}}</el-button>
</el-form-item>
</el-form>
<!-- 操作工具栏 -->
<el-row :gutter="10">
<right-toolbar :showSearch.sync="showSearch" @queryTable="handleQuery('toBePre')"></right-toolbar>
</el-row>
<!-- 表格 -->
<el-card style="margin-top: 15px" class="preinstall-card">
<el-row class="preinstall-title">
<div>
<p>{{$t('自编号')}}</p>
<p>{{shipmentObj.selfNo}}</p>
</div>
<div>
<p>{{$t('柜号')}}</p>
<p>{{shipmentObj.cubNo}}</p>
</div>
<div>
<p>{{$t('容量')}}</p>
<p>{{calcCapacity}}</p>
</div>
<div>
<p>{{$t('始发地')}}</p>
<p>{{importCityName(shipmentObj.startWarehouseId)}}</p>
</div>
<div>
<p>{{$t('目的地')}}</p>
<p>{{importCityName(shipmentObj.destWarehouseId)}}</p>
</div>
</el-row>
<el-row class="preinstall-table">
<!-- 已预装订单 -->
<el-col :span="12">
<el-row class="preinstall-title">
<div class="table-label">{{$t('已预装订单')}}</div>
<div>
<p>{{$t('总计')}}</p>
<p>{{getTotlContent(preList.loadStatistics)}}</p>
</div>
<div class="red-label">
<p>{{$t('可预装方数')}}</p>
<p>{{preList.remainVolume}}</p>
</div>
<div class="red-label">
<p>{{$t('重量')}}</p>
<p>{{preList.remainWeight}}kg</p>
</div>
<div class="table-button">
<el-button type="success" size="small" @click="addPart" :disabled="isAudit">{{$t('增加')}}</el-button>
</div>
</el-row>
<el-scrollbar style="height:calc(100% - 43px)">
<el-row v-for="(part, index) in preList.sectionGoodList" :key="index" class="pre-part">
<el-row class="preinstall-title">
<div class="pre-part-info">
<p>{{$t('第{index}部分', {index: index+1})}}</p>
<p>{{getTotlContent(part.secStatistics)}}</p>
</div>
<div class="table-button">
<el-button type="danger" size="small" @click="deletePart(part)" :disabled="isAudit">{{$t('删除部分')}}</el-button>
<el-button type="danger" size="small" @click="deleteOrder('selected', part)" :disabled="isAudit">{{$t('删除订单')}}</el-button>
<el-button type="primary" size="small" @click="foldTable(index, part)">{{part.fold ? $t('展开') : $t('收起')}}</el-button>
</div>
</el-row>
<el-collapse-transition>
<div v-show="!part.fold">
<el-table v-loading="preLoading" border :data="part.sectionGoodsList" @select="(selection)=>checkboxSelect(selection, part)" @select-all="(selection)=>checkboxSelect(selection, part)">
<el-table-column type="selection" align="center" width="55" fixed="left" />
<el-table-column :label="$t('序号')" align="center" prop="tidanNum" width="50" />
<el-table-column :label="$t('订单号')" align="center" prop="orderNo" width="120">
<template slot-scope="scope">
<div>
{{scope.row.orderNo}}
</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="destWarehouseName" width="120" />
<el-table-column :label="$t('入仓时间')" align="center" prop="rucangTime" width="120">
<template slot-scope="scope">
{{formatDate(scope.row.rucangTime)}}
</template>
</el-table-column>
<el-table-column :label="$t('品名')" align="center" prop="" width="120">
<template slot-scope="{row}">
{{$l(row,'prodTitle')}}
</template>
</el-table-column>
<el-table-column :label="$t('箱数')" align="center" prop="warehouseInInfoVO.cartonsNum" />
<el-table-column :label="$t('体积') + '/' + $t('重量') + '/' + $t('重货比')" align="center" width="140" prop="volumeWeight">
<template slot-scope="scope">
<p v-if="scope.row.warehouseInInfoVO.volume">{{getTotlContent(scope.row.warehouseInInfoVO,['volume'])}}</p>
<p v-if="scope.row.warehouseInInfoVO.weight">{{getTotlContent(scope.row.warehouseInInfoVO,['weight'])}}</p>
<p>{{getRatioMax(scope.row.warehouseInInfoVO)}}</p>
</template>
</el-table-column>
<el-table-column :label="$t('报关方式')" align="center" prop="customsType" width="120">
<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="productRecord" width="100">
<template slot-scope="{row}">
<template v-if="row.brandName">{{row.brandName}}</template>
<dict-tag v-else :type="DICT_TYPE.ECW_IS_BRAND" :value="row.feeType" />
</template>
</el-table-column>
<el-table-column :label="$t('操作')" align="center" width="160" class-name="small-padding fixed-width" fixed="right">
<template slot-scope="scope">
<el-dropdown trigger="click" @command="(command)=>handleGoods('single',scope.row,command)" :disabled="isAudit">
<el-button type="primary" size="small" icon="el-icon-edit-outline" circle :disabled="isAudit"></el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="bPart" v-for="(bPart, index) in preList.sectionGoodList" :key="bPart.id" v-show="bPart.id !== part.id">
{{$t('第{index}部分', {index: index+1})}}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button type="danger" size="small" icon="el-icon-minus" circle style="margin-left:10px;" @click="deleteOrder('row',scope.row)" :disabled="isAudit"></el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-collapse-transition>
</el-row>
</el-scrollbar>
</el-col>
<!-- 待预装订单 -->
<el-col :span="12">
<el-row class="preinstall-title">
<div class="table-label red-label">{{$t('待预装订单')}}</div>
<div class="preinstall-title preinstalled">
<div class="red-label">
<p>{{$t('筛选后待预装数量')}}</p>
<p>{{getTotlContent(unloadStatistics,['num'])}}</p>
</div>
<div class="red-label">
<p>{{$t('方数')}}</p>
<p>{{getTotlContent(unloadStatistics,['volume'])}}</p>
</div>
<div class="red-label">
<p>{{$t('重量')}}</p>
<p>{{getTotlContent(unloadStatistics,['weight'])}}</p>
</div>
</div>
</el-row>
<el-pagination background layout="prev, pager, next" :current-page="pageParam.pageNo" :page-size="pageParam.pageSize" :total="total" @current-change="pageChange" v-show="total > 0"></el-pagination>
<el-scrollbar style="height:calc(100% - 75px)">
<el-row v-for="(item, index) in toBePreList" :key="index" class="tobePre-row">
<el-row class="preinstall-title order-title">
<div>
<p>{{item.orderNo}}</p>
</div>
<div>
<p>{{$t('发往')}}</p>
<p>{{item.destWarehouseName}}</p>
</div>
<div>
<p :class="item.customsType !== 1 ? 'custom_type_red' : ''">
<dict-tag :type="DICT_TYPE.ECW_CUSTOMS_TYPE" :value="item.customsType" />
</p>
</div>
<div>
<p>{{$t('入仓时间')}}</p>
<p>{{formatDate(item.rucangTime)}}</p>
</div>
<div>
<p>{{$t('重货比')}}</p>
<p>{{item.weightRatio}}</p>
</div>
<div v-if="item.isExternalWarehouse === 1" style="color:blue;fontWeight:bold;">
<p>{{$t('外部仓')}}</p>
</div>
<div class="table-button">
<el-button v-if="item.relateOrderList" type="primary" size="small" style="margin-right: 20px;" @click="getRelationOrder(item)">{{$t('关联订单')}}</el-button>
<el-dropdown trigger="click" @command="(command)=>handleGoods('all',item,command)">
<el-button type="success" size="small" :disabled="isAudit">{{$t('预装全部')}}</el-button>
<el-dropdown-menu slot="dropdown" v-if="preList.sectionGoodList">
<el-dropdown-item :command="part" v-for="(part, index) in preList.sectionGoodList" :key="part.id">
{{$t('第{index}部分', {index: index+1})}}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</el-row>
<el-table v-loading="toBePreLoading" :data="item.boxOrderItemList" border show-summary :summary-method="getSummaries">
<el-table-column type="index" align="center" :label="$t('序号')" width="50" />
<el-table-column :label="$t('品名')" align="center" prop="">
<template slot-scope="{row}">
{{$l(row,'prodTitle')}}
</template>
</el-table-column>
<el-table-column :label="$t('备案')" align="center" prop="feeType">
<template slot-scope="{row}">
<template>{{row.brandName}}</template>{{ $t('(') }}
<dict-tag :type="DICT_TYPE.BRAND_CUSTOMER_CHARGING_MODEL" :value="row.feeType" />{{ $t('') }}
</template>
</el-table-column>
<el-table-column :label="$t('箱数')" align="center" prop="warehouseInInfoVO.cartonsNum" />
<el-table-column :label="$t('体积') +'/' + $t('重量')" align="center" prop="volumeWeight">
<template slot-scope="scope">
<p v-if="scope.row.warehouseInInfoVO && scope.row.warehouseInInfoVO.volume">{{getTotlContent(scope.row.warehouseInInfoVO,['volume'])}}</p>
<p v-if="scope.row.warehouseInInfoVO && scope.row.warehouseInInfoVO.weight">{{getTotlContent(scope.row.warehouseInInfoVO,['weight'])}}</p>
</template>
</el-table-column>
<el-table-column :label="$t('报关方式')" align="center" prop="">
<div :class="item.customsType !== 1 ? 'custom_type_red' : ''">
<dict-tag :type="DICT_TYPE.ECW_CUSTOMS_TYPE" :value="item.customsType" />
</div>
</el-table-column>
<el-table-column :label="$t('包装类型')" align="center" prop="">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.ECW_PACKAGING_TYPE" :value="scope.row.warehouseInInfoVO && scope.row.warehouseInInfoVO.unit" />
</template>
</el-table-column>
<el-table-column :label="$t('材质')" align="center" prop="material">{{ $t('') }}<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.ECW_PRODUCT_MATERIAL" :value="scope.row.material" />
</template>
</el-table-column>
<!-- <el-table-column :label="$t('操作')" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-dropdown trigger="click" @command="(command)=>handleGoods('single',scope.row,command)">
<el-button type="primary" size="small">{{$t('预装')}}</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="part" v-for="(part, index) in preList" :key="part.id">{{index+1}}部分</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column> -->
</el-table>
</el-row>
</el-scrollbar>
</el-col>
</el-row>
</el-card>
<!-- 操作员 -->
<el-row style="margin-top: 15px" v-show="!isAudit">
<el-row>
<el-form ref="operatorForm" :model="operatorData" size="small" :inline="true" label-width="120px" :rules="rules">
<el-form-item :label="$t('目的地操作员')" prop="noticeUser">
<userSelect v-model="operatorData.noticeUser" :placeholder="$t('请选择目的地操作员')" :allUsers="this.$attrs.allUsers" size="small" />
</el-form-item>
</el-form>
</el-row>
</el-row>
<!-- 审核流程 -->
<el-row class="process-area">
<div class="process">
<div>{{$t('审批流程')}}</div>
<work-flow xmlkey="shipment_preassemble" v-model="selectedUsers"></work-flow>
</div>
<div v-show="isAudit">
<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="closeDialog">{{$t('返回')}}</el-button>
</div>
<div v-show="!isAudit">
<el-button type="primary" @click="onSubmit">{{$t('提交申请')}}</el-button>
</div>
</el-row>
<!-- 关联订单弹窗 -->
<el-dialog :title="relationOrderListDialog.title" :visible.sync="relationOrderListDialog.visible" width="30%" append-to-body>
<el-card>
<div v-html="relationOrderListDialog.data"></div>
</el-card>
<el-row style="margin-top: 10px;text-align: center;">
<el-button type="primary" @click="relationOrderListDialog.visible = false">{{$t('关闭窗口')}}</el-button>
</el-row>
</el-dialog>
</div>
</template>
<script>
import { DICT_TYPE } from "@/utils/dict";
import {
secGoodsList,
preloadPage,
createSection,
deleteSection,
createGoods,
deleteGoods,
changeSection,
approvalCreate,
approvalCancel,
loadRelationOrder,
getAllRelateOrderList
} from "@/api/ecw/boxSea";
import userSelect from "./common/userSelect.vue";
import {
formatDate,
getTotlContent,
serviceMsg,
getCapacity,
toReviewDetail,
} from "../utils";
import dayjs from "dayjs";
import WorkFlow from "@/components/WorkFlow";
import Decimal from "decimal.js";
/**
* 预装
*/
export default {
name: "preinstall",
inheritAttrs: false,
components: { userSelect, WorkFlow },
data() {
return {
// 状态
stateOps: [
{ value: "1", label: this.$t("拆单") },
{ value: "2", label: this.$t("关联单") },
],
// 备案
filingOps: this.getDictDatas(DICT_TYPE.BRAND_CUSTOMER_CHARGING_MODEL),
// 报关方式
declarationMethodOps: this.getDictDatas(DICT_TYPE.ECW_CUSTOMS_TYPE),
// 查询标识
type: "",
// 已预装 遮罩层
preLoading: false,
preList: {
sectionGoodList: [],
remainWeight: 0,
remainVolume: 0,
},
// 选中行
selectedRows: {},
// 待预装
toBePreLoading: false,
toBePreList: [],
total: 0,
unloadStatistics: {},
// 显示搜索条件
showSearch: true,
// 查询参数
queryParams: {},
pageParam: { pageNo: 1, pageSize: 10 },
// 目的地操作员
operatorData: {},
// 校验
rules: {
noticeUser: [
{
required: true,
message: this.$t("目的地操作员必填"),
trigger: "change",
},
],
},
// 出货信息
shipmentObj: this.$attrs.shipmentObj,
// 抄送人数组
selectedUsers: [],
// 智慧预装
smartInstall: 1,
//关联订单
relationOrderListDialog: {
title: '',
visible: false,
data: []
},
};
},
computed: {
/** 始发地 */
exportWarehouseList() {
return this.$attrs.warehouseList.filter(
(item) => item.tradeType == "2" || item.type == "3"
);
},
/** 目的地 */
importWarehouseList() {
return this.$attrs.warehouseList.filter(
(item) => item.tradeType == "1" || item.type == "3"
);
},
/* 是否审核中 */
isAudit() {
const { currNode, shipmentObj } = this.$attrs;
return shipmentObj[currNode.keyName] === 23;
},
/* 容量 */
calcCapacity() {
const { cabinetRespVO } = this.$attrs.shipmentObj;
return getCapacity(cabinetRespVO);
},
},
created() {
// 查询待预装
this.handleQuery("toBePre");
this.handleQuery("pre");
this.smartInstall = 0;
},
methods: {
formatDate,
getTotlContent,
/* 获取城市 */
importCityName(id) {
var arr = this.$attrs.warehouseList.filter((item) => item.id == id);
return arr.length > 0 ? this.$l(arr[0], "title") : this.$t("");
},
/* 选中行 */
checkboxSelect(selection, part) {
this.selectedRows[part.id] = selection;
},
/* 查询已预装 */
getSecGoods() {
this.preLoading = true;
// 处理查询参数
let params = this.getParams();
// 已预装单号
params.orderNo = params.preOrderNo;
params.shipmentId = this.shipmentObj.id;
params.smartInstall = this.smartInstall;
secGoodsList(params).then((res) => {
if (res.data) {
res.data.sectionGoodList.map((data) => {
if (data.sectionGoodsList) {
data.sectionGoodsList.map((data1) => {
data1.warehouseInInfoVO = data1.warehouseInInfo
? JSON.parse(data1.warehouseInInfo)
: {};
return data1;
});
}
return data;
});
}
this.preList = res.data;
this.preLoading = false;
});
},
/* 查询待预装 */
getPreLoad() {
this.toBePreLoading = true;
// 处理查询参数
let params = this.getParams();
// 订单号
params.orderNo = params.toBePreOrderNo;
params.transportType = this.shipmentObj.transportType;
preloadPage({ ...params, ...this.pageParam }).then((res) => {
const { data } = res;
this.toBePreList = data.dataList?.list ?? [];
this.total = data.dataList?.total ?? 0;
this.unloadStatistics = data.unloadStatistics ?? {};
this.toBePreLoading = false;
if(this.toBePreList.length == 0&&this.total!=0){
--this.pageParam.pageNo
this.getPreLoad()
}
});
},
/**查看关联订单 */
getRelationOrder(item) {
getAllRelateOrderList({orderId:item.orderId,orderNo:item.orderNo}).then(res=>{
this.relationOrderListDialog.title = item.orderNo+'关联订单'
this.relationOrderListDialog.visible = true
this.relationOrderListDialog.data = res.msg.replace(/\n/g,'<br>')
})
},
/** 搜索按钮操作 */
handleQuery(type) {
this.pageParam.pageNo = 1;
if (type === "pre") {
this.getSecGoods();
} else {
this.getPreLoad();
}
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams = {};
this.$refs["queryForm"].resetFields();
},
/** 提交 */
onSubmit() {
this.$refs["operatorForm"].validate((valid, errors) => {
if (!valid) {
return this.$showFormValidateErrors(errors);
}
approvalCreate({
...this.operatorData,
applyReason: this.$t("预装审核"),
approvalStatus: 0,
approvalType: 1, // 预装
copyUserId: this.selectedUsers,
shipmentId: this.$attrs.shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("closeDialog", "submit");
});
});
});
},
/* 统计列 */
getSummaries(param) {
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (column.property === "brandType") {
sums[index] = this.$t("合计");
return;
}
if (column.property === "num") {
sums[index] = new Decimal(
this.calcSum(column.property, data)
).toNumber();
}
if (column.property === "volumeWeight") {
let volume = this.calcSum("volume", data);
let weight = this.calcSum("weight", data);
volume = volume === 0 ? volume : new Decimal(volume).toFixed(2);
weight = weight === 0 ? weight : new Decimal(weight).toFixed(2);
sums[index] = getTotlContent({ volume, weight }, [
"volume",
"weight",
]);
sums[index] = sums[index].replace(" ", "\n");
}
});
return sums;
},
/* 计算总和 */
calcSum(key, data) {
const values = data?.map((item) => Number(item[key])) ?? [];
if (!values.every((value) => isNaN(value))) {
return values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
}
return 0;
},
/* 待预装订单分页 */
pageChange(page) {
this.pageParam.pageNo = page;
this.getPreLoad();
},
/* 折叠 */
foldTable(index, part) {
part.fold = !part.fold;
this.$set(this.preList.sectionGoodList, index, part);
},
/* 增加部分 */
addPart() {
createSection({ shipmentId: this.shipmentObj.id, isCover: 0 }).then(
(res) => {
serviceMsg(res, this).then(() => {
this.getSecGoods();
});
}
);
},
/* 删除部分 */
deletePart(part) {
this.$confirm(
this.$t("确认删除该部分及其已预装订单?"),
this.$t("提示"),
{
type: "warning",
}
)
.then((_) => {
let params = {
id: part.id,
deleteType: 2
};
deleteSection(params).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch((_) => {});
},
/** 预装 */
handleGoods(type, item, part) {
if (type === "all") {
let params = {
secId: part.id,
shipmentId: this.shipmentObj.id,
orderId: item.orderId,
orderItemIdList: item.boxOrderItemList.map(
(data) => data.orderItemId
),
};
createGoods(params)
.then((res) => {
const { data } = res;
if (data.relationMsg) {
const msg = data.relationMsg.replaceAll(",", "");
this.$confirm(msg, this.$t("提示"), {
dangerouslyUseHTMLString: true,
type: "warning",
})
.then((_) => {
loadRelationOrder(data).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch((_) => {
this.queryAllData();
});
} else {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
}
})
.catch((res) => {
if (res.code === 555) {
const msg = res.msg && res.msg.replaceAll(",", "");
this.$confirm(msg, this.$t("提示"), {
dangerouslyUseHTMLString: true,
type: "warning",
})
.then((_) => {
createGoods({ ...params, relationStatus: 1 }).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch((_) => {
this.queryAllData();
});
}
if (res.code === 566) {
this.$confirm(res.msg+this.$t('是否需要一起预装?'), this.$t("提示"), {
dangerouslyUseHTMLString: true,
type: "warning",
})
.then((_) => {
createGoods({ ...params, relationStatus: 2 }).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch((_) => {
this.queryAllData();
});
}
});
} else {
let params = {
secId: part.id,
id: item.id,
};
changeSection(params).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
}
},
/* 删除订单 */
deleteOrder(type, data) {
let ids = [];
if (type === "selected") {
// 根据parid 构建的对象
const rows = this.selectedRows[data.id] ?? [];
if (!rows.length) {
this.$message.error(this.$t("请选择订单"));
return;
}
ids = rows.map((item) => item.id);
}
if (type === "row") {
ids.push(data.id);
}
let param = {
ids: ids.join(",")
}
deleteGoods(param).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
}).catch((res) => {
if (res.code === 666) {
this.$confirm("<div style='max-height:500px;overflow:auto'>"+res.msg+this.$t('是否需要一起移出?')+"</div>", this.$t("提示"), {
dangerouslyUseHTMLString: true,
distinguishCancelAndClose: true,
confirmButtonText: '确定移出',
cancelButtonText: '仅移出当前订单'
})
.then((_) => {
deleteGoods({ ...param, deleteType: 2 }).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
})
.catch(action => {
if(action =='cancel'){
deleteGoods({ ...param, deleteType: 1 }).then((res) => {
serviceMsg(res, this).then(() => {
this.queryAllData();
});
});
}
});
}
});
},
/* 查询所有数据 */
queryAllData() {
this.getSecGoods();
this.getPreLoad();
},
/* 获取参数 */
getParams() {
const { rucangtime = [] } = this.queryParams;
return {
...this.queryParams,
...this.$attrs.params,
rucangTimeStart: rucangtime[0]
? dayjs(rucangtime[0]).format("YYYY-MM-DD 00:00:00")
: rucangtime[0],
rucangTimeEnd: rucangtime[1]
? dayjs(rucangtime[1]).format("YYYY-MM-DD 23:59:59")
: rucangtime[1],
};
},
/* 关闭弹框 */
closeDialog() {
this.$emit("closeDialog");
},
/* 取消审核 */
canclAudit() {
const { currNode, shipmentObj } = this.$attrs;
const { voName } = currNode;
approvalCancel({
applyReason: this.$t("取消审核"),
id: shipmentObj[voName].id,
shipmentId: shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("closeDialog", "submit");
});
});
},
jumpReviewDetail() {
const { currNode, shipmentObj } = this.$attrs;
toReviewDetail.apply(this, [shipmentObj[currNode.voName].bpmProcessId]);
this.$emit("closeDialog");
},
getRatioMax(row) {
let volume = row.volume ?? 0;
let weight = row.weight ?? 0;
return Decimal.div(weight, volume).toFixed(2);
},
},
};
</script>
<style lang="scss">
.preinstall {
display: flex;
flex-direction: column;
p {
margin: 0;
}
.preinstall-title {
display: flex;
align-items: center;
margin-bottom: 10px;
padding: 0 10px;
&.preinstalled {
flex: 1;
display: flex;
justify-content: flex-end;
> div {
display: flex;
}
}
&.order-title {
margin-bottom: 0px;
background-color: #e6ebf5;
height: 45px;
}
> div {
display: flex;
margin-right: 10px;
}
.table-label {
font-size: 16px;
font-weight: bolder;
}
.red-label {
color: red;
}
.table-button {
flex: 1;
margin: 0;
display: flex;
justify-content: flex-end;
}
}
.preinstall-table {
display: flex;
height: calc(100% - 30px);
> div {
border: 1px solid #e6ebf5;
padding: 10px 0px;
}
> div:first-child {
margin-right: 10px;
}
}
.pre-part {
margin-bottom: 10px;
margin-right: 10px;
.pre-part-info {
font-weight: bolder;
> p:first-child {
color: #13ce66;
margin-right: 10px;
}
> p:last-child {
> span {
margin-right: 5px;
}
}
}
}
.preinstall-card {
min-height: 800px;
.el-card__body {
height: 100%;
.tobePre-row {
margin-top: 10px;
.el-table {
.cell {
white-space: pre-line;
}
}
}
}
}
.process-area {
margin-top: 15px;
padding-bottom: 30px;
.process {
display: flex;
flex-direction: column;
> :first-child {
color: #606266;
font-weight: bolder;
font-size: 16px;
}
}
}
}
</style>
<template>
<div>
<el-form ref="reviewForm" :model="reviewObj" label-width="120px">
<el-form-item :label="$t('申请理由')">
<el-input v-model="reviewObj.applyReason" type="textarea" rows="2" :placeholder="$t('请输入申请理由')" :disabled="isReview"></el-input>
</el-form-item>
<span v-if="voKey=='preInstallBackInfo'" style="color: red;margin-left: 120px;">{{$t('请注意,预装反审后,全部提单需重新制作')}}</span>
</el-form>
<el-row class="operate-button">
<el-button type="success" @click="onSubmit" v-show="!isReview">{{$t('发起申请')}}</el-button>
<el-button type="primary" @click="jumpReviewDetail" v-show="isReview">{{$t('审核中')}}</el-button>
<el-button plain type="primary" @click="canclAudit" v-show="isReview">{{$t('取消审核')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { approvalCreate, approvalCancel } from "@/api/ecw/boxSea";
import { serviceMsg, toReviewDetail } from "../utils";
/**
* 反审
*/
export default {
name: "review",
inheritAttrs: false,
data() {
return {
// 反审对象
reviewObj: {},
isReview: false,
bpmProcessId: "",
voKey: "",
};
},
created() {
const { currNode, shipmentObj } = this.$attrs;
let voKey = "";
switch (currNode.type) {
case "preinstall":
voKey = "preInstallBackInfo";
break;
case "cabinet":
voKey = "cabinetBackInfo";
break;
case "unloading":
voKey = "cabinetUnloadBackApprovalInfo";
break;
}
if (voKey) {
this.isReview = shipmentObj[voKey] ? true : false;
if (shipmentObj[voKey] && shipmentObj[voKey].approvalStatus !== 1) {
this.isReview = false;
}
if (shipmentObj[voKey]) {
this.bpmProcessId = shipmentObj[voKey].bpmProcessId;
}
if (this.isReview) {
this.$set(
this.reviewObj,
"applyReason",
shipmentObj[voKey].applyReason
);
}
}
this.voKey = voKey;
},
methods: {
/* 取消审核 */
canclAudit() {
const { shipmentObj } = this.$attrs;
approvalCancel({
applyReason: this.$t("取消反审核"),
id: shipmentObj[this.voKey].id,
shipmentId: shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("closeDialog", "submit");
});
});
},
jumpReviewDetail() {
toReviewDetail.apply(this, [this.bpmProcessId]);
this.$emit("closeDialog");
},
/** 提交 */
onSubmit() {
this.$refs["reviewForm"].validate((valid) => {
if (valid) {
const { currNode, shipmentObj } = this.$attrs;
let approvalType = 4; // 预装反审
if (currNode.type === "cabinet") approvalType = 9; // 装柜反审
if (currNode.type === "unloading") approvalType = 7; // 卸柜反审核
approvalCreate({
shipmentId: shipmentObj.id,
...this.reviewObj,
approvalStatus: 0,
approvalType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<template>
<div>
<el-form ref="settlementForm" :model="settlementObj" label-width="80px">
<el-form-item :label="$t('可结算')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="settlementObj.slSettlementTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('已结算')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="settlementObj.slSettledTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { settlementCreate } from "@/api/ecw/boxSea";
import { formatDateStr, serviceMsg } from "../utils";
/**
* 结算
*/
export default {
name: "settlement",
inheritAttrs: false,
data() {
return {
// 结算对象
settlementObj: {},
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, ["slSettlementTime", "slSettledTime"]);
this.settlementObj = oldData;
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["settlementForm"].validate((valid) => {
if (valid) {
settlementCreate({
...this.settlementObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-form ref="shipForm" :model="shipObj" :rules="rules" label-width="80px">
<el-form-item :label="$t('状态')" prop="saExmtStatus">
<el-radio-group v-model="shipObj.saExmtStatus">
<el-radio v-for="item in status" :key="item.value" :label="item.value">{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('配船时间')" v-show="shipObj.saExmtStatus === '2'">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="shipObj.configTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { shipConfigure } from "@/api/ecw/boxSea";
import {
formatNumberString,
formatDateStr,
constantDict,
serviceMsg,
} from "../utils";
/**
* 配船
*/
export default {
name: "ship",
inheritAttrs: false,
props: {
shipmentObj: Object,
},
data() {
return {
// 配船对象
shipObj: {},
// 状态
status: constantDict.saExmtStatus,
// 校验
rules: {
saExmtStatus: [{ required: true, message: this.$t("必填"), trigger: "change" }],
},
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.shipmentObj[voName] };
oldData = formatNumberString(oldData, ["saExmtStatus"]);
oldData = formatDateStr(oldData, ["configTime"]);
this.shipObj = oldData;
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["shipForm"].validate((valid) => {
if (valid) {
shipConfigure({
operateType,
shipmentId: this.shipmentObj.id,
...this.shipObj,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-form ref="subMaterialForm" :model="subMaterialObj" label-width="140px">
<el-form-item :label="$t('代理商AGENT')">
<supplierSelect v-model="subMaterialObj.agentId" :areaType="1" :placeholder="$t('请选择供应商')" :allSupplier="this.$attrs.allSupplier" disabled />
</el-form-item>
<el-form-item :label="$t('提单号M/BL NO.')" class="two-element">
<el-input v-model="subMaterialObj.blMblNo" :placeholder="$t('请输入提单号')"></el-input>
</el-form-item>
<el-form-item label="SO NO.">
<el-input v-model="subMaterialObj.soNo" :placeholder="$t('请输入SO NO')"></el-input>
</el-form-item>
<el-form-item :label="$t('起运港')">
<dockSelect v-model="subMaterialObj.startPortId" :placeholder="$t('请选择起运港')" :allDocks="this.$attrs.allDocks" />
</el-form-item>
<el-form-item :label="$t('目的港')">
<dockSelect v-model="subMaterialObj.destPortId" :placeholder="$t('请选择目的港')" :allDocks="this.$attrs.allDocks" />
</el-form-item>
<el-form-item :label="$t('船公司')">
<supplierSelect v-model="subMaterialObj.shipCompanyId" :companyType="'9'" :placeholder="$t('请选择船公司')" :allSupplier="this.$attrs.allSupplier" />
</el-form-item>
<el-form-item :label="$t('托运人')">
<ladingSelect v-model="subMaterialObj.shipperId" :placeholder="$t('请选择托运人')" :allUsers="this.$attrs.allLading" />
</el-form-item>
<el-form-item :label="$t('收货人')">
<el-input v-model="subMaterialObj.consigneeName" disabled></el-input>
<!-- <userSelect v-model="subMaterialObj.consigneeId" :placeholder="$t('请选择收货人')" :allUsers="this.$attrs.allUsers" /> -->
</el-form-item>
<el-form-item :label="$t('通知方')">
<el-input v-model="subMaterialObj.notifyingName" disabled></el-input>
<!-- <userSelect v-model="subMaterialObj.notifyingId" :placeholder="$t('请选择通知方')" :allUsers="this.$attrs.allUsers" /> -->
</el-form-item>
<el-form-item label="Mark & No.">
<el-input v-model="subMaterialObj.markNo" placeholder="请输入Mark & No."></el-input>
</el-form-item>
<el-form-item :label="$t('包装数量与单位')" class="two-element">
<el-input v-model="subMaterialObj.packageNum" :placeholder="$t('请输入包装数量')"></el-input>
<dict-selector v-model="subMaterialObj.packageUnit" type="packaging_type" />
</el-form-item>
<el-form-item :label="$t('货物毛重(KGS)')">
<el-input v-model="subMaterialObj.kgs" :placeholder="$t('请输入货物毛重') + '(KGS)'"></el-input>
</el-form-item>
<el-form-item :label="$t('立方数(CBM)')">
<el-input v-model="subMaterialObj.cbm" :placeholder="$t('请输入立方数') + '(CBM)'"></el-input>
</el-form-item>
<el-form-item :label="$t('货物描述')">
<el-input v-model="subMaterialObj.goodsDesc" type="textarea" autosize :placeholder="$t('请输入货物描述')"></el-input>
</el-form-item>
<el-form-item :label="$t('柜号') + '/' + $t('封条')">
<el-input v-model="subMaterialObj.containerSealNo" :placeholder="$t('请输入柜号') + '/' + $t('封条')"></el-input>
</el-form-item>
<el-form-item :label="$t('柜型')">
{{cabinetType}}
</el-form-item>
<el-form-item :label="$t('出单方式')">
<el-radio-group v-model="subMaterialObj.issueType">
<el-radio v-for="item in method" :key="item.value" :label="item.value">{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('备注')">
<el-input v-model="subMaterialObj.remarks" type="textarea" rows="2" :placeholder="$t('请输入备注')"></el-input>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button :disabled="shipmentObj.ladingBillInfo == null" @click="download">{{$t('下载提单确认件')}}</el-button>
</el-row>
</div>
</template>
<script>
import supplierSelect from "./common/supplierSelect.vue";
import dockSelect from "./common/dockSelect.vue";
import userSelect from "./common/userSelect.vue";
import ladingSelect from "./common/ladingSelect.vue";
import { getUnitList } from "@/api/ecw/unit";
import { getCabinetPage } from "@/api/ecw/cabinet";
import { billCreate, getBoxLadingBillPdf } from "@/api/ecw/boxSea";
import { getSupplier } from "@/api/ecw/supplier";
import { formatNumberString, constantDict, serviceMsg } from "../utils";
import FileSaver from 'file-saver'
/**
* 提单补料
*/
export default {
name: "subMaterial",
inheritAttrs: false,
components: { supplierSelect, dockSelect, userSelect, ladingSelect },
props: {
shipmentObj: Object,
},
data() {
return {
// 提单补料对象
subMaterialObj: {
markNo: "N/M",
},
// 出单方式
method: constantDict.billingMethod,
// 单位
units: [],
// 柜型
cabinetType: "/",
};
},
created() {
// 获取单位
getUnitList().then((res) => {
const { data } = res;
this.units = data ?? [];
});
// 柜型
getCabinetPage(null).then((response) => {
const cabinetList = response.data.list;
for (let index in cabinetList) {
let cabinetItem = cabinetList[index];
if (cabinetItem.id == this.shipmentObj.cabinetId) {
this.cabinetType = cabinetItem.name;
this.$set(this.subMaterialObj,'cbm',cabinetItem.ladingBill)
}
}
});
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.shipmentObj[voName] };
oldData = formatNumberString(oldData, ["issueType"]);this.subMaterialObj = {
...oldData,
packageUnit: oldData.packageUnit === 0 ? undefined : oldData.packageUnit,
};
if(!this.shipmentObj.ladingBillInfo){
this.$set(this.subMaterialObj,'agentId',this.shipmentObj.agentInfo?.agentId||undefined)
this.$set(this.subMaterialObj,'soNo',this.shipmentObj.bookSeaInfo?.sono||undefined)
this.$set(this.subMaterialObj,'blMblNo',this.shipmentObj.bookSeaInfo?.sono||undefined)
this.$set(this.subMaterialObj,'markNo',"N/M")
this.$set(this.subMaterialObj,'startPortId',this.shipmentObj.bookSeaInfo?.bigPortId||undefined)
this.$set(this.subMaterialObj,'shipCompanyId',Number(this.shipmentObj.bookSeaInfo?.shipCompanyType)||undefined)
this.$set(this.subMaterialObj,'destPortId',this.shipmentObj.bookSeaInfo?.destPortId||undefined)
this.$set(this.subMaterialObj,'kgs',this.shipmentObj.customsInfo?.dcGoodsWgt||undefined)
this.$set(this.subMaterialObj,'containerSealNo',(this.shipmentObj.trailerInfo?.tlContainerNo||'')+'/'+(this.shipmentObj.trailerInfo?.tlStripSeal||'/'))
this.subMaterialObj.containerSealNo = this.subMaterialObj.containerSealNo.replace('//','')
this.getSup(this.subMaterialObj.agentId)
}
},
methods: {
getSup(id) {
getSupplier(id).then(response => {
if(response.data.externalBackVO){
this.$set(this.subMaterialObj,'consigneeName',response.data.externalBackVO?.receiveCompanyName||'/')
this.$set(this.subMaterialObj,'notifyingName',response.data.externalBackVO?.notifyCompanyName||'/')
this.$set(this.subMaterialObj,'packageNum',response.data.externalBackVO?.packNum)
this.$set(this.subMaterialObj,'packageUnit',response.data.externalBackVO?.packUnit)
var goodName = '',baNo = '',fromNo = '',ctnNo = ''
if(response.data.externalBackVO.goodName && response.data.externalBackVO.goodName != '') goodName = response.data.externalBackVO.goodName
if(response.data.externalBackVO.fromNo && response.data.externalBackVO.fromNo != '') fromNo = (goodName!=''?'\n':'')+'FROM M NO:'+response.data.externalBackVO.fromNo
if(response.data.externalBackVO.baNo && response.data.externalBackVO.baNo != '') baNo = '\nBA NO:'+response.data.externalBackVO.baNo
if(response.data.externalBackVO.ctnNo && response.data.externalBackVO.ctnNo != '') ctnNo = '\nCTN NO:'+response.data.externalBackVO.ctnNo
this.$set(this.subMaterialObj,'goodsDesc',goodName+fromNo+baNo+ctnNo)
if(this.subMaterialObj.goodsDesc == null){
this.$set(this.subMaterialObj,'goodsDesc','/')
}
}
})
},
/** 提交 */
onSubmit(operateType) {
this.$refs["subMaterialForm"].validate((valid) => {
if (valid) {
billCreate({
...this.subMaterialObj,
shipmentId: this.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
if(operateType == 2) this.download()
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
download() {
getBoxLadingBillPdf({shipmentId: this.shipmentObj.id}).then(res=>{
let blob = new Blob([res], {type: "application/vnd.ms-excel"})
FileSaver.saveAs(blob, this.$t('提单确认件.xlsx'));
})
}
},
};
</script>
<style lang="scss">
</style>
<template>
<div class="shipping-batchTally">
<el-row v-if="$attrs.type === 'batchTally'">
<el-button type="text" size="small" @click="()=>openStorage('all')">{{$t('批量修改储位')}}</el-button>
</el-row>
<el-scrollbar viewClass="tally-list">
<el-row class="tally-detail" v-for="(item, index) in storageList" :key="item.id">
<div class="status-number">{{++index}}</div>
<div class="detail-info">
<div>{{$t('入仓单号')}}{{item.orderNo}}</div>
<div>{{$t('入仓统计')}}{{getTotlContent(item)}}</div>
<div class="detail-modify">
<el-tooltip effect="dark" :content="item.positionNo" placement="top">
<div>{{$t('储位')}}{{item.positionNo}}</div>
</el-tooltip>
<el-button type="text" size="small" @click="()=>openStorage('single', item)">{{$t('修改')}}</el-button>
</div>
</div>
</el-row>
</el-scrollbar>
<el-row class="operate-button">
<el-button size="small" type="primary" @click="tallyModify">{{$t('确定')}}</el-button>
<el-button size="small" @click="$emit('closeDialog')">{{$t('关闭')}}</el-button>
</el-row>
<warehouse-area-dialog ref="area" :visible.sync="visible" v-model="storageSpaces" :order-id="orderId" :warehouseId="warehouseId" :modal-append-to-body=false append-to-body />
</div>
</template>
<script>
import { getTotlContent, serviceMsg } from "../../utils";
import WarehouseAreaDialog from "@/components/WarehouseAreaDialog";
import { deepClone } from "@/utils";
import { tallyLocationUpdate } from "@/api/ecw/boxSea";
export default {
name: "batchTally",
inheritAttrs: false,
components: { WarehouseAreaDialog },
props: {
tallyRows: Array,
},
data() {
return {
visible: false,
// 储位
storageSpaces: [],
// 订单ID
orderId: -1,
// 仓位数据
storageList: deepClone(this.tallyRows),
// 仓库id
warehouseId: this.$attrs.shipmentObj.startWarehouseId,
};
},
mounted() {
this.$refs.area.updateArea()
},
methods: {
getTotlContent,
// 打开储位
openStorage(type, item) {
if (type === "all") {
this.orderId = -1;
} else {
this.orderId = item.orderId;
}
this.visible = true;
},
// 修改储位
tallyModify() {
// 查找数据中存在storageList的订单
let orderLocationList = [];
this.storageList.forEach((item) => {
const { storageList } = item;
if (storageList && storageList.length) {
storageList.forEach((sItem) => {
orderLocationList.push({
...sItem,
orderId: item.orderId,
});
});
}
});
if (orderLocationList.length === 0) {
this.$message.error(this.$t("没有需要修改储位的订单"));
return;
}
tallyLocationUpdate({
shipmentId: this.$attrs.shipmentObj.id,
orderLocationList,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("closeDialog", "query");
});
});
},
},
watch: {
storageSpaces(val) {
let newList = [];
const { selected = [] } = this.$refs.area;
// 批量修改储位
if (this.orderId === -1) {
newList = this.storageList.map((item) => {
item.positionNo = selected.join(",");
item.storageList = val;
return item;
});
} else {
newList = this.storageList.map((item) => {
if (item.orderId === this.orderId) {
item.positionNo = selected.join(",");
item.storageList = val;
}
return item;
});
}
this.storageList = newList;
},
},
};
</script>
<style lang="scss">
.shipping-batchTally {
.el-scrollbar__wrap {
max-height: 500px;
.tally-list {
.tally-detail {
display: flex;
padding: 10px 0px;
border-bottom: 1px solid rgb(223, 230, 236);
.status-number {
width: 26px;
height: 26px;
border: 1px solid #ccc;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20px;
}
.detail-info {
> div {
height: 30px;
line-height: 30px;
}
.detail-modify {
display: flex;
align-items: center;
> :first-child {
width: 150px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 10px;
}
}
}
}
> .tally-detail:last-child {
border-bottom: none;
}
}
}
}
</style>
<template>
<div class="shipping-tally">
<el-row type="flex" style="margin-top: 15px; margin-bottom: 15px" justify="center">
<el-col :xs="24" :sm="24" :md="24" :lg="20" :xl="22">
<el-card>
<el-descriptions :column="4" border>
<el-descriptions-item :label="$t('自编号')">
{{shipmentObj.selfNo}}
</el-descriptions-item>
<el-descriptions-item :label="$t('运输方式')">
<dict-tag :type="DICT_TYPE.ECW_TRANSPORT_TYPE" :value="shipmentObj.transportType" />
</el-descriptions-item>
<el-descriptions-item :label="$t('始发地')">
{{getCityName(shipmentObj.startWarehouseId)}}
</el-descriptions-item>
<el-descriptions-item :label="$t('目的地')">
{{getCityName(shipmentObj.destWarehouseId)}}
</el-descriptions-item>
</el-descriptions>
</el-card>
<el-row style="margin-top: 15px">
<el-row>
<el-button size="small" type="primary" @click="()=>tallyClick('batch')">{{$t('批量理货')}}</el-button>
<el-button size="small" type="primary" @click="()=>removeClick('batch')">{{$t('批量移出')}}</el-button>
</el-row>
<el-row style="margin-top: 5px">
<el-table border :data="tallyList" @select="checkboxSelect" @select-all="checkboxSelect" max-height="600px">
<el-table-column type="selection" align="center" width="55" fixed="left" />
<el-table-column align="center" :label="$t('序号')" width="50" prop="tidanNum" />
<el-table-column :label="$t('订单号')" align="center" prop="orderNo">
<template slot-scope="scope">
<div>
{{scope.row.orderNo}}
</div>
<div style="color:blue;fontWeight:bold;">
{{ scope.row.isExternalWarehouse === 1 ? ('('+$t('外部仓')+')') : ''}}
</div>
<div style="color:red;fontWeight:bold;">
{{ scope.row.adjustToDestWarehouseId > 0 ? ('('+$t('调仓')+')') : ''}}
</div>
</template>
</el-table-column>
<el-table-column :label="$t('商品信息')" width="250px" align="center" prop="">
<template slot-scope="{row}">
{{$l(row,'prodTitle')}}
</template>
</el-table-column>
<el-table-column :label="$t('备案')" align="center" prop="feeType">
<template slot-scope="{row}">
<template v-if="row.brandName">{{row.brandName}}</template>
<dict-tag v-else :type="DICT_TYPE.ECW_IS_BRAND" :value="row.feeType" />
</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="warehouseInInfo.cartonsNum">
<template slot-scope="scope">
<el-link type="primary" @click.native="showWarehouseLogs(scope.row)">
{{scope.row.warehouseInInfo.cartonsNum}}
</el-link>
<div style="color:blue;fontWeight:bold;">
{{ scope.row.multiSpecification === true ? '(多规格)' : ''}}
</div>
</template>
</el-table-column>
<el-table-column :label="$t('纸箱尺寸')" align="center" prop="warehouseInInfo.boxGauge">
</el-table-column>
<el-table-column :label="$t('体积')" align="center" prop="warehouseInInfo.volume">
</el-table-column>
<el-table-column :label="$t('重量')" align="center" prop="warehouseInInfo.weight">
</el-table-column>
<el-table-column :label="$t('数量(个)')" align="center" prop="quantity"></el-table-column>
<el-table-column :label="$t('储位')" align="center" prop="positionNo" width="250px">
<template slot-scope="scope">
{{notset(scope.row.positionNo)}}
</template>
</el-table-column>
<el-table-column :label="$t('状态')" align="center" prop="tallyStatus">
<template slot-scope="scope">
{{scope.row.tallyStatus === 1 ? $t('已理货') : $t('未理货')}}
</template>
</el-table-column>
<el-table-column :label="$t('理货时间')" align="center" prop="tallyTime">
<template slot-scope="scope">
{{formatDate(scope.row.tallyTime,'YYYY-MM-DD HH:mm:ss')}}
</template>
</el-table-column>
<el-table-column :label="$t('操作')" align="center" width="160" class-name="small-padding fixed-width" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="small" @click="tallyClick('single',scope.row)">{{$t('理货')}}</el-button>
<el-button type="text" size="small" @click="removeClick('single',scope.row)">{{$t('移出')}}</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-row>
<el-row style="margin-top: 15px" class="operate-button">
<el-button size="small" type="primary" @click="tallyFinish">{{$t('完成理货')}}</el-button>
<el-button size="small" @click="cancel">{{$t('取消')}}</el-button>
</el-row>
</el-col>
</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>
<batchTally v-if="dialogConfig.dialogVisible" v-bind="$attrs" @closeDialog="closeDialog" :type="dialogConfig.type" :tallyRows="tallyRows" :shipmentObj="shipmentObj" />
</el-dialog>
<warehouse-detail :order="order" :orderItemId="showWarehouseInItemId" v-if="showWarehouseInItemId" @close="showWarehouseInItemId=null" />
</div>
</template>
<script>
import batchTally from "./batchTally.vue";
import { getTallyList, tallyRemove, tallyCommit } from "@/api/ecw/boxSea";
import { formatDate, serviceMsg } from "../../utils";
import WarehouseDetail from "./warehouseDetail";
import { getOrder } from "@/api/ecw/order";
export default {
name: "tally",
inheritAttrs: false,
components: {
batchTally,
WarehouseDetail,
},
props: {
shipmentObj: Object,
},
data() {
return {
showWarehouseInItemId: null,
order: null,
tallyList: [],
// 理货数据
tallyRows: [],
// 勾选行
selectedRows: [],
// 弹窗配置
dialogConfig: {
title: "",
dialogVisible: false,
width: "30%",
type: "",
fullscreen: false,
},
};
},
created() {
this.getList();
},
methods: {
// 格式化日期
formatDate,
//去重
notset(string){
if(!string) return string
let arr = string.split(',')
arr = arr.filter((item,index)=>{return arr.indexOf(item)==index})
return arr.toString()
},
// 查询理货列表
getList() {
getTallyList({ shipmentId: this.shipmentObj.id }).then((res) => {
let list = [];
res.data.forEach((item) => {
item.orderItemList.forEach((oItem) => {
let warehouseInInfo = {};
if (oItem.warehouseInInfo) {
warehouseInInfo = JSON.parse(oItem.warehouseInInfo ?? {});
}
list.push({
...oItem,
warehouseInInfo,
multiSpecification: item.multiSpecification,
positionNo: oItem.positionNo,
tallyStatus: item.tallyStatus,
tallyTime: item.tallyTime,
});
});
});
// let relist = []
// list.forEach(l=>{
// let index = relist.findIndex(i=>i.orderId == l.orderId && i.positionNo == l.positionNo)
// if(index == -1){
// relist.push(l)
// }else{
// relist[index].warehouseInInfo.cartonsNum = parseInt(relist[index].warehouseInInfo.cartonsNum)+parseInt(l.warehouseInInfo.cartonsNum)
// }
// })
this.tallyList = list;
});
},
// 选中
checkboxSelect(selection) {
this.selectedRows = selection;
},
// 理货点击
tallyClick(type, data) {
if (type === "batch") {
if (this.selectedRows.length === 0) {
this.$message.error(this.$t("请选择需要理货的订单"));
return;
}
this.tallyRows = this.selectedRows;
this.showDialog("batchTally");
} else {
this.tallyRows = [data];
this.showDialog("singleTally");
}
},
// 移出点击
removeClick(type, data) {
let orderNos = [],
orderIds = [];
if (type === "batch") {
if (this.selectedRows.length === 0) {
this.$message.error(this.$t("请选择需要移出的订单"));
return;
}
orderNos = this.selectedRows.map((item) => item.orderNo);
orderIds = this.selectedRows.map((item) => item.orderId);
} else {
orderNos = [data.orderNo];
orderIds = [data.orderId];
}
let msgTitle = this.$t("您确定要将 {no} 移出 {selfNo} 吗?", {
no: orderNos.join(""),
selfNo: this.shipmentObj.selfNo,
});
this.$confirm(msgTitle, this.$t("提示"), {
type: "warning",
})
.then((_) => {
let param = {
orderIdLIst: orderIds,
shipmentId: this.shipmentObj.id,
}
tallyRemove(param).then((res) => {
serviceMsg(res, this).then(() => {
this.getList();
});
}).catch((res) => {
if (res.code === 666) {
this.$confirm("<div style='max-height:500px;overflow:auto'>"+res.msg+this.$t('是否需要一起移出?')+"</div>", this.$t("提示"), {
dangerouslyUseHTMLString: true,
distinguishCancelAndClose: true,
confirmButtonText: '确定移出',
cancelButtonText: '仅移出当前订单'
})
.then((_) => {
tallyRemove({ ...param, deleteType: 2 }).then((res) => {
serviceMsg(res, this).then(() => {
this.getList();
});
});
})
.catch(action => {
if(action =='cancel'){
tallyRemove({ ...param, deleteType: 1 }).then((res) => {
serviceMsg(res, this).then(() => {
this.getList();
});
});
}
});
}
});
})
.catch((_) => {});
},
// 关闭弹窗
closeDialog(type) {
this.$set(this.dialogConfig, "dialogVisible", false);
if (type === "query") {
this.getList();
}
},
// 打开弹窗
showDialog(type) {
switch (type) {
case "batchTally":
this.$set(this.dialogConfig, "title", this.$t("批量理货"));
this.$set(this.dialogConfig, "width", "500px");
break;
case "singleTally":
this.$set(this.dialogConfig, "title", this.$t("理货确认"));
this.$set(this.dialogConfig, "width", "500px");
break;
}
this.$set(this.dialogConfig, "type", type);
this.$set(this.dialogConfig, "dialogVisible", true);
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
// 理货完成
tallyFinish() {
tallyCommit({ shipmentId: this.shipmentObj.id }).then((res) => {
serviceMsg(res, this).then(() => {
this.$emit("closeDialog", "submit");
});
});
},
// 显示入仓记录
showWarehouseLogs(row) {
getOrder(row.orderId).then((response) => {
this.order = response.data;
this.showWarehouseInItemId = row.orderItemId;
});
},
},
computed: {
/* 获取仓库 */
getCityName() {
return (id) => {
let arr = this.$attrs.warehouseList.filter((item) => item.id == id);
return arr.length > 0 ? this.$l(arr[0], "title") : this.$t("");
};
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<!-- 订单获取入仓记录 -->
<el-dialog :title="title" visible :before-close="closeDialog" :close-on-click-modal="false" width="95%" append-to-body>
<el-table v-if="warehouseItem && warehouseItem.orderWarehouseInBackItemDoList" :data="warehouseItem.orderWarehouseInBackItemDoList">
<el-table-column type="index" :label="$t('序号')" />
<el-table-column :label="$t('箱数')" prop="cartonsNum" />
<el-table-column :label="$t('入仓类型')" prop="cartonsNum">
<template slot-scope="{row}">
<dict-tag :type="DICT_TYPE.WAREHOUSING_SPECIFICATION_TYPE" :value="row.specificationType" />
</template>
</el-table-column>
<el-table-column :label="$t('包装类型')" prop="unit">
<template slot-scope="{row}">
<dict-tag :type="DICT_TYPE.ECW_PACKAGING_TYPE" :value="row.unit" />
</template>
</el-table-column>
<el-table-column :label="$t('长')" prop="boxGauge">
<template slot-scope="{row}">
{{row.boxGauge.split('*')[0]}}
</template>
</el-table-column>
<el-table-column :label="$t('宽')" prop="boxGauge">
<template slot-scope="{row}">
{{row.boxGauge.split('*')[1]}}
</template>
</el-table-column>
<el-table-column :label="$t('高')" prop="boxGauge">
<template slot-scope="{row}">
{{row.boxGauge.split('*')[2]}}
</template>
</el-table-column>
<el-table-column :label="$t('体积') + '(m³)'" prop="volume" />
<el-table-column :label="$t('重量') + '(kg)'" prop="weight" />
<el-table-column :label="$t('数量(个)')" prop="quantityAll" />
<el-table-column :label="$t('快递单号')" prop="expressNo" />
<el-table-column :label="$t('储位')" align="center" prop="positionNo" width="250px">
<template slot-scope="{row}">{{row.orderLocationBackVOList.map(e => (e.areaName + (e.locationName === null ? '' : e.locationName))).join(',')}}</template>
</el-table-column>
<el-table-column :label="$t('首次入仓时间')" prop="inTime">
<template slot-scope="{row}">{{row.inTime|parseTime}}</template>
</el-table-column>
</el-table>
</el-dialog>
</template>
<script>
import { getOrder, getOrderWarehouseIn } from "@/api/ecw/order";
import { DICT_TYPE } from "@/utils/dict";
import { parseTime } from "@/utils/ruoyi";
export default {
filters: { parseTime },
props: {
order: Object, // order 和 orderId 二选一
orderId: Number,
orderItemId: Number,
},
data() {
return {
orderDetail: null,
warehouseList: null,
};
},
computed: {
info() {
return this.orderDetail || this.order;
},
orderItem() {
if (!this.info) return null;
return this.info.orderItemVOList.find(
(item) => item.orderItemId == this.orderItemId
);
},
warehouseItem() {
if (!this.warehouseList) return [];
return (
this.warehouseList.find(
(item) => item.orderItemId == this.orderItemId
) || []
);
},
title() {
if (!this.orderItem) return "-";
return this.$l(this.orderItem, "prodTitle") + " - " + this.$t("入仓记录");
}
},
created() {
this.show = true;
if (!this.order && this.orderId) {
getOrder(this.orderId).then((res) => {
this.orderDetail = res.data;
});
}
this.getOrderWarehouseIn();
},
methods: {
closeDialog() {
this.show = false;
this.$emit("close");
},
getOrderWarehouseIn() {
getOrderWarehouseIn(this.info.orderId).then((res) => {
this.warehouseList = res.data;
});
},
},
};
</script>
<template>
<div>
<el-form ref="trailerForm" :rules="rules" :model="trailerObj" label-width="120px">
<el-form-item :label="$t('状态')">
<el-select v-model="trailerObj.tlContainerStatus" :placeholder="$t('请选择状态')">
<el-option v-for="type in this.getDictDatas(DICT_TYPE.BOX_SHIPPING_TRAILER_STATUS)" :key="type.value" :label="$l(type, 'label')" :value="type.value"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('拖车公司')">
<supplierSelect v-model="trailerObj.tlCompanyId" :companyType="'4'" :areaType="0" :placeholder="$t('请选择拖车公司')" :allSupplier="this.$attrs.allSupplier" />
</el-form-item>
<el-form-item :label="$t('拖车时间')" prop="tlTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" value-format="yyyy-MM-dd HH:mm:ss" v-model="trailerObj.tlTime"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('车牌')">
<el-input v-model="trailerObj.tlLicensePlate " :placeholder="$t('请输入车牌')"></el-input>
</el-form-item>
<el-form-item :label="$t('司机')">
<el-input v-model="trailerObj.tlDriver" :placeholder="$t('请输入司机')"></el-input>
</el-form-item>
<el-form-item :label="$t('司机联系方式')">
<el-input v-model="trailerObj.tlDriverContact" :placeholder="$t('请输入司机联系方式')"></el-input>
</el-form-item>
<el-form-item :label="$t('货柜号')">
<el-input v-model="trailerObj.tlContainerNo" :placeholder="$t('请输入货柜号')"></el-input>
</el-form-item>
<el-form-item :label="$t('封条')">
<el-input v-model="trailerObj.tlStripSeal" :placeholder="$t('请输入封条')"></el-input>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { trailer } from "@/api/ecw/boxSea";
import supplierSelect from "./common/supplierSelect.vue";
import {
formatStringNumber,
formatDateStr,
formatNumberString,
serviceMsg,
} from "../utils";
/**
* 拖车
*/
export default {
inheritAttrs: false,
name: "trailer",
components: { supplierSelect },
data() {
return {
// 拖车对象
trailerObj: {},
// 校验
rules: {
tlTime: [{ required: true, message: this.$t("必填"), trigger: "change" }],
},
};
},
created() {
const { currNode, shipmentObj } = this.$attrs;
const voName = currNode.voName;console.log(shipmentObj[voName])
let oldData = { ...shipmentObj[voName] };
oldData = formatNumberString(oldData, ["tlContainerStatus"]);
oldData = formatStringNumber(oldData, ["tlCompanyId"]);
oldData = formatDateStr(oldData, ["tlTime"]);
this.trailerObj = oldData;
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["trailerForm"].validate((valid) => {
if (valid) {
trailer({
...this.trailerObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<template>
<div>
<el-form ref="twoWayArrivalForm" :rules="rules" :model="twoWayArrivalObj" label-width="120px">
<el-form-item :label="$t('预计到达时间')" prop="estTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="twoWayArrivalObj.estTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('实际到达时间')" prop="actTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="twoWayArrivalObj.actTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('实际二程时间')" prop="actSecondTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="twoWayArrivalObj.actSecondTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button type="primary" @click="exceptionReg">{{$t('异常登记')}}</el-button>
</el-row>
<!-- 对话框 -->
<el-dialog custom-class="shipping-dialog" :title="$t('异常登记')" :visible.sync="dialogVisible" width="700px" :modal-append-to-body=false append-to-body destroy-on-close>
<regError @closeDialog="dialogVisible = false" v-bind="$attrs" />
</el-dialog>
</div>
</template>
<script>
import regError from "../../regError";
import { arrivalCreate } from "@/api/ecw/boxSeaAir";
import { formatDateStr, serviceMsg } from "../utils";
/**
* 起飞
*/
export default {
name: "twoWayArrival",
inheritAttrs: false,
components: {
regError,
},
data() {
return {
// 清关对象
twoWayArrivalObj: {},
// 校验
rules: {
actTime: [{ required: true, message: this.$t("必填"), trigger: "blur" }]
},
// 弹窗配置
dialogVisible: false,
// 提示消息
showMsg: false,
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, ["actTime"], "YYYY-MM-DD HH:mm:ss");
oldData = formatDateStr(oldData, ["actSecondTime"], "YYYY-MM-DD HH:mm:ss");
oldData = formatDateStr(oldData, ["estTime"], "YYYY-MM-DD HH:mm:ss");
this.twoWayArrivalObj = oldData;
},
watch: {
},
methods: {
// 异常登记
exceptionReg() {
this.dialogVisible = true;
},
/** 提交 */
onSubmit(operateType) {
this.$refs["twoWayArrivalForm"].validate((valid) => {
if (valid) {
arrivalCreate({
...this.twoWayArrivalObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
.message-area {
margin: 0;
color: red;
}
</style>
<template>
<div>
<el-form ref="twoWayTakeoffForm" :rules="rules" :model="twoWayTakeoffObj" label-width="120px">
<el-form-item :label="$t('预计头程时间')" prop="estHeadTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="twoWayTakeoffObj.estHeadTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('实际头程时间')" prop="actHeadTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="twoWayTakeoffObj.actHeadTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('预计二程时间')" prop="estSecondTime">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="twoWayTakeoffObj.estSecondTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button type="primary" @click="exceptionReg">{{$t('异常登记')}}</el-button>
</el-row>
<!-- 对话框 -->
<el-dialog custom-class="shipping-dialog" :title="$t('异常登记')" :visible.sync="dialogVisible" width="700px" :modal-append-to-body=false append-to-body destroy-on-close>
<regError @closeDialog="dialogVisible = false" v-bind="$attrs" />
</el-dialog>
</div>
</template>
<script>
import regError from "../../regError";
import { takeoffCreate } from "@/api/ecw/boxSeaAir";
import { formatDateStr, serviceMsg } from "../utils";
/**
* 起飞
*/
export default {
name: "twoWayTakeoff",
inheritAttrs: false,
components: {
regError,
},
data() {
return {
// 清关对象
twoWayTakeoffObj: {},
// 校验
rules: {
actHeadTime: [{ required: true, message: this.$t("必填"), trigger: "blur" }],
estHeadTime: [{ required: true, message: this.$t("必填"), trigger: "blur" }],
estSecondTime: [{ required: true, message: this.$t("必填"), trigger: "blur" }],
},
// 弹窗配置
dialogVisible: false,
// 提示消息
showMsg: false,
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, ["actHeadTime"], "YYYY-MM-DD HH:mm:ss");
oldData = formatDateStr(oldData, ["estHeadTime"], "YYYY-MM-DD HH:mm:ss");
oldData = formatDateStr(oldData, ["estSecondTime"], "YYYY-MM-DD HH:mm:ss");
this.twoWayTakeoffObj = oldData;
},
watch: {
},
methods: {
// 异常登记
exceptionReg() {
this.dialogVisible = true;
},
/** 提交 */
onSubmit(operateType) {
this.$refs["twoWayTakeoffForm"].validate((valid) => {
if (valid) {
takeoffCreate({
...this.twoWayTakeoffObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
},
};
</script>
<style lang="scss" scoped>
.message-area {
margin: 0;
color: red;
}
</style>
<template>
<div>
<el-form ref="unloadingForm" :model="unloadingObj" label-width="100px">
<el-form-item :label="$t('网点')">
<el-select filterable v-model="unloadingObj.ulOutletsId" clearable :placeholder="$t('请选择')">
<el-option v-for="node in nodes" :key="node.id" :label="$l(node, 'title')" :value="node.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('到仓时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="unloadingObj.ulWarehouseTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item :label="$t('卸柜时间')">
<el-date-picker type="datetime" :placeholder="$t('请选择日期')" v-model="unloadingObj.ulBoxTime" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="primary" @click="onSubmit(1)">{{$t('保存')}}</el-button>
<el-button type="success" @click="onSubmit(2)">{{$t('提交')}}</el-button>
<el-button @click="cancel">{{$t('关闭')}}</el-button>
<el-button type="danger" @click="startUnloading" :disabled="isStartUnloading">{{$t('开始卸柜')}}</el-button>
</el-row>
<!-- 开始卸柜 -->
<el-dialog :title="$t('开始卸柜')" :visible.sync="dialogVisible" fullscreen :modal-append-to-body=false append-to-body>
<startUnloading v-if="dialogVisible" v-bind="$attrs" @closeStart="closeStart" />
</el-dialog>
</div>
</template>
<script>
import startUnloading from "./startUnloading.vue";
import { unloadCreate } from "@/api/ecw/boxSea";
import { formatDateStr, serviceMsg } from "../../utils";
import { getNodePage } from "@/api/ecw/node";
/**
* 卸柜
*/
export default {
name: "unloading",
inheritAttrs: false,
components: { startUnloading },
data() {
return {
// 清关对象
unloadingObj: {},
// 弹窗状态
dialogVisible: false,
nodes: [],
};
},
created() {
const voName = this.$attrs.currNode.voName;
let oldData = { ...this.$attrs.shipmentObj[voName] };
oldData = formatDateStr(oldData, ["ulWarehouseTime", "ulBoxTime"]);
this.unloadingObj = oldData;
// 进入卸柜,仓库给了默认值为0,并且底下显示无匹配数据。应该默认为空,让手动去选择
if(this.unloadingObj.ulOutletsId === 0) this.unloadingObj.ulOutletsId = ''
getNodePage({ pageNo: 1, pageSize: 1000, status: 0 }).then((res) => {
const { data } = res;
this.nodes = data?.list ?? [];
});
},
methods: {
/** 提交 */
onSubmit(operateType) {
this.$refs["unloadingForm"].validate((valid) => {
if (valid) {
if (operateType === 2) {
const { keyName } = this.$attrs.currNode;
const ulStatus = this.$attrs.shipmentObj[keyName];
if (ulStatus !== 185) {
this.$message.error(this.$t("请先通过卸柜审批"));
return;
}
}
unloadCreate({
...this.unloadingObj,
shipmentId: this.$attrs.shipmentObj.id,
operateType,
}).then((res) => {
serviceMsg(res, this).then(() => {
this.cancel("submit");
});
});
}
});
},
/** 取消 */
cancel(type) {
this.$emit("closeDialog", type);
},
/* 关闭弹窗 */
closeStart(type) {
this.dialogVisible = false;
if (type) this.cancel(type);
},
// 开始卸柜
startUnloading() {
this.dialogVisible = true;
},
},
computed: {
isStartUnloading() {
const { currNode, shipmentObj } = this.$attrs;
const status = shipmentObj[currNode.keyName];
return status === 186 ? true : false;
},
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div class="app-startUnloading">
<!-- 自编号 -->
<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" @click="modifyUnload">{{$t('提交')}}</el-button>
<el-button type="primary" @click="modifyBatchUnload">{{$t('批量输入')}}</el-button>
<el-button type="primary" @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 class="table-area">
<el-table v-loading="loading" :data="pageData.sectionOrderList" border max-height="500px">
<el-table-column :label="$t('序号')" align="center" width="50" prop="tidanNum" />
<el-table-column :label="$t('订单号')" align="center" prop="orderNo">
<template slot-scope="scope">
{{ scope.row.orderNo }}
</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" />
<el-table-column :label="$t('卸柜箱数')" align="center" prop="unloadNum" />
<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="volume" />
<el-table-column :label="$t('重量')" align="center" prop="weight" />
<el-table-column :label="$t('订单状态')" align="center" prop="">
<template slot-scope="scope">
{{getOrderError(scope.row, 'orderStatus')}}
</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">
<el-button type="danger" size="small" @click="openError(scope.row)">{{$t('异常')}}</el-button>
</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" @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="$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>
</div>
</template>
<script>
import unloadingError from "./unloadingError.vue";
import {
loadGoodsList,
batchUnload,
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";
/**
* 开始卸柜
*/
export default {
name: "startUnloading",
inheritAttrs: false,
components: { unloadingError, WorkFlow },
data() {
return {
// 标签号
labelNo: "",
// 当前部分
currPart: "",
// loading
loading: false,
// 页面数据
pageData: {},
// 弹窗配置
dialogVisible: false,
// 自编号
selfNo: this.$attrs.shipmentObj.selfNo,
// 当前行
currRow: {},
// 部分
sectionList: [],
// 已选部分
sectionId: "0",
// 部分订单商品
sectionObj: {
secStatistics: {},
sectionOrderList: [],
totalStatistics: {},
},
selectedUsers: [],
};
},
created() {
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: {
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;
}
batchUnload({
orderNo: this.labelNo,
shipmentId: this.$attrs.shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then((res) => {
this.labelNo = "";
this.getLoadGoodsList();
});
});
},
/* 一键卸柜 */
modifyAllUnload() {
this.$confirm(this.$t("确认卸柜?"), this.$t("提示"), {
type: "warning",
})
.then((_) => {
allUnload({ shipmentId: this.$attrs.shipmentObj.id }).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();
});
});
},
/** 取消 */
cancel() {
this.$emit("closeStart", "submit");
},
/* 关闭弹窗 */
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");
},
},
computed: {
/* 是否审核中 */
isUnderReview() {
const { currNode, shipmentObj } = this.$attrs;
return shipmentObj[currNode.keyName] === 183 ? 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>
.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>
<template>
<div>
<el-form ref="errorForm" :model="errorObj" label-width="100px" :rules="rules">
<el-form-item :label="$t('异常')" prop="exceptionType">
<el-radio-group v-model="errorObj.exceptionType">
<el-radio v-for="item in this.getDictDatas(DICT_TYPE.BOX_SHIPPING_UNLOADING_ERROR)" :key="item.value" :label="item.value">{{$l(item, 'label')}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('品名')">
<el-select v-model="errorObj.productId" :placeholder="$t('请选择品名')">
<el-option v-for="(item, index) in goodsList" :key="index" :value="item.orderItemId" :label="$l(item, 'prodTitle')"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('件数')" prop="productNum">
<el-input-number v-model="errorObj.productNum" controls-position="right" :min="1"></el-input-number>
</el-form-item>
<el-form-item :label="$t('异常详情')">
<el-input v-model="errorObj.exceptionDetail" type="textarea" rows="2" :placeholder="$t('请输入异常详情')"></el-input>
</el-form-item>
</el-form>
<el-row class="operate-button">
<el-button type="success" @click="onSubmit">{{$t('提交')}}</el-button>
<el-button @click="$emit('closeDialog')">{{$t('关闭')}}</el-button>
</el-row>
</div>
</template>
<script>
import { createError } from "@/api/ecw/boxSea";
import { serviceMsg } from "../../utils";
import { debounce } from "throttle-debounce";
/**
* 卸柜异常
*/
export default {
name: "unloadingError",
inheritAttrs: false,
data() {
const { currRow } = this.$attrs;
return {
// 校验
rules: {
exceptionType: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
productNum: [
{ required: true, message: this.$t("必填"), trigger: "change" },
],
},
// 异常对象
errorObj: {
productId: currRow.goodsList[0].orderItemId,
},
// 品名
goodsList: currRow.goodsList ?? [],
};
},
methods: {
/** 提交 */
onSubmit: debounce(340, function onSubmit() {
this.$refs["errorForm"].validate((valid) => {
if (valid) {
const { productNum = 0 } = this.errorObj;
const { currRow } = this.$attrs;
if (productNum > currRow.installNum) {
this.$message.error(this.$t("货物异常数量不能大于装柜数量"));
return;
}
createError({
...this.errorObj,
orderId: this.$attrs.currRow.orderId,
shipmentId: this.$attrs.shipmentObj.id,
}).then((res) => {
serviceMsg(res, this).then((res) => {
this.$emit("closeDialog", "query");
});
});
}
});
}),
},
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div class="app-seaProcess">
<!-- 海运流程图 -->
<el-scrollbar :vertical="true" viewClass="shipping-chart">
<div v-for="(nodes,index) in processData" :key="index" class="chart-nodes">
<div class="node-area">
<div v-for="node in nodes" :key="node.title" @click="nodeClick(index, node)" class="node-div">
<div>
<img :src="getImgSrc(node)" alt="" :width="width" :height="height">
<p>{{node.title}}</p>
</div>
</div>
</div>
<div class="arrow-area" v-if="index !== (processData.length-1)">
<img src="@/assets/images/shipping/jt-start.png" alt="" v-if="index >= currIndex">
<img src="@/assets/images/shipping/jt-end.png" alt="" v-if="index < currIndex">
</div>
</div>
</el-scrollbar>
<!-- 弹窗 -->
<el-dialog custom-class="shipping-dialog" :title="dialogConfig.title" :visible.sync="dialogConfig.dialogVisible" :width="dialogConfig.width" :fullscreen="dialogConfig.fullscreen" :close-on-click-modal=false :modal-append-to-body=false append-to-body>
<component v-bind:is="currentComponent" v-if="dialogConfig.dialogVisible" @closeDialog="closeDialog" v-bind="$attrs" v-on="$listeners" :shipmentObj="shipmentObj" :currNode="currNode"></component>
</el-dialog>
</div>
</template>
<script>
import bookingWidget from "./nodePage/booking.vue";
import trailerWidget from "./nodePage/trailer.vue";
import preinstallWidget from "./nodePage/preinstall.vue";
import agentWidget from "./nodePage/agent.vue";
import cabinetWidget from "./nodePage/cabinet/index.vue";
import cusDeclarationWidget from "./nodePage/cusDeclaration.vue";
import shipWidget from "./nodePage/ship.vue";
import subMaterialWidget from "./nodePage/subMaterial.vue";
import bargeWidget from "./nodePage/barge.vue";
import departureWidget from "./nodePage/departure.vue";
import blCopyWidget from "./nodePage/blCopy.vue";
import clrDocumentWidget from "./nodePage/clrDocument.vue";
import arrivalWidget from "./nodePage/arrival.vue";
import cusClearanceWidget from "./nodePage/cusClearance.vue";
import twoWayTakeoffWidget from "./nodePage/twoWayTakeoff.vue";
import twoWayArrivalWidget from "./nodePage/twoWayArrival.vue";
import unloadingWidget from "./nodePage/unloading/index.vue";
import settlementWidget from "./nodePage/settlement.vue";
import reviewWidget from "./nodePage/review.vue";
import tallyWidget from "./nodePage/tally/index.vue";
import {checkPermi} from '@/utils/permission'
/**
* 海运流程图
*/
export default {
name: "shippingChart",
inheritAttrs: false,
components: {
bookingWidget,
trailerWidget,
preinstallWidget,
agentWidget,
cabinetWidget,
cusDeclarationWidget,
shipWidget,
subMaterialWidget,
bargeWidget,
departureWidget,
blCopyWidget,
clrDocumentWidget,
arrivalWidget,
cusClearanceWidget,
twoWayTakeoffWidget,
twoWayArrivalWidget,
unloadingWidget,
settlementWidget,
reviewWidget,
tallyWidget,
},
props: {
shipmentObj: Object,
seaBaseData: Array,
width: {
type: String,
default: "76px",
},
height: {
type: String,
default: "76px",
},
},
data() {
return {
// 弹窗配置
dialogConfig: {
dialogVisible: false,
title: "",
width: "",
fullscreen: false,
},
// 当前组件
currentComponent: "",
// 当前步骤节点坐标
currIndex: 0,
// 当前节点
currNode: {},
// 数据
processData: this.seaBaseData,
errorMsg: this.$t('请先完成上一步')
};
},
created() {},
/* computed: {
isShowAgent() {
return (type) => {
if (type === "agent") {
const { preInstallInfo } = this.shipmentObj;
const user = this.$store.state.user;
if (preInstallInfo && preInstallInfo.noticeUser === user.id)
return true;
return false;
}
return true;
};
},
}, */
methods: {
/** 关闭弹窗 */
closeDialog(type) {
this.$set(this.dialogConfig, "dialogVisible", false);
if (type === "submit") {
this.$emit("getBoxInfo");
}
},
/** 节点点击 */
nodeClick(currIndex, node) {
if (!checkPermi(['box:'+node.type+':show'])) {
this.$message.error(this.$t("没有此操作的权限"));
return;
}
if (currIndex > this.currIndex) {
this.$message.error(this.errorMsg);
return;
}
this.currNode = node;
this.currentComponent = `${node.type}Widget`;
this.$set(this.dialogConfig, "width", "500px");
this.$set(this.dialogConfig, "title", node.title);
this.$set(this.dialogConfig, "fullscreen", false);
switch (node.type) {
// 订舱
case "booking":
// 驳船
case "barge":
// 清关文件
case "clrDocument":
this.$set(this.dialogConfig, "width", "700px");
break;
// AGENT
case "agent":
this.$set(this.dialogConfig, "title", this.$t("代理商设置"));
break;
// 理货
case "tally":
this.$set(this.dialogConfig, "fullscreen", true);
break;
// 预装
case "preinstall":
// 预装反审
const preStatus = this.shipmentObj[node.keyName];
if ([25].includes(preStatus)) {
this.currentComponent = `reviewWidget`;
this.$set(this.dialogConfig, "width", "700px");
this.$set(this.dialogConfig, "title", this.$t("预装反审"));
} else {
this.$set(this.dialogConfig, "fullscreen", true);
this.$set(this.dialogConfig, "title", this.$t("出货安排(预装)"));
}
// 装柜
case "cabinet":
// 装柜反审
const cabStatus = this.shipmentObj[node.keyName];
if ([47].includes(cabStatus)) {
this.currentComponent = `reviewWidget`;
this.$set(this.dialogConfig, "width", "700px");
this.$set(this.dialogConfig, "title", this.$t("装柜反审"));
}
break;
// 卸柜
case "unloading":
// 卸柜反审
const unStatus = this.shipmentObj[node.keyName];
if ([186].includes(unStatus)) {
this.currentComponent = `reviewWidget`;
this.$set(this.dialogConfig, "width", "700px");
this.$set(this.dialogConfig, "title", this.$t("卸柜反审"));
}
break;
}
this.$set(this.dialogConfig, "dialogVisible", true);
},
/* 获取图片路径 */
getImgSrc(node) {
return node.imgSrc[node.currStatus ?? "start"];
},
},
watch: {
/* 监听发货对象 */
shipmentObj(val) {
let newNodes = [],
finish = 0;
// 迭代每个节点
for (let i = 0; i < this.seaBaseData.length; i++) {
const nodes = this.seaBaseData[i];
let nodeIndex = 0;
for (let j = 0; j < nodes.length; j++) {
const node = nodes[j];
const { keyName, voName, status, type } = node;
// agent
if (!keyName && type === "agent") {
if (val[voName]) {
// 已完成agent节点
node.currStatus = "end";
++nodeIndex;
}
continue;
}
const { start, wait, end } = status;
if (start.includes(val[keyName])) {
node.currStatus = "start";
}
if (start.includes(val[keyName]) && val[voName]) {
node.currStatus = "wait";
}
if (wait.includes(val[keyName])) {
node.currStatus = "wait";
}
if (end.includes(val[keyName])) {
node.currStatus = "end";
// 判断是否存在异常未处理
if (
(type === "cusDeclaration" && val.customsHasAbnormal) ||
(type === "departure" && val.shippingHasAbnormal) ||
(type === "arrival" && val.arrivalHasAbnormal)
) {
this.errorMsg = this.$t('请先处理完出货异常,再进行操作')
continue;
}
// 报关
if (type === "cusDeclaration") {
const { dcCustomsStatus, dcCheckStatus } = val;
// 查验状态并且是退场/部分退场
if (dcCustomsStatus === 3 && [1, 2].includes(dcCheckStatus)) {
// 只有审核通过并且已处理才算完成
if (val.checkExamineStatus === 2 && val.checkDealStatus === 1) {
// 已完成节点个数
++nodeIndex;
} else {
continue;
}
}
}
// 已完成节点个数
++nodeIndex;
}
}
// 如果相等标识该步骤已完成
if (nodeIndex === nodes.length) {
// 加1表示为已完成步骤后一步
finish = finish + 1;
}
newNodes.push(nodes);
}
this.currIndex = finish;
this.processData = newNodes;
},
},
};
</script>
<style lang="scss">
.app-seaProcess {
.shipping-chart {
display: flex;
padding: 10px 10px;
min-width: 1300px;
width: max-content;
.chart-nodes {
display: flex;
align-items: center;
justify-content: center;
.node-area {
display: flex;
flex-direction: column;
align-items: center;
.node-div {
text-align: center;
margin-top: 10px;
cursor: pointer;
p {
margin-top: -10px;
margin-bottom: 0px;
text-align: center;
}
}
}
.arrow-area {
margin: 0 6px;
}
}
}
}
</style>
<template>
<div class="app-seaStepDetail">
<el-scrollbar :vertical="true" viewClass="shipping-step">
<template v-for="(step, index) in flatSeaStep">
<div :key="index" v-if="shipmentObj[step.voName] && columnsMapping[step.voName] && checkPermi(['box:'+step.type+':show'])" class="step-table">
<div class="step-title">{{step.title}}</div>
<div v-for="(data, index) in columnsMapping[step.voName]" :key="index" class="step-content">
<p>{{data.title}}</p>
<p>{{getObjInfo(step.voName, data)}}</p>
</div>
</div>
</template>
</el-scrollbar>
</div>
</template>
<script>
import dayjs from "dayjs";
import * as _C from "./utils";
import {checkPermi} from '@/utils/permission'
export default {
name: "seaStepDetail",
inheritAttrs: false,
props: {
shipmentObj: Object,
seaBaseData: Array,
},
data() {
return {
flatSeaStep: this.seaBaseData.flat(),
columnsMapping: _C.getColmnMapping(),
};
},
methods: {
checkPermi, // 检查权限
getObjInfo(voName, data) {
const { key, type } = data;
let val = this.shipmentObj[voName]?.[key] ?? "";
if (val) {
switch (type) {
case "date":
case "datetime":
val = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
break;
case "supplier":
val = this.getSupplier(Number(val));
break;
case "dock":
val = this.getDock(Number(val));
break;
case "warehouse":
val = this.getWarehouse(Number(val));
break;
case "shipping_dcCustoms_status":
case "shipping_customs_type":
val = this.getDict(type, String(val));
break;
case "saExmtStatus":
case "bgExmtStatus":
case "isFile":
case "billingMethod":
val = this.getConstant(type, String(val));
break;
case "user":
val = this.getUser(val);
break;
}
}
return val === 0 ? "" : val;
},
getSupplier(id) {
return (
this.$l(this.$attrs.allSupplier.find((item) => item.id === id), 'company') // ?? id
);
},
getDock(id) {
return this.$l(this.$attrs.allDocks.find((item) => item.id === id), 'title') ?? id;
},
getWarehouse(id) {
return (
this.$l(this.$attrs.warehouseList.find((item) => item.id === id), 'title') ?? id
);
},
getUser(id) {
return (
this.$attrs.allUsers.find((item) => item.id === id)?.nickname ?? id
);
},
getDict(code, id) {
return (
this.$l(this.getDictDatas(code).find((item) => item.value === id), 'label') ?? id
);
},
getConstant(code, id) {
return (
_C.constantDict[code].find((item) => item.value === id)?.label ?? id
);
},
},
};
</script>
<style lang="scss">
.app-seaStepDetail {
.shipping-step {
margin-top: 15px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: flex-start;
height: 550px;
min-width: 1300px;
padding: 10px 10px;
overflow-x: auto;
p {
margin: 0;
}
.step-table {
width: 200px;
border: 1px solid gray;
margin-bottom: 15px;
margin-right: 15px;
.step-title {
font-size: 16px;
font-weight: bolder;
background-color: #c6c8ce;
line-height: 30px;
text-align: center;
}
.step-content {
display: grid;
border-top: 1px solid gray;
font-size: 14px;
line-height: 25px;
grid-template-columns: repeat(2, 1fr);
> p:first-child {
border-right: 1px solid gray;
}
> p {
padding: 0 5px;
}
}
}
}
}
</style>
<template>
<div>
<el-row type="flex" style="margin-top: 15px; margin-bottom: 15px" justify="center">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="19">
<div style="display: flex; justify-content: space-between;align-items: flex-end;">
<h2>{{$t('空运出货操作')}}</h2>
</div>
<!-- 信息 -->
<el-card style="margin-top: 15px">
<el-descriptions :column="5" border>
<el-descriptions-item :label="$t('自编号')">{{shipmentObj.selfNo}}</el-descriptions-item>
<el-descriptions-item :label="$t('运输方式')">
<dict-tag :type="DICT_TYPE.ECW_TRANSPORT_TYPE" :value="shipmentObj.transportType" />
</el-descriptions-item>
<el-descriptions-item :label="$t('始发地')">
{{importCityName(shipmentObj.startWarehouseId)}}
</el-descriptions-item>
<el-descriptions-item :label="$t('目的地')">
{{importCityName(shipmentObj.destWarehouseId)}}
</el-descriptions-item>
<el-descriptions-item :label="$t('状态')">
{{shipmentObj.shipmentStatusText}}
</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 海运流程图 -->
<seaProcess :seaBaseData="seaBaseData" :shipmentObj="shipmentObj" :allSupplier="allSupplier" :allDocks="allDocks" :allUsers="allUsers" :allLading="allLading" :warehouseList="warehouseList" @getBoxInfo="getBoxInfo" />
<!-- 海运步骤图 -->
<seaStepDetail :seaBaseData="seaBaseData" :shipmentObj="shipmentObj" :allSupplier="allSupplier" :allDocks="allDocks" :allUsers="allUsers" :warehouseList="warehouseList" />
</el-col>
</el-row>
</div>
</template>
<script>
import seaProcess from "./seaProcess.vue";
import seaStepDetail from "./seaStepDetail.vue";
import { getbox } from "@/api/ecw/box";
import { getWarehouseList } from "@/api/ecw/warehouse";
import { getSupplierPage } from "@/api/ecw/supplier";
import { getDockPage } from "@/api/ecw/dock";
import { listUser } from "@/api/system/user";
import { getLadingShipperPage } from "@/api/ecw/ladingShipper";
// 这里引入的数据切换语言后要刷新才生效,优化办法是label同时配备labelEn字段,然后再页面上用$l函数调用
import { airBaseData } from "./utils";
/**
* 海运操作主页面
*/
export default {
name: "shippingSea",
components: {
seaProcess,
seaStepDetail,
},
props: {
shipmentId: String,
},
data() {
return {
shipmentObj: {},
warehouseList: [],
// 供应商
allSupplier: [],
// 托运人
allLading: [],
// 码头
allDocks: [],
// 用户
allUsers: [],
// 流程图节点
seaBaseData: airBaseData(),
// 状态
statusLabel: "",
};
},
created() {
this.getBoxInfo();
// 仓库
getWarehouseList().then((r) => {
this.warehouseList = r.data;
});
// 供应商
getSupplierPage({ pageNo: "1", pageSize: "10000" }).then((res) => {
const { data } = res;
this.allSupplier = data.list.map((item) => {
if (item.companyType) {
item.companyTypes = item.companyType.split(",");
}
return item;
});
});
// 托运人
getLadingShipperPage({ pageNo: "1", pageSize: "10000" }).then(res=>{
this.allLading = res.data.list
})
// 码头
getDockPage({ pageNo: "1", pageSize: "10000" }).then((res) => {
const { data } = res;
this.allDocks = data.list;
});
// 用户
listUser({ pageNo: "1", pageSize: "10000" }).then((res) => {
const { data } = res;
this.allUsers = data.list ?? [];
});
},
methods: {
/* 获取仓库 */
importCityName(id) {
var arr = this.warehouseList.filter((item) => item.id == id);
return arr.length > 0 ? this.$l(arr[0], 'title') : "/";
},
// 出货
getBoxInfo() {
getbox(this.shipmentId).then((res) => {
const { data } = res;
this.shipmentObj = data ?? {};
});
},
},
};
</script>
<style lang="scss">
// 海运操作统一弹窗样式
.shipping-dialog {
.custom_type_red {
color: red;
}
.el-dialog__body {
height: calc(100% - 54px);
> :first-child {
height: 100%;
}
}
// 页面内元素弹窗form控件宽度设置
.el-form-item__content {
> div:not(.el-input-number) {
width: 100%;
}
}
.operate-button {
padding-top: 10px;
text-align: center;
}
.two-element {
.el-form-item__content {
display: flex;
> :last-child {
margin-left: 10px;
}
}
}
}
</style>
import dayjs from "dayjs";
import * as _BOX from "@/api/ecw/box";
import FileSaver from "file-saver";
import Decimal from "decimal.js";
import i18n from "@/i18n";
/**
* 空运流程
*
* @return {*}
*/
function airBaseData() {
return [
[
{
title: i18n.$t("订舱"),
imgSrc: {
start: require("@/assets/images/shipping/dc-start.png"),
end: require("@/assets/images/shipping/dc-end.png"),
},
type: "booking", // 类型
dataKey: "1", // 字典数据键值
/**
* 订舱状态:11、未订舱;12、已订舱
*/
voName: "bookAirInfo", // 订舱对象vo
keyName: "bkStatus",
status: {
start: [11],
wait: [],
end: [12],
},
},
],
[
{
title: i18n.$t("排单"),
imgSrc: {
start: require("@/assets/images/shipping/yz-start.png"),
wait: require("@/assets/images/shipping/yz-wait.png"),
end: require("@/assets/images/shipping/yz-end.png"),
},
type: "preinstall",
dataKey: "2", // 字典数据键值
/**
* 预装状态:21、未预装;22、预装中;23、预装审核中;24、预装审核失败;25、预装审核成功
*/
voName: "preInstallInfo",
keyName: "prStatus",
status: {
start: [21],
wait: [22, 23, 24],
end: [25],
},
},
{
title: "AGENT",
imgSrc: {
start: require("@/assets/images/shipping/agent-start.png"),
wait: require("@/assets/images/shipping/agent-wait.png"),
end: require("@/assets/images/shipping/agent-end.png"),
},
type: "agent",
voName: "agentInfo",
currStatus: "start",
},
],
[
{
title: i18n.$t("理货"),
imgSrc: {
start: require("@/assets/images/shipping/lh-start.png"),
wait: require("@/assets/images/shipping/lh-wait.png"),
end: require("@/assets/images/shipping/lh-end.png"),
},
type: "tally",
dataKey: "16", // 字典数据键值
/**
* 理货状态:2111、未理货;2112、已理货
*/
voName: "tallyInfo",
keyName: "tyStatus",
status: {
start: [2111],
wait: [],
end: [2112],
},
},
{
title: i18n.$t("拖车"),
imgSrc: {
start: require("@/assets/images/shipping/tc-start.png"),
wait: require("@/assets/images/shipping/tc-wait.png"),
end: require("@/assets/images/shipping/tc-end.png"),
},
type: "trailer",
dataKey: "3", // 字典数据键值
/**
* 拖车状态:31、未派车;32、已派车
*/
voName: "trailerInfo",
keyName: "tlStatus",
status: {
start: [31],
wait: [],
end: [32],
},
},
],
[
{
title: i18n.$t("装柜"),
imgSrc: {
start: require("@/assets/images/shipping/zg-start.png"),
wait: require("@/assets/images/shipping/zg-wait.png"),
end: require("@/assets/images/shipping/zg-end.png"),
},
type: "cabinet",
dataKey: "4", // 字典数据键值
/**
* 装柜状态:41、未装柜;42、装柜中;43、已装柜、待封柜;44、封柜审核中;45、封柜审核失败;46、封柜审核成功;47、已封柜,待出仓
*/
voName: "cabinetInfo",
keyName: "ldStatus",
status: {
start: [41],
wait: [42, 43, 44, 45, 46],
end: [47],
},
},
],
[
{
title: i18n.$t("报关"),
imgSrc: {
start: require("@/assets/images/shipping/bg-start.png"),
wait: require("@/assets/images/shipping/bg-wait.png"),
end: require("@/assets/images/shipping/bg-end.png"),
},
type: "cusDeclaration",
dataKey: "5", // 字典数据键值
/**
*报关状态:51、未报关;52、报关中;53、已报关
*/
voName: "customsInfo",
keyName: "dcStatus",
status: {
start: [51],
wait: [52],
end: [53],
},
},
{
title: i18n.$t("配船"),
imgSrc: {
start: require("@/assets/images/shipping/pc-start.png"),
wait: require("@/assets/images/shipping/pc-wait.png"),
end: require("@/assets/images/shipping/pc-end.png"),
},
type: "ship",
dataKey: "6", // 字典数据键值
/**
* 配船状态:61、未配船;62、已配船
*/
voName: "shipConfigInfo",
keyName: "saStatus",
status: {
start: [61],
wait: [],
end: [62],
},
},
{
title: i18n.$t("提单补料"),
imgSrc: {
start: require("@/assets/images/shipping/tdcl-start.png"),
wait: require("@/assets/images/shipping/tdcl-wait.png"),
end: require("@/assets/images/shipping/tdcl-end.png"),
},
type: "subMaterial",
dataKey: "7", // 字典数据键值
/**
* 提单补料状态:71、未提单补料;72、已提单补料
*/
voName: "ladingBillInfo",
keyName: "blStatus",
status: {
start: [71],
wait: [],
end: [72],
},
},
],
[
{
title: i18n.$t("驳船"),
imgSrc: {
start: require("@/assets/images/shipping/bc-start.png"),
wait: require("@/assets/images/shipping/bc-wait.png"),
end: require("@/assets/images/shipping/bc-end.png"),
},
type: "barge",
dataKey: "8", // 字典数据键值
/**
* 驳船状态:81、未驳船;82、已驳船
*/
voName: "bargeInfo",
keyName: "bgStatus",
status: {
start: [81],
wait: [],
end: [82],
},
},
],
[
{
title: i18n.$t("起运"),
imgSrc: {
start: require("@/assets/images/shipping/qy-start.png"),
wait: require("@/assets/images/shipping/qy-wait.png"),
end: require("@/assets/images/shipping/qy-end.png"),
},
type: "departure",
dataKey: "9", // 字典数据键值
/**
* 起运状态:91、未起运;92、已起运
*/
voName: "shippingInfo",
keyName: "dtStatus",
status: {
start: [91],
wait: [],
end: [92],
},
},
],
[
{
title: i18n.$t("提单Copy"),
imgSrc: {
start: require("@/assets/images/shipping/tdcopy-start.png"),
wait: require("@/assets/images/shipping/tdcopy-wait.png"),
end: require("@/assets/images/shipping/tdcopy-end.png"),
},
type: "blCopy",
dataKey: "10", // 字典数据键值
/**
* 提单COPY状态:101、未上传;102、已上传
*/
voName: "ladingCopyInfo",
keyName: "cpStatus",
status: {
start: [101],
wait: [],
end: [102],
},
},
{
type: "clrDocument",
imgSrc: {
start: require("@/assets/images/shipping/qg-start.png"),
wait: require("@/assets/images/shipping/qg-wait.png"),
end: require("@/assets/images/shipping/qg-end.png"),
},
title: i18n.$t("清关文件"),
dataKey: "11", // 字典数据键值
/**
* 清关文件状态:111、未清关文件;112、已清关文件
*/
voName: "clearanceDocInfo",
keyName: "cdStatus",
status: {
start: [111],
wait: [],
end: [112],
},
},
],
[
{
title: i18n.$t("到港"),
imgSrc: {
start: require("@/assets/images/shipping/dg-start.png"),
wait: require("@/assets/images/shipping/dg-wait.png"),
end: require("@/assets/images/shipping/dg-end.png"),
},
type: "arrival",
dataKey: "12", // 字典数据键值
/**
* 到港状态:121、未到港;112、已到港
*/
voName: "arrivalInfo",
keyName: "apStatus",
status: {
start: [121],
wait: [],
end: [122],
},
},
],
[
{
title: i18n.$t("清关"),
imgSrc: {
start: require("@/assets/images/shipping/qg-start.png"),
wait: require("@/assets/images/shipping/qg-wait.png"),
end: require("@/assets/images/shipping/qg-end.png"),
},
type: "cusClearance",
dataKey: "13", // 字典数据键值
/**
* 清关状态:131、未清关;132、已清关
*/
voName: "clearanceInfo",
keyName: "clStatus",
status: {
start: [131],
wait: [],
end: [132],
},
},
],
[
{
title: i18n.$t("卸柜"),
imgSrc: {
start: require("@/assets/images/shipping/xg-start.png"),
wait: require("@/assets/images/shipping/xg-wait.png"),
end: require("@/assets/images/shipping/xg-end.png"),
},
type: "unloading",
dataKey: "14", // 字典数据键值
/**
* 卸柜状态:181、未卸柜;182、卸柜中;183、卸柜审核中;184、卸柜审核失败;185、卸柜审核成功;186、已卸柜
*/
voName: "cabinetUnloadInfo",
keyName: "ulStatus",
status: {
start: [181],
wait: [182, 183, 184, 185],
end: [186],
},
},
],
[
{
title: i18n.$t("结算"),
imgSrc: {
start: require("@/assets/images/shipping/js-start.png"),
wait: require("@/assets/images/shipping/js-wait.png"),
end: require("@/assets/images/shipping/js-end.png"),
},
type: "settlement",
dataKey: "15", // 字典数据键值
/**
* 结算状态:191、未结算;192、结算中;193、已结算
*/
voName: "settlementInfo",
keyName: "slStatus",
status: {
start: [191],
wait: [192],
end: [193],
},
},
],
];
}
/**
* 海空联运流程
*
* @return {*}
*/
function seaAirBaseData() {
return [
[
{
title: i18n.$t("订舱"),
imgSrc: {
start: require("@/assets/images/shipping/dc-start.png"),
end: require("@/assets/images/shipping/dc-end.png"),
},
type: "booking", // 类型
dataKey: "1", // 字典数据键值
/**
* 订舱状态:11、未订舱;12、已订舱
*/
voName: "bookSeaInfo", // 订舱对象vo
keyName: "bkStatus",
status: {
start: [11],
wait: [],
end: [12],
},
},
],
[
{
title: i18n.$t("排单"),
imgSrc: {
start: require("@/assets/images/shipping/yz-start.png"),
wait: require("@/assets/images/shipping/yz-wait.png"),
end: require("@/assets/images/shipping/yz-end.png"),
},
type: "preinstall",
dataKey: "2", // 字典数据键值
/**
* 预装状态:21、未预装;22、预装中;23、预装审核中;24、预装审核失败;25、预装审核成功
*/
voName: "preInstallInfo",
keyName: "prStatus",
status: {
start: [21],
wait: [22, 23, 24],
end: [25],
},
},
{
title: "AGENT",
imgSrc: {
start: require("@/assets/images/shipping/agent-start.png"),
wait: require("@/assets/images/shipping/agent-wait.png"),
end: require("@/assets/images/shipping/agent-end.png"),
},
type: "agent",
voName: "agentInfo",
currStatus: "start",
},
],
[
{
title: i18n.$t("理货"),
imgSrc: {
start: require("@/assets/images/shipping/lh-start.png"),
wait: require("@/assets/images/shipping/lh-wait.png"),
end: require("@/assets/images/shipping/lh-end.png"),
},
type: "tally",
dataKey: "16", // 字典数据键值
/**
* 理货状态:2111、未理货;2112、已理货
*/
voName: "tallyInfo",
keyName: "tyStatus",
status: {
start: [2111],
wait: [],
end: [2112],
},
},
{
title: i18n.$t("拖车"),
imgSrc: {
start: require("@/assets/images/shipping/tc-start.png"),
wait: require("@/assets/images/shipping/tc-wait.png"),
end: require("@/assets/images/shipping/tc-end.png"),
},
type: "trailer",
dataKey: "3", // 字典数据键值
/**
* 拖车状态:31、未派车;32、已派车
*/
voName: "trailerInfo",
keyName: "tlStatus",
status: {
start: [31],
wait: [],
end: [32],
},
},
],
[
{
title: i18n.$t("装柜"),
imgSrc: {
start: require("@/assets/images/shipping/zg-start.png"),
wait: require("@/assets/images/shipping/zg-wait.png"),
end: require("@/assets/images/shipping/zg-end.png"),
},
type: "cabinet",
dataKey: "4", // 字典数据键值
/**
* 装柜状态:41、未装柜;42、装柜中;43、已装柜、待封柜;44、封柜审核中;45、封柜审核失败;46、封柜审核成功;47、已封柜,待出仓
*/
voName: "cabinetInfo",
keyName: "ldStatus",
status: {
start: [41],
wait: [42, 43, 44, 45, 46],
end: [47],
},
},
],
[
{
title: i18n.$t("报关"),
imgSrc: {
start: require("@/assets/images/shipping/bg-start.png"),
wait: require("@/assets/images/shipping/bg-wait.png"),
end: require("@/assets/images/shipping/bg-end.png"),
},
type: "cusDeclaration",
dataKey: "5", // 字典数据键值
/**
*报关状态:51、未报关;52、报关中;53、已报关
*/
voName: "customsInfo",
keyName: "dcStatus",
status: {
start: [51],
wait: [52],
end: [53],
},
},
{
title: i18n.$t("配船"),
imgSrc: {
start: require("@/assets/images/shipping/pc-start.png"),
wait: require("@/assets/images/shipping/pc-wait.png"),
end: require("@/assets/images/shipping/pc-end.png"),
},
type: "ship",
dataKey: "6", // 字典数据键值
/**
* 配船状态:61、未配船;62、已配船
*/
voName: "shipConfigInfo",
keyName: "saStatus",
status: {
start: [61],
wait: [],
end: [62],
},
},
{
title: i18n.$t("提单补料"),
imgSrc: {
start: require("@/assets/images/shipping/tdcl-start.png"),
wait: require("@/assets/images/shipping/tdcl-wait.png"),
end: require("@/assets/images/shipping/tdcl-end.png"),
},
type: "subMaterial",
dataKey: "7", // 字典数据键值
/**
* 提单补料状态:71、未提单补料;72、已提单补料
*/
voName: "ladingBillInfo",
keyName: "blStatus",
status: {
start: [71],
wait: [],
end: [72],
},
},
],
[
{
title: i18n.$t("驳船"),
imgSrc: {
start: require("@/assets/images/shipping/bc-start.png"),
wait: require("@/assets/images/shipping/bc-wait.png"),
end: require("@/assets/images/shipping/bc-end.png"),
},
type: "barge",
dataKey: "8", // 字典数据键值
/**
* 驳船状态:81、未驳船;82、已驳船
*/
voName: "bargeInfo",
keyName: "bgStatus",
status: {
start: [81],
wait: [],
end: [82],
},
},
],
[
{
title: i18n.$t("起运"),
imgSrc: {
start: require("@/assets/images/shipping/qy-start.png"),
wait: require("@/assets/images/shipping/qy-wait.png"),
end: require("@/assets/images/shipping/qy-end.png"),
},
type: "departure",
dataKey: "9", // 字典数据键值
/**
* 起运状态:91、未起运;92、已起运
*/
voName: "shippingInfo",
keyName: "dtStatus",
status: {
start: [91],
wait: [],
end: [92],
},
},
],
[
{
title: i18n.$t("提单Copy"),
imgSrc: {
start: require("@/assets/images/shipping/tdcopy-start.png"),
wait: require("@/assets/images/shipping/tdcopy-wait.png"),
end: require("@/assets/images/shipping/tdcopy-end.png"),
},
type: "blCopy",
dataKey: "10", // 字典数据键值
/**
* 提单COPY状态:101、未上传;102、已上传
*/
voName: "ladingCopyInfo",
keyName: "cpStatus",
status: {
start: [101],
wait: [],
end: [102],
},
},
{
type: "clrDocument",
imgSrc: {
start: require("@/assets/images/shipping/qg-start.png"),
wait: require("@/assets/images/shipping/qg-wait.png"),
end: require("@/assets/images/shipping/qg-end.png"),
},
title: i18n.$t("清关文件"),
dataKey: "11", // 字典数据键值
/**
* 清关文件状态:111、未清关文件;112、已清关文件
*/
voName: "clearanceDocInfo",
keyName: "cdStatus",
status: {
start: [111],
wait: [],
end: [112],
},
},
],
[
{
title: i18n.$t("到港"),
imgSrc: {
start: require("@/assets/images/shipping/dg-start.png"),
wait: require("@/assets/images/shipping/dg-wait.png"),
end: require("@/assets/images/shipping/dg-end.png"),
},
type: "arrival",
dataKey: "12", // 字典数据键值
/**
* 到港状态:121、未到港;112、已到港
*/
voName: "arrivalInfo",
keyName: "apStatus",
status: {
start: [121],
wait: [],
end: [122],
},
},
],
[
{
title: i18n.$t("清关"),
imgSrc: {
start: require("@/assets/images/shipping/qg-start.png"),
wait: require("@/assets/images/shipping/qg-wait.png"),
end: require("@/assets/images/shipping/qg-end.png"),
},
type: "cusClearance",
dataKey: "13", // 字典数据键值
/**
* 清关状态:131、未清关;132、已清关
*/
voName: "clearanceInfo",
keyName: "clStatus",
status: {
start: [131],
wait: [],
end: [132],
},
},
],
[
{
title: i18n.$t("二程起飞"),
imgSrc: {
start: require("@/assets/images/shipping/ecqf-start.png"),
wait: require("@/assets/images/shipping/ecqf-wait.png"),
end: require("@/assets/images/shipping/ecqf-end.png"),
},
type: "twoWayTakeoff",
dataKey: "14", // 字典数据键值
/**
* 起飞状态:141、未起飞;142、已起飞
*/
voName: "takeOffInfo",
keyName: "stkStatus",
status: {
start: [141],
wait: [],
end: [142],
},
},
],
[
{
title: i18n.$t("二程到港"),
imgSrc: {
start: require("@/assets/images/shipping/ecdg-start.png"),
wait: require("@/assets/images/shipping/ecdg-wait.png"),
end: require("@/assets/images/shipping/ecdg-end.png"),
},
type: "twoWayArrival",
dataKey: "15", // 字典数据键值
/**
* 清关状态:131、未清关;132、已清关
*/
voName: "airArrivalInfo",
keyName: "sapStatus",
status: {
start: [151],
wait: [],
end: [152],
},
},
],
[
{
title: i18n.$t("卸柜"),
imgSrc: {
start: require("@/assets/images/shipping/xg-start.png"),
wait: require("@/assets/images/shipping/xg-wait.png"),
end: require("@/assets/images/shipping/xg-end.png"),
},
type: "unloading",
dataKey: "14", // 字典数据键值
/**
* 卸柜状态:181、未卸柜;182、卸柜中;183、卸柜审核中;184、卸柜审核失败;185、卸柜审核成功;186、已卸柜
*/
voName: "cabinetUnloadInfo",
keyName: "ulStatus",
status: {
start: [181],
wait: [182, 183, 184, 185],
end: [186],
},
},
],
[
{
title: i18n.$t("结算"),
imgSrc: {
start: require("@/assets/images/shipping/js-start.png"),
wait: require("@/assets/images/shipping/js-wait.png"),
end: require("@/assets/images/shipping/js-end.png"),
},
type: "settlement",
dataKey: "15", // 字典数据键值
/**
* 结算状态:191、未结算;192、结算中;193、已结算
*/
voName: "settlementInfo",
keyName: "slStatus",
status: {
start: [191],
wait: [192],
end: [193],
},
},
],
];
}
/**
* 详情显示列
*
* @return {*}
*/
function getColmnMapping() {
return {
bookSeaInfo: [
{
title: "SO NO",
key: "sono",
},
{
title: i18n.$t("船公司类型"),
key: "shipCompanyType",
type: "supplier",
},
{
title: i18n.$t("驳船港"),
key: "bargePortId",
type: "dock",
},
{
title: i18n.$t("大船港"),
key: "bigPortId",
type: "dock",
},
{
title: i18n.$t("目的港"),
key: "destPortId",
type: "dock",
},
{
title: i18n.$t("订舱公司"),
key: "spaceCompanyId",
type: "supplier",
},
{
title: i18n.$t("预计驳船时间"),
key: "bargeTime",
type: "date",
},
{
title: i18n.$t("预计开船时间"),
key: "sailTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
preInstallInfo: [
{
title: i18n.$t("预装时间"),
key: "createTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
trailerInfo: [
{
title: i18n.$t("货柜号"),
key: "tlContainerNo",
},
{
title: i18n.$t("封条"),
key: "tlStripSeal",
},
{
title: i18n.$t("拖车公司"),
key: "tlCompanyId",
type: "supplier",
},
{
title: i18n.$t("拖车时间"),
key: "tlTime",
type: "date",
},
{
title: i18n.$t("车牌"),
key: "tlLicensePlate",
},
{
title: i18n.$t("司机"),
key: "tlDriver",
},
{
title: i18n.$t("联系方式"),
key: "tlDriverContact",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
tallyInfo: [
{
title: i18n.$t("完成理货时间"),
key: "tyTime",
type: "datetime",
},
{
title: i18n.$t("业务员"),
key: "tyOperator",
},
],
agentInfo: [
{
title: i18n.$t("代理商"),
key: "agentId",
type: "supplier",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
cabinetInfo: [
{
title: i18n.$t("到仓时间"),
key: "ldInWarehouseTime",
type: "date",
},
{
title: i18n.$t("仓库类型"),
key: "ldWarehouseType",
type: "warehouse",
},
{
title: i18n.$t("装柜时间"),
key: "ldBoxTime",
type: "date",
},
{
title: i18n.$t("出仓时间"),
key: "ldOutWarehouseTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
customsInfo: [
{
title: i18n.$t("报关方式"),
key: "dcCustomsType",
type: "shipping_customs_type",
},
{
title: i18n.$t("报关行公司"),
key: "dcCompanyId",
type: "supplier",
},
{
title: i18n.$t("截关时间"),
key: "dcCutOffTime",
type: "date",
},
{
title: i18n.$t("状态"),
key: "dcCustomsStatus",
type: "shipping_dcCustoms_status",
},
{
title: i18n.$t("放行时间"),
key: "dcPassTime",
type: "date",
},
{
title: i18n.$t("新封条"),
key: "dcStripSeal",
},
{
title: i18n.$t("柜重"),
key: "dcBoxWgt",
},
{
title: i18n.$t("货重"),
key: "dcGoodsWgt",
},
{
title: i18n.$t("VGM重量"),
key: "dcVgmWgt",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
shipConfigInfo: [
{
title: i18n.$t("已配/免配"),
key: "saExmtStatus",
type: "saExmtStatus",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
ladingBillInfo: [
{
title: i18n.$t("清关代理"),
key: "agentId",
type: "supplier",
},
{
title: i18n.$t("提单号"),
key: "blMblNo",
},
{
title: i18n.$t("通知方"),
key: "notifyingName",
},
{
title: i18n.$t("提单备注"),
key: "remarks",
},
{
title: i18n.$t("数量(个)"),
key: "packageNum",
},
{
title: i18n.$t("体积"),
key: "cbm",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
bargeInfo: [
{
title: i18n.$t("驳船"),
key: "bgExmtStatus",
type: "bgExmtStatus",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
shippingInfo: [
{
title: i18n.$t("实际开船时间"),
key: "dtRealShipTime",
type: "datetime",
},
{
title: i18n.$t("预计到港时间"),
key: "dtEstArrivalTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
clearanceDocInfo: [
{
title: "agent list",
key: "cdAgentlistType",
type: "isFile",
},
{
title: "soncap",
key: "cdSoncapType",
type: "isFile",
},
{
title: i18n.$t("出单方式"),
key: "cdOutBillType",
type: "billingMethod",
},
{
title: i18n.$t("寄送时间"),
key: "cdSendTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
arrivalInfo: [
{
title: i18n.$t("实际到港时间"),
key: "apRealTime",
type: "datetime",
},
{
title: i18n.$t("确认到港"),
key: "apConfirmTime",
type: "datetime",
},
{
title: i18n.$t("卸港时间"),
key: "apUnloadPortTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
clearanceInfo: [
{
title: i18n.$t("预计清关时间"),
key: "clEstTime",
type: "date",
},
{
title: i18n.$t("清关时间"),
key: "clClearTime",
type: "datetime",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
takeOffInfo: [
{
title: i18n.$t("预计头程时间"),
key: "estHeadTime",
type: "datetime",
},
{
title: i18n.$t("实际头程时间"),
key: "actHeadTime",
type: "datetime",
},
{
title: i18n.$t("预计二程时间"),
key: "estSecondTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
airArrivalInfo: [
{
title: i18n.$t("预计到达时间"),
key: "estTime",
type: "datetime",
},
{
title: i18n.$t("实际到达时间"),
key: "actTime",
type: "datetime",
},
{
title: i18n.$t("实际二程时间"),
key: "actSecondTime",
type: "datetime",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
cabinetUnloadInfo: [
{
title: i18n.$t("到仓时间"),
key: "ulWarehouseTime",
type: "date",
},
{
title: i18n.$t("卸货时间"),
key: "ulBoxTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
settlementInfo: [
{
title: i18n.$t("可结算"),
key: "slSettlementTime",
type: "date",
},
{
title: i18n.$t("已结算"),
key: "slSettledTime",
type: "date",
},
{
title: i18n.$t("业务员"),
key: "operator",
},
],
};
}
/**
* 常量字典
*/
const constantDict = {
//航程
voyageData: [
{
value: 1,
label: i18n.$t("直飞"),
},
{
value: 2,
label: i18n.$t("中转"),
},
],
// 配船状态
saExmtStatus: [
{
value: "1",
label: i18n.$t("免配"),
},
{
value: "2",
label: i18n.$t("已配"),
},
],
// 驳船
bgExmtStatus: [
{
value: "1",
label: i18n.$t("无驳船"),
},
{
value: "2",
label: i18n.$t("有驳船"),
},
],
// 出单方式
billingMethod: [
{
value: "1",
label: i18n.$t("电放"),
},
{
value: "2",
label: i18n.$t("正本"),
},
],
// 是否有文件
isFile: [
{
value: "1",
label: i18n.$t("无需"),
},
{
value: "2",
label: i18n.$t("已做"),
},
],
};
/**
* string format number
*
* @param {*} obj
* @param {*} keys
* @return {*}
*/
function formatStringNumber(obj, keys) {
for (const [key, value] of Object.entries(obj)) {
if (keys.includes(key) && !Number.isNaN(Number(value))) {
obj[key] = Number(value);
}
}
return obj;
}
/**
* number format string
*
* @param {*} obj
* @param {*} keys
* @return {*}
*/
function formatNumberString(obj, keys) {
for (const [key, value] of Object.entries(obj)) {
if (keys.includes(key) && value) {
obj[key] = String(value);
}
}
return obj;
}
/**
* stringDate format Date
*
* @param {*} obj
* @param {*} keys
* @param {string} [format="YYYY-MM-DD HH:mm:ss"]
* @return {*}
*/
function formatDateStr(obj, keys, format = "YYYY-MM-DD HH:mm:ss") {
for (const [key, value] of Object.entries(obj)) {
if (keys.includes(key) && dayjs(value).isValid()) {
obj[key] = dayjs(value).format(format);
}
}
return obj;
}
/**
* 格式化日期
*
* @param {*} date
* @param {string} [format="YYYY-MM-DD HH:mm:ss"]
* @return {*}
*/
function formatDate(date, format = "YYYY-MM-DD HH:mm:ss") {
if (!date) return date;
return dayjs(date).format(format);
}
/**
* 获取海运流程状态
*
* @param {*} val
* @return {*}
*/
function getSeaStatus(val) {
let currNodeStatus = 11,
isBreak = false,
datas = seaBaseData();
// 迭代每个节点
for (let i = 0; i < datas.length; i++) {
const nodes = datas[i];
for (let j = 0; j < nodes.length; j++) {
const node = nodes[j];
const { keyName, voName, status } = node;
if (!keyName) continue;
const { start, wait, end } = status;
if (start.includes(val[keyName]) && val[voName]) {
currNodeStatus = val[keyName];
}
if (wait.includes(val[keyName])) {
currNodeStatus = val[keyName];
isBreak = true;
break;
}
if (end.includes(val[keyName])) {
currNodeStatus = val[keyName];
}
}
if (isBreak) break;
}
return currNodeStatus;
}
/**
* 组装统计信息文字
*
* @param {*} total
* @param {string} [keys=["num", "volume", "weight"]]
* @return {*}
*/
function getTotlContent(total, keys = ["num", "volume", "weight"]) {
let content = [];
for (const key of keys) {
if (key === "num") {
content.push(`${total?.num ?? 0}${i18n.$t("")}`);
}
if (key === "volume") {
let volume = total?.volume ?? 0;
volume = volume === 0 ? volume : new Decimal(volume).toFixed(2);
content.push(`${volume}m³`);
}
if (key === "weight") {
let weight = total?.weight ?? 0;
weight = weight === 0 ? weight : new Decimal(weight).toFixed(2);
content.push(`${weight}kg`);
}
}
return content.join(" ");
}
function getCapacity(capacity) {
return `${capacity?.name ?? ""}${i18n.$t("柜型")} ${capacity?.volume ?? 0}m³ ${
capacity?.weight ?? 0
}kg`;
}
function sumStatistics(val) {
let count = { num: 0, volume: 0, weight: 0 };
if (Array.isArray(val)) {
val.forEach((item) => {
const { secStatistics } = item;
if (secStatistics) {
if (!Number.isNaN(Number(secStatistics.num))) {
count.num = Decimal.add(
count.num,
Number(secStatistics.num)
).toNumber();
}
if (!Number.isNaN(Number(secStatistics.volume))) {
count.volume = Decimal.add(
count.volume,
Number(secStatistics.volume)
);
}
if (!Number.isNaN(Number(secStatistics.weight))) {
count.weight = Decimal.add(
count.weight,
Number(secStatistics.weight)
);
}
}
});
}
return getTotlContent(count);
}
export const fileTypes = [
"doc",
"xls",
"ppt",
"txt",
"pdf",
"png",
"jpg",
"jpeg",
];
/**
* 服务提示消息回调
*
* @export
* @param {*} result
* @param {*} _vue
* @return {*}
*/
function serviceMsg(result, _vue) {
return new Promise((resolve, reject) => {
const { code, msg } = result;
if (code === 0) {
_vue.$message.success(i18n.$t("操作成功"));
resolve();
} else {
_vue.$message.error(msg);
reject();
}
});
}
/**
* 跳转审核详情
*
* @param {*} bpmProcessId
*/
function toReviewDetail(bpmProcessId) {
this.$router.push({
path: "/bpm/process-instance/detail",
query: { id: bpmProcessId },
});
}
function downloadFile(funName, params, fileName, fileFormat) {
_BOX[funName](params).then((res) => {
const reader = new FileReader();
reader.onload = (event) => {
try {
// 将读取的string转换为json
// 若果能转换成功 => 接口返回的是json数据,提示报错信息
const json = JSON.parse(event.target.result);
if (json.code) {
window.ElementUI.Message.error(json.msg);
}
} catch (err) {
let blob = new Blob([res], { type: `application/${fileFormat}` });
FileSaver.saveAs(blob, fileName);
}
};
reader.readAsText(res);
});
}
function downloadFileByUrl(funName, params) {
_BOX[funName](params).then((res) => {
if (res.data) FileSaver.saveAs(res.data);
});
}
export {
getColmnMapping,
getSeaStatus,
airBaseData,
seaAirBaseData,
constantDict,
formatStringNumber,
formatDateStr,
formatNumberString,
formatDate,
getTotlContent,
getCapacity,
sumStatistics,
serviceMsg,
toReviewDetail,
downloadFile,
downloadFileByUrl,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment