Browse Source

领料发货

master
shenzhouyu 6 months ago
parent
commit
d7681e5a3e
  1. 410
      src/views/modules/production-issue/pick.vue
  2. 1425
      src/views/modules/production-issue/productionIssuePda.vue

410
src/views/modules/production-issue/pick.vue

@ -1,187 +1,121 @@
<template> <template>
<div class="pick-container"> <div class="pick-container">
<van-nav-bar title="生产拣料" left-arrow @click-left="$router.back()" />
<!-- 订单信息 -->
<div class="order-info">
<div class="info-header">
<div class="order-no">{{ orderInfo.orderNo }}</div>
<div class="order-status">{{ getStatusText(orderInfo.status) }}</div>
<!-- 顶部栏 -->
<div class="header-bar">
<div class="header-left" @click="$router.back()">
<i class="el-icon-arrow-left"></i>
<span>拣货出库</span>
</div> </div>
<van-cell-group>
<van-cell title="产品编码" :value="orderInfo.productCode" />
<van-cell title="产品名称" :value="orderInfo.productName" />
<van-cell title="生产数量" :value="orderInfo.planQuantity" />
<van-cell title="工作中心" :value="orderInfo.workCenter" />
</van-cell-group>
</div>
<!-- 物料清单 -->
<div class="material-section">
<div class="section-title">物料清单</div>
<div
v-for="(item, index) in materialList"
:key="index"
class="material-item"
>
<div class="material-info">
<div class="material-name">{{ item.materialCode }} - {{ item.materialName }}</div>
<div class="material-spec">规格{{ item.specification }}</div>
<div class="material-location">
<van-tag type="primary" size="small">{{ item.locationCode }}</van-tag>
<span class="stock-info">库存{{ item.stock }}</span>
</div>
<div class="material-quantity">
需求{{ item.requiredQuantity }} | 已发{{ item.issuedQuantity }}
</div>
</div>
<div class="pick-input">
<van-stepper
v-model="item.currentPick"
:min="0"
:max="Math.min(item.requiredQuantity - item.issuedQuantity, item.stock)"
integer
/>
</div>
<div class="header-right" @click="$router.push({ path: '/' })">
首页
</div> </div>
</div> </div>
<!-- 批次信息 -->
<div class="batch-section">
<div class="section-title">批次信息</div>
<van-field
v-model="batchInfo.batchNo"
label="批次号"
placeholder="请输入或扫描批次号"
>
<template #right-icon>
<van-icon name="scan" @click="handleScanBatch" />
</template>
</van-field>
<van-field
v-model="batchInfo.workOrder"
label="工单号"
:value="orderInfo.orderNo"
disabled
<!-- 搜索框 -->
<div class="search-container">
<el-input
v-model="scanCode"
placeholder="请扫描标签条码"
clearable
@keyup.enter.native="handleAdd"
ref="scanInput"
/> />
<el-button type="primary" @click="handleAdd" class="add-btn">添加</el-button>
</div> </div>
<!-- 备注 -->
<div class="remark-section">
<van-field
v-model="remark"
label="备注"
type="textarea"
placeholder="请输入发料备注"
rows="3"
autosize
/>
<!-- 订单信息卡片 -->
<div class="order-card">
<div class="order-row">
<span class="label">出库单号</span>
<span class="value">{{ orderInfo.orderNo }}</span>
</div>
<div class="order-row">
<span class="label">关联单号</span>
<span class="value">{{ orderInfo.linkedNo }}</span>
</div>
<div class="order-row">
<span class="label">标签张数</span>
<span class="value success">{{ orderInfo.labelCount }}/{{ orderInfo.labelTotal }}</span>
</div>
<div class="order-row">
<span class="label">物料总数</span>
<span class="value success">{{ orderInfo.materialCount }}/{{ orderInfo.materialTotal }}</span>
</div>
</div>
<!-- 出库信息确认表格 -->
<div class="table-section">
<div class="table-title">出库信息确认</div>
<el-table :data="tableData" border style="width: 100%" class="pick-table">
<el-table-column prop="no" label="NO." align="center" />
<el-table-column prop="labelCode" label="标签条码" align="center" />
<el-table-column prop="materialCode" label="物料编码" align="center" />
<el-table-column prop="unit" label="单位" align="center" />
<el-table-column prop="labelCount" label="标签数量" align="center" />
</el-table>
</div> </div>
<!-- 底部按钮 --> <!-- 底部按钮 -->
<div class="bottom-actions"> <div class="bottom-actions">
<van-button
type="primary"
block
:loading="submitting"
@click="handleSubmit"
>
确认发料
</van-button>
<el-button type="primary" @click="handleConfirm" :loading="submitting">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'ProductionIssuePick',
name: 'ProductionPickOut',
data() { data() {
return { return {
scanCode: '',
submitting: false,
orderInfo: { orderInfo: {
orderNo: 'MO202401001',
productCode: 'PROD001',
productName: '成品A',
planQuantity: 100,
workCenter: '装配线1',
status: 0
},
materialList: [
{
materialCode: 'MAT001',
materialName: '原材料A',
specification: '100*50*20mm',
locationCode: 'A01-01-01',
stock: 500,
requiredQuantity: 200,
issuedQuantity: 0,
currentPick: 0
},
{
materialCode: 'MAT002',
materialName: '原材料B',
specification: '200*100*30mm',
locationCode: 'A01-02-01',
stock: 300,
requiredQuantity: 150,
issuedQuantity: 0,
currentPick: 0
}
],
batchInfo: {
batchNo: '',
workOrder: ''
orderNo: 'W20250721001',
linkedNo: '20250723001-1',
labelCount: 10,
labelTotal: 20,
materialCount: 100,
materialTotal: 2000
}, },
remark: '',
submitting: false
tableData: [
{ no: 8, labelCode: '2025070002', materialCode: '2025070002', unit: '↑', labelCount: 2 },
{ no: 7, labelCode: '2025070003', materialCode: '2025070003', unit: '↑', labelCount: 3 },
{ no: 6, labelCode: '2025070004', materialCode: '2025070004', unit: '↑', labelCount: 4 },
{ no: 5, labelCode: '2025070005', materialCode: '2025070005', unit: '↑', labelCount: 5 },
{ no: 4, labelCode: '2025070006', materialCode: '2025070006', unit: '↑', labelCount: 6 },
{ no: 3, labelCode: '2025070006', materialCode: '2025070006', unit: '↑', labelCount: 6 },
{ no: 2, labelCode: '2025070006', materialCode: '2025070006', unit: '↑', labelCount: 6 },
{ no: 1, labelCode: '2025070006', materialCode: '2025070006', unit: '↑', labelCount: 6 }
]
} }
}, },
mounted() {
this.loadOrderData()
},
methods: { methods: {
loadOrderData() {
const orderNo = this.$route.params.orderNo
console.log('加载生产订单数据:', orderNo)
},
handleScanBatch() {
this.$toast('扫描批次功能开发中...')
handleAdd() {
if (!this.scanCode.trim()) return;
// tableData
this.$message.success('添加成功(演示)');
this.scanCode = '';
this.$nextTick(() => {
if (this.$refs.scanInput) this.$refs.scanInput.focus();
});
}, },
async handleSubmit() {
//
const hasPick = this.materialList.some(item => item.currentPick > 0)
if (!hasPick) {
this.$toast('请输入发料数量')
return
}
//
const insufficientStock = this.materialList.find(item => item.currentPick > item.stock)
if (insufficientStock) {
this.$toast(`${insufficientStock.materialName} 库存不足`)
return
}
this.submitting = true
try {
await new Promise(resolve => setTimeout(resolve, 2000))
this.$toast.success('发料成功')
this.$router.back()
} catch (error) {
this.$toast.fail('发料失败')
} finally {
this.submitting = false
}
handleConfirm() {
this.submitting = true;
setTimeout(() => {
this.submitting = false;
this.$message.success('出库成功');
this.$router.back();
}, 1000);
}, },
getStatusText(status) {
const statusMap = {
0: '待发料',
1: '部分发料',
2: '已完成'
}
return statusMap[status] || '未知'
handleCancel() {
this.$router.back();
} }
},
mounted() {
this.$nextTick(() => {
if (this.$refs.scanInput) this.$refs.scanInput.focus();
});
} }
} }
</script> </script>
@ -192,106 +126,132 @@ export default {
background-color: #f7f8fa; background-color: #f7f8fa;
padding-bottom: 80px; padding-bottom: 80px;
} }
.order-info {
background: white;
margin-bottom: 10px;
}
.info-header {
.header-bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 16px;
border-bottom: 1px solid #ebedf0;
padding: 8px 16px;
background: #17B3A3;
color: white;
height: 40px;
min-height: 40px;
} }
.order-no {
font-size: 18px;
font-weight: bold;
color: #323233;
.header-left {
display: flex;
align-items: center;
cursor: pointer;
font-size: 16px;
font-weight: 500;
} }
.order-status {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
color: white;
background-color: #ff976a;
.header-right {
cursor: pointer;
} }
.material-section,
.batch-section,
.remark-section {
.search-container {
display: flex;
align-items: center;
padding: 10px 16px;
background: white; background: white;
margin-bottom: 10px;
}
.search-container .el-input {
flex: 1;
}
.add-btn {
margin-left: 10px;
background: #17B3A3;
color: #fff;
border: none;
border-radius: 16px;
height: 32px;
min-width: 56px;
font-size: 15px;
font-weight: 500;
box-shadow: none;
transition: background 0.2s;
}
.add-btn:hover, .add-btn:focus {
background: #13998c;
color: #fff;
} }
.section-title {
.order-card {
background: white;
margin: 16px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
padding: 16px; padding: 16px;
font-size: 16px;
font-weight: bold;
color: #323233;
border-bottom: 1px solid #ebedf0;
margin-bottom: 10px;
} }
.material-item {
.order-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 16px;
border-bottom: 1px solid #ebedf0;
}
.material-item:last-child {
border-bottom: none;
font-size: 15px;
margin-bottom: 6px;
} }
.material-info {
flex: 1;
.label {
color: #969799;
} }
.material-name {
font-size: 16px;
font-weight: bold;
.value {
color: #323233; color: #323233;
margin-bottom: 4px;
font-weight: 500;
} }
.material-spec {
font-size: 12px;
color: #969799;
margin-bottom: 6px;
.value.success {
color: #19be6b;
} }
.material-location {
display: flex;
align-items: center;
margin-bottom: 4px;
.table-section {
background: white;
margin: 0 16px 10px 16px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
padding: 16px 8px 8px 8px;
} }
.stock-info {
font-size: 12px;
color: #646566;
.table-title {
font-size: 15px;
color: #17B3A3;
font-weight: bold;
margin-bottom: 8px;
margin-left: 8px; margin-left: 8px;
} }
.material-quantity {
.pick-table {
font-size: 14px; font-size: 14px;
color: #646566;
} }
.pick-input {
margin-left: 16px;
}
.bottom-actions { .bottom-actions {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
padding: 16px;
padding: 16px 0 24px 0;
background: white; background: white;
border-top: 1px solid #ebedf0; border-top: 1px solid #ebedf0;
display: flex;
justify-content: center;
gap: 32px;
}
.bottom-actions .el-button {
min-width: 120px;
height: 36px;
border-radius: 18px;
font-size: 16px;
font-weight: 500;
border: 1.5px solid #17B3A3;
color: #17B3A3;
background: #fff;
box-shadow: none;
transition: background 0.2s, color 0.2s;
}
.bottom-actions .el-button:hover, .bottom-actions .el-button:focus {
background: #17B3A3;
color: #fff;
border-color: #17B3A3;
}
.bottom-actions .el-button--primary {
background: #17B3A3;
color: #fff;
border-color: #17B3A3;
}
.bottom-actions .el-button--primary:hover, .bottom-actions .el-button--primary:focus {
background: #13998c;
color: #fff;
border-color: #13998c;
} }
</style> </style>

1425
src/views/modules/production-issue/productionIssuePda.vue
File diff suppressed because it is too large
View File

Loading…
Cancel
Save