emis-frontend/src/views/emis/emisTmsSiteBatch/panel/BatchImportSiteBatch.vue
2025-02-22 16:59:48 +08:00

783 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<XdPageContainer >
<div slot="pageHeader"></div>
<XdTable
slot="pageContent"
slot-scope="slotProps"
:height="(slotProps.contentHeight)+'px'"
storageName="batchSiteBatchRecord_main_9"
ref="multipleTable"
:row-class-name="tableRowClassName"
v-loading="loading"
border
size="mini"
:data="orderList"
:showSearch.sync="showSearch"
:queryParams="queryParams"
:total="total"
@queryTable="getList"
@selection-change="handleSelectionChange"
@sort-change="handleSortChange"
>
<div slot="toolbar">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-upload
action=""
name="file"
accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
:show-file-list="true"
:limit="1"
:file-list="fileList"
:tooltip="fileName"
:on-change="fileChange"
:before-upload="beforeUpload">
<el-button slot="trigger" plain class="filter-item" size="mini" type="primary" >选择文件</el-button>
<el-link type="primary" style="line-height: 28px;font-size:13px;color:blue" href="/static/tpl/import_site_batch.xlsx">下载导入Excel模板</el-link>
</el-upload>
</el-col>
<el-col :span="1.5">
<el-button
type="primary"
plain
size="mini"
@click="handleRealUploadAll"
>批量发送</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除</el-button>
</el-col>
</el-row>
</div>
<el-table-column type="selection" width="55" align="center" />
<el-table-column :label="$t('状态')" align="center" prop="uploadStatus" min-width="80" :show-overflow-tooltip="true" >
<template slot-scope="scope">
<el-tag v-if="scope.row.uploadStatus==1" type="success">发送成功</el-tag>
<el-tag v-if="scope.row.uploadStatus==0" type="info">待发送</el-tag>
<el-tag v-if="scope.row.uploadStatus==-1" type="danger">发送异常</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('异常信息')" align="center" prop="errorInfo" min-width="300" :show-overflow-tooltip="true" >
<template slot-scope="scope">
<span v-if="scope.row.uploadStatus==-1" style="color:red">{{ scope.row.errorInfo }}</span>
<span v-if="scope.row.uploadStatus==1">发送成功</span>
<span v-if="scope.row.uploadStatus==0">待发送</span>
</template>
</el-table-column>
<el-table-column :label="$t('批次号')" align="center" prop="batchNo" min-width="120" :show-overflow-tooltip="true" />
<el-table-column :label="$t('供应商')" align="center" prop="supplierName" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('批次类型')" align="center" prop="batchType" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('运输方式')" align="center" prop="transType" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('起始网点')" align="center" prop="startSiteCode" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('下一网点')" align="center" prop="nextSiteCode" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('发出时间')" align="center" prop="etd" min-width="100" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.etd, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('运输号')" align="center" prop="carNo" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('目的国家')" align="center" prop="destCountry" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('承运重量')" align="center" prop="transWeight" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('包裹数')" align="center" prop="packNum" min-width="100" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('加入运单号')" align="center" prop="billCode" min-width="100" :show-overflow-tooltip="true"/>
</XdTable>
</XdPageContainer>
</template>
<script>
import { listEmisTmsSiteBatch, getTmsGroupBatchNo, getEmisTmsSiteBatch, delEmisTmsSiteBatch, addEmisTmsSiteBatch, updateEmisTmsSiteBatch } from "@/api/emis/emisTmsSiteBatch";
import { listSimpleEmisSite } from "@/api/emis/emisSite";
import { listSimpleEmisSupplier } from "@/api/emis/emisSupplier";
import { listEmisTmsSiteBatchDtl, delEmisTmsSiteBatchDtl, addEmisTmsSiteBatchDtl } from "@/api/emis/emisTmsSiteBatchDtl";
import { listEmisWaybill } from "@/api/emis/emisWaybill";
import { parseTime,parseExcelTime } from "@/utils/custom";
import {timeDiffTime,timeFormat} from '@/utils/dateUtils'
import { formatSearchStr,deepClone } from '@/utils/index'
import { result } from "lodash";
import dayjs from "dayjs";
import XLSX from 'xlsx'
import moment from 'moment'
export default {
name: "BatchWaybillRecord",
components: {
},
dicts: ['emis_waybill_status', 'emis_payment_type', 'emis_biz_shipping_method', 'emis_qujian_fangshi', 'cebp_return_status','emis_declare_mode','emis_customs_clear','emis_big_batch_type'],
data() {
return {
resetRefreshId:null,
// 遮罩层
loading: false,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 运单列表表格数据
orderList: [],
tmpDataList: [],
selectionList:[],
selectionIndexList: [],
form:{},
rules:{},
openUploadForm:false,
uploadMsg:"",
uploadExcelDataInfo:"",
fileName:"",
fileList:[],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
queryKey:null,
batchNo: null,
batchName: null,
transType: null,
startSiteCode: null,
nextSiteCode: null,
carNo: null,
destCountry: null,
supplierCode:null,
},
};
},
created() {
},
mounted() {
},
methods: {
getUUID() {
return Math.random().toString(36).substring(3,10);
},
handleBatchImport(){
this.resetRefreshId="importForm-"+this.getUUID();
this.openUploadForm=true;
this.fileList=[];
this.uploadExcelDataInfo="";
this.fileName="";
},
calcDeliveryTime(startData,endDate){
return timeDiffTime(startData,endDate)
},
//标红table指定行
tableRowClassName(row, index) {
row.row.index = row.rowIndex;
if (row.uploadStatus=='1') {
return 'success-row';
}
else if (row.uploadStatus=='-1') {
return 'warning-row';
}
return '';
},
/** 查询运单列表列表 */
getList() {
this.loading = true;
},
fileChange(file, fileList) {
this.fileList = fileList;
},
beforeUpload(file) {
this.fileName = file.name;
this.form.batchName = file.name;
this.readerData(file)
return false
},
readerData(rawFile) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = e => {
const data = e.target.result
const workbook = XLSX.read(data, { type: 'array' ,cellDates: true})
const firstSheetName = workbook.SheetNames[0] // firstSheetName
// if (!excelTypes.includes(firstSheetName)) {
// reject('无法识别当前Excel模板')
// this.$modal.msgError('无法识别当前Excel模板')
// return
// }
const worksheet = workbook.Sheets[firstSheetName]
// const header = this.getHeaderRow(worksheet) // 标题
const results = XLSX.utils.sheet_to_json(worksheet)
console.log(results);
this.batchImportData(results);
resolve()
}
reader.readAsArrayBuffer(rawFile)
})
},
getHeaderRow(sheet) {
const headers = []
const range = XLSX.utils.decode_range(sheet['!ref'])
let C
const R = range.s.r
/* start in the first row */
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
/* find the cell in the first row */
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
headers.push(hdr)
}
return headers
},
async batchImportData(results) {
const _index = 1
let loadingInstance = this.$loading({
text: '正在解析 ' + _index + ' 数据...'
})
this.orderList = [];
let lastOrderSn = '';
let orderIndex = 0;
// 组装提交的数据
for (let index = 0; index < results.length; index++) {
const element = results[index]
// 批次类型 供应商 运输方式 运输号 承运重量 包裹数 发出时间 起始网点 下一网点 目的国家 加入运单号
let rowIndex=element['__rowNum__']
let orderData={
batchNo: null,
// batchName: null,
// batchDate: null,
// supplierCode: null,
supplierName: element['供应商'],
batchType: element['批次类型'],
transType: element['运输方式'],
startSiteCode: element['起始网点'],
nextSiteCode: element['下一网点'],
etd: parseExcelTime(element['发出时间'],false),
carNo: element['运输号'],
destCountry: element['目的国家'],
destCountryName: null,
transWeight: element['承运重量'],
packNum: element['包裹数'],
billCode: element['加入运单号'],
uploadStatus: 0,
errorInfo:'',
}
this.tmpDataList.push(orderData);
}
// 判断是否有数据
this.orderList=[];
if(this.tmpDataList.length==0){
this.$modal.msgError('表格中没有数据');
loadingInstance.close()
return;
}
this.orderList = this.orderList.concat(this.tmpDataList);
this.tmpDataList=[];
// this.uploadExcelDataInfo="总共 " + this.tmpDataList.length +" 条数据。";
loadingInstance.close()
},
handleRealUploadAll(){
if (this.ids && this.ids.length>0) {
this.$confirm("确认发送吗?", "提示", {
cancelButtonText: "取消",
confirmButtonText: "确认",
type: "warning",
distinguishCancelAndClose: true,
closeOnClickModal: false
}).then(async () => {
if(this.selectionList&&this.selectionList.length>0){
for(let i=0;i<this.selectionList.length;i++){
let orderItem=this.selectionList[i];
// 检查数据后发送
let res=await this.uploadAndCheckData(orderItem)
console.log("====uploadAndCheckData===mmm1====>",res);
let rstData=res.data;
if(rstData.result=='success'){
orderItem.uploadStatus=1;
orderItem.errorInfo="发送成功";
orderItem.batchNo=rstData.batchNo;
}
else{
orderItem.uploadStatus=-1;
orderItem.errorInfo=res.msg;
}
}
this.$modal.msgSuccess("上传成功");
}
});
}
},
async uploadAndCheckData(itemData){
let postForm = {
id: null,
batchNo: null,
batchName: null,
batchDate: null,
supplierCode: null,
supplierName: null,
supplierNameEn: null,
transLineType: null,
productType: null,
batchType: null,
transType: null,
startSiteCode: null,
startSiteSizeCode3:null,
sendCountry: null,
nextSiteCode: null,
nextSiteSizeCode3:null,
airBilllNo: null,
etd: null,
eta: null,
carNo: null,
shipNo: null,
clearanceResStatus: null,
declareResStatus: null,
destCountry: null,
destCountryName: null,
transWeight: null,
packNum: null,
totalParcelQty: null,
totalWaybillQty: null,
totalVolume: null,
totalWeight: null,
// 批次明细列表
batchDtlList:null,
};
postForm.destCountry=itemData.destCountry;
postForm.packNum=itemData.packNum;
postForm.transWeight=itemData.transWeight;
postForm.etd=itemData.etd;
// 检查单号是否存在
if(!(itemData.billCode) ){
let rst = {
code:500,
msg:'加入单号不能为空',
data:{
result:'fail'
}
}
return rst;
}
if(!(itemData.carNo) ){
let rst = {
code:500,
msg:'运输号不能为空',
data:{
result:'fail'
}
}
return rst;
}
if(!(itemData.supplierName) ){
let rst = {
code:500,
msg:'供应商不能为空',
data:{
result:'fail'
}
}
return rst;
}
postForm.carNo=itemData.carNo;
if(!(itemData.etd) ){
let rst = {
code:500,
msg:'发出日期不能为空',
data:{
result:'fail'
}
}
return rst;
}
postForm.etd=itemData.etd;
// 转换运输类型
const transTypeDict=this.dict.type.emis_biz_shipping_method.find(item=>item.label==itemData.transType);
if(transTypeDict==null){
let rst = {
code:500,
msg:'运输类型不存在',
data:{
result:'fail'
}
}
return rst;
}
postForm.transType=Number(transTypeDict.value);
// 批次类型
let batchTypeDict=this.dict.type.emis_big_batch_type.find(item=>item.label==itemData.batchType);
if(batchTypeDict==null){
let rst = {
code:500,
msg:'批次类型不存在',
data:{
result:'fail'
}
}
return rst;
}
postForm.batchType=batchTypeDict.value;
let startSite = await this.getSiteBySiteName(itemData.startSiteCode);
if(startSite==null||startSite==undefined){
let rst = {
code:500,
msg:'起始网点不存在',
data:{
result:'fail'
}
}
return rst;
}
postForm.startSiteCode=startSite.siteCode;
postForm.startSiteName=startSite.siteName;
postForm.startSiteSizeCode3=startSite.sizeCode3||'-';
// 下一网点
let nextSite = await this.getSiteBySiteName(itemData.nextSiteCode);
if(nextSite==null||nextSite==undefined){
let rst = {
code:500,
msg:'下一网点不存在',
data:{
result:'fail'
}
}
return rst;
}
postForm.nextSiteCode=nextSite.siteCode;
postForm.nextSiteName=nextSite.siteName;
postForm.nextSiteSizeCode3=nextSite.sizeCode3||'-';
// 供应商
let supplier=await this.getSupplierByName(itemData.supplierName);
if(supplier==null){
let rst = {
code:500,
msg:'供应商不存在',
data:{
result:'fail'
}
}
return rst;
}
postForm.supplierCode=supplier.code;
postForm.supplierName=supplier.name;
postForm.supplierNameEn=supplier.nameEn||'-';
// 获取批次号
let resPack = await getTmsGroupBatchNo();
postForm.batchNo = resPack.data;
// 计算批次名称
let batchName=this.calcBatchName(postForm);
postForm.batchName = batchName;
// 计算子单
let totalParcelQty=0;
let totalWeight=0;
let totalVolume=0;
postForm.batchDtlList = [];
let bcList=itemData.billCode.trim().split(/[;\;\,\,\n]/)||[];
for(let i = 0; i < bcList.length; i++){
let billcode = bcList[i].trim();
let billRes = await listEmisWaybill(
{
billCode:billcode,
params:{
isNeedBatch:1,
batchType:postForm.batchType
}
}
);
if(!billRes || billRes.code != 200){
let rst = {
code:500,
msg:billRes && billRes.msg,
data:{
result:'fail'
}
}
return rst;
}
else if(!billRes.rows || billRes.rows.length < 1){
let rst = {
code:500,
msg:'运单不存在或状态异常(已签收,已占用,已派送),不能组批次: ' + billcode,
data:{
result:'fail'
}
}
return rst;
}
let itemBill = billRes.rows[0];
let packDetail = {
batchNo: postForm.batchNo,
billCode: billcode,
groupStatus: "1",//已组批次
};
totalParcelQty +=itemBill.parcelQty;
totalWeight +=itemBill.billWeight;
totalVolume +=itemBill.totalVolume;
postForm.batchDtlList.push(packDetail);
}
postForm.totalWaybillQty=postForm.batchDtlList.length;
postForm.totalParcelQty=totalParcelQty;
postForm.totalWeight=totalWeight.toFixed(2);
postForm.totalVolume=totalVolume.toFixed(4);
// 插入数据
let response = await addEmisTmsSiteBatch(postForm);
if(!response || response.code != 200){
let rst = {
code:500,
msg:response && response.msg || '新增组批次失败',
data:{
result:'fail'
}
}
return rst;
}else{
let rst = {
code:200,
msg:'发送成功',
data:{
result:'success',
batchNo:postForm.batchNo
}
}
return rst;
}
},
// 批次名称计算
calcBatchName(postForm){
/*
1、批次名称规则:
1)快递(E):
快递(E)-南京分拨中心(NJ)-东航(DH)-昆明(KM)-250113-提单号
ENJDHKM250113+提单号
2)空运(A):
空运(A)-南京分拨中心(NJ)-南航(NH)-昆明(KM)-250113-提单号
ANJNHKM250113+提单号
3)陆运(L):
陆运(L)-南京分拨中心(NJ)-九通(JT)-昆明(KM)-250113-车牌
LNJJTKM250113+车牌
4)海运(S):
海运(S)-上海-西港-250113-提单号
SSHXG250113+提单号
5)铁路(R):
铁路(R)-上海-南宁-250113-集装箱号
RSHNN250113+集装箱号
6)国内进仓(D):
上海-顺丰-南京分拨中心-250113-运单号/订单号 (顺丰、跨越、百世、安能、中通、申通、货拉拉、运满满等)
DSHNN250113+运单号/订单号
*/
let startPrefix="N";
if(postForm.transType==1){
// 快递(E)-南京分拨中心(NJ)-东航(DH)-昆明(KM)-250113-提单号
startPrefix = "E";
}
else if(postForm.transType==2){
// 空运(A)-南京分拨中心(NJ)-南航(NH)-昆明(KM)-250113-提单号
startPrefix="A"
}
else if(postForm.transType==3){
// 陆运(L)-南京分拨中心(NJ)-九通(JT)-昆明(KM)-250113-车牌
startPrefix="L"
}
else if(postForm.transType==4){
// 海运(S)-上海-供应商-西港-250113-提单号
startPrefix="S"
}
else if(postForm.transType==5){
// 铁路(R)-上海-南宁-250113-集装箱号
startPrefix="R"
}
else if(postForm.transType==6){
// 国内进仓(D)-上海-供应商-南宁-250113-集装箱号
startPrefix="D"
}
let yymmdd = moment(new Date(postForm.etd)).format('YYMMDD');
return startPrefix+postForm.startSiteSizeCode3+""+postForm.supplierNameEn+""+postForm.nextSiteSizeCode3+yymmdd+postForm.carNo;
// postForm.batchName =
},
async getSiteBySiteName(siteName){
// 计算网点是否存在
let qParam = {
pageNum:1,
pageSize:1,
siteName:siteName
};
let resStartSite = await listSimpleEmisSite(qParam);
if(!resStartSite || resStartSite.code != 200){
return null;
}
if(resStartSite.rows==null || resStartSite.rows.length==0){
return null;
}
return resStartSite.rows[0];
},
async getSupplierByName(supplierName){
// 计算网点是否存在
let qParam = {
pageNum:1,
pageSize:1,
name:supplierName
};
let res= await listSimpleEmisSupplier(qParam);
if(!res || res.code != 200){
return null;
}
if(res.rows==null || res.rows.length==0){
return null;
}
return res.rows[0];
},
/** 搜索按钮操作 */
handleQuery() {
// this.queryParams.pageNum = 1;
// this.getList();
},
/** 重置按钮操作 */
resetQuery() {
// this.resetForm("queryForm");
// this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.selectionList=selection;
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
// 排序 查询字段是表格中字段名字 动态取值排序顺序
handleSortChange(column) {
this.queryParams.orderByColumn = column.prop;
this.queryParams.isAsc = column.order;
this.getList();
},
cancel(){
this.openUploadForm = false;
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
let that=this;
this.$modal.confirm('是否确认删除').then(function() {
that.selectionList.forEach((item,index) =>{
that.orderList.forEach((v,i)=>{
if(item.index === v.index){
that.orderList.splice(i,1)
}
})
})
that.$refs.multipleTable.clearSelection();
}).then(() => {
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 列索引函数 */
getIndex($index) {
return (this.queryParams.pageNum - 1) * this.queryParams.pageSize + $index + 1
},
}
};
</script>
<style lang="scss" scoped>
:deep .el-form-item__label-wrap {
margin-left: 0 !important;
}
.el-divider{
margin-top: 0px;
background: 0 0;
border-top: 1px solid #E6EBF5;
}
.el-divider__text {
color: #0955ee;
cursor: pointer;
}
.query-label {
.el-radio{
display: block;
line-height: 23px;
white-space: normal;
margin-right: 0;
}
}
.queryForm .el-form-item {
margin-bottom: 0px !important;
}
:deep .el-table .success-row {
color: rgb(21, 174, 31) !important;
}
:deep .el-table .warning-row {
color: #f51f1f !important;
}
:deep .el-form-item__label {
text-align: left;
}
</style>