feat:多项功能优化
This commit is contained in:
@@ -40,15 +40,34 @@ const zoneFilter = reactive({
|
||||
const zonePage = reactive({ current: 1, size: 10 })
|
||||
|
||||
const zoneDialog = ref(false)
|
||||
const zoneEditingId = ref(0)
|
||||
// 区域维护按「区域编码」分组:编辑键是 zoneCode(不是单行 id),一个区域可挂多个货位
|
||||
const zoneEditingCode = ref('')
|
||||
// 区域库位:区域 → 货架号 → 第几层 → 位置号(客户诉求 问题记录 L32/L169,手填)
|
||||
const zoneForm = reactive({ zoneCode: '', zoneName: '', description: '', shelfNo: '', layerNo: '', positionNo: '' })
|
||||
// 一个区域下可有多个货位,故 locations 为数组;新增时默认给一行
|
||||
const zoneForm = reactive({ zoneCode: '', zoneName: '', description: '', status: '启用', locations: [] })
|
||||
const zoneSaving = ref(false)
|
||||
|
||||
// 批量生成货位(货架号 × 层区间 × 位置区间),解决「一个货架不止一层、每层不止一个位置号」的逐条录入
|
||||
const genForm = reactive({ shelfNo: '', layerFrom: 1, layerTo: 1, posFrom: 1, posTo: 1 })
|
||||
|
||||
function newZoneLocation() {
|
||||
return { id: 0, shelfNo: '', layerNo: '', positionNo: '' }
|
||||
}
|
||||
|
||||
// 货位标签(区域-货架-层-位置),仅用于分组子表展示,口径与后端 locLabel 一致
|
||||
function zoneLocLabel(zoneCode, loc) {
|
||||
const parts = []
|
||||
if (zoneCode) parts.push(zoneCode)
|
||||
if (loc.shelfNo) parts.push(loc.shelfNo + '架')
|
||||
if (loc.layerNo) parts.push(loc.layerNo + '层')
|
||||
if (loc.positionNo) parts.push(loc.positionNo + '位')
|
||||
return parts.length ? parts.join('-') : '(未填写货位)'
|
||||
}
|
||||
|
||||
async function loadZones() {
|
||||
zoneLoading.value = true
|
||||
try {
|
||||
const data = await request.get('/zone/list', {
|
||||
const data = await request.get('/zone/grouped', {
|
||||
params: {
|
||||
zoneCode: zoneFilter.zoneCode.trim().toUpperCase(),
|
||||
zoneName: zoneFilter.zoneName.trim(),
|
||||
@@ -70,25 +89,75 @@ function searchZones() {
|
||||
}
|
||||
|
||||
function openZoneCreate() {
|
||||
zoneEditingId.value = 0
|
||||
Object.assign(zoneForm, { zoneCode: '', zoneName: '', description: '', shelfNo: '', layerNo: '', positionNo: '' })
|
||||
zoneEditingCode.value = ''
|
||||
Object.assign(zoneForm, {
|
||||
zoneCode: '', zoneName: '', description: '', status: '启用',
|
||||
locations: [newZoneLocation()]
|
||||
})
|
||||
Object.assign(genForm, { shelfNo: '', layerFrom: 1, layerTo: 1, posFrom: 1, posTo: 1 })
|
||||
zoneDialog.value = true
|
||||
}
|
||||
|
||||
function openZoneEdit(row) {
|
||||
zoneEditingId.value = row.id
|
||||
zoneEditingCode.value = row.zoneCode
|
||||
Object.assign(zoneForm, {
|
||||
zoneCode: row.zoneCode, zoneName: row.zoneName, description: row.description || '',
|
||||
shelfNo: row.shelfNo || '', layerNo: row.layerNo || '', positionNo: row.positionNo || ''
|
||||
zoneCode: row.zoneCode,
|
||||
zoneName: row.zoneName,
|
||||
description: row.description || '',
|
||||
status: row.status || '启用',
|
||||
locations: (row.locations || []).map((l) => ({
|
||||
id: l.id, shelfNo: l.shelfNo || '', layerNo: l.layerNo || '', positionNo: l.positionNo || ''
|
||||
}))
|
||||
})
|
||||
if (!zoneForm.locations.length) zoneForm.locations.push(newZoneLocation())
|
||||
Object.assign(genForm, { shelfNo: '', layerFrom: 1, layerTo: 1, posFrom: 1, posTo: 1 })
|
||||
zoneDialog.value = true
|
||||
}
|
||||
|
||||
function addZoneLocation() {
|
||||
zoneForm.locations.push(newZoneLocation())
|
||||
}
|
||||
|
||||
function removeZoneLocation(idx) {
|
||||
if (zoneForm.locations.length <= 1) {
|
||||
ElMessage.warning('至少保留一个货位')
|
||||
return
|
||||
}
|
||||
zoneForm.locations.splice(idx, 1)
|
||||
}
|
||||
|
||||
// 按 货架号 × [层区间] × [位置区间] 笛卡尔积批量追加货位行
|
||||
function genZoneLocations() {
|
||||
const shelf = (genForm.shelfNo || '').trim()
|
||||
const lf = Number(genForm.layerFrom), lt = Number(genForm.layerTo)
|
||||
const pf = Number(genForm.posFrom), pt = Number(genForm.posTo)
|
||||
if (!Number.isInteger(lf) || !Number.isInteger(lt) || !Number.isInteger(pf) || !Number.isInteger(pt) ||
|
||||
lf < 0 || lt < lf || pf < 0 || pt < pf) {
|
||||
ElMessage.warning('层/位置的起止值不合法(起始需 ≤ 结束)')
|
||||
return
|
||||
}
|
||||
const count = (lt - lf + 1) * (pt - pf + 1)
|
||||
if (count > 200) {
|
||||
ElMessage.warning('一次最多生成 200 个货位,请缩小范围')
|
||||
return
|
||||
}
|
||||
for (let l = lf; l <= lt; l++) {
|
||||
for (let p = pf; p <= pt; p++) {
|
||||
zoneForm.locations.push({ id: 0, shelfNo: shelf, layerNo: String(l), positionNo: String(p) })
|
||||
}
|
||||
}
|
||||
ElMessage.success(`已生成 ${count} 个货位行,可再手动微调`)
|
||||
}
|
||||
|
||||
async function saveZone() {
|
||||
if (!zoneForm.zoneCode || !zoneForm.zoneName) {
|
||||
ElMessage.warning('区域编码和区域名称必填')
|
||||
return
|
||||
}
|
||||
if (!zoneForm.locations.length) {
|
||||
ElMessage.warning('至少填写一个货位')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm('确认保存该区域信息吗?保存后将写入数据库。', '操作确认', {
|
||||
confirmButtonText: '确认保存',
|
||||
@@ -100,11 +169,23 @@ async function saveZone() {
|
||||
}
|
||||
zoneSaving.value = true
|
||||
try {
|
||||
if (zoneEditingId.value) {
|
||||
await request.post('/zone/update', { id: zoneEditingId.value, ...zoneForm })
|
||||
const payload = {
|
||||
zoneCode: zoneForm.zoneCode,
|
||||
zoneName: zoneForm.zoneName,
|
||||
description: zoneForm.description,
|
||||
status: zoneForm.status,
|
||||
locations: zoneForm.locations.map((l) => ({
|
||||
id: l.id || 0,
|
||||
shelfNo: (l.shelfNo || '').trim(),
|
||||
layerNo: (l.layerNo || '').trim(),
|
||||
positionNo: (l.positionNo || '').trim()
|
||||
}))
|
||||
}
|
||||
if (zoneEditingCode.value) {
|
||||
await request.post('/zone/update', payload)
|
||||
ElMessage.success('区域修改成功')
|
||||
} else {
|
||||
await request.post('/zone/create', { ...zoneForm })
|
||||
await request.post('/zone/create', payload)
|
||||
ElMessage.success('区域新增成功')
|
||||
}
|
||||
zoneDialog.value = false
|
||||
@@ -346,18 +427,36 @@ async function onMaterialFile(e) {
|
||||
<el-button type="success" @click="openZoneCreate">新增区域</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="zones" border size="small" v-loading="zoneLoading" empty-text="暂无区域,请点击【新增区域】">
|
||||
<el-table-column label="ID" prop="id" width="60" align="center" />
|
||||
<el-table :data="zones" border size="small" v-loading="zoneLoading" row-key="zoneCode"
|
||||
empty-text="暂无区域,请点击【新增区域】">
|
||||
<!-- 分组展示:一个区域一行,展开后是该区域下的货位明细(不再重复区域编码/名称) -->
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<div style="padding:4px 16px 10px">
|
||||
<el-table :data="row.locations" border size="small" empty-text="该区域暂无货位">
|
||||
<el-table-column label="序号" type="index" width="60" align="center" />
|
||||
<el-table-column label="货架号" width="120" align="center">
|
||||
<template #default="{ row: loc }">{{ loc.shelfNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="第几层" width="100" align="center">
|
||||
<template #default="{ row: loc }">{{ loc.layerNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="位置号" width="110" align="center">
|
||||
<template #default="{ row: loc }">{{ loc.positionNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="货位标签" min-width="180">
|
||||
<template #default="{ row: loc }">{{ zoneLocLabel(row.zoneCode, loc) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zoneCode" label="区域编码" min-width="120" />
|
||||
<el-table-column prop="zoneName" label="区域名称" min-width="150" />
|
||||
<el-table-column prop="shelfNo" label="货架号" width="90" align="center">
|
||||
<template #default="{ row }">{{ row.shelfNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="layerNo" label="层" width="70" align="center">
|
||||
<template #default="{ row }">{{ row.layerNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="positionNo" label="位置号" width="90" align="center">
|
||||
<template #default="{ row }">{{ row.positionNo || '-' }}</template>
|
||||
<el-table-column label="货位数" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" type="info">{{ row.locationCount || 0 }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
@@ -385,27 +484,74 @@ async function onMaterialFile(e) {
|
||||
@size-change="(s) => { zonePage.size = s; zonePage.current = 1; loadZones() }" />
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="zoneDialog" :title="zoneEditingId ? '编辑区域' : '新增区域'" width="460px"
|
||||
<el-dialog v-model="zoneDialog" :title="zoneEditingCode ? '编辑区域' : '新增区域'" width="740px"
|
||||
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 @input="zoneForm.zoneCode = (zoneForm.zoneCode || '').toUpperCase()" />
|
||||
<el-input v-model="zoneForm.zoneCode" placeholder="如 Z05" :disabled="!!zoneEditingCode" clearable
|
||||
@input="zoneForm.zoneCode = (zoneForm.zoneCode || '').toUpperCase()" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域名称" required>
|
||||
<el-input v-model="zoneForm.zoneName" placeholder="如 待检区" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="货架号">
|
||||
<el-input v-model="zoneForm.shelfNo" placeholder="如 A / 03(可空,手填)" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="第几层">
|
||||
<el-input v-model="zoneForm.layerNo" placeholder="如 3(可空,手填)" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="位置号">
|
||||
<el-input v-model="zoneForm.positionNo" placeholder="如 12(可空,手填)" clearable />
|
||||
<el-form-item v-if="zoneEditingCode" label="状态">
|
||||
<el-select v-model="zoneForm.status" style="width:130px">
|
||||
<el-option label="启用" value="启用" />
|
||||
<el-option label="停用" value="停用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="zoneForm.description" type="textarea" :rows="2" placeholder="备注(可空)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="货位">
|
||||
<div style="width:100%">
|
||||
<el-table :data="zoneForm.locations" border size="small" max-height="240">
|
||||
<el-table-column label="货架号" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.shelfNo" placeholder="如 A" size="small" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="第几层" width="140">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.layerNo" placeholder="如 3" size="small" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="位置号" width="140">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.positionNo" placeholder="如 12" size="small" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
<template #default="{ $index }">
|
||||
<el-button link type="danger" size="small" @click="removeZoneLocation($index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="margin-top:8px">
|
||||
<el-button size="small" @click="addZoneLocation">添加一行</el-button>
|
||||
</div>
|
||||
<el-divider content-position="left" style="margin:12px 0" />
|
||||
<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap">
|
||||
<el-input v-model="genForm.shelfNo" placeholder="货架号" size="small" style="width:90px" clearable />
|
||||
<span style="font-size:12px;color:#606266">层</span>
|
||||
<el-input-number v-model="genForm.layerFrom" :min="0" :step="1" step-strictly size="small"
|
||||
controls-position="right" style="width:92px" />
|
||||
<span style="font-size:12px;color:#606266">至</span>
|
||||
<el-input-number v-model="genForm.layerTo" :min="0" :step="1" step-strictly size="small"
|
||||
controls-position="right" style="width:92px" />
|
||||
<span style="font-size:12px;color:#606266">位置</span>
|
||||
<el-input-number v-model="genForm.posFrom" :min="0" :step="1" step-strictly size="small"
|
||||
controls-position="right" style="width:92px" />
|
||||
<span style="font-size:12px;color:#606266">至</span>
|
||||
<el-input-number v-model="genForm.posTo" :min="0" :step="1" step-strictly size="small"
|
||||
controls-position="right" style="width:92px" />
|
||||
<el-button size="small" type="primary" plain @click="genZoneLocations">生成货位</el-button>
|
||||
</div>
|
||||
<div style="color:#909399;font-size:12px;margin-top:6px">
|
||||
例:货架号 A、层 1 至 3、位置 1 至 4 → 一次生成 12 个货位(A架1层1位 … A架3层4位)
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="zoneDialog = false">取消</el-button>
|
||||
|
||||
Reference in New Issue
Block a user