Browse Source

领料申请单优化

master
shenzhouyu 4 months ago
parent
commit
f249029875
  1. 9
      src/views/modules/production-issue/directIssue.vue
  2. 29
      src/views/modules/production-issue/directIssueDetail.vue
  3. 120
      src/views/modules/production-issue/productionPicking.vue
  4. 72
      src/views/modules/production-issue/productionPickingDetail.vue

9
src/views/modules/production-issue/directIssue.vue

@ -86,7 +86,7 @@
<div class="detail-label">需求数量</div> <div class="detail-label">需求数量</div>
<div class="detail-value">{{ material.qtyRequired }}</div> <div class="detail-value">{{ material.qtyRequired }}</div>
</div> </div>
<div class="detail-item">
<div class="detail-item" :class="{ 'issued-qty-highlight': (material.qtyIssued || 0) > 0 }">
<div class="detail-label">已发数量</div> <div class="detail-label">已发数量</div>
<div class="detail-value">{{ material.qtyIssued || 0 }}</div> <div class="detail-value">{{ material.qtyIssued || 0 }}</div>
</div> </div>
@ -533,6 +533,13 @@ export default {
margin-left: -12px; margin-left: -12px;
} }
/* 已发数量高亮样式 */
.detail-item.issued-qty-highlight .detail-label,
.detail-item.issued-qty-highlight .detail-value {
font-weight: bold;
color: #ff0000;
}
/* 扫描区域 */ /* 扫描区域 */
.scan-section { .scan-section {
margin-top: 16px; margin-top: 16px;

29
src/views/modules/production-issue/directIssueDetail.vue

@ -70,16 +70,18 @@
<div class="col-qty">数量</div> <div class="col-qty">数量</div>
</div> </div>
<div v-for="(label, index) in scannedLabels" :key="label.id" class="list-item">
<div class="col-no">{{ index+1 }}</div>
<div class="col-label">{{ label.labelCode }}</div>
<div class="col-batch">{{label.warehouseId}}</div>
<div class="col-batch">{{ label.batchNo || '-' }}</div>
<div class="col-qty">{{ label.quantity }}</div>
</div>
<div class="list-body">
<div v-for="(label, index) in scannedLabels" :key="label.id" class="list-item">
<div class="col-no">{{ index+1 }}</div>
<div class="col-label">{{ label.labelCode }}</div>
<div class="col-batch">{{label.warehouseId}}</div>
<div class="col-batch">{{ label.batchNo || '-' }}</div>
<div class="col-qty">{{ label.quantity }}</div>
</div>
<div v-if="scannedLabels.length === 0" class="empty-labels">
<p>暂无扫描标签</p>
<div v-if="scannedLabels.length === 0" class="empty-labels">
<p>暂无扫描标签</p>
</div>
</div> </div>
</div> </div>
@ -516,6 +518,9 @@ export default {
margin: 0 16px 12px; margin: 0 16px 12px;
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
display: flex;
flex-direction: column;
max-height: calc(100vh - 320px);
} }
.list-header { .list-header {
display: flex; display: flex;
@ -525,6 +530,12 @@ export default {
font-size: 12px; font-size: 12px;
color: #666; color: #666;
font-weight: 500; font-weight: 500;
flex-shrink: 0;
}
.list-body {
overflow-y: auto;
flex: 1;
min-height: 0;
} }
.list-item { .list-item {
display: flex; display: flex;

120
src/views/modules/production-issue/productionPicking.vue

@ -87,9 +87,9 @@
<div class="detail-label">申请物料行号</div> <div class="detail-label">申请物料行号</div>
<div class="detail-value">{{ material.bomItemNo }}</div> <div class="detail-value">{{ material.bomItemNo }}</div>
</div> </div>
<div class="detail-item">
<div class="detail-label">单位</div>
<div class="detail-value">{{ material.uom || "个" }}</div>
<div :class="['detail-item', { 'issued-qty-highlight': (material.qtyIssuedHis || 0) > 0 }]">
<div class="detail-label">已发数量</div>
<div class="detail-value">{{ material.qtyIssuedHis || 0 }}</div>
</div> </div>
</div> </div>
</div> </div>
@ -239,10 +239,106 @@ export default {
}); });
}, },
// sessionStorage
savePageStateForDetail() {
const state = {
searchCode: this.searchCode,
currentNotifyNo: this.currentNotifyNo,
outboundList: this.outboundList,
// notifyNo + itemNo + soorderNo
selectedWorkOrderKey: this.selectedWorkOrder ? {
notifyNo: this.selectedWorkOrder.notifyNo,
itemNo: this.selectedWorkOrder.itemNo,
soorderNo: this.selectedWorkOrder.soorderNo || this.selectedWorkOrder.orderNo
} : null,
materialList: this.materialList,
showOnlySelected: this.showOnlySelected,
};
sessionStorage.setItem('productionPicking_state_fromDetail', JSON.stringify(state));
},
// sessionStorage
restorePageStateFromDetail() {
try {
const shouldRestore = sessionStorage.getItem('productionPicking_shouldRestore');
const savedState = sessionStorage.getItem('productionPicking_state_fromDetail');
if (shouldRestore === 'true' && savedState) {
const state = JSON.parse(savedState);
this.searchCode = state.searchCode || '';
this.currentNotifyNo = state.currentNotifyNo || '';
this.outboundList = state.outboundList || [];
this.materialList = state.materialList || [];
this.showOnlySelected = state.showOnlySelected || false;
// outboundList
// 使 notifyNo + itemNo + soorderNo
if (state.selectedWorkOrderKey && this.outboundList.length > 0) {
const key = state.selectedWorkOrderKey;
//
if (typeof key === 'string') {
const matchedWorkOrder = this.outboundList.find(wo =>
(wo.orderNo || wo.soorderNo) === key
);
this.selectedWorkOrder = matchedWorkOrder || null;
} else {
// 使 notifyNoitemNosoorderNo
const matchedWorkOrder = this.outboundList.find(wo =>
wo.notifyNo === key.notifyNo &&
wo.itemNo === key.itemNo &&
(wo.soorderNo || wo.orderNo) === key.soorderNo
);
if (matchedWorkOrder) {
this.selectedWorkOrder = matchedWorkOrder;
} else {
this.selectedWorkOrder = null;
}
}
} else {
this.selectedWorkOrder = null;
}
//
const issueInfoStr = sessionStorage.getItem('productionPicking_issueInfo');
if (issueInfoStr) {
try {
const issueInfo = JSON.parse(issueInfoStr);
// materialList
const material = this.materialList.find(m =>
m.partNo === issueInfo.componentPartNo &&
m.bomItemNo === issueInfo.lineItemNo
);
if (material) {
// = +
material.qtyIssuedHis = (material.qtyIssuedHis || 0) + (issueInfo.issueQty || 0);
}
//
sessionStorage.removeItem('productionPicking_issueInfo');
} catch (error) {
console.error('解析本次扫描信息失败:', error);
sessionStorage.removeItem('productionPicking_issueInfo');
}
}
//
sessionStorage.removeItem('productionPicking_shouldRestore');
sessionStorage.removeItem('productionPicking_state_fromDetail');
}
} catch (error) {
console.error('恢复页面状态失败:', error);
//
sessionStorage.removeItem('productionPicking_shouldRestore');
sessionStorage.removeItem('productionPicking_state_fromDetail');
}
},
// //
goToPickingPage(item) { goToPickingPage(item) {
console.log("选中物料:", item, this.selectedWorkOrder); console.log("选中物料:", item, this.selectedWorkOrder);
//
this.savePageStateForDetail();
this.$router.push({ this.$router.push({
name: 'productionPickingDetail', name: 'productionPickingDetail',
query: { query: {
@ -251,6 +347,7 @@ export default {
orderNo: this.selectedWorkOrder.soorderNo, orderNo: this.selectedWorkOrder.soorderNo,
componentPartNo: item.partNo, componentPartNo: item.partNo,
qtyToIssue: item.requestQty, qtyToIssue: item.requestQty,
itemNo: this.selectedWorkOrder.itemNo,
lineItemNo: item.bomItemNo, lineItemNo: item.bomItemNo,
releaseNo: this.selectedWorkOrder.releaseNo, releaseNo: this.selectedWorkOrder.releaseNo,
sequenceNo: this.selectedWorkOrder.sequenceNo, sequenceNo: this.selectedWorkOrder.sequenceNo,
@ -261,6 +358,10 @@ export default {
}, },
mounted() { mounted() {
//
const hasRestored = sessionStorage.getItem('productionPicking_shouldRestore') === 'true';
this.restorePageStateFromDetail();
// //
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.searchInput) { if (this.$refs.searchInput) {
@ -268,8 +369,10 @@ export default {
} }
}); });
//
this.loadOutboundList();
//
if (!hasRestored) {
this.loadOutboundList();
}
} }
}; };
</script> </script>
@ -446,6 +549,13 @@ export default {
color: #333; color: #333;
} }
/* 已发数量高亮样式 */
.detail-item.issued-qty-highlight .detail-label,
.detail-item.issued-qty-highlight .detail-value {
font-weight: bold;
color: #ff0000;
}
/* 空状态 */ /* 空状态 */
.empty-state { .empty-state {
display: flex; display: flex;

72
src/views/modules/production-issue/productionPickingDetail.vue

@ -2,7 +2,7 @@
<div class="pda-container"> <div class="pda-container">
<!-- 头部栏 --> <!-- 头部栏 -->
<div class="header-bar"> <div class="header-bar">
<div class="header-left" @click="$router.back()">
<div class="header-left" @click="handleBack">
<i class="el-icon-arrow-left"></i> <i class="el-icon-arrow-left"></i>
<span>生产领料</span> <span>生产领料</span>
</div> </div>
@ -86,20 +86,22 @@
<div class="col-qty">标签数量</div> <div class="col-qty">标签数量</div>
</div> </div>
<div
v-for="(label, index) in labelList"
:key="label.id"
class="list-item"
>
<div class="col-no">{{ labelList.length - index }}</div>
<div class="col-label">{{ label.labelCode }}</div>
<div class="col-part">{{ label.locationId }}</div>
<div class="col-qty">{{ label.quantity }}</div>
</div>
<div class="list-body">
<div
v-for="(label, index) in labelList"
:key="label.id"
class="list-item"
>
<div class="col-no">{{ labelList.length - index }}</div>
<div class="col-label">{{ label.labelCode }}</div>
<div class="col-part">{{ label.locationId }}</div>
<div class="col-qty">{{ label.quantity }}</div>
</div>
<!-- 空状态 -->
<div v-if="labelList.length === 0" class="empty-labels">
<p>暂无扫描标签</p>
<!-- 空状态 -->
<div v-if="labelList.length === 0" class="empty-labels">
<p>暂无扫描标签</p>
</div>
</div> </div>
</div> </div>
@ -281,10 +283,9 @@ export default {
qty += label.quantity; qty += label.quantity;
} }
if (qty > this.outboundInfo.qtyToIssue) { if (qty > this.outboundInfo.qtyToIssue) {
this.$message.warning('扫描标签总数量超过需求数量');
this.$confirm('取消后将清空已扫描的标签,确定取消吗?', '提示', {
this.$confirm('扫描标签总数量超过需求数量确定出库吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '继续操作',
cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
this.confirmProductionPicking(); this.confirmProductionPicking();
@ -297,10 +298,12 @@ export default {
confirmProductionPicking(){ confirmProductionPicking(){
const params = { const params = {
site: localStorage.getItem('site'), site: localStorage.getItem('site'),
notifyNo:this.outboundInfo.outboundNo,
workOrderNo: this.outboundInfo.orderNo, workOrderNo: this.outboundInfo.orderNo,
componentPartNo: this.outboundInfo.componentPartNo, componentPartNo: this.outboundInfo.componentPartNo,
operatorName: localStorage.getItem('userName'), operatorName: localStorage.getItem('userName'),
itemNo: this.outboundInfo.lineItemNo,
itemNo: this.outboundInfo.itemNo,
lineItemNo:this.outboundInfo.lineItemNo,
releaseNo:this.outboundInfo.releaseNo, releaseNo:this.outboundInfo.releaseNo,
sequenceNo:this.outboundInfo.sequenceNo, sequenceNo:this.outboundInfo.sequenceNo,
selectedMaterials: this.labelList.map((l, i) => ({ selectedMaterials: this.labelList.map((l, i) => ({
@ -317,6 +320,15 @@ export default {
confirmProductionPicking(params).then(({ data }) => { confirmProductionPicking(params).then(({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
this.$message.success('操作成功'); this.$message.success('操作成功');
// productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
//
const issueInfo = {
componentPartNo: this.outboundInfo.componentPartNo,
lineItemNo: this.outboundInfo.lineItemNo,
issueQty: this.totalScannedQty
};
sessionStorage.setItem('productionPicking_issueInfo', JSON.stringify(issueInfo));
this.$router.back(); this.$router.back();
} else { } else {
this.$message.error(data.msg || '操作失败'); this.$message.error(data.msg || '操作失败');
@ -344,18 +356,29 @@ export default {
if (this.labelList.length > 0) { if (this.labelList.length > 0) {
this.$confirm('取消后将清空已扫描的标签,确定取消吗?', '提示', { this.$confirm('取消后将清空已扫描的标签,确定取消吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '继续操作',
cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
// productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
this.$router.back(); this.$router.back();
}).catch(() => { }).catch(() => {
// //
}); });
} else { } else {
// productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
this.$router.back(); this.$router.back();
} }
}, },
//
handleBack() {
// productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
this.$router.back();
},
// //
showMaterialListDialog() { showMaterialListDialog() {
this.showMaterialDialog = true; this.showMaterialDialog = true;
@ -425,6 +448,7 @@ export default {
this.outboundInfo.orderNo = this.$route.query.notifyInfo.orderNo this.outboundInfo.orderNo = this.$route.query.notifyInfo.orderNo
this.outboundInfo.componentPartNo = this.$route.query.notifyInfo.componentPartNo this.outboundInfo.componentPartNo = this.$route.query.notifyInfo.componentPartNo
this.outboundInfo.qtyToIssue = this.$route.query.notifyInfo.qtyToIssue this.outboundInfo.qtyToIssue = this.$route.query.notifyInfo.qtyToIssue
this.outboundInfo.itemNo = this.$route.query.notifyInfo.itemNo
this.outboundInfo.lineItemNo = this.$route.query.notifyInfo.lineItemNo this.outboundInfo.lineItemNo = this.$route.query.notifyInfo.lineItemNo
this.outboundInfo.releaseNo = this.$route.query.notifyInfo.releaseNo this.outboundInfo.releaseNo = this.$route.query.notifyInfo.releaseNo
this.outboundInfo.sequenceNo = this.$route.query.notifyInfo.sequenceNo this.outboundInfo.sequenceNo = this.$route.query.notifyInfo.sequenceNo
@ -709,6 +733,9 @@ export default {
margin: 0 16px 12px; margin: 0 16px 12px;
border-radius: 0 0 8px 8px; border-radius: 0 0 8px 8px;
overflow: hidden; overflow: hidden;
display: flex;
flex-direction: column;
max-height: calc(100vh - 320px);
} }
.list-header { .list-header {
@ -719,6 +746,13 @@ export default {
font-size: 12px; font-size: 12px;
color: #666; color: #666;
font-weight: 500; font-weight: 500;
flex-shrink: 0;
}
.list-body {
overflow-y: auto;
flex: 1;
min-height: 0;
} }
.list-item { .list-item {

Loading…
Cancel
Save