feat: 完成客户第12条需求+多系统改造
1. 新增预警表添加工单号字段,支持按工单号检索预警 2. 添加工单过滤在制品/绩效报表/预警中心查询 3. 补全WMS台账字段口径与权限配置 4. 修复备料单与数量不符处理流程 5. 新增配送进度/库位联动/自动出库功能 6. 修复AGV配送状态更新逻辑 7. 优化退料与库存管理细节
This commit is contained in:
@@ -16,7 +16,7 @@ export const helpInbound = {
|
||||
{ name: '数量', source: '手工填写整数。', purpose: '本批到货数量', fill: '整数 ≥1' },
|
||||
{ name: '区域', source: '下拉选择(必填)。数据来自"区域维护"。', purpose: '放到哪个库区(待检/合格/不合格…)', fill: '必填;新到货一般先放"待检"区,检验合格后再转"合格"区' },
|
||||
{ name: '货架/层/位', source: '手工填写(选填)。库位四级贯通的三级货位。', purpose: '精确到货位,便于拣配与盘点', fill: '如 货架A / 3层 / 12位;可留空只记区域' },
|
||||
{ name: '库位自动带入', source: '选物料后前端自动调 /inbound/last-location。', purpose: '回填该物料最近一次入库的库位(区域/货架/层/位置号),免手输', fill: '选物料即自动填入;可手动改到其他库位' },
|
||||
{ name: '库位自动带入', source: '选物料后前端自动调 /inbound/last-location;该物料无历史库位时(新物料)再调 /zone/vacant 推荐同区空位。', purpose: '有历史→回填最近一次入库库位;无历史→按所选区域自动挑一个未被占用的空闲货位,免手输也避免撞位', fill: '选物料即自动填入;切换区域会按新区域重新推荐空位;结果均可手动改' },
|
||||
{ name: '生产日期', source: '手动选择日期。', purpose: '生产时间,用于时效和批次管理', fill: '选择日期' },
|
||||
{ name: '供应商', source: '手工填写。', purpose: '来料来源', fill: '供应商名称,可空' },
|
||||
{ name: '批量导入', source: '本页签下方。', purpose: '整表校验后一次性入库', fill: '模板(首行忽略表头):图号 | 批次号(可空自动生成) | 数量 | 生产日期 | 供应商 | 区域 | 备注。任一行错误则整体回退' }
|
||||
@@ -68,9 +68,13 @@ export const helpOutbound = {
|
||||
{ name: '备料出库-目标工位', source: '下拉选择 DOCK01~DOCK20(选填,可过滤搜索)。', purpose: 'AGV 配送送达的接驳台(toDock 参数)', fill: '选择如 DOCK05;不选默认运到产线入口 DOCK01' },
|
||||
{ name: '备料出库-一键分配出库', source: '系统自动按 FIFO 分配。数据来自合格区Z02的批次库存。', purpose: '从合格区按先进先出凑够缺口并出库', fill: '点按钮,系统自动算批次并二次确认' },
|
||||
{ name: '通用出库-物料/类型', source: '下拉选择物料;类型选"结构件(批次)"或"电气件(SN)"。', purpose: '决定走批次扣减还是 SN 扣减', fill: '选物料后选类型;批次填批次号+数量,SN 扫入 SN 列表' },
|
||||
{ name: '通用出库-区域 / 货架 / 层 / 位置(四级库位)', source: '与入库同口径的逐级联动下拉(选填)。选物料或批次后自动带入:① 该批次在库的实际库位 ② 该物料最近一次入库库位 ③ 都无则按所选区域推荐同区空位。', purpose: '指明从哪个货位取料,免手工挑选,出库留痕到具体货位', fill: '选物料/批次即自动填入四级,可逐级手动改;切换上级会自动清空下级' },
|
||||
{ name: '通用出库-箱号', source: '手动填写(选填)。', purpose: '整箱发货时填写,装箱信息随出库单记录(无需再单独录入装箱)', fill: '填箱号后,本出库单即带装箱属性,可在"出库记录"按箱号追溯' },
|
||||
{ name: '通用出库-合同号', source: '手动填写(选填)。', purpose: '关联合同,便于按合同追溯', fill: '可空' },
|
||||
{ name: '出库记录-导出 CSV', source: '按钮操作。', purpose: '把统一主表当前筛选结果一次导出为 CSV(含箱号/装箱SN)', fill: '点【导出 CSV】下载全部出库记录' }
|
||||
{ name: '出库类型(备料/补料/通用)', source: '系统按来源自动写入:备料=按日排产自动出库;补料=工位叫料或数量不符补发(优先发);通用=本页手工出库。', purpose: '区分出库来源,仓库先发补料', fill: '只读,可在"出库记录"按类型筛选' },
|
||||
{ name: '出库状态(已出库/已送达)', source: '系统维护:出库即记「已出库」;叫 AGV 配送到位后自动转「已送达」。工位接料在 MES 备料单上确认,不在本表。', purpose: '跟踪料是否已送到接驳台', fill: '只读,可按状态筛选' },
|
||||
{ name: '超领原因', source: '出库数量超过工单物料清单需求时必填(损耗/报废/返修)。', purpose: '超领不硬卡但必须留痕,可统计、可预警', fill: 'WMS/MES 出库时按提示填写原因后放行' },
|
||||
{ name: '出库记录-导出 CSV', source: '按钮操作。', purpose: '把统一主表当前筛选结果一次导出为 CSV(含库位/箱号/装箱SN)', fill: '点【导出 CSV】下载全部出库记录' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -141,6 +145,7 @@ export const helpSemi = {
|
||||
{ name: '物料', source: '下拉选择。来自物料档案(最近100条+模糊搜索)。', purpose: '入库物料(MES 自动同步时以请求传入为准,WMS 补齐物料名称)', fill: '选择图号' },
|
||||
{ name: '已完成工序', source: 'MES 自动带出(doneProcessCodes,如 [1,3,5]);手工录入填逗号分隔,如 1,3,5。', purpose: '该件已做到哪些工序,重上线时 MES 从下一工序继续', fill: '如 1,3,5,可空' },
|
||||
{ name: '工单号', source: '自动带出/手工填写。来自工单。', purpose: '来源工单', fill: '输入工单号' },
|
||||
{ name: '归属', source: '下拉:工单号 / 科技项目号 / 其他(必选,与入库管理同口径,不再有"无")。', purpose: '标记该件归属哪个工单或科技项目', fill: '必选一项;选"其他"可不填编号,选"工单号/科技项目号"须填归属编号' },
|
||||
{ name: '区域', source: '手动填写(可空)。', purpose: '存放库区', fill: '如 Z05' },
|
||||
{ name: '扫码录入', source: '扫码枪连续扫码。来自工件 SN 条码。', purpose: '半成品 SN 清单', fill: '扫入 SN 回车追加' }
|
||||
]
|
||||
|
||||
@@ -78,7 +78,11 @@ function zonePositions(zoneCode, shelfNo, layerNo) {
|
||||
return [...set].sort()
|
||||
}
|
||||
// 切换上级库位时清空下级,避免残留无效值(用户诉求:库位逐级联动选择,禁止手填)
|
||||
function onZoneChange(form) { form.shelfNo = ''; form.layerNo = ''; form.positionNo = '' }
|
||||
function onZoneChange(form) {
|
||||
form.shelfNo = ''; form.layerNo = ''; form.positionNo = ''
|
||||
// 手动切换区域后,按新区域重新推荐空位(物料已选时)
|
||||
if (form.materialCode) suggestVacant(form)
|
||||
}
|
||||
function onShelfChange(form) { form.layerNo = ''; form.positionNo = '' }
|
||||
function onLayerChange(form) { form.positionNo = '' }
|
||||
|
||||
@@ -502,6 +506,7 @@ function locText(row) {
|
||||
// 后端 /inbound/last-location 取该物料 created_at 最近一条入库记录的库位;未找到则不动。
|
||||
async function fillLastLocation(form) {
|
||||
if (!form.materialCode) return
|
||||
let filled = false
|
||||
try {
|
||||
const loc = await request.get('/inbound/last-location', { params: { materialCode: form.materialCode } })
|
||||
if (loc && loc.zoneCode) {
|
||||
@@ -509,10 +514,33 @@ async function fillLastLocation(form) {
|
||||
form.shelfNo = loc.shelfNo || ''
|
||||
form.layerNo = loc.layerNo || ''
|
||||
form.positionNo = loc.positionNo || ''
|
||||
filled = true
|
||||
}
|
||||
} catch {
|
||||
/* 查询失败不影响主流程 */
|
||||
}
|
||||
// 无历史库位(新物料):按同区空位自动推荐一个空闲货位
|
||||
if (!filled) await suggestVacant(form)
|
||||
}
|
||||
|
||||
// 同区空位推荐:物料无历史入库库位时,自动在当前区域(未选区域则取第一个可用区域)内挑一个空闲货位回填。
|
||||
// 后端 /zone/vacant 只返回未被在库库存占用的位置节点(level=4)。
|
||||
async function suggestVacant(form, notifyEmpty = false) {
|
||||
try {
|
||||
const v = await request.get('/zone/vacant', { params: { zoneCode: form.zoneCode || '', limit: 1 } })
|
||||
const hit = Array.isArray(v) ? v[0] : null
|
||||
if (!hit) {
|
||||
if (notifyEmpty) ElMessage.info('当前区域暂无可推荐空位,请先在「基础数据 → 区域库位」中维护位置节点')
|
||||
return false
|
||||
}
|
||||
form.zoneCode = hit.zoneCode
|
||||
form.shelfNo = hit.shelfNo || ''
|
||||
form.layerNo = hit.layerNo || ''
|
||||
form.positionNo = hit.positionNo || ''
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function onOwnershipChange(form) {
|
||||
// 切换归属类型:清空已填编号(归属类型必选,不再有"无")
|
||||
|
||||
@@ -57,8 +57,10 @@ function onTabChange(name) {
|
||||
if (name === 'return' && !retQueried.value) loadReturn()
|
||||
}
|
||||
|
||||
// 缺口按净领用计算:净领用 = 已出库 − 已退回(退料自动回补缺口,退料后可再次补料)
|
||||
function gapOf(row) {
|
||||
return Math.max((row.totalQty || 0) - (row.outQty || 0), 0)
|
||||
const net = (row.outQty || 0) - (row.returnedQty || 0)
|
||||
return Math.max((row.totalQty || 0) - net, 0)
|
||||
}
|
||||
|
||||
async function load() {
|
||||
@@ -159,6 +161,8 @@ function statusView(row) {
|
||||
<template #default="{ row }">{{ row.availableQty ?? 0 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="outQty" label="已出库" width="90" align="center" />
|
||||
<el-table-column prop="returnedQty" label="已退回" width="90" align="center" />
|
||||
<el-table-column prop="consumedQty" label="已消耗" width="90" align="center" />
|
||||
<el-table-column label="缺口" width="90" align="center">
|
||||
<template #default="{ row }">{{ gapOf(row) }}</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
defineOptions({ name: 'Outbound' })
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import request from '../utils/request'
|
||||
import { getRealName } from '../utils/auth'
|
||||
@@ -118,6 +118,7 @@ const OWNERSHIP_OPTIONS = [
|
||||
const zones = ref([])
|
||||
const genForm = reactive({
|
||||
materialCode: '', mode: 1, batchNo: '', qty: 1, zoneCode: '',
|
||||
shelfNo: '', layerNo: '', positionNo: '',
|
||||
boxNo: '', contractNo: '', remark: '',
|
||||
outboundCategory: 'other', ownershipType: 'none', ownershipNo: '', targetStation: ''
|
||||
})
|
||||
@@ -155,6 +156,73 @@ const zoneOptions = computed(() => {
|
||||
return [...map.values()]
|
||||
})
|
||||
|
||||
// 库位三级联动(与入库同口径):基于已加载 zones(每行是完整四级货位)派生可选项
|
||||
function zoneShelves(zoneCode) {
|
||||
const set = new Set()
|
||||
zones.value.forEach(z => { if (z.zoneCode === zoneCode && z.shelfNo) set.add(z.shelfNo) })
|
||||
return [...set].sort()
|
||||
}
|
||||
function zoneLayers(zoneCode, shelfNo) {
|
||||
const set = new Set()
|
||||
zones.value.forEach(z => { if (z.zoneCode === zoneCode && z.shelfNo === shelfNo && z.layerNo) set.add(z.layerNo) })
|
||||
return [...set].sort()
|
||||
}
|
||||
function zonePositions(zoneCode, shelfNo, layerNo) {
|
||||
const set = new Set()
|
||||
zones.value.forEach(z => { if (z.zoneCode === zoneCode && z.shelfNo === shelfNo && z.layerNo === layerNo && z.positionNo) set.add(z.positionNo) })
|
||||
return [...set].sort()
|
||||
}
|
||||
function onGenZoneChange() {
|
||||
genForm.shelfNo = ''; genForm.layerNo = ''; genForm.positionNo = ''
|
||||
if (genForm.materialCode || genForm.batchNo) fillZoneFromHistory()
|
||||
}
|
||||
function onGenShelfChange() { genForm.layerNo = ''; genForm.positionNo = '' }
|
||||
function onGenLayerChange() { genForm.positionNo = '' }
|
||||
function locText(row) {
|
||||
const parts = []
|
||||
if (row?.shelfNo) parts.push(row.shelfNo + '架')
|
||||
if (row?.layerNo) parts.push(row.layerNo + '层')
|
||||
if (row?.positionNo) parts.push(row.positionNo + '位')
|
||||
return parts.length ? parts.join('/') : '-'
|
||||
}
|
||||
|
||||
// 出库库位联动(客户诉求 一.9「出库相同」):与入库同口径回填 区域/货架/层/位置 四级。
|
||||
// 优先级:① 指定批次在库的实际库位 ② 该物料最近一次入库库位 ③ 无历史时按所选区域推荐同区空位。
|
||||
async function fillZoneFromHistory() {
|
||||
if (!genForm.materialCode && !genForm.batchNo) return
|
||||
let filled = false
|
||||
try {
|
||||
const loc = await request.get('/outbound/location-hint', {
|
||||
params: { materialCode: genForm.materialCode, batchNo: genForm.batchNo }
|
||||
})
|
||||
if (loc && loc.zoneCode) {
|
||||
genForm.zoneCode = loc.zoneCode
|
||||
genForm.shelfNo = loc.shelfNo || ''
|
||||
genForm.layerNo = loc.layerNo || ''
|
||||
genForm.positionNo = loc.positionNo || ''
|
||||
filled = true
|
||||
}
|
||||
} catch {
|
||||
/* 查询失败不影响主流程 */
|
||||
}
|
||||
if (filled) return
|
||||
// 无历史库位:按区域推荐同区空位(与入库同源接口,返回数组取第一条)
|
||||
try {
|
||||
const v = await request.get('/zone/vacant', { params: { zoneCode: genForm.zoneCode || '', limit: 1 } })
|
||||
const hit = Array.isArray(v) ? v[0] : (v?.list || [])[0]
|
||||
if (hit) {
|
||||
genForm.zoneCode = hit.zoneCode
|
||||
genForm.shelfNo = hit.shelfNo || ''
|
||||
genForm.layerNo = hit.layerNo || ''
|
||||
genForm.positionNo = hit.positionNo || ''
|
||||
}
|
||||
} catch {
|
||||
/* 忽略 */
|
||||
}
|
||||
}
|
||||
watch(() => genForm.materialCode, (v) => { if (v) { genForm.batchNo = ''; fillZoneFromHistory() } })
|
||||
watch(() => genForm.batchNo, (v) => { if (v && genForm.materialCode) fillZoneFromHistory() })
|
||||
|
||||
async function loadGenRows() {
|
||||
loadingGen.value = true
|
||||
try {
|
||||
@@ -180,6 +248,9 @@ async function submitGen() {
|
||||
ownershipNo: genForm.ownershipType !== 'none' ? genForm.ownershipNo.trim() : undefined,
|
||||
targetStation: genForm.targetStation.trim() || undefined,
|
||||
zoneCode: genForm.zoneCode || undefined,
|
||||
shelfNo: genForm.shelfNo || undefined,
|
||||
layerNo: genForm.layerNo || undefined,
|
||||
positionNo: genForm.positionNo || undefined,
|
||||
boxNo: genForm.boxNo.trim() || undefined,
|
||||
contractNo: genForm.contractNo.trim() || undefined,
|
||||
remark: genForm.remark.trim() || undefined
|
||||
@@ -198,7 +269,7 @@ async function submitGen() {
|
||||
try {
|
||||
const res = await request.post('/outbound/general', payload)
|
||||
ElMessage.success(`通用出库成功:${res?.outboundNo}${res?.boxNo ? ' 箱号 ' + res.boxNo : ''}`)
|
||||
Object.assign(genForm, { materialCode: '', mode: 1, batchNo: '', qty: 1, zoneCode: '', boxNo: '', contractNo: '', remark: '', outboundCategory: 'other', ownershipType: 'none', ownershipNo: '', targetStation: '' })
|
||||
Object.assign(genForm, { materialCode: '', mode: 1, batchNo: '', qty: 1, zoneCode: '', shelfNo: '', layerNo: '', positionNo: '', boxNo: '', contractNo: '', remark: '', outboundCategory: 'other', ownershipType: 'none', ownershipNo: '', targetStation: '' })
|
||||
snInput.value = ''
|
||||
snList.value = []
|
||||
genPage.current = 1
|
||||
@@ -208,7 +279,7 @@ async function submitGen() {
|
||||
}
|
||||
|
||||
/* ===================== 出库记录(统一主表,全部 + 导出) ===================== */
|
||||
const recFilters = reactive({ outboundType: '', materialCode: '', boxNo: '', ownershipType: '', dateRange: [] })
|
||||
const recFilters = reactive({ outboundType: '', status: '', materialCode: '', boxNo: '', ownershipType: '', dateRange: [] })
|
||||
const recRows = ref([])
|
||||
const recTotal = ref(0)
|
||||
const loadingRec = ref(false)
|
||||
@@ -221,6 +292,7 @@ async function loadRecords() {
|
||||
try {
|
||||
const params = {
|
||||
outboundType: recFilters.outboundType,
|
||||
status: recFilters.status,
|
||||
materialCode: recFilters.materialCode.trim(),
|
||||
boxNo: recFilters.boxNo.trim(),
|
||||
ownershipType: recFilters.ownershipType,
|
||||
@@ -236,11 +308,12 @@ async function loadRecords() {
|
||||
} finally { loadingRec.value = false }
|
||||
}
|
||||
function searchRec() { recPage.current = 1; loadRecords() }
|
||||
function resetRec() { Object.assign(recFilters, { outboundType: '', materialCode: '', boxNo: '', dateRange: [] }); searchRec() }
|
||||
function resetRec() { Object.assign(recFilters, { outboundType: '', status: '', materialCode: '', boxNo: '', dateRange: [] }); searchRec() }
|
||||
|
||||
function downloadCSV() {
|
||||
exportXlsxFetch('/api/outbound/export', {
|
||||
outboundType: recFilters.outboundType,
|
||||
status: recFilters.status,
|
||||
materialCode: recFilters.materialCode.trim(),
|
||||
boxNo: recFilters.boxNo.trim()
|
||||
}, '出库管理.xlsx')
|
||||
@@ -374,11 +447,24 @@ onMounted(loadDicts)
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<el-form-item label="出库区域">
|
||||
<el-select v-model="genForm.zoneCode" filterable clearable placeholder="可选" style="width:100%">
|
||||
<el-form-item label="区域">
|
||||
<el-select v-model="genForm.zoneCode" filterable clearable placeholder="选择区域(选物料/批次后自动带出最近库位)" style="width:100%" @change="onGenZoneChange">
|
||||
<el-option v-for="z in zoneOptions" :key="z.zoneCode" :value="z.zoneCode" :label="`${z.zoneCode} ${z.zoneName}`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架 / 层 / 位置">
|
||||
<div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center">
|
||||
<el-select v-model="genForm.shelfNo" placeholder="货架" clearable style="width:120px" @change="onGenShelfChange">
|
||||
<el-option v-for="s in zoneShelves(genForm.zoneCode)" :key="s" :label="s + ' 架'" :value="s" />
|
||||
</el-select>
|
||||
<el-select v-model="genForm.layerNo" placeholder="层" clearable style="width:100px" :disabled="!genForm.shelfNo" @change="onGenLayerChange">
|
||||
<el-option v-for="l in zoneLayers(genForm.zoneCode, genForm.shelfNo)" :key="l" :label="l + ' 层'" :value="l" />
|
||||
</el-select>
|
||||
<el-select v-model="genForm.positionNo" placeholder="位置" clearable style="width:110px" :disabled="!genForm.shelfNo">
|
||||
<el-option v-for="p in zonePositions(genForm.zoneCode, genForm.shelfNo, genForm.layerNo)" :key="p" :label="p + ' 位'" :value="p" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="箱号">
|
||||
<el-input v-model="genForm.boxNo" placeholder="选填:整箱发货时填写,装箱信息随出库单记录(无需单独录入装箱)" clearable style="width:100%" />
|
||||
</el-form-item>
|
||||
@@ -401,6 +487,9 @@ onMounted(loadDicts)
|
||||
<el-table-column prop="batchNo" label="批次号" min-width="120">
|
||||
<template #default="{ row }">{{ row.batchNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库位" min-width="120" align="center">
|
||||
<template #default="{ row }">{{ row.zoneCode ? row.zoneCode + ' ' + locText(row) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="SN" min-width="180">
|
||||
<template #default="{ row }">{{ row.snCodes || '-' }}</template>
|
||||
</el-table-column>
|
||||
@@ -440,9 +529,16 @@ onMounted(loadDicts)
|
||||
<el-form-item label="类型">
|
||||
<el-select v-model="recFilters.outboundType" clearable placeholder="全部" style="width:140px">
|
||||
<el-option label="备料出库" value="workorder" />
|
||||
<el-option label="工位补料" value="refill" />
|
||||
<el-option label="通用出库" value="general" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="recFilters.status" clearable placeholder="全部" style="width:120px">
|
||||
<el-option label="已出库" value="已出库" />
|
||||
<el-option label="已送达" value="已送达" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料">
|
||||
<MaterialSelect v-model="recFilters.materialCode" placeholder="物料" width="180px" />
|
||||
</el-form-item>
|
||||
@@ -466,11 +562,16 @@ onMounted(loadDicts)
|
||||
<el-table-column prop="outboundNo" label="出库单号" min-width="150" />
|
||||
<el-table-column label="类型" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.outboundType === 'general' ? 'warning' : 'primary'" size="small">
|
||||
{{ row.outboundType === 'general' ? '通用' : '备料' }}
|
||||
<el-tag :type="row.outboundType === 'general' ? 'warning' : row.outboundType === 'refill' ? 'danger' : 'primary'" size="small">
|
||||
{{ row.outboundType === 'general' ? '通用' : row.outboundType === 'refill' ? '补料' : '备料' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '已送达' ? 'success' : 'info'" size="small">{{ row.status || '已出库' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderNo" label="工单号" min-width="130">
|
||||
<template #default="{ row }">{{ row.orderNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
@@ -478,6 +579,9 @@ onMounted(loadDicts)
|
||||
<el-table-column prop="batchNo" label="批次号" min-width="110">
|
||||
<template #default="{ row }">{{ row.batchNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库位" min-width="120" align="center">
|
||||
<template #default="{ row }">{{ row.zoneCode ? row.zoneCode + ' ' + locText(row) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="SN" min-width="160">
|
||||
<template #default="{ row }">{{ row.snCodes || '-' }}</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -26,7 +26,8 @@ const todayStr = new Date().toLocaleDateString('sv-SE')
|
||||
function newInForm() {
|
||||
return {
|
||||
materialCode: '', zoneCode: '', orderNo: '', completedProcess: '',
|
||||
ownershipType: 'workorder', ownershipNo: '',
|
||||
// 归属:与入库管理同口径——必选(无「无」选项),选其他可不填编号,工单号/科技项目号必填编号
|
||||
ownershipType: '', ownershipNo: '',
|
||||
productStatus: '', relatedStandard: '', testRecordNo: '',
|
||||
recordedBy: operator, recordedAt: todayStr
|
||||
}
|
||||
@@ -64,6 +65,15 @@ async function submitInbound(cat) {
|
||||
ElMessage.warning('成品入库请选择产品状态(已通过/部分通过/返修)')
|
||||
return
|
||||
}
|
||||
// 归属必选(与入库管理同口径,不再有「无」);选其他可不填编号,工单号/科技项目号必须填编号
|
||||
if (!f.ownershipType) {
|
||||
ElMessage.warning('请选择归属(工单号 / 科技项目号 / 其他)')
|
||||
return
|
||||
}
|
||||
if ((f.ownershipType === 'workorder' || f.ownershipType === 'project') && !f.ownershipNo.trim()) {
|
||||
ElMessage.warning('请填写归属编号(工单号 / 科技项目号)')
|
||||
return
|
||||
}
|
||||
inbounding[cat] = true
|
||||
let ok = 0
|
||||
try {
|
||||
@@ -209,12 +219,12 @@ onMounted(() => {
|
||||
</el-form-item>
|
||||
<el-form-item label="归属">
|
||||
<div style="display:flex;gap:8px;width:100%">
|
||||
<el-select v-model="inForms[2].ownershipType" style="width:150px">
|
||||
<el-select v-model="inForms[2].ownershipType" placeholder="请选择" style="width:150px">
|
||||
<el-option value="workorder" label="工单号" />
|
||||
<el-option value="project" label="科技项目号" />
|
||||
<el-option value="none" label="无" />
|
||||
<el-option value="other" label="其他" />
|
||||
</el-select>
|
||||
<el-input v-model="inForms[2].ownershipNo" placeholder="归属编号(可空)" clearable />
|
||||
<el-input v-model="inForms[2].ownershipNo" placeholder="归属编号" clearable />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="相关标准">
|
||||
@@ -276,12 +286,12 @@ onMounted(() => {
|
||||
</el-form-item>
|
||||
<el-form-item label="归属">
|
||||
<div style="display:flex;gap:8px;width:100%">
|
||||
<el-select v-model="inForms[3].ownershipType" style="width:150px">
|
||||
<el-select v-model="inForms[3].ownershipType" placeholder="请选择" style="width:150px">
|
||||
<el-option value="workorder" label="工单号" />
|
||||
<el-option value="project" label="科技项目号" />
|
||||
<el-option value="none" label="无" />
|
||||
<el-option value="other" label="其他" />
|
||||
</el-select>
|
||||
<el-input v-model="inForms[3].ownershipNo" placeholder="归属编号(可空)" clearable />
|
||||
<el-input v-model="inForms[3].ownershipNo" placeholder="归属编号" clearable />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="相关标准">
|
||||
|
||||
Reference in New Issue
Block a user