合并收货功能

This commit is contained in:
wuteng 2026-03-20 14:21:26 +08:00
parent 9a45600e0e
commit 11864bf6d6
7 changed files with 637 additions and 9 deletions

View File

@ -59,3 +59,12 @@ export function delEmisWarehouseIn(id) {
method: 'delete'
})
}
// 确认进仓单完成
export function confirmStockInComplete(id) {
return request({
url: '/emis/emisWarehouseInBatch/confirmStockInComplete/' + id,
method: 'get',
params: {id:id}
})
}

View File

@ -56,3 +56,12 @@ export function delEmisWarehouseInBatch(id) {
method: 'delete'
})
}
// 批量进仓登记
export function registerWarehouseInInfoBatch(data) {
return request({
url: 'emis/emisWarehouseInBatch/mergeRegisterWarehouseInInfo',
method: 'post',
data: data
})
}

View File

@ -4,7 +4,7 @@
<div class="tab-container">
<el-tabs v-model="activeTab" class="center-tabs" @tab-click="handleTabsClick" @tab-remove="removeTab">
<el-tab-pane label="进仓单" name="billList" >
<WarehouseInPanel @onSelect="onSelectBill" @onStockIn="onStockIn" > </WarehouseInPanel>
<WarehouseInPanel ref="billPanel" @onSelect="onSelectBill" @onStockIn="onStockIn" @onBatchStockIn="onBatchStockIn"> </WarehouseInPanel>
</el-tab-pane>
<el-tab-pane label="收货入仓" name="wsInPanel" v-if="showWsInPanel" closable>
<WarehouseStockIn :key="selectInNo" :inNo="selectInNo"></WarehouseStockIn>
@ -12,7 +12,9 @@
<!-- <el-tab-pane v-for="(item, index) in billTabs" :key="index" :name="item.inNo" :label="'进仓单:'+item.inNo" closable >
<WarehouseInBatchPanel :inNo="item.inNo"></WarehouseInBatchPanel>
</el-tab-pane> -->
<el-tab-pane label="合并进仓" name="wsInBatchPanel" v-if="showWsInBatchPanel" closable>
<WarehouseStockInBatch :key="selectInNo" :inNos="selectInNos" @on-changed="onBatchStockInChanged"></WarehouseStockInBatch>
</el-tab-pane>
<el-tab-pane label="查看进仓详情" name="wsInView" v-if="openViewForm" closable >
<WarehouseInBatchPanel :key="'batchView_'+selectInNo" :inNo="selectInNo"></WarehouseInBatchPanel>
</el-tab-pane>
@ -26,13 +28,14 @@
import WarehouseInPanel from '@/views/emis/emisWarehouseIn/panel/WarehouseInPanel.vue';
import WarehouseInBatchPanel from '@/views/emis/emisWarehouseInBatch/WarehouseInBatchPanel.vue';
import WarehouseStockIn from '@/views/emis/emisWarehouseInBatch/WarehouseStockIn.vue';
import WarehouseStockInBatch from '@/views/emis/emisWarehouseInBatch/WarehouseStockInBatch.vue';
export default {
name: "WarehouseInList",
components: {
WarehouseInPanel,
WarehouseInBatchPanel,
WarehouseStockIn
WarehouseStockIn,
WarehouseStockInBatch,
},
dicts: [
],
@ -41,8 +44,9 @@ export default {
activeTab:'billList',
billTabs:[],
showWsInPanel:false,
showWsInBatchPanel:false,
selectInNo:null,
selectInNos:[],
openViewForm:false,
};
},
@ -57,6 +61,13 @@ export default {
this.showWsInPanel=true;
this.activeTab='wsInPanel';
},
onBatchStockIn(list){
this.selectInNos=list.map(item=>item.inNo);
this.showWsInBatchPanel=true;
this.activeTab='wsInBatchPanel';
},
onSelectBill(item) {
// let old=this.billTabs.find(mItem=>mItem.inNo==item.inNo);
@ -80,6 +91,10 @@ export default {
this.openViewForm=false;
this.activeTab="billList";
}
else if(targetName=='wsInBatchPanel'){
this.showWsInBatchPanel=false;
this.activeTab="billList";
}
else{
var self=this;
let tabs = self.billTabs;
@ -92,6 +107,11 @@ export default {
}
},
onBatchStockInChanged(){
//刷新进仓单列表
this.removeTab('wsInBatchPanel');
this.$refs.billPanel.getList();
},
}
};

View File

@ -218,6 +218,26 @@
@click="handleExportDtl"
>导出进仓明细</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="primary"
plain
size="mini"
v-hasPermi="['emis:emisWarehouseInBatch:mergeRegisterWarehouseInInfo']"
@click="handleBatchStockIn "
:disabled="multiple || !allSelectedStockInFlag || selectionList.length <2"
>合并收货</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
size="mini"
v-hasPermi="['emis:emisWarehouseInBatch:confirmStockInComplete']"
@click="handleConfirmStockInComplete"
:disabled="single || selectedStockInFlag!=2"
>手动确认</el-button>
</el-col>
</el-row>
</div>
@ -260,7 +280,14 @@
<el-tag v-if="scope.row.stockInFlag=='2'" type="warning">部分入仓</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('进仓批次号')" align="center" prop="warehouseInBatchNo" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('总件数')" align="center" prop="totalParcelQty" min-width="100" />
<el-table-column :label="$t('预计入仓件数')" align="center" prop="waybillDetail.parcelQty" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('剩余件数')" align="center" prop="remainParcelQty" min-width="80" :show-overflow-tooltip="true">
<template slot-scope="scope">
{{scope.row.waybillDetail.parcelQty-scope.row.totalParcelQty}}
</template>
</el-table-column>
<el-table-column :label="$t('总体积')" align="center" prop="totalVolume" min-width="100" />
<el-table-column :label="$t('总重量')" align="center" prop="totalWeight" min-width="100" />
<el-table-column :label="$t('图片上传')" align="center" prop="blUploadPic" min-width="100" >
@ -295,7 +322,7 @@
<el-table-column :label="$t('目的地')" align="center" prop="waybillDetail.destinationName" min-width="80" :show-overflow-tooltip="true"/>
<el-table-column :label="$t('目的网点')" align="center" prop="waybillDetail.dispatchUnderlingSiteName" min-width="80" :show-overflow-tooltip="true"/>
<!-- <el-table-column :label="$t('状态')" align="center" prop="status" min-width="100" /> -->
<!-- <el-table-column :label="$t('备注')" align="center" prop="remark" min-width="100" /> -->
@ -317,7 +344,7 @@
</template>
<script>
import { listEmisWarehouseIn, getEmisWarehouseIn, delEmisWarehouseIn, addEmisWarehouseIn, updateEmisWarehouseIn } from "@/api/emis/emisWarehouseIn";
import { listEmisWarehouseIn, getEmisWarehouseIn, delEmisWarehouseIn, addEmisWarehouseIn, updateEmisWarehouseIn, confirmStockInComplete } from "@/api/emis/emisWarehouseIn";
import elDateSimplePicker from '@/components/DatePickerAdv/elDateSimplePicker';
import elDateAdvPicker from '@/components/DatePickerAdv/elDateAdvPicker';
// import emisWarehouseInView from '@/views/emis/emisWarehouseIn/emisWarehouseInView';
@ -337,6 +364,7 @@ export default {
'emis_tab_packing_type','emis_tab_dispatch_mode','emis_payment_type',
'emis_calc_fee_type','emis_print_type','emis_payment_status','emis_waybill_status','emis_tab_dispatch_mode'
],
emits: ["onBatchStockIn"],
data() {
return {
// 遮罩层
@ -357,7 +385,8 @@ export default {
emisWarehouseInList: [],
selectionList:[],
selectedStockInFlag:null, // 选中的进仓单状态
allSelectedStockInFlag:null, // 所有选中的进仓单状态
currentId:null,
openForm: false,
titleForm: "",
@ -468,6 +497,23 @@ export default {
this.$emit("onStockIn",inNo);
}
},
handleBatchStockIn(){
//判断选中数据是否都是同一客户
// let customerCodes = this.selectionList.map(item => item.customerCode);
// let uniqueCustomerCodes = new Set(customerCodes);
// if (uniqueCustomerCodes.size !== 1) {
// this.$message.error('不同客户的单据无法合并入库');
// return;
// }
// 跳转收货入仓
if(this.selectionList&&this.selectionList.length>0){
let inNo=this.selectionList[0].inNo;
let id=this.selectionList[0].id;
// this.$router.push({ path: '/d24/orderManagement/WarehouseStockIn', query: {name:"收货入仓", action: "add",id:id,inNo: inNo,addFrom:"stockIn"}})
}
this.$emit("onBatchStockIn",this.selectionList);
},
handleAccept(){
// 跳转到开单界面
if(this.selectionList&&this.selectionList.length>0){
@ -494,6 +540,8 @@ export default {
this.selectionList=selection;
if(this.selectionList&&this.selectionList.length>0){
// this.currentSelectOrder=this.selectionList[0];
this.selectedStockInFlag=this.selectionList[0].stockInFlag;
this.allSelectedStockInFlag=this.selectionList.every(item => (item.stockInFlag === '0'|| item.stockInFlag === '2')); // 所有选中的进仓单状态都是0或2
}
},
@ -865,6 +913,31 @@ export default {
dateTimeChange(value){
this.dateTimeRange=value;
},
// 手动确认进仓单完成
handleConfirmStockInComplete(){
const selectedItem = this.selectionList[0];
console.log('this.selectionList',this.selectionList[0]);
this.$confirm(`该单据本次入仓${selectedItem.totalParcelQty}件,预计入仓${selectedItem.waybillDetail.parcelQty}件,是否完成入仓操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
confirmStockInComplete(selectedItem.id).then(response => {
if (response.code == 200) {
this.$message({
message: '手动确认进仓单完成成功',
type: 'success'
});
this.getList();
}
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消手动确认进仓单完成'
});
});
}
}
};
</script>

View File

@ -498,7 +498,22 @@ export default {
async handleInput(item, size){
},
deleteGoodsItem(row, index) {
this.$confirm('确定删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.form.cargoList.splice(index, 1)
this.handleCalcVolume(row);
}).catch(() => {
})
},
copyGoodsItem(row, index) {
let newItem = Object.assign({}, row);
newItem.cargoQty = 1;
this.form.cargoList.splice(index + 1, 0, newItem);
},
}
};
</script>

View File

@ -0,0 +1,78 @@
<template>
<div class="app-container">
<!-- 循环子表单 -->
<WarehouseStockInItem
v-for="(inNo, index) in inNos"
:key="inNo"
:in-no="inNo"
:index="index"
style="margin-bottom: 20px;"
ref="stockItem"
/>
<!-- 底部按钮 -->
<div class="text-center mb-50 mt-50">
<el-button type="primary" @click="submitAll">确定</el-button>
<el-button @click="cancelAll">取消</el-button>
</div>
</div>
</template>
<script>
import WarehouseStockInItem from './WarehouseStockInItem.vue'
import { registerWarehouseInInfoBatch } from "@/api/emis/emisWarehouseInBatch";
export default {
name: 'WarehouseStockInBatch',
components: { WarehouseStockInItem },
props: {
inNos: {
type: Array,
default: () => []
}
},
methods: {
// 统一提交
async submitAll() {
const items = this.$refs.stockItem || []
if (!items.length) {
this.$modal.msgWarning('没有可提交的进仓单')
return
}
for (let item of items) {
const valid = await item.validateForm();
if (!valid) {
this.$modal.msgError("请完善表单信息");
return;
}
}
// 收集所有表单数据
const forms = items.map(it => it.form)
// 提交进仓单
registerWarehouseInInfoBatch(forms).then(res => {
if (res.code === 200) {
this.$modal.msgSuccess("进仓单提交成功");
this.$emit("on-changed");
}
});
},
// 统一取消
cancelAll() {
this.$children.forEach(child => child.reset())
this.$emit('on-cancel')
}
}
}
</script>
<style scoped>
.text-center {
text-align: center;
}
.mb-50 {
margin-bottom: 50px;
}
.mt-50 {
margin-top: 50px;
}
</style>

View File

@ -0,0 +1,424 @@
<template>
<el-form
ref="form"
:model="form"
size="mini"
:rules="rules"
label-width="80px"
>
<el-row :gutter="0" class="flex-wrap">
<el-col :span="24" style="border-right: 1px solid #e6ebf5; padding-right: 20px;">
<div class="head-container">
<el-row :gutter="0" class="flex-wrap">
<el-col :span="7">
<el-form-item :label="`进仓单号${index + 1}`" prop="inNo">
<el-input
v-model="form.inNo"
clearable
placeholder="单号输入后按回车"
disabled
>
<i slot="suffix" class="iconfont">&#xe656;</i>
</el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item :label="`进仓后缀${index + 1}`" prop="inBatchNo">
<el-input v-model="form.inBatchNo" placeholder="例如:001" />
</el-form-item>
</el-col>
</el-row>
</div>
<el-collapse v-model="activeNames">
<!-- 货物明细 -->
<el-collapse-item title="" name="2">
<template slot="title">
<div class="form-group-title">
<span class="title">{{ $t('货物明细') }}</span>
</div>
</template>
<el-row class="flex-wrap">
<el-col :span="24">
<div class="inline-flex mb-10">
<el-button
size="mini"
type="primary"
class="iconfont icon-add"
@click="handleAddGoods"
>
{{ $t('添加货物') }}
</el-button>
</div>
<el-table
class="cargoList"
border
stripe
:data="form.cargoList"
size="mini"
style="width: 100%"
>
<el-table-column label="序号" align="center" width="60">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column
prop="goodsName"
label="品名"
align="center"
width="120"
show-overflow-tooltip
>
<template slot-scope="scope">
<GoodsInput v-model="scope.row.goodsName" size="mini" />
</template>
</el-table-column>
<el-table-column prop="cargoQty" label="件数" align="center" width="60">
<template slot-scope="scope">
<el-input v-model="scope.row.cargoQty" size="mini" />
</template>
</el-table-column>
<el-table-column prop="length" label="长(cm)" align="center" width="80">
<template slot-scope="scope">
<el-input v-model="scope.row.length" size="mini" />
</template>
</el-table-column>
<el-table-column prop="width" label="宽(cm)" align="center" width="80">
<template slot-scope="scope">
<el-input v-model="scope.row.width" size="mini" />
</template>
</el-table-column>
<el-table-column prop="height" label="高(cm)" align="center" width="80">
<template slot-scope="scope">
<el-input v-model="scope.row.height" size="mini" />
</template>
</el-table-column>
<el-table-column
prop="brand"
label="品牌"
align="center"
width="80"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-input v-model="scope.row.brand" size="mini" />
</template>
</el-table-column>
<el-table-column
prop="material"
label="材质"
align="center"
width="60"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-input v-model="scope.row.material" size="mini" />
</template>
</el-table-column>
<el-table-column
prop="purpose"
label="用途"
align="center"
width="60"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-input v-model="scope.row.purpose" size="mini" />
</template>
</el-table-column>
<el-table-column
prop="ingredients"
label="成分"
align="center"
width="60"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-input v-model="scope.row.ingredients" size="mini" />
</template>
</el-table-column>
<el-table-column
prop="supplier"
label="供应商"
align="center"
width="80"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-input v-model="scope.row.supplier" size="mini" />
</template>
</el-table-column>
<el-table-column label="操作" align="left" min-width="50">
<template slot-scope="scope">
<i
class="iconfont icon-delete"
style="cursor: pointer; font-size: 21px; color: #6e6e6e;margin-right:5px"
@click="deleteGoodsItem(scope.$index)"
/>
<i
class="iconfont icon-copy"
style="cursor: pointer; font-size: 21px; color: #6e6e6e;"
@click="copyGoodsItem(scope.row, scope.$index)"
/>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :span="24">
<el-row class="flex-wrap mt-20">
<el-col :span="4">
<el-form-item label="总件数" prop="parcelQty" label-width="70px">
<el-input v-model="form.parcelQty" style="text-align: right" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="总重量" prop="billWeight" label-width="70px">
<el-input v-model="form.billWeight" style="text-align: right">
<span slot="suffix">(kg)</span>
</el-input>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="总体积" prop="totalVolume" label-width="70px">
<el-input v-model="form.totalVolume" style="text-align: right">
<span slot="suffix">(m³)</span>
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-col>
<el-col :span="24">
<el-row class="flex-wrap mt-20">
<el-col :span="5">
<el-form-item label="快递公司" prop="prepareInExpress">
<el-select filterable clearable v-model="form.prepareInExpress" style="width:100%">
<el-option
v-for="item in dict.type.emis_express_code"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="快递单号" prop="prepareInBillCode">
<el-input v-model="form.prepareInBillCode" placeholder="请输入快递单号" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="是否代垫运费" prop="blPrepareInFreight" label-width="100px">
<el-radio-group v-model="form.blPrepareInFreight">
<el-radio label="1">是</el-radio>
<el-radio label="0">否</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="5" v-if="form.blPrepareInFreight == 1">
<el-form-item label="代垫运费" prop="prepareInEstFee">
<el-input v-model="form.prepareInEstFee" />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="自定义标识" prop="prepareInRemark">
<el-input v-model="form.prepareInRemark" placeholder="自定义标识" />
</el-form-item>
</el-col>
</el-row>
</el-col>
</el-row>
</el-collapse-item>
<!-- 收货图片 -->
<el-collapse-item title="" name="3">
<template slot="title">
<div class="form-group-title">
<span class="title">{{ $t('收货图片') }}</span>
</div>
</template>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item :label="`收货图片${index + 1}`" prop="picUrl">
<ImageUpload
ref="imageUpload"
v-model="form.picUrl"
:file-size="1"
:limit="20"
/>
</el-form-item>
</el-col>
</el-row>
</el-collapse-item>
</el-collapse>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { getWarehouseInInfo } from '@/api/emis/emisWarehouseIn'
import GoodsInput from '@/views/emis/EmisBaseTools/GoodsInput.vue'
import ImageUpload from '@/components/ImageUpload/index.vue'
export default {
name: 'WarehouseStockInItem',
components: { GoodsInput, ImageUpload },
dicts: ['emis_express_code'],
props: {
inNo: {
type: String,
required: true
},
index: {
type: Number,
default: 0
}
},
data() {
return {
activeNames: ['1', '2', '3'],
loading: false,
form: this.getEmptyForm(),
rules: {
inNo: [{ required: true, message: '进仓单号不能为空', trigger: 'blur' }],
totalVolume: [{ required: true, message: '总体积不能为空', trigger: 'blur' }],
parcelQty: [{ required: true, message: '总件数不能为空', trigger: 'blur' }],
billWeight: [{ required: true, message: '总重量不能为空', trigger: 'blur' }]
}
}
},
created() {
this.initData()
},
methods: {
// 空表单
getEmptyForm() {
return {
id: null,
inNo: null,
inBatchNo: null,
customerCode: null,
customerName: null,
orderSn: null,
billCode: null,
parcelQty: null, //预计进仓件数
billWeight: null,
totalVolume: null,
blPrepareInFreight: '0',
prepareInEstFee: null,
prepareInExpress: null,
prepareInBillCode: null,
prepareInRemark: null,
picUrl: null,
cargoList: []
}
},
// 初始化
async initData() {
if (!this.inNo) return
this.loading = true
try {
const { data } = await getWarehouseInInfo(this.inNo)
this.form.inNo = data.inNo
this.form.customerCode = data.customerCode
this.form.customerName = data.customerName
this.form.orderSn = data.orderSn
this.form.billCode = data.billCode
} finally {
this.loading = false
}
},
// 添加货物
handleAddGoods() {
this.form.cargoList.push({
goodsName: '填写货物名称',
cargoQty: 1,
length: 0,
width: 0,
height: 0,
brand: '',
material: '',
purpose: '',
ingredients: '',
supplier: ''
})
},
// 删除货物
deleteGoodsItem(index) {
this.$confirm('确定删除该货物?', '提示', { type: 'warning' }).then(() => {
this.form.cargoList.splice(index, 1)
})
},
// 复制货物
copyGoodsItem(row, index) {
const newItem = { ...row, cargoQty: 1 }
this.form.cargoList.splice(index + 1, 0, newItem)
},
// 重置
reset() {
this.form = this.getEmptyForm()
this.$refs.form?.resetFields()
},
validateForm() {
return new Promise((resolve) => {
if (!this.$refs.form) return resolve(false);
this.$refs.form.validate((valid) => {
resolve(valid);
});
});
}
}
}
</script>
<style lang="scss" scoped>
.flex-wrap {
display: flex;
flex-wrap: wrap;
}
.inline-flex {
display: inline-flex;
}
.mt-20 {
margin-top: 20px;
}
.mb-10 {
margin-bottom: 10px;
}
.cargoList {
::v-deep .el-input__inner {
height: 28px;
line-height: 28px;
border: none;
background: #ffffcd;
font-size: 10px;
padding: 0;
text-align: center;
}
}
</style>