feat&refactor: 2026-09-22 半成品业务模型重构与功能完善

- 重构半成品流转逻辑:进度权威源改为 workpiece.currentStationNo,新增 completedText 快照字段,废除 doneProcessCodes
- 清理物料品类中半成品类型,存量数据幂等清理,调整物料管理方式文案为批次/序列号
- 新增日排产状态专用更新接口,修复工单工艺校验逻辑
- 新增物料档案代理接口、深路径文件下载接口
- 优化前端界面文案与工位选择逻辑,补充追溯页半成品流转展示
- 调整WMS端物料品类校验与入库接口契约
- 新增/更新数据库表结构与实体类代码
This commit is contained in:
SunYF
2026-09-22 14:42:52 +08:00
parent 09cfc6ca1c
commit d3eda6b588
49 changed files with 1155 additions and 1122 deletions
+79 -44
View File
@@ -161,53 +161,62 @@
</div>
</el-form-item>
<!-- 物料清单子表(整表覆盖保存) -->
<!-- 物料清单子表(整表覆盖保存;物料编号下拉选择,快照信息取自物料档案) -->
<el-form-item label="物料清单">
<div style="width:100%">
<el-alert v-if="!flowDlg.id" type="info" :closable="false" style="margin-bottom:8px"
title="新工艺请先保存,保存后即可维护物料清单。" />
<el-table v-else :data="flowDlg.materials" border size="small">
<el-table-column label="物料编码" min-width="130">
<template #default="{ row }"><el-input v-model="row.materialCode" placeholder="手填" /></template>
</el-table-column>
<el-table-column label="物料名称" min-width="120">
<template #default="{ row }"><el-input v-model="row.materialName" placeholder="手填" /></template>
</el-table-column>
<el-table-column label="规格" min-width="110">
<template #default="{ row }"><el-input v-model="row.spec" /></template>
</el-table-column>
<el-table-column label="单位" width="80">
<template #default="{ row }"><el-input v-model="row.unit" /></template>
</el-table-column>
<el-table-column label="管控方式" width="150">
<template #default="{ row }">
<el-select v-model="row.manageMode" placeholder="请选择">
<el-option value="1" label="批次·结构件" />
<el-option value="2" label="序列号·电气件" />
</el-select>
</template>
</el-table-column>
<el-table-column label="单台用量" width="120">
<template #default="{ row }">
<el-input-number v-model="row.unitQty" :min="0" size="small" controls-position="right" style="width:100%" />
</template>
</el-table-column>
<el-table-column label="损耗率%" width="110">
<template #default="{ row }">
<el-input-number v-model="row.lossRate" :min="0" size="small" controls-position="right" style="width:100%" />
</template>
</el-table-column>
<el-table-column label="操作" width="70" align="center">
<template #default="{ row }">
<el-button link type="danger" size="small" @click="removeMaterial(row)">删</el-button>
</template>
</el-table-column>
</el-table>
<div style="display:flex;gap:10px;margin-top:10px;align-items:center">
<el-button v-if="flowDlg.id" size="small" @click="addMaterial">新增物料行</el-button>
<el-button v-if="flowDlg.id" size="small" type="primary" :loading="matSaving" @click="saveMaterials">保存物料清单</el-button>
<span style="color:#909399;font-size:12px">物料编码/名称/规格/单位手填,须属于产品物料清单范围,工单保存时校验;备料需求 = 各工位分产量 × 单台用量 ×(1+损耗率%)。</span>
</div>
<template v-else>
<el-alert v-if="materialsUnavailable" type="warning" :closable="false" style="margin-bottom:8px"
title="物料档案服务不可用,清单暂只读:不可新增物料行,已有行仅可调整单台用量/损耗率。" />
<el-table :data="flowDlg.materials" border size="small">
<el-table-column label="物料编号" min-width="150">
<template #default="{ row }">
<el-select v-model="row.materialCode" filterable placeholder="请选择物料编号" style="width:100%"
@change="(code) => onMaterialPicked(row, code)">
<el-option v-for="m in materialOptions" :key="m.code" :label="m.code" :value="m.code" />
</el-select>
</template>
</el-table-column>
<el-table-column label="物料名称" min-width="120">
<template #default="{ row }"><el-input v-model="row.materialName" disabled /></template>
</el-table-column>
<el-table-column label="规格" min-width="110">
<template #default="{ row }"><el-input v-model="row.spec" disabled /></template>
</el-table-column>
<el-table-column label="单位" width="80">
<template #default="{ row }"><el-input v-model="row.unit" disabled /></template>
</el-table-column>
<el-table-column label="管控方式" width="110">
<template #default="{ row }">
<el-select v-model="row.manageMode" disabled>
<el-option value="1" label="批次" />
<el-option value="2" label="序列号" />
</el-select>
</template>
</el-table-column>
<el-table-column label="单台用量" width="120">
<template #default="{ row }">
<el-input-number v-model="row.unitQty" :min="0" size="small" controls-position="right" style="width:100%" />
</template>
</el-table-column>
<el-table-column label="损耗率%" width="110">
<template #default="{ row }">
<el-input-number v-model="row.lossRate" :min="0" size="small" controls-position="right" style="width:100%" />
</template>
</el-table-column>
<el-table-column label="操作" width="70" align="center">
<template #default="{ row }">
<el-button link type="danger" size="small" @click="removeMaterial(row)">删</el-button>
</template>
</el-table-column>
</el-table>
<div style="display:flex;gap:10px;margin-top:10px;align-items:center">
<el-button v-if="!materialsUnavailable" size="small" @click="addMaterial">新增物料行</el-button>
<el-button size="small" type="primary" :loading="matSaving" @click="saveMaterials">保存物料清单</el-button>
<span style="color:#909399;font-size:12px">物料编号取自物料档案编码(结构件通常即图号),选中后名称/规格/单位/管控方式自动带出、不可改;备料需求 = 各工位分产量 × 单台用量 ×(1+损耗率%)。</span>
</div>
</template>
</div>
</el-form-item>
</el-form>
@@ -369,6 +378,31 @@ function blankMaterial() {
return { materialCode: '', materialName: '', spec: '', unit: '', manageMode: '2', unitQty: 1, lossRate: 0 }
}
/* ---------- 物料档案(物料清单「物料编号」下拉数据源) ---------- */
const materialOptions = ref([])
const materialsUnavailable = ref(false)
async function loadMaterialArchive() {
materialsUnavailable.value = false
try {
const list = (await request.get('/materials')) || []
materialOptions.value = Array.isArray(list) ? list : []
} catch {
materialOptions.value = []
}
if (!materialOptions.value.length) materialsUnavailable.value = true
}
// 选中物料编号后,快照字段(名称/规格/单位/管控方式)自动带出,均不可手改
function onMaterialPicked(row, code) {
const m = materialOptions.value.find((x) => x.code === code)
if (!m) return
row.materialName = m.name || ''
row.spec = m.spec || ''
row.unit = m.unit || ''
if (m.manageMode != null && m.manageMode !== '') row.manageMode = String(m.manageMode)
}
// 加载该工艺的物料清单(整表编辑,保存时整表覆盖)
async function loadMaterials(flowId) {
flowDlg.materials = []
@@ -399,7 +433,7 @@ async function saveMaterials() {
unitQty: Number(m.unitQty) || 0,
lossRate: Number(m.lossRate) || 0
}))
if (items.some((m) => !m.materialCode)) return ElMessage.warning('存在未填写物料编码的行,请补全或删除')
if (items.some((m) => !m.materialCode)) return ElMessage.warning('存在未选择物料编号的行,请补全或删除')
matSaving.value = true
try {
await request.post(`/process-flows/${flowDlg.id}/materials`, { items })
@@ -552,6 +586,7 @@ async function toggleStatus(row) {
onMounted(() => {
loadFlows()
loadMaterialArchive()
})
</script>