refactor: 全链路统一将物料编码改称图号,优化入库流程
1. 统一全系统UI与文档中的"物料编码"为客户口径"图号",覆盖前端页面、后端导出表头与帮助文档
2. 优化入库模块:
- 新增归属类型"其他"并完善注释
- 入库时自动回写入库单批次号
- 优化库位选择为三级联动下拉选择,替换原手动输入
- 新增入库归属编号录入功能
3. 更新需求文档,同步完成图号全链路改造的验收标记
This commit is contained in:
@@ -61,7 +61,7 @@ export const helpInbound = {
|
||||
export const helpOutbound = {
|
||||
title: '出库管理(统一主表)',
|
||||
overview:
|
||||
'所有出库都落在同一张「出库主表」(OutboundOrder),用"类型"区分,装箱信息(箱号/SN清单/合同号)也直接记在主表上,不再单独建装箱表。\n两个出库页签 + 一个记录页签:\n· 工单备料出库(MES):对接 MES 工单台账领料,强约束"单物料累计出库 ≤ 工单需求总量";未启用 MES 或工单未同步时,工单下拉可能为空,可直接手输工单号(需台账已同步)。\n· 通用出库:不依赖工单的手动出库(退料/样品/报废/发货),支持结构件批次与电气件 SN,填箱号即一并记录装箱;MES 不可用或无需挂靠工单时请用本页。\n· 出库记录:统一主表的全量查询与导出(一键导出 CSV,含装箱信息)。\n选用原则:有 MES 工单要按 物料清单 领料 → 工单备料出库;无工单的自由出库/装箱发货 → 通用出库。\n\n说明:出库列表中的"图号"即物料编码(客户口径统一称"图号");通用出库涵盖退料/样品/报废/发货等场景,无固定分类下拉,具体去向记在"备注"。质量门禁:质量状态为「不合格/待退」的批次禁止领料上线,须先完成不合格处置。',
|
||||
'所有出库都落在同一张「出库主表」(OutboundOrder),用"类型"区分,装箱信息(箱号/SN清单/合同号)也直接记在主表上,不再单独建装箱表。\n两个出库页签 + 一个记录页签:\n· 工单备料出库(MES):对接 MES 工单台账领料,强约束"单物料累计出库 ≤ 工单需求总量";未启用 MES 或工单未同步时,工单下拉可能为空,可直接手输工单号(需台账已同步)。\n· 通用出库:不依赖工单的手动出库(退料/样品/报废/发货),支持结构件批次与电气件 SN,填箱号即一并记录装箱;MES 不可用或无需挂靠工单时请用本页。\n· 出库记录:统一主表的全量查询与导出(一键导出 CSV,含装箱信息)。\n选用原则:有 MES 工单要按 物料清单 领料 → 工单备料出库;无工单的自由出库/装箱发货 → 通用出库。\n\n说明:出库列表统一以"图号"展示物料(客户口径统一称"图号");通用出库涵盖退料/样品/报废/发货等场景,无固定分类下拉,具体去向记在"备注"。质量门禁:质量状态为「不合格/待退」的批次禁止领料上线,须先完成不合格处置。',
|
||||
fields: [
|
||||
{ name: '备料出库-工单号', source: '手动输入。数据来自 MES 已建的工单及导入的物料台账。', purpose: '出库挂靠的工单,决定可领料总量与需求缺口', fill: '输入工单号回车,查询该工单的物料台账' },
|
||||
{ name: '备料出库-目标工位', source: '下拉选择 DOCK01~DOCK20(选填,可过滤搜索)。', purpose: 'AGV 配送送达的接驳台(toDock 参数)', fill: '选择如 DOCK05;不选默认运到产线入口 DOCK01' },
|
||||
@@ -216,9 +216,9 @@ export const helpZone = {
|
||||
export const helpMaterial = {
|
||||
title: '物料档案',
|
||||
overview:
|
||||
'定义每一种物料的字典:叫什么、什么规格、什么品类(原材料/半成品/成品)、是【结构件(批次)】还是【电气件(SN)】。\n此处维护的物料会作为下拉选项出现在入库/出库/装箱等页面;其中"类型"直接决定后续入库方式——结构件走批次(一批多件)、电气件走 SN 逐件扫码(单件追溯)。\n\n品类说明:1=原材料(默认) / 2=半成品 / 3=成品。编码主数据单一来源在本表:产品型号档案即本表中"成品"品类的行(MES 实时拉取,不双录);库存主表 inventories 的品类与其呼应。列表支持按品类筛选,导出含品类列。\n\n物料档案是库房的另一道地基:先建好物料,入库时才能选到;类型选错会导致入库方式与追溯粒度不符。\n\n命名说明:物料编码在出库/看板等页面统一显示为"图号"(客户口径)。安全库存在本档案维护,可用量低于它时会在「库房看板」首页触发缺货预警。',
|
||||
'定义每一种物料的字典:叫什么、什么规格、什么品类(原材料/半成品/成品)、是【结构件(批次)】还是【电气件(SN)】。\n此处维护的物料会作为下拉选项出现在入库/出库/装箱等页面;其中"类型"直接决定后续入库方式——结构件走批次(一批多件)、电气件走 SN 逐件扫码(单件追溯)。\n\n品类说明:1=原材料(默认) / 2=半成品 / 3=成品。编码主数据单一来源在本表:产品型号档案即本表中"成品"品类的行(MES 实时拉取,不双录);库存主表 inventories 的品类与其呼应。列表支持按品类筛选,导出含品类列。\n\n物料档案是库房的另一道地基:先建好物料,入库时才能选到;类型选错会导致入库方式与追溯粒度不符。\n\n命名说明:本档案维护的物料在出库/看板等页面统一以"图号"展示(客户口径)。安全库存在本档案维护,可用量低于它时会在「库房看板」首页触发缺货预警。',
|
||||
fields: [
|
||||
{ name: '物料编码', source: '手工填写,仓库自定义(新增后不可改)。在出库/看板等页面显示为"图号"。', purpose: '物料唯一编号(即图号)', fill: '如 SCREW-M3;新增后不可改编码' },
|
||||
{ name: '图号', source: '手工填写,仓库自定义(新增后不可改)。在出库/看板等页面显示为"图号"。', purpose: '物料唯一编号(即图号)', fill: '如 SCREW-M3;新增后不可改编码' },
|
||||
{ name: '名称', source: '手工填写。', purpose: '物料名称', fill: '如 螺丝 M3' },
|
||||
{ name: '简称', source: '手工填写(可空)。', purpose: '简写', fill: '可空' },
|
||||
{ name: '规格', source: '手工填写(可空)。', purpose: '规格型号', fill: '可空' },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
defineOptions({ name: 'BaseData' })
|
||||
import { computed, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import request from '../utils/request'
|
||||
import { fmtTime } from '../utils/format'
|
||||
import { can } from '../utils/perm'
|
||||
@@ -50,7 +50,7 @@ async function loadZones() {
|
||||
try {
|
||||
const data = await request.get('/zone/list', {
|
||||
params: {
|
||||
zoneCode: zoneFilter.zoneCode.trim(),
|
||||
zoneCode: zoneFilter.zoneCode.trim().toUpperCase(),
|
||||
zoneName: zoneFilter.zoneName.trim(),
|
||||
status: zoneFilter.status,
|
||||
page: zonePage.current,
|
||||
@@ -89,6 +89,15 @@ async function saveZone() {
|
||||
ElMessage.warning('区域编码和区域名称必填')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm('确认保存该区域信息吗?保存后将写入数据库。', '操作确认', {
|
||||
confirmButtonText: '确认保存',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
zoneSaving.value = true
|
||||
try {
|
||||
if (zoneEditingId.value) {
|
||||
@@ -188,6 +197,15 @@ async function saveMaterial() {
|
||||
ElMessage.warning('「其他」类物料必须填写规格型号')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm('确认保存该物料档案吗?保存后将写入数据库。', '操作确认', {
|
||||
confirmButtonText: '确认保存',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
mSaving.value = true
|
||||
try {
|
||||
if (mEditingId.value) {
|
||||
@@ -199,18 +217,21 @@ async function saveMaterial() {
|
||||
manageMode: mForm.manageMode
|
||||
})
|
||||
ElMessage.success('物料修改成功')
|
||||
matDialog.value = false
|
||||
} else {
|
||||
await request.post('/material/create', { ...mForm, itemType: Number(mForm.itemType), safetyStock: Number(mForm.safetyStock) || 0 })
|
||||
ElMessage.success('物料新增成功')
|
||||
const created = await request.post('/material/create', { ...mForm, itemType: Number(mForm.itemType), safetyStock: Number(mForm.safetyStock) || 0 })
|
||||
ElMessage.success('物料新增成功,可继续上传图纸/附件')
|
||||
// 创建成功后切到编辑态:保持弹窗打开,便于立即上传附件
|
||||
mEditingId.value = created?.id || 0
|
||||
if (created?.code) mForm.code = created.code
|
||||
}
|
||||
matDialog.value = false
|
||||
await loadMaterials()
|
||||
} finally {
|
||||
mSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 物料附件(bizType=material,bizId=物料编码):零件图纸 PDF 等
|
||||
// 物料附件(bizType=material,bizId=图号):零件图纸 PDF 等
|
||||
const attachDrawer = reactive({ visible: false, code: '', name: '' })
|
||||
function openMatAttach(row) {
|
||||
Object.assign(attachDrawer, { visible: true, code: row.code, name: row.name })
|
||||
@@ -308,7 +329,7 @@ async function onMaterialFile(e) {
|
||||
<el-form inline style="margin-bottom:14px" @submit.prevent="searchZones">
|
||||
<el-form-item label="区域编码">
|
||||
<el-input v-model="zoneFilter.zoneCode" placeholder="区域编码" clearable style="width:140px"
|
||||
@keyup.enter="searchZones" />
|
||||
@keyup.enter="searchZones" @input="zoneFilter.zoneCode = (zoneFilter.zoneCode || '').toUpperCase()" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域名称">
|
||||
<el-input v-model="zoneFilter.zoneName" placeholder="区域名称" clearable style="width:150px"
|
||||
@@ -368,7 +389,7 @@ async function onMaterialFile(e) {
|
||||
append-to-body destroy-on-close>
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="区域编码" required>
|
||||
<el-input v-model="zoneForm.zoneCode" placeholder="如 Z05" :disabled="!!zoneEditingId" clearable />
|
||||
<el-input v-model="zoneForm.zoneCode" placeholder="如 Z05" :disabled="!!zoneEditingId" clearable @input="zoneForm.zoneCode = (zoneForm.zoneCode || '').toUpperCase()" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域名称" required>
|
||||
<el-input v-model="zoneForm.zoneName" placeholder="如 待检区" clearable />
|
||||
@@ -486,8 +507,8 @@ async function onMaterialFile(e) {
|
||||
<el-dialog v-model="matDialog" :title="mEditingId ? '编辑物料' : '新增物料'" width="560px"
|
||||
append-to-body destroy-on-close>
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="物料编码/图号" required>
|
||||
<el-input v-model="mForm.code" placeholder="图号即物料编码,如 SCREW-M3" :disabled="!!mEditingId" clearable />
|
||||
<el-form-item label="图号" required>
|
||||
<el-input v-model="mForm.code" placeholder="图号,如 SCREW-M3" :disabled="!!mEditingId" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" required>
|
||||
<el-input v-model="mForm.name" placeholder="如 螺丝 M3" clearable />
|
||||
@@ -523,6 +544,7 @@ async function onMaterialFile(e) {
|
||||
<el-input v-model="mForm.description" type="textarea" :rows="2" placeholder="备注(可空)" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<AttachmentPanel v-if="mEditingId" biz-type="material" :biz-id="mForm.code" title="附件(零件图纸 / 资料)" />
|
||||
<template #footer>
|
||||
<el-button @click="matDialog = false">取消</el-button>
|
||||
<el-button type="primary" :loading="mSaving" @click="saveMaterial">保存</el-button>
|
||||
|
||||
@@ -28,6 +28,27 @@ async function loadDicts() {
|
||||
zones.value = Array.isArray(zs) ? zs : zs?.list || []
|
||||
}
|
||||
|
||||
// 库位三级联动:基于已加载的 zones(每行是完整四级货位 zoneCode+shelfNo+layerNo+positionNo)派生可选项
|
||||
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 onZoneChange(form) { form.shelfNo = ''; form.layerNo = ''; form.positionNo = '' }
|
||||
function onShelfChange(form) { form.layerNo = ''; form.positionNo = '' }
|
||||
function onLayerChange(form) { form.positionNo = '' }
|
||||
|
||||
/* ===================== Tab1 结构件入库(批次,支持多批到货追加) ===================== */
|
||||
const batchRef = ref()
|
||||
const submitting1 = ref(false)
|
||||
@@ -35,6 +56,7 @@ const lastInboundNo = ref('')
|
||||
const form1 = reactive({
|
||||
materialCode: '', batchNo: '', quantity: 1,
|
||||
zoneCode: '', shelfNo: '', layerNo: '', positionNo: '',
|
||||
ownershipType: 'none', ownershipNo: '',
|
||||
productionDate: '', supplier: '', remark: '', inspectionNo: ''
|
||||
})
|
||||
const rules1 = {
|
||||
@@ -71,6 +93,8 @@ async function submitBatch() {
|
||||
positionNo: form1.positionNo.trim(),
|
||||
productionDate: form1.productionDate,
|
||||
supplier: form1.supplier.trim(),
|
||||
ownershipType: form1.ownershipType,
|
||||
ownershipNo: form1.ownershipNo.trim(),
|
||||
remark: form1.remark.trim(),
|
||||
inspectionNo: form1.inspectionNo.trim(),
|
||||
operator
|
||||
@@ -90,7 +114,7 @@ async function submitBatch() {
|
||||
const snInput = ref('')
|
||||
const submitting2 = ref(false)
|
||||
const snList = ref([])
|
||||
const form2 = reactive({ materialCode: '', zoneCode: '', shelfNo: '', layerNo: '', positionNo: '', remark: '', inspectionNo: '' })
|
||||
const form2 = reactive({ materialCode: '', zoneCode: '', shelfNo: '', layerNo: '', positionNo: '', ownershipType: 'none', ownershipNo: '', remark: '', inspectionNo: '' })
|
||||
|
||||
// 支持多种分隔符:中英文逗号、中英文句号、分号、顿号、空格、回车、制表符等
|
||||
const SN_SEP = /[,,.。;;、\s]+/
|
||||
@@ -142,6 +166,8 @@ async function submitSn() {
|
||||
layerNo: form2.layerNo.trim(),
|
||||
positionNo: form2.positionNo.trim(),
|
||||
snList: [...snList.value],
|
||||
ownershipType: form2.ownershipType,
|
||||
ownershipNo: form2.ownershipNo.trim(),
|
||||
remark: form2.remark.trim(),
|
||||
inspectionNo: form2.inspectionNo.trim(),
|
||||
operator
|
||||
@@ -476,16 +502,22 @@ onActivated(() => {
|
||||
<el-input-number v-model="form1.quantity" :min="1" :step="1" step-strictly style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域" prop="zoneCode">
|
||||
<el-select v-model="form1.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%">
|
||||
<el-select v-model="form1.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%" @change="onZoneChange(form1)">
|
||||
<el-option v-for="z in zones" :key="z.id" :value="z.zoneCode"
|
||||
:label="`${z.zoneCode} ${z.zoneName || ''}`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架/层/位">
|
||||
<div style="display:flex;gap:6px;width:100%">
|
||||
<el-input v-model="form1.shelfNo" placeholder="货架 如A" clearable />
|
||||
<el-input v-model="form1.layerNo" placeholder="层 如3" clearable />
|
||||
<el-input v-model="form1.positionNo" placeholder="位置 如12" clearable />
|
||||
<el-form-item label="货架 / 层 / 位置">
|
||||
<div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center">
|
||||
<el-select v-model="form1.shelfNo" placeholder="货架" clearable style="width:120px" @change="onShelfChange(form1)">
|
||||
<el-option v-for="s in zoneShelves(form1.zoneCode)" :key="s" :label="s + ' 架'" :value="s" />
|
||||
</el-select>
|
||||
<el-select v-model="form1.layerNo" placeholder="层" clearable style="width:100px" :disabled="!form1.shelfNo" @change="onLayerChange(form1)">
|
||||
<el-option v-for="l in zoneLayers(form1.zoneCode, form1.shelfNo)" :key="l" :label="l + ' 层'" :value="l" />
|
||||
</el-select>
|
||||
<el-select v-model="form1.positionNo" placeholder="位置" clearable style="width:110px" :disabled="!form1.shelfNo">
|
||||
<el-option v-for="p in zonePositions(form1.zoneCode, form1.shelfNo, form1.layerNo)" :key="p" :label="p + ' 位'" :value="p" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button link type="primary" size="small" style="margin-top:2px" @click="openRecommend('form1')">推荐库位</el-button>
|
||||
</el-form-item>
|
||||
@@ -499,6 +531,17 @@ onActivated(() => {
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form1.remark" placeholder="备注(可空)" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="归属">
|
||||
<el-select v-model="form1.ownershipType" style="width:160px;margin-right:8px">
|
||||
<el-option label="无" value="none" />
|
||||
<el-option label="工单号" value="workorder" />
|
||||
<el-option label="科技项目号" value="project" />
|
||||
<el-option label="其他" value="other" />
|
||||
<el-option label="其他" value="other" />
|
||||
</el-select>
|
||||
<el-input v-if="form1.ownershipType !== 'none'" v-model="form1.ownershipNo"
|
||||
placeholder="请填写归属编号" clearable style="width:260px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检测单号" required>
|
||||
<el-input v-model="form1.inspectionNo" placeholder="入库检报告单号(必填)" clearable />
|
||||
</el-form-item>
|
||||
@@ -534,16 +577,22 @@ onActivated(() => {
|
||||
<MaterialSelect v-model="form2.materialCode" :manage-mode="2" placeholder="请选择电气件物料(必填)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域" required>
|
||||
<el-select v-model="form2.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%">
|
||||
<el-select v-model="form2.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%" @change="onZoneChange(form2)">
|
||||
<el-option v-for="z in zones" :key="z.id" :value="z.zoneCode"
|
||||
:label="`${z.zoneCode} ${z.zoneName || ''}`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架/层/位">
|
||||
<div style="display:flex;gap:6px;width:100%">
|
||||
<el-input v-model="form2.shelfNo" placeholder="货架 如A" clearable />
|
||||
<el-input v-model="form2.layerNo" placeholder="层 如3" clearable />
|
||||
<el-input v-model="form2.positionNo" placeholder="位置 如12" clearable />
|
||||
<el-form-item label="货架 / 层 / 位置">
|
||||
<div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center">
|
||||
<el-select v-model="form2.shelfNo" placeholder="货架" clearable style="width:120px" @change="onShelfChange(form2)">
|
||||
<el-option v-for="s in zoneShelves(form2.zoneCode)" :key="s" :label="s + ' 架'" :value="s" />
|
||||
</el-select>
|
||||
<el-select v-model="form2.layerNo" placeholder="层" clearable style="width:100px" :disabled="!form2.shelfNo" @change="onLayerChange(form2)">
|
||||
<el-option v-for="l in zoneLayers(form2.zoneCode, form2.shelfNo)" :key="l" :label="l + ' 层'" :value="l" />
|
||||
</el-select>
|
||||
<el-select v-model="form2.positionNo" placeholder="位置" clearable style="width:110px" :disabled="!form2.shelfNo">
|
||||
<el-option v-for="p in zonePositions(form2.zoneCode, form2.shelfNo, form2.layerNo)" :key="p" :label="p + ' 位'" :value="p" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button link type="primary" size="small" style="margin-top:2px" @click="openRecommend('form2')">推荐库位</el-button>
|
||||
</el-form-item>
|
||||
@@ -559,6 +608,17 @@ onActivated(() => {
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form2.remark" type="textarea" :rows="2" placeholder="本批 SN 的统一备注(可空)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="归属">
|
||||
<el-select v-model="form2.ownershipType" style="width:160px;margin-right:8px">
|
||||
<el-option label="无" value="none" />
|
||||
<el-option label="工单号" value="workorder" />
|
||||
<el-option label="科技项目号" value="project" />
|
||||
<el-option label="其他" value="other" />
|
||||
<el-option label="其他" value="other" />
|
||||
</el-select>
|
||||
<el-input v-if="form2.ownershipType !== 'none'" v-model="form2.ownershipNo"
|
||||
placeholder="请填写归属编号" clearable style="width:260px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检测单号" required>
|
||||
<el-input v-model="form2.inspectionNo" placeholder="入库检报告单号(必填)" clearable />
|
||||
</el-form-item>
|
||||
@@ -620,16 +680,22 @@ onActivated(() => {
|
||||
<el-input-number v-model="form3.quantity" :min="1" :step="1" step-strictly style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域" prop="zoneCode">
|
||||
<el-select v-model="form3.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%">
|
||||
<el-select v-model="form3.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%" @change="onZoneChange(form3)">
|
||||
<el-option v-for="z in zones" :key="z.id" :value="z.zoneCode"
|
||||
:label="`${z.zoneCode} ${z.zoneName || ''}`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架/层/位">
|
||||
<div style="display:flex;gap:6px;width:100%">
|
||||
<el-input v-model="form3.shelfNo" placeholder="货架 如A" clearable />
|
||||
<el-input v-model="form3.layerNo" placeholder="层 如3" clearable />
|
||||
<el-input v-model="form3.positionNo" placeholder="位置 如12" clearable />
|
||||
<el-form-item label="货架 / 层 / 位置">
|
||||
<div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center">
|
||||
<el-select v-model="form3.shelfNo" placeholder="货架" clearable style="width:120px" @change="onShelfChange(form3)">
|
||||
<el-option v-for="s in zoneShelves(form3.zoneCode)" :key="s" :label="s + ' 架'" :value="s" />
|
||||
</el-select>
|
||||
<el-select v-model="form3.layerNo" placeholder="层" clearable style="width:100px" :disabled="!form3.shelfNo" @change="onLayerChange(form3)">
|
||||
<el-option v-for="l in zoneLayers(form3.zoneCode, form3.shelfNo)" :key="l" :label="l + ' 层'" :value="l" />
|
||||
</el-select>
|
||||
<el-select v-model="form3.positionNo" placeholder="位置" clearable style="width:110px" :disabled="!form3.shelfNo">
|
||||
<el-option v-for="p in zonePositions(form3.zoneCode, form3.shelfNo, form3.layerNo)" :key="p" :label="p + ' 位'" :value="p" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button link type="primary" size="small" style="margin-top:2px" @click="openRecommend('form3')">推荐库位</el-button>
|
||||
</el-form-item>
|
||||
@@ -638,6 +704,7 @@ onActivated(() => {
|
||||
<el-option label="无" value="none" />
|
||||
<el-option label="工单号" value="workorder" />
|
||||
<el-option label="科技项目号" value="project" />
|
||||
<el-option label="其他" value="other" />
|
||||
</el-select>
|
||||
<el-input v-if="form3.ownershipType !== 'none'" v-model="form3.ownershipNo"
|
||||
placeholder="请填写归属编号" clearable style="width:260px" />
|
||||
|
||||
@@ -56,7 +56,7 @@ const inputPlaceholder = computed(() =>
|
||||
)
|
||||
|
||||
// 库存拾取器:直接选已存在的批次号/SN,避免手输。
|
||||
// 规范:库存量不确定 → 只加载最近 100 条(created_at desc),输入走远程模糊搜索(keyword 匹配 物料编码/批次号/SN)
|
||||
// 规范:库存量不确定 → 只加载最近 100 条(created_at desc),输入走远程模糊搜索(keyword 匹配 图号/批次号/SN)
|
||||
const pickerOptions = ref([])
|
||||
const pickerLoading = ref(false)
|
||||
async function loadPicker(kw = '') {
|
||||
|
||||
Reference in New Issue
Block a user