Browse Source

部分发料

master
shenzhouyu 2 months ago
parent
commit
40c9f84b1f
  1. 1
      src/api/production/production-return.js
  2. 322
      src/views/modules/production-issue/directIssueDetail.vue
  3. 600
      src/views/modules/production-issue/productionPickingDetail.vue
  4. 2
      src/views/modules/production-return/production.vue
  5. 10
      src/views/modules/production-return/productionReturnIssueList.vue
  6. 156
      src/views/modules/production-return/productionReturnPickingDetail.vue

1
src/api/production/production-return.js

@ -29,3 +29,4 @@ export const printLabelInfo = data => createAPI('/label/setting/printLabel','pos
// 打印标签 // 打印标签
export const printLabelCommon = data => createAPI('/label/setting/printLabelCommon','post',data) export const printLabelCommon = data => createAPI('/label/setting/printLabelCommon','post',data)
export const createNewReturnHandlingUnits = data => createAPI(`/pda/production/return/createNewReturnHandlingUnits`,'post',data)

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

@ -23,6 +23,13 @@
</div> </div>
</div> </div>
<!-- 是否部分勾选框 -->
<div class="partial-checkbox-container">
<el-checkbox v-model="isPartial" :disabled="scannedLabels.length > 0">是否部分领料</el-checkbox>
</div>
<!-- 统一滚动容器 -->
<div class="scrollable-content">
<!-- 工单物料信息 --> <!-- 工单物料信息 -->
<div class="work-order-list" v-if="workOrderNo && componentPartNo"> <div class="work-order-list" v-if="workOrderNo && componentPartNo">
<div class="work-order-card"> <div class="work-order-card">
@ -67,16 +74,22 @@
<div class="col-label">标签条码</div> <div class="col-label">标签条码</div>
<div class="col-batch">库位</div> <div class="col-batch">库位</div>
<div class="col-batch">批次号</div> <div class="col-batch">批次号</div>
<div v-if="isPartial" class="col-qty">剩余高</div>
<div class="col-qty">数量</div> <div class="col-qty">数量</div>
</div> </div>
<div class="list-body"> <div class="list-body">
<div v-for="(label, index) in scannedLabels" :key="label.id" class="list-item">
<div v-for="(label, index) in scannedLabels" :key="label.id" class="list-item"
:class="{ 'clickable': isPartial }" @click="isPartial ? handleLabelClick(label, index) : null">
<div class="col-no">{{ index+1 }}</div> <div class="col-no">{{ index+1 }}</div>
<div class="col-label">{{ label.labelCode }}</div> <div class="col-label">{{ label.labelCode }}</div>
<div class="col-batch">{{label.locationId}}</div> <div class="col-batch">{{label.locationId}}</div>
<div class="col-batch">{{ label.batchNo }}</div> <div class="col-batch">{{ label.batchNo }}</div>
<div class="col-qty">{{ label.quantity }}</div>
<div v-if="isPartial" class="col-qty">{{ label.height.toFixed(3) }}</div>
<div class="col-qty">
<span class="quantity-display">{{ label.quantity }}</span>
<i v-if="isPartial" class="el-icon-edit edit-icon"></i>
</div>
</div> </div>
<div v-if="scannedLabels.length === 0" class="empty-labels"> <div v-if="scannedLabels.length === 0" class="empty-labels">
@ -84,6 +97,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- 底部操作按钮 --> <!-- 底部操作按钮 -->
<div class="bottom-actions"> <div class="bottom-actions">
@ -97,6 +111,47 @@
取消 取消
</button> </button>
</div> </div>
<!-- 修改数量弹框 -->
<div v-if="quantityDialogVisible" class="edit-overlay" @click.self="quantityDialogVisible = false">
<div class="edit-modal">
<div class="modal-header">
<span class="modal-title">修改数量</span>
<i class="el-icon-close close-btn" @click="quantityDialogVisible = false"></i>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">标签条码</label>
<el-input v-model="currentEditLabel.labelCode" disabled class="form-input" />
</div>
<div class="form-group">
<label class="form-label">当前数量</label>
<el-input v-model="currentEditLabel.quantity" disabled class="form-input" />
</div>
<div class="form-group">
<label class="form-label">剩余高度(mm) <span class="required">*</span></label>
<el-input-number v-model="editHeight" :min="0.001" :precision="3" :step="0.001" class="form-input"
style="width: 100%;" :controls="false">
</el-input-number>
</div>
<div class="form-group">
<label class="form-label">修改数量 <span class="required">*</span></label>
<el-input-number v-model="editQuantity" :min="0.0001" :precision="4" :step="0.0001" class="form-input"
style="width: 100%;" :controls="false">
</el-input-number>
</div>
</div>
<div class="modal-footer">
<button class="btn-cancel" @click="quantityDialogVisible = false">取消</button>
<button class="btn-confirm" @click="confirmQuantityChange">确定</button>
</div>
</div>
</div>
</div> </div>
</template> </template>
@ -113,6 +168,7 @@ export default {
return { return {
scanCode: '', scanCode: '',
isRemoveMode: false, isRemoveMode: false,
isPartial: false,
scannedLabels: [], scannedLabels: [],
workOrderNo: '', workOrderNo: '',
componentPartNo: '', componentPartNo: '',
@ -121,12 +177,19 @@ export default {
issuedQty: 0, issuedQty: 0,
itemNo: '', itemNo: '',
loading: false, loading: false,
issueInfo:{}
issueInfo: {},
quantityDialogVisible: false,
currentEditLabel: {},
currentEditIndex: -1,
editQuantity: 0,
editHeight: 0,
} }
}, },
computed: { computed: {
totalScannedQty() { totalScannedQty() {
return this.scannedLabels.reduce((sum, l) => sum + (l.quantity || 0), 0)
const total = this.scannedLabels.reduce((sum, l) => sum + (l.quantity || 0), 0)
// 4
return Math.round(total * 10000) / 10000
}, },
}, },
methods: { methods: {
@ -163,7 +226,7 @@ export default {
this.$message.error('标签物料编码与选择的材料不匹配') this.$message.error('标签物料编码与选择的材料不匹配')
return return
} */ } */
this.scannedLabels.push({
const newLabel = {
id: Date.now(), id: Date.now(),
labelCode, labelCode,
componentPartNo: data.labelInfo.partNo, componentPartNo: data.labelInfo.partNo,
@ -171,12 +234,22 @@ export default {
batchNo: data.labelInfo.batchNo, batchNo: data.labelInfo.batchNo,
warehouseId: data.labelInfo.warehouseId, warehouseId: data.labelInfo.warehouseId,
locationId: data.labelInfo.locationId, locationId: data.labelInfo.locationId,
height: data.labelInfo.height || 0,
wdrNo: data.labelInfo.wdrNo, wdrNo: data.labelInfo.wdrNo,
engChgLevel: data.labelInfo.engChgLevel, engChgLevel: data.labelInfo.engChgLevel,
})
console.log(this.scannedLabels);
}
this.scannedLabels.push(newLabel)
console.log(this.scannedLabels)
this.$message.success('扫描成功') this.$message.success('扫描成功')
// ""
if (this.isPartial) {
const newIndex = this.scannedLabels.length - 1
this.$nextTick(() => {
this.handleLabelClick(newLabel, newIndex)
})
}
} else { } else {
this.$message.error(data.msg || '标签验证失败') this.$message.error(data.msg || '标签验证失败')
} }
@ -224,7 +297,6 @@ export default {
return return
} }
const params = { const params = {
site: localStorage.getItem('site'), site: localStorage.getItem('site'),
workOrderNo: this.workOrderNo, workOrderNo: this.workOrderNo,
@ -233,6 +305,7 @@ export default {
itemNo: this.itemNo, itemNo: this.itemNo,
releaseNo: this.issueInfo.releaseNo, releaseNo: this.issueInfo.releaseNo,
sequenceNo: this.issueInfo.sequenceNo, sequenceNo: this.issueInfo.sequenceNo,
isPartial: this.isPartial,
selectedMaterials: this.scannedLabels.map((l, i) => ({ selectedMaterials: this.scannedLabels.map((l, i) => ({
labelCode: l.labelCode, labelCode: l.labelCode,
issueQty: l.quantity, issueQty: l.quantity,
@ -241,6 +314,7 @@ export default {
locationId: l.locationId, locationId: l.locationId,
materialCode: l.materialCode, materialCode: l.materialCode,
wdrNo: l.wdrNo, wdrNo: l.wdrNo,
height: l.height,
engChgLevel: l.engChgLevel, engChgLevel: l.engChgLevel,
})), })),
} }
@ -259,7 +333,8 @@ export default {
}) })
.catch(() => { .catch(() => {
this.$message.error('发料失败') this.$message.error('发料失败')
}).finally(()=>{
})
.finally(() => {
this.loading = false this.loading = false
}) })
}, },
@ -275,7 +350,7 @@ export default {
sequenceNo: this.$route.query.sequenceNo, sequenceNo: this.$route.query.sequenceNo,
requiredQty: Number(this.$route.query.requiredQty || 0), requiredQty: Number(this.$route.query.requiredQty || 0),
issuedQty: Number(this.$route.query.issuedQty || 0), issuedQty: Number(this.$route.query.issuedQty || 0),
partDesc: this.$route.query.partDesc || ''
partDesc: this.$route.query.partDesc || '',
} }
/* if (!this.workOrderNo || !this.materialCode) { /* if (!this.workOrderNo || !this.materialCode) {
@ -289,6 +364,35 @@ export default {
sessionStorage.setItem('directIssue_shouldRestore', 'true') sessionStorage.setItem('directIssue_shouldRestore', 'true')
this.$router.back() this.$router.back()
}, },
//
handleLabelClick(label, index) {
if (!this.isPartial) return
this.currentEditLabel = { ...label }
this.currentEditIndex = index
this.editHeight = label.height
this.editQuantity = label.quantity
this.quantityDialogVisible = true
},
//
confirmQuantityChange() {
if (this.editHeight < 0) {
this.$message.warning('高度不能小于0')
return
}
if (this.editQuantity <= 0) {
this.$message.warning('数量必须大于0')
return
}
if (
this.currentEditIndex >= 0 &&
this.currentEditIndex < this.scannedLabels.length
) {
this.scannedLabels[this.currentEditIndex].quantity = this.editQuantity
this.scannedLabels[this.currentEditIndex].height = this.editHeight
this.$message.success('数量修改成功')
this.quantityDialogVisible = false
}
},
}, },
mounted() { mounted() {
this.initFromRoute() this.initFromRoute()
@ -364,6 +468,17 @@ export default {
.custom-switch { .custom-switch {
transform: scale(1.3); transform: scale(1.3);
} }
.partial-checkbox-container {
padding: 8px 16px;
background: white;
border-top: 1px solid #f0f0f0;
display: flex;
align-items: center;
}
.partial-checkbox-container ::v-deep .el-checkbox__label {
font-size: 14px;
color: #333;
}
.switch-text { .switch-text {
position: absolute; position: absolute;
left: 25%; left: 25%;
@ -410,9 +525,15 @@ export default {
width: 60px; width: 60px;
height: 28px; height: 28px;
} }
/* 统一滚动容器 */
.scrollable-content {
flex: 1;
overflow-y: auto;
min-height: 0;
}
/* 工单列表 */ /* 工单列表 */
.work-order-list { .work-order-list {
overflow-y: auto;
padding: 12px 16px; padding: 12px 16px;
} }
@ -420,7 +541,6 @@ export default {
.work-order-card { .work-order-card {
background: white; background: white;
border-radius: 8px; border-radius: 8px;
margin-bottom: 12px;
padding: 16px; padding: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer; cursor: pointer;
@ -467,7 +587,7 @@ export default {
justify-content: space-between; justify-content: space-between;
padding: 6px 8px; padding: 6px 8px;
background: white; background: white;
margin: 0 16px;
margin: 0 8px;
margin-top: 4px; margin-top: 4px;
border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0;
border-bottom: 2px solid #17b3a3; border-bottom: 2px solid #17b3a3;
@ -522,7 +642,6 @@ export default {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
max-height: calc(100vh - 320px);
} }
.list-header { .list-header {
display: flex; display: flex;
@ -535,7 +654,6 @@ export default {
flex-shrink: 0; flex-shrink: 0;
} }
.list-body { .list-body {
overflow-y: auto;
flex: 1; flex: 1;
min-height: 0; min-height: 0;
} }
@ -547,12 +665,22 @@ export default {
color: #333; color: #333;
align-items: flex-start; align-items: flex-start;
min-height: 40px; min-height: 40px;
transition: background-color 0.2s;
} }
.list-item:last-child { .list-item:last-child {
border-bottom: none; border-bottom: none;
} }
.list-item.clickable {
cursor: pointer;
}
.list-item.clickable:hover {
background-color: #f5f5f5;
}
.list-item.clickable:active {
background-color: #e8e8e8;
}
.col-no { .col-no {
width: 20px;
width: 10px;
text-align: center; text-align: center;
} }
.col-label { .col-label {
@ -567,6 +695,7 @@ export default {
text-align: center; text-align: center;
} }
.col-qty { .col-qty {
flex: 0.6;
width: 60px; width: 60px;
text-align: center; text-align: center;
} }
@ -600,6 +729,165 @@ export default {
.action-btn:active { .action-btn:active {
transform: scale(0.98); transform: scale(0.98);
} }
/* 编辑弹框样式 */
.edit-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.edit-modal {
background: white;
border-radius: 12px;
width: 100%;
max-width: 400px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
overflow: hidden;
display: flex;
flex-direction: column;
}
.edit-modal .modal-header {
background: #17b3a3;
color: white;
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.edit-modal .modal-title {
font-size: 16px;
font-weight: 500;
margin: 0;
}
.edit-modal .close-btn {
font-size: 16px;
cursor: pointer;
color: white;
transition: color 0.2s ease;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
}
.edit-modal .close-btn:hover {
color: #e0e0e0;
}
.edit-modal .modal-body {
padding: 20px;
}
.edit-modal .form-group {
margin-bottom: 16px;
}
.edit-modal .form-group:last-child {
margin-bottom: 0;
}
.edit-modal .form-label {
display: block;
font-size: 14px;
color: #333;
margin-bottom: 6px;
font-weight: 500;
}
.edit-modal .required {
color: #ff4949;
}
.edit-modal .form-input {
width: 100%;
}
.edit-modal .form-input ::v-deep .el-input__inner {
height: 40px;
border: 2px solid #dcdfe6;
border-radius: 6px;
font-size: 14px;
padding: 0 12px;
}
.edit-modal .form-input ::v-deep .el-input__inner:focus {
border-color: #17b3a3;
outline: none;
}
.edit-modal .form-input ::v-deep .el-input__inner:disabled {
background: #f5f7fa;
color: #c0c4cc;
border-color: #e4e7ed;
}
.edit-modal .form-input ::v-deep .el-input-number {
width: 100%;
}
.edit-modal .form-input ::v-deep .el-input-number .el-input__inner {
height: 40px;
border: 2px solid #dcdfe6;
border-radius: 6px;
font-size: 14px;
padding: 0 12px;
}
.edit-modal .form-input ::v-deep .el-input-number .el-input__inner:focus {
border-color: #17b3a3;
outline: none;
}
.edit-modal .modal-footer {
padding: 16px 20px;
display: flex;
gap: 12px;
justify-content: flex-end;
border-top: 1px solid #f0f0f0;
}
.edit-modal .btn-cancel {
padding: 10px 20px;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
border: 1px solid #dcdfe6;
background: white;
color: #606266;
}
.edit-modal .btn-cancel:hover {
background: #f5f7fa;
border-color: #c0c4cc;
}
.edit-modal .btn-confirm {
padding: 10px 20px;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
border: 1px solid #17b3a3;
background: #17b3a3;
color: white;
}
.edit-modal .btn-confirm:hover {
background: #13998c;
border-color: #13998c;
}
@media (max-width: 360px) { @media (max-width: 360px) {
.header-bar { .header-bar {
padding: 8px 12px; padding: 8px 12px;
@ -623,7 +911,7 @@ export default {
min-width: 50px; min-width: 50px;
} }
.label-list { .label-list {
margin: 0 12px 8px;
margin: 0 8px 8px;
} }
} }
</style> </style>

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

@ -13,26 +13,22 @@
<!-- 搜索框 --> <!-- 搜索框 -->
<div class="search-container"> <div class="search-container">
<el-input clearable class="compact-input"
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@keyup.enter.native="handleScan"
ref="scanInput"
/>
<el-input clearable class="compact-input" v-model="scanCode" placeholder="请扫描标签条码" prefix-icon="el-icon-search"
@keyup.enter.native="handleScan" ref="scanInput" />
<div class="mode-switch"> <div class="mode-switch">
<el-switch
class="custom-switch"
v-model="isRemoveMode"
active-color="#ff4949"
inactive-color="#13ce66">
<el-switch class="custom-switch" v-model="isRemoveMode" active-color="#ff4949" inactive-color="#13ce66">
</el-switch> </el-switch>
<span v-if="isRemoveMode" class="switch-text">{{ '移除' }}</span> <span v-if="isRemoveMode" class="switch-text">{{ '移除' }}</span>
<span v-else class="switch-text2">{{ '添加' }}</span> <span v-else class="switch-text2">{{ '添加' }}</span>
</div> </div>
</div> </div>
<!-- 是否部分勾选框 -->
<div class="partial-checkbox-container">
<el-checkbox v-model="isPartial" :disabled="labelList.length > 0">是否部分领料</el-checkbox>
</div>
<!-- 出库单信息卡片 --> <!-- 出库单信息卡片 -->
<div class="scrollable-content">
<div class="material-info-card" v-if="outboundNo"> <div class="material-info-card" v-if="outboundNo">
<div class="card-title"> <div class="card-title">
<span class="title-label">出库单号:{{ outboundInfo.outboundNo }}</span> <span class="title-label">出库单号:{{ outboundInfo.outboundNo }}</span>
@ -72,9 +68,6 @@
<i class="el-icon-circle-check"></i> <i class="el-icon-circle-check"></i>
<span>出库信息确认</span> <span>出库信息确认</span>
</div> </div>
<!-- <div class="title-right">
<span class="material-list-link" @click="showMaterialListDialog">物料清单</span>
</div> -->
</div> </div>
<!-- 标签列表 --> <!-- 标签列表 -->
@ -83,19 +76,20 @@
<div class="col-no">NO.</div> <div class="col-no">NO.</div>
<div class="col-label">标签条码</div> <div class="col-label">标签条码</div>
<div class="col-part">库位</div> <div class="col-part">库位</div>
<div class="col-qty">剩余高度</div>
<div class="col-qty">标签数量</div> <div class="col-qty">标签数量</div>
</div> </div>
<div class="list-body"> <div class="list-body">
<div
v-for="(label, index) in labelList"
:key="label.id"
class="list-item"
>
<div v-for="(label, index) in labelList" :key="label.id" class="list-item" :class="{ clickable: isPartial }"
@click="isPartial ? handleLabelClick(label, index) : null">
<div class="col-no">{{ labelList.length - index }}</div> <div class="col-no">{{ labelList.length - index }}</div>
<div class="col-label">{{ label.labelCode }}</div> <div class="col-label">{{ label.labelCode }}</div>
<div class="col-part">{{ label.locationId }}</div> <div class="col-part">{{ label.locationId }}</div>
<div class="col-qty">{{ label.quantity }}</div>
<div class="col-qty">
<span class="quantity-display">{{ label.quantity }}</span>
<i v-if="isPartial" class="el-icon-edit edit-icon"></i>
</div>
</div> </div>
<!-- 空状态 --> <!-- 空状态 -->
@ -104,6 +98,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- 底部操作按钮 --> <!-- 底部操作按钮 -->
<div class="bottom-actions"> <div class="bottom-actions">
@ -117,64 +112,57 @@
取消 取消
</button> </button>
</div> </div>
<!-- 物料清单弹窗 -->
<div v-if="showMaterialDialog" class="material-overlay">
<div class="material-modal">
<!-- 修改数量弹框 -->
<div v-if="quantityDialogVisible" class="edit-overlay" @click.self="quantityDialogVisible = false">
<div class="edit-modal">
<div class="modal-header"> <div class="modal-header">
<span class="modal-title">物料清单</span>
<i class="el-icon-close close-btn" @click="closeMaterialDialog"></i>
<span class="modal-title">修改数量</span>
<i class="el-icon-close close-btn" @click="quantityDialogVisible = false"></i>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<!-- 加载状态 -->
<div v-if="materialListLoading" class="loading-container">
<i class="el-icon-loading"></i>
<span>加载中...</span>
<div class="form-group">
<label class="form-label">标签条码</label>
<el-input v-model="currentEditLabel.labelCode" disabled class="form-input" />
</div> </div>
<!-- 物料表格 -->
<div v-else-if="materialList.length > 0" class="material-table">
<div class="table-header">
<div class="col-no">NO.</div>
<div class="col-material-code">物料编码</div>
<div class="col-required-qty">需求数量</div>
<div class="col-picked-qty">已领数量</div>
<div class="form-group">
<label class="form-label">当前数量</label>
<el-input v-model="currentEditLabel.quantity" disabled class="form-input" />
</div> </div>
<div class="table-body">
<div
v-for="(item, index) in materialList"
:key="index"
class="table-row"
>
<div class="col-no">{{ index + 1 }}</div>
<div class="col-material-code">{{ item.materialCode || item.partNo }}</div>
<div class="col-required-qty">{{ item.requiredQty || 0 }}</div>
<div class="col-picked-qty">{{ item.pickedQty || 0 }}</div>
</div>
</div>
<div class="form-group">
<label class="form-label">剩余高度(mm) <span class="required">*</span></label>
<el-input-number v-model="editHeight" :min="0.001" :precision="3" :step="0.001" class="form-input"
style="width: 100%;" :controls="false">
</el-input-number>
</div> </div>
<!-- 空数据状态 -->
<div v-else class="empty-material">
<i class="el-icon-document"></i>
<p>暂无物料数据</p>
<div class="form-group">
<label class="form-label">修改数量 <span class="required">*</span></label>
<el-input-number v-model="editQuantity" :min="0.0001" :precision="4" :step="0.0001" class="form-input"
style="width: 100%;" :controls="false" />
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn-close" @click="closeMaterialDialog">关闭</button>
<button class="btn-cancel" @click="quantityDialogVisible = false">取消</button>
<button class="btn-confirm" @click="confirmQuantityChange">确定</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { scanMaterialLabelIssue,getRequestMaterials,confirmProductionPicking } from '@/api/production/production-issue';
import moment from 'moment';
import { notify } from 'node-notifier';
import {
scanMaterialLabelIssue,
getRequestMaterials,
confirmProductionPicking,
} from '@/api/production/production-issue'
import moment from 'moment'
import { notify } from 'node-notifier'
export default { export default {
data() { data() {
@ -188,33 +176,39 @@ export default {
materialList: [], materialList: [],
materialListLoading: false, materialListLoading: false,
isRemoveMode: false, // isRemoveMode: false, //
pickingLoading: false
};
pickingLoading: false,
isPartial: false,
quantityDialogVisible: false,
currentEditLabel: {},
currentEditIndex: -1,
editQuantity: 0,
editHeight: 0,
}
}, },
computed: { computed: {
totalScannedQty() { totalScannedQty() {
return this.labelList.reduce( return this.labelList.reduce(
(sum, l) => sum + (Number(l.quantity) || 0), (sum, l) => sum + (Number(l.quantity) || 0),
0 0
);
)
}, },
}, },
methods: { methods: {
formatDate(date) { formatDate(date) {
return date ? moment(date).format('YYYY-MM-DD') : '';
return date ? moment(date).format('YYYY-MM-DD') : ''
}, },
// //
handleScan() { handleScan() {
if (!this.scanCode.trim()) { if (!this.scanCode.trim()) {
return;
return
} }
if (this.isRemoveMode) { if (this.isRemoveMode) {
this.removeLabelByCode(this.scanCode.trim());
this.removeLabelByCode(this.scanCode.trim())
} else { } else {
this.validateAndAddLabel(this.scanCode.trim());
this.validateAndAddLabel(this.scanCode.trim())
} }
this.scanCode = '';
this.scanCode = ''
}, },
// //
@ -223,20 +217,23 @@ export default {
scannedLabel: labelCode, scannedLabel: labelCode,
notifyNo: this.outboundNo, notifyNo: this.outboundNo,
site: localStorage.getItem('site'), site: localStorage.getItem('site'),
componentPartNo: this.outboundInfo.componentPartNo
};
componentPartNo: this.outboundInfo.componentPartNo,
}
scanMaterialLabelIssue(params).then(({ data }) => {
scanMaterialLabelIssue(params)
.then(({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
// //
const exists = this.labelList.find(item => item.labelCode === labelCode);
const exists = this.labelList.find(
(item) => item.labelCode === labelCode
)
if (exists) { if (exists) {
this.$message.warning('该标签已扫描,请勿重复扫描');
return;
this.$message.warning('该标签已扫描,请勿重复扫描')
return
} }
// //
this.labelList.push({
const newLabel = {
id: Date.now(), id: Date.now(),
labelCode: labelCode, labelCode: labelCode,
partNo: data.labelInfo.partNo, partNo: data.labelInfo.partNo,
@ -246,55 +243,107 @@ export default {
locationId: data.labelInfo.locationId, locationId: data.labelInfo.locationId,
warehouseId: data.labelInfo.warehouseId, warehouseId: data.labelInfo.warehouseId,
wdrNo: data.labelInfo.wdrNo, wdrNo: data.labelInfo.wdrNo,
height: data.labelInfo.height || 0,
engChgLevel: data.labelInfo.engChgLevel, engChgLevel: data.labelInfo.engChgLevel,
});
}
this.labelList.push(newLabel)
this.$message.success('操作成功')
this.$message.success('操作成功');
if (this.isPartial) {
const newIndex = this.labelList.length - 1
this.$nextTick(() => {
this.handleLabelClick(newLabel, newIndex)
})
}
} else { } else {
this.$message.error(data.msg || '该标签与出库单不符,请检查');
this.$message.error(data.msg || '该标签与出库单不符,请检查')
} }
}).catch(error => {
this.$message.error('操作失败');
});
})
.catch((error) => {
this.$message.error('操作失败')
})
}, },
// //
removeLabelByCode(labelCode) { removeLabelByCode(labelCode) {
const index = this.labelList.findIndex(item => item.labelCode === labelCode);
const index = this.labelList.findIndex(
(item) => item.labelCode === labelCode
)
if (index !== -1) { if (index !== -1) {
this.labelList.splice(index, 1);
this.$message.success('操作成功');
this.labelList.splice(index, 1)
this.$message.success('操作成功')
} else { } else {
this.$message.warning('未找到该标签');
this.$message.warning('未找到该标签')
}
},
//
handleLabelClick(label, index) {
if (!this.isPartial) {
return
}
this.currentEditLabel = { ...label }
this.currentEditIndex = index
this.editHeight = label.height
this.editQuantity = Number(label.quantity) || 0
this.quantityDialogVisible = true
},
//
confirmQuantityChange() {
if (this.editHeight < 0) {
this.$message.warning('高度不能小于0')
return
}
if (this.editQuantity <= 0) {
this.$message.warning('数量必须大于0')
return
}
if (
this.currentEditIndex >= 0 &&
this.currentEditIndex < this.labelList.length
) {
this.$set(
this.labelList[this.currentEditIndex],
'quantity',
this.editQuantity
)
this.$set(
this.labelList[this.currentEditIndex],
'height',
this.editHeight
)
this.$message.success('数量修改成功')
this.quantityDialogVisible = false
} }
}, },
// //
confirmOutbound() { confirmOutbound() {
if (this.labelList.length === 0) { if (this.labelList.length === 0) {
this.$message.warning('请先扫描标签');
return;
this.$message.warning('请先扫描标签')
return
} }
let qty = 0;
let qty = 0
for (const label of this.labelList) { for (const label of this.labelList) {
if (label.quantity <= 0) { if (label.quantity <= 0) {
this.$message.warning(`标签 ${label.labelCode} 数量无效`);
return;
this.$message.warning(`标签 ${label.labelCode} 数量无效`)
return
} }
qty += label.quantity;
qty += label.quantity
} }
if (qty > this.outboundInfo.qtyToIssue) { if (qty > this.outboundInfo.qtyToIssue) {
this.$confirm('扫描标签总数量超过需求数量确定出库吗?', '提示', { this.$confirm('扫描标签总数量超过需求数量确定出库吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning'
type: 'warning',
}).then(() => { }).then(() => {
this.confirmProductionPicking();
this.confirmProductionPicking()
}) })
} else { } else {
this.confirmProductionPicking();
this.confirmProductionPicking()
} }
}, },
confirmProductionPicking() { confirmProductionPicking() {
const params = { const params = {
@ -307,6 +356,7 @@ export default {
lineItemNo: this.outboundInfo.lineItemNo, lineItemNo: this.outboundInfo.lineItemNo,
releaseNo: this.outboundInfo.releaseNo, releaseNo: this.outboundInfo.releaseNo,
sequenceNo: this.outboundInfo.sequenceNo, sequenceNo: this.outboundInfo.sequenceNo,
isPartial: this.isPartial,
selectedMaterials: this.labelList.map((l, i) => ({ selectedMaterials: this.labelList.map((l, i) => ({
labelCode: l.labelCode, labelCode: l.labelCode,
issueQty: l.quantity, issueQty: l.quantity,
@ -315,42 +365,49 @@ export default {
locationId: l.locationId, locationId: l.locationId,
materialCode: l.materialCode, materialCode: l.materialCode,
wdrNo: l.wdrNo, wdrNo: l.wdrNo,
height: l.height,
engChgLevel: l.engChgLevel, engChgLevel: l.engChgLevel,
})), })),
};
}
this.pickingLoading = true this.pickingLoading = true
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 // productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
sessionStorage.setItem('productionPicking_shouldRestore', 'true')
// //
const issueInfo = { const issueInfo = {
componentPartNo: this.outboundInfo.componentPartNo, componentPartNo: this.outboundInfo.componentPartNo,
lineItemNo: this.outboundInfo.lineItemNo, lineItemNo: this.outboundInfo.lineItemNo,
issueQty: this.totalScannedQty
};
sessionStorage.setItem('productionPicking_issueInfo', JSON.stringify(issueInfo));
this.$router.back();
issueQty: this.totalScannedQty,
}
sessionStorage.setItem(
'productionPicking_issueInfo',
JSON.stringify(issueInfo)
)
this.$router.back()
} else { } else {
this.$message.error(data.msg || '操作失败');
this.$message.error(data.msg || '操作失败')
} }
}).catch(error => {
console.error('出库确认失败:', error);
this.$message.error('操作失败');
}).finally(() => {
})
.catch((error) => {
console.error('出库确认失败:', error)
this.$message.error('操作失败')
})
.finally(() => {
this.pickingLoading = false this.pickingLoading = false
});
})
}, },
// //
printLabels() { printLabels() {
if (this.labelList.length === 0) { if (this.labelList.length === 0) {
this.$message.warning('暂无标签可打印');
return;
this.$message.warning('暂无标签可打印')
return
} }
this.$message.warning('打印功能开发中...');
this.$message.warning('打印功能开发中...')
}, },
// //
@ -359,67 +416,33 @@ export default {
this.$confirm('取消后将清空已扫描的标签,确定取消吗?', '提示', { this.$confirm('取消后将清空已扫描的标签,确定取消吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning'
}).then(() => {
type: 'warning',
})
.then(() => {
// productionPicking // productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
this.$router.back();
}).catch(() => {
sessionStorage.setItem('productionPicking_shouldRestore', 'true')
this.$router.back()
})
.catch(() => {
// //
});
})
} else { } else {
// productionPicking // productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
this.$router.back();
sessionStorage.setItem('productionPicking_shouldRestore', 'true')
this.$router.back()
} }
}, },
// //
handleBack() { handleBack() {
// productionPicking // productionPicking
sessionStorage.setItem('productionPicking_shouldRestore', 'true');
this.$router.back();
},
//
showMaterialListDialog() {
this.showMaterialDialog = true;
this.loadMaterialList();
},
//
loadMaterialList() {
console.log('加载物料清单', this.outboundInfo, this.outboundNo);
if (!localStorage.getItem('site') || !this.outboundNo) {
this.$message.error('缺少必要参数,无法获取物料清单');
return;
}
this.materialListLoading = true;
const params = {
site: localStorage.getItem('site'),
outboundNo: this.outboundNo
};
getRequestMaterials(params).then(({ data }) => {
this.materialListLoading = false;
if (data && data.code === 0) {
this.materialList = data.materials || [];
} else {
this.$message.error(data.msg || '获取物料清单失败');
this.materialList = [];
}
}).catch(error => {
this.materialListLoading = false;
this.$message.error('获取物料清单失败');
this.materialList = [];
});
sessionStorage.setItem('productionPicking_shouldRestore', 'true')
this.$router.back()
}, },
// //
closeMaterialDialog() { closeMaterialDialog() {
this.showMaterialDialog = false;
this.showMaterialDialog = false
}, },
// //
@ -427,8 +450,8 @@ export default {
const params = { const params = {
outboundNo: this.outboundNo, outboundNo: this.outboundNo,
site: localStorage.getItem('site'), site: localStorage.getItem('site'),
};
console.log('加载出库单详情参数:', params);
}
console.log('加载出库单详情参数:', params)
/* getOutboundDetails(params).then(({ data }) => { /* getOutboundDetails(params).then(({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
@ -440,7 +463,7 @@ export default {
console.error('获取出库单详情失败:', error); console.error('获取出库单详情失败:', error);
this.$message.error('获取出库单详情失败'); this.$message.error('获取出库单详情失败');
}); */ }); */
}
},
}, },
mounted() { mounted() {
@ -448,33 +471,32 @@ export default {
this.outboundNo = this.$route.query.outboundNo this.outboundNo = this.$route.query.outboundNo
this.outboundInfo.outboundNo = this.$route.query.outboundNo this.outboundInfo.outboundNo = this.$route.query.outboundNo
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.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
console.log("路由参数:", this.$route.query.notifyInfo );
console.log('路由参数:', this.$route.query.notifyInfo)
if (!this.outboundNo) { if (!this.outboundNo) {
this.$message.error('参数错误');
this.$router.back();
return;
this.$message.error('参数错误')
this.$router.back()
return
} }
// //
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.scanInput) { if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
this.$refs.scanInput.focus()
} }
});
})
// //
this.loadOutboundDetails();
this.loadOutboundDetails()
},
} }
};
</script> </script>
<style scoped> <style scoped>
@ -493,7 +515,7 @@ export default {
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 8px 16px; padding: 8px 16px;
background: #17B3A3;
background: #17b3a3;
color: white; color: white;
height: 40px; height: 40px;
min-height: 40px; min-height: 40px;
@ -532,6 +554,24 @@ export default {
margin-right: 12px; margin-right: 12px;
} }
.partial-checkbox {
display: flex;
align-items: center;
margin-left: auto;
}
.partial-checkbox ::v-deep .el-checkbox__label {
font-size: 14px;
color: #333;
}
.partial-checkbox
::v-deep
.el-checkbox__input.is-disabled
+ .el-checkbox__label {
color: #c0c4cc;
}
/* 紧凑型输入框样式 */ /* 紧凑型输入框样式 */
.compact-input ::v-deep .el-input__inner { .compact-input ::v-deep .el-input__inner {
height: 36px; height: 36px;
@ -556,6 +596,23 @@ export default {
.custom-switch { .custom-switch {
transform: scale(1.3); transform: scale(1.3);
} }
.partial-checkbox-container {
padding: 8px 16px;
background: white;
border-top: 1px solid #f0f0f0;
display: flex;
align-items: center;
}
.partial-checkbox-container ::v-deep .el-checkbox__label {
font-size: 14px;
color: #333;
}
.scrollable-content {
flex: 1;
overflow-y: auto;
min-height: 0;
}
/* 中间文字 */ /* 中间文字 */
.switch-text { .switch-text {
position: absolute; position: absolute;
@ -667,7 +724,7 @@ export default {
} }
.detail-value .qualified { .detail-value .qualified {
color: #17B3A3;
color: #17b3a3;
font-weight: 500; font-weight: 500;
} }
@ -691,7 +748,7 @@ export default {
margin: 0 10px; margin: 0 10px;
margin-top: 4px; margin-top: 4px;
border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0;
border-bottom: 2px solid #17B3A3;
border-bottom: 2px solid #17b3a3;
} }
.title-left { .title-left {
@ -700,13 +757,13 @@ export default {
} }
.title-left i { .title-left i {
color: #17B3A3;
color: #17b3a3;
font-size: 16px; font-size: 16px;
margin-right: 8px; margin-right: 8px;
} }
.title-left span { .title-left span {
color: #17B3A3;
color: #17b3a3;
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
} }
@ -717,7 +774,7 @@ export default {
} }
.material-list-link { .material-list-link {
color: #17B3A3;
color: #17b3a3;
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
cursor: pointer; cursor: pointer;
@ -737,7 +794,6 @@ export default {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
max-height: calc(100vh - 320px);
} }
.list-header { .list-header {
@ -752,7 +808,6 @@ export default {
} }
.list-body { .list-body {
overflow-y: auto;
flex: 1; flex: 1;
min-height: 0; min-height: 0;
} }
@ -767,6 +822,19 @@ export default {
min-height: 40px; min-height: 40px;
} }
.list-item.clickable {
cursor: pointer;
transition: background-color 0.2s;
}
.list-item.clickable:hover {
background-color: #f5f5f5;
}
.list-item.clickable:active {
background-color: #e8e8e8;
}
.list-item:last-child { .list-item:last-child {
border-bottom: none; border-bottom: none;
} }
@ -799,6 +867,16 @@ export default {
text-align: center; text-align: center;
} }
.quantity-display {
display: inline-block;
}
.edit-icon {
margin-left: 4px;
color: #17b3a3;
font-size: 14px;
}
.empty-labels { .empty-labels {
padding: 40px 20px; padding: 40px 20px;
text-align: center; text-align: center;
@ -822,9 +900,9 @@ export default {
.action-btn { .action-btn {
flex: 1; flex: 1;
padding: 12px; padding: 12px;
border: 1px solid #17B3A3;
border: 1px solid #17b3a3;
background: white; background: white;
color: #17B3A3;
color: #17b3a3;
border-radius: 20px; border-radius: 20px;
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
@ -832,7 +910,7 @@ export default {
} }
.action-btn:hover { .action-btn:hover {
background: #17B3A3;
background: #17b3a3;
color: white; color: white;
} }
@ -868,7 +946,7 @@ export default {
} }
.material-modal .modal-header { .material-modal .modal-header {
background: #17B3A3;
background: #17b3a3;
color: white; color: white;
padding: 5px 16px; padding: 5px 16px;
display: flex; display: flex;
@ -913,7 +991,7 @@ export default {
display: flex; display: flex;
background: #f8f9fa; background: #f8f9fa;
padding: 10px 6px; padding: 10px 6px;
border-bottom: 2px solid #17B3A3;
border-bottom: 2px solid #17b3a3;
font-size: 12px; font-size: 12px;
color: #333; color: #333;
font-weight: 600; font-weight: 600;
@ -986,13 +1064,13 @@ export default {
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
transition: all 0.2s; transition: all 0.2s;
border: 1px solid #17B3A3;
border: 1px solid #17b3a3;
background: white; background: white;
color: #17B3A3;
color: #17b3a3;
} }
.btn-close:hover { .btn-close:hover {
background: #17B3A3;
background: #17b3a3;
color: white; color: white;
} }
@ -1009,7 +1087,7 @@ export default {
.loading-container i { .loading-container i {
font-size: 24px; font-size: 24px;
margin-bottom: 12px; margin-bottom: 12px;
color: #17B3A3;
color: #17b3a3;
} }
.loading-container span { .loading-container span {
@ -1037,6 +1115,146 @@ export default {
font-size: 14px; font-size: 14px;
} }
/* 修改数量弹框 */
.edit-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.edit-modal {
background: white;
border-radius: 12px;
width: 100%;
max-width: 400px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
overflow: hidden;
display: flex;
flex-direction: column;
}
.edit-modal .modal-header {
background: #17b3a3;
color: white;
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.edit-modal .modal-title {
font-size: 16px;
font-weight: 500;
}
.edit-modal .close-btn {
font-size: 16px;
cursor: pointer;
color: white;
transition: color 0.2s ease;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
}
.edit-modal .close-btn:hover {
color: #e0e0e0;
}
.edit-modal .modal-body {
padding: 20px;
}
.edit-modal .form-group {
margin-bottom: 16px;
}
.edit-modal .form-label {
display: block;
font-size: 14px;
color: #333;
margin-bottom: 6px;
font-weight: 500;
}
.edit-modal .required {
color: #ff4949;
}
.edit-modal .form-input {
width: 100%;
}
.edit-modal .form-input ::v-deep .el-input__inner,
.edit-modal .form-input ::v-deep .el-input-number .el-input__inner {
height: 40px;
border: 2px solid #dcdfe6;
border-radius: 6px;
font-size: 14px;
padding: 0 12px;
}
.edit-modal .form-input ::v-deep .el-input__inner:focus,
.edit-modal .form-input ::v-deep .el-input-number .el-input__inner:focus {
border-color: #17b3a3;
outline: none;
}
.edit-modal .form-input ::v-deep .el-input__inner:disabled {
background: #f5f7fa;
color: #c0c4cc;
border-color: #e4e7ed;
}
.edit-modal .modal-footer {
padding: 16px 20px;
display: flex;
gap: 12px;
justify-content: flex-end;
border-top: 1px solid #f0f0f0;
}
.edit-modal .btn-cancel {
padding: 10px 20px;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
border: 1px solid #dcdfe6;
background: white;
color: #606266;
}
.edit-modal .btn-cancel:hover {
background: #f5f7fa;
border-color: #c0c4cc;
}
.edit-modal .btn-confirm {
padding: 10px 20px;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
border: 1px solid #17b3a3;
background: #17b3a3;
color: white;
}
.edit-modal .btn-confirm:hover {
background: #13998c;
border-color: #13998c;
}
/* 响应式设计 */ /* 响应式设计 */
@media (max-width: 360px) { @media (max-width: 360px) {
.header-bar { .header-bar {
@ -1072,11 +1290,13 @@ export default {
min-width: 50px; min-width: 50px;
} }
.list-header, .list-item {
.list-header,
.list-item {
font-size: 11px; font-size: 11px;
} }
.col-label, .col-part {
.col-label,
.col-part {
flex: 1.5; flex: 1.5;
} }
} }

2
src/views/modules/production-return/production.vue

@ -33,8 +33,6 @@ export default {
buttons: [ buttons: [
{ icon: 'scan', label: '直接退料', iconClass: 'direct', to: 'productionReturnPicking', disabled: false }, { icon: 'scan', label: '直接退料', iconClass: 'direct', to: 'productionReturnPicking', disabled: false },
{ icon: 'records', label: '申请单退料', iconClass: 'request', to: 'productionReturnPDA', disabled: false }, { icon: 'records', label: '申请单退料', iconClass: 'request', to: 'productionReturnPDA', disabled: false },
{ icon: 'logistics', label: '移库退料', iconClass: 'move', to: 'productionReturnPicking', disabled: true },
{ icon: 'revoke', label: '退料撤销', iconClass: 'cancel', to: 'productionReturnPicking', disabled: true },
] ]
} }
}, },

10
src/views/modules/production-return/productionReturnIssueList.vue

@ -45,12 +45,12 @@
<div class="detail-value">{{ item.QUANTITY }}</div> <div class="detail-value">{{ item.QUANTITY }}</div>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<div class="detail-label">撤销数量</div>
<div class="detail-label">已退数量</div>
<div class="detail-value">{{ item.QTY_REVERSED || 0 }}</div> <div class="detail-value">{{ item.QTY_REVERSED || 0 }}</div>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<div class="detail-label">单位</div>
<div class="detail-value">{{ item.uom || '个' }}</div>
<div class="detail-label">WDR号</div>
<div class="detail-value">{{ item.WAIV_DEV_REJ_NO }}</div>
</div> </div>
</div> </div>
</div> </div>
@ -135,6 +135,7 @@ export default {
componentPartDesc: this.componentPartDesc, componentPartDesc: this.componentPartDesc,
releaseNo: this.releaseNo, releaseNo: this.releaseNo,
sequenceNo: this.sequenceNo, sequenceNo: this.sequenceNo,
wdrNo: item.WAIV_DEV_REJ_NO ,
}, },
}); });
}, },
@ -154,6 +155,9 @@ export default {
</script> </script>
<style scoped> <style scoped>
.search-container {
margin-bottom: 10px;
}
.pda-container { width: 100vw; height: 100vh; display: flex; flex-direction: column; background: #f5f5f5; } .pda-container { width: 100vw; height: 100vh; display: flex; flex-direction: column; background: #f5f5f5; }
.header-bar { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: #17B3A3; color: white; height: 40px; min-height: 40px; } .header-bar { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: #17B3A3; color: white; height: 40px; min-height: 40px; }
.header-left { display: flex; align-items: center; cursor: pointer; font-size: 16px; font-weight: 500; } .header-left { display: flex; align-items: center; cursor: pointer; font-size: 16px; font-weight: 500; }

156
src/views/modules/production-return/productionReturnPickingDetail.vue

@ -21,6 +21,7 @@
</div> </div>
</div> </div>
<div class="scrollable-content">
<!-- 订单信息卡片对齐直接领料明细样式 --> <!-- 订单信息卡片对齐直接领料明细样式 -->
<div class="work-order-list" v-if="orderNo"> <div class="work-order-list" v-if="orderNo">
<div class="work-order-card"> <div class="work-order-card">
@ -90,6 +91,7 @@
<p>暂无扫描标签</p> <p>暂无扫描标签</p>
</div> </div>
</div> </div>
</div>
<!-- 底部操作按钮 --> <!-- 底部操作按钮 -->
<div class="bottom-actions"> <div class="bottom-actions">
@ -123,15 +125,15 @@
<div class="form-group"> <div class="form-group">
<label class="form-label">库位 <span class="required">*</span></label> <label class="form-label">库位 <span class="required">*</span></label>
<el-input v-model="editForm.locationId" placeholder="请输入库位" class="form-input" />
<el-input v-model="editForm.locationId" placeholder="请输入库位" class="form-input" clearable/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">高度(单位毫米)</label> <label class="form-label">高度(单位毫米)</label>
<el-input v-model="editForm.height" type="number" :min="0" placeholder="请输入高度(单位毫米)" class="form-input" />
<el-input v-model="editForm.height" type="number" :min="0" placeholder="请输入高度(单位毫米)" class="form-input" clearable/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">标签数量 <span class="required">*</span></label> <label class="form-label">标签数量 <span class="required">*</span></label>
<el-input v-model="editForm.quantity" type="number" :min="0" placeholder="请输入标签数量" class="form-input" />
<el-input v-model="editForm.quantity" type="number" :min="0" placeholder="请输入标签数量" class="form-input" clearable/>
</div> </div>
</div> </div>
@ -245,6 +247,7 @@ export default {
loading: false, loading: false,
releaseNo: '', releaseNo: '',
sequenceNo: '', sequenceNo: '',
wdrNo: '',
} }
}, },
computed: { computed: {
@ -273,6 +276,114 @@ export default {
this.scanCode = '' this.scanCode = ''
}, },
goManualPrint() {
this.saveStateForManualPrint()
this.$router.push({
name: 'productionReturnManualPrint',
query: {
orderNo: this.orderNo,
orderType: this.orderType,
componentPartNo: this.componentPartNo,
transactionId: this.transactionId,
accountingId: this.accountingId,
quantity: this.quantity,
qtyReversed: this.qtyReversed,
batchNo: this.batchNo,
lineItemNo: this.lineItemNo,
componentPartDesc: this.componentPartDesc,
releaseNo: this.releaseNo,
sequenceNo: this.sequenceNo,
wdrNo: this.wdrNo,
},
})
},
saveStateForManualPrint() {
const state = {
scanCode: this.scanCode,
orderInfo: this.orderInfo,
labelList: this.labelList,
orderNo: this.orderNo,
orderType: this.orderType,
showMaterialDialog: this.showMaterialDialog,
materialList: this.materialList,
materialListLoading: this.materialListLoading,
isRemoveMode: this.isRemoveMode,
returnReason: this.returnReason,
showEditDialog: this.showEditDialog,
editForm: this.editForm,
editIndex: this.editIndex,
loading: this.loading,
transactionId: this.transactionId,
componentPartNo: this.componentPartNo,
accountingId: this.accountingId,
quantity: this.quantity,
qtyReversed: this.qtyReversed,
batchNo: this.batchNo,
lineItemNo: this.lineItemNo,
componentPartDesc: this.componentPartDesc,
releaseNo: this.releaseNo,
sequenceNo: this.sequenceNo,
}
sessionStorage.setItem(
'productionReturnPickingDetail_state_manual',
JSON.stringify(state)
)
sessionStorage.setItem(
'productionReturnPickingDetail_shouldRestore',
'true'
)
},
restoreStateFromManual() {
try {
const shouldRestore = sessionStorage.getItem(
'productionReturnPickingDetail_shouldRestore'
)
const savedState = sessionStorage.getItem(
'productionReturnPickingDetail_state_manual'
)
if (shouldRestore === 'true' && savedState) {
const state = JSON.parse(savedState)
this.scanCode = state.scanCode || ''
this.orderInfo = state.orderInfo || {}
this.labelList = state.labelList || []
this.orderNo = state.orderNo || this.orderNo
this.orderType = state.orderType || this.orderType
this.showMaterialDialog = state.showMaterialDialog || false
this.materialList = state.materialList || []
this.materialListLoading = state.materialListLoading || false
this.isRemoveMode = state.isRemoveMode || false
this.returnReason = state.returnReason || ''
this.showEditDialog = false
this.editForm = state.editForm || this.editForm
this.editIndex =
typeof state.editIndex === 'number' ? state.editIndex : -1
this.loading = state.loading || false
this.transactionId = state.transactionId || this.transactionId
this.componentPartNo = state.componentPartNo || this.componentPartNo
this.accountingId = state.accountingId || this.accountingId
this.quantity = state.quantity || this.quantity
this.qtyReversed = state.qtyReversed || this.qtyReversed
this.batchNo = state.batchNo || this.batchNo
this.lineItemNo = state.lineItemNo || this.lineItemNo
this.componentPartDesc =
state.componentPartDesc || this.componentPartDesc
this.releaseNo = state.releaseNo || this.releaseNo
this.sequenceNo = state.sequenceNo || this.sequenceNo
}
} catch (error) {
console.warn('恢复生产退料手动页面状态失败', error)
} finally {
sessionStorage.removeItem(
'productionReturnPickingDetail_shouldRestore'
)
sessionStorage.removeItem(
'productionReturnPickingDetail_state_manual'
)
}
},
// 退 // 退
validateAndAddLabel(labelCode) { validateAndAddLabel(labelCode) {
const params = { const params = {
@ -435,11 +546,11 @@ export default {
this.$router.back() this.$router.back()
this.loading = false this.loading = false
} else { } else {
this.$message.error(data.message || '操作失败')
this.$message.error(data.msg || '操作失败')
} }
}) })
.catch(() => { .catch(() => {
this.$message.error('操作失败')
this.$message.error(data.msg ||'操作失败')
}) })
.finally(() => { .finally(() => {
this.loading = false this.loading = false
@ -586,6 +697,7 @@ export default {
this.componentPartDesc = this.$route.query.componentPartDesc this.componentPartDesc = this.$route.query.componentPartDesc
this.releaseNo = this.$route.query.releaseNo this.releaseNo = this.$route.query.releaseNo
this.sequenceNo = this.$route.query.sequenceNo this.sequenceNo = this.$route.query.sequenceNo
this.wdrNo = this.$route.query.wdrNo
console.log( console.log(
'订单号:', '订单号:',
this.orderNo, this.orderNo,
@ -610,6 +722,7 @@ export default {
// //
this.loadOrderDetails() this.loadOrderDetails()
this.restoreStateFromManual()
}, },
} }
</script> </script>
@ -669,6 +782,33 @@ export default {
margin-right: 12px; margin-right: 12px;
} }
.manual-btn {
border: 1px solid #1abc4a;
background: #1abc4a;
color: white;
border-radius: 6px;
width:60px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s ease;
}
.manual-btn:hover {
background: #17b3a3;
color: white;
}
.manual-btn:active {
transform: scale(0.98);
}
.scrollable-content {
flex: 1;
overflow-y: auto;
min-height: 0;
}
/* 紧凑型输入框样式 */ /* 紧凑型输入框样式 */
.compact-input ::v-deep .el-input__inner { .compact-input ::v-deep .el-input__inner {
height: 36px; height: 36px;
@ -836,7 +976,6 @@ export default {
/* 对齐直接领料明细的工单卡片样式 */ /* 对齐直接领料明细的工单卡片样式 */
/* 工单列表容器背景与间距 */ /* 工单列表容器背景与间距 */
.work-order-list { .work-order-list {
overflow-y: auto;
padding: 12px 10px; padding: 12px 10px;
} }
@ -844,7 +983,6 @@ export default {
.work-order-card { .work-order-card {
background: white; background: white;
border-radius: 8px; border-radius: 8px;
margin-bottom: 12px;
padding: 16px; padding: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease; transition: all 0.2s ease;
@ -914,8 +1052,8 @@ export default {
margin: 0 10px 12px; margin: 0 10px 12px;
border-radius: 0 0 8px 8px; border-radius: 0 0 8px 8px;
overflow: hidden; overflow: hidden;
max-height: 300px;
overflow-y: auto;
display: flex;
flex-direction: column;
} }
.list-header { .list-header {

Loading…
Cancel
Save