docs(test): 更新电表箱装配业务回归测试文档
- 将文档从代码审计任务转换为端到端业务回归测试链路 - 重新组织文档结构为链路总览、示例数据基线和详细步骤 - 添加完整的业务场景清单涵盖WMS/MES/工位终端三大系统 - 定义统一的测试数据包括产品型号、物料清单、工位派工等 - 提供详细的步骤断言和数量等式验证方法 - 建立贯穿全链路的数据流向和状态变更追踪体系
This commit is contained in:
@@ -54,6 +54,16 @@ function preview(row) {
|
||||
window.open(row.url, '_blank')
|
||||
}
|
||||
|
||||
// 下载:后端 /uploads/{id}?dl=1 返回 Content-Disposition: attachment,用临时 <a> 触发真实下载(绕开弹窗拦截)
|
||||
function download(row) {
|
||||
const a = document.createElement('a')
|
||||
a.href = row.url + '?dl=1'
|
||||
a.download = row.fileName || ''
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
}
|
||||
|
||||
async function remove(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确认删除附件「${row.fileName}」?`, '删除确认', { type: 'warning' })
|
||||
@@ -91,10 +101,14 @@ defineExpose({ load })
|
||||
上传附件
|
||||
</el-button>
|
||||
</el-upload>
|
||||
<span class="ap-tip">支持 PDF / 图纸 / 图片 / Office,单个不超过 20MB;点「查看」新窗口打开</span>
|
||||
<span class="ap-tip">支持 PDF / 图纸 / 图片 / Office,单个不超过 20MB;点文件名或「下载」下载,点「查看」新窗口预览</span>
|
||||
</div>
|
||||
<el-table :data="list" size="small" border v-loading="loading" empty-text="暂无附件">
|
||||
<el-table-column prop="fileName" label="文件名" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="文件名" min-width="200" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" :underline="false" @click="download(row)">{{ row.fileName }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="大小" width="100" align="center">
|
||||
<template #default="{ row }">{{ sizeText(row.fileSize) }}</template>
|
||||
</el-table-column>
|
||||
@@ -104,9 +118,10 @@ defineExpose({ load })
|
||||
<el-table-column label="上传时间" width="165" align="center">
|
||||
<template #default="{ row }">{{ fmtTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="130" align="center">
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="preview(row)">查看</el-button>
|
||||
<el-button link type="primary" size="small" @click="download(row)">下载</el-button>
|
||||
<el-button link type="danger" size="small" :disabled="disabled" @click="remove(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -70,13 +70,16 @@ function onChange(v) {
|
||||
}
|
||||
}
|
||||
|
||||
// 展开下拉即重拉最近 100 条(仅在未输入搜索词时):新建/修改物料后无需刷新页面即可选到最新数据。
|
||||
function onVisible(v) { if (v) load('') }
|
||||
|
||||
onMounted(() => load(''))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-select :model-value="modelValue" :multiple="multiple" filterable remote clearable
|
||||
:remote-method="load" :loading="loading" :placeholder="placeholder"
|
||||
:style="{ width }" @change="onChange">
|
||||
:style="{ width }" @change="onChange" @visible-change="onVisible">
|
||||
<el-option v-for="m in options" :key="m.id" :value="m.code" :label="optionLabel(m)">
|
||||
<span style="float:left">{{ m.code }} {{ m.name || '' }}</span>
|
||||
<span style="float:right;color:#8492a6;font-size:12px;margin-left:16px">
|
||||
|
||||
@@ -244,28 +244,14 @@ export const helpZone = {
|
||||
{ name: '名称(四级)', source: '手工填写(可空)。区域/货架/层/位置四级均可命名。', purpose: '本级中文名称,便于识别', fill: '区域如 合格区/待检区;位置如 A架3层12位' },
|
||||
{ name: '货架号', source: '新增货架时从「所属区域」下拉选,再填货架号。', purpose: '库位第二级,细化存放位置', fill: '如 A、B' },
|
||||
{ name: '层号', source: '新增层时从「所属区域+货架」下拉选,再填层号。', purpose: '库位第三级', fill: '如 3' },
|
||||
{ name: '位置号', source: '新增位置号时从「区域+货架+(层)」下拉选,再填位置号;层留空=该货架默认位置。', purpose: '库位第四级,最小存放单位', fill: '如 12' },
|
||||
{ name: '位置号', source: '新增位置号时从「区域+货架+层」下拉逐级选(层必选,父级不能为空),再填位置号。', purpose: '库位第四级,最小存放单位', fill: '如 12' },
|
||||
{ name: '实时库存', source: '系统实时聚合(不缓存)。', purpose: '直观看到该区域/货架/层/位置当前在库总量', fill: '只读;区域为全区域合计,逐级向下细化' },
|
||||
{ name: '状态', source: '启用/停用(新建默认启用)。', purpose: '不删除、只停用;停用后不再进入可选库位下拉', fill: '编辑弹窗切换启用/停用' },
|
||||
{ name: '批量生成', source: '位置号页签「批量生成」按钮。', purpose: '一次生成一批位置号(货架 × 层范围 × 位置范围)', fill: '选区域+货架+层范围+位置范围 → 预览 → 确认生成;已存在的自动跳过' },
|
||||
{ name: '批量生成', source: '位置号页签「批量生成」按钮。', purpose: '在选定的某个已存在层下,一次生成一批位置号(位置范围)', fill: '选区域+货架+具体层+位置范围 → 预览 → 确认生成;只生成位置号、不创建父级层,已存在的自动跳过' },
|
||||
{ name: '备注', source: '手工填写(可空),四级均可。', purpose: '补充描述', fill: '可空' }
|
||||
]
|
||||
}
|
||||
|
||||
export const helpDock = {
|
||||
title: '接驳台维护',
|
||||
overview:
|
||||
'查看全厂接驳台(AGV 取送货的物理停靠位)。接驳台是系统预置的只读主数据,本页仅供查看,不提供新增/修改/删除。\n\n三种类型:\n· 产线:位于产线工位旁,与工位一一对应(DOCK01~20 对应工位 1~20,一个工位一个接驳台);\n· 库房:库房收货/发货口(如 DOCK21),不绑定工位;\n· 其他:缓存区、暂存位等,不绑定工位。\n\n接驳台编码是产线与 AGV 任务的引用锚点;MES「关联工位」页绑定接驳台时从本页数据实时拉取。',
|
||||
fields: [
|
||||
{ name: '接驳台编码', source: '系统预置,只读。', purpose: '接驳台唯一编号,产线/AGV 任务据此定位', fill: '只读查看,如 DOCK01~DOCK21' },
|
||||
{ name: '接驳台名称', source: '系统预置,只读。', purpose: '接驳台中文名,便于识别', fill: '只读查看' },
|
||||
{ name: '类型', source: '系统预置:产线 / 库房 / 其他。', purpose: '区分接驳台所处位置与用途', fill: '只读;产线接驳台绑定工位号,库房/其他不绑定' },
|
||||
{ name: '绑定工位号', source: '仅产线类型有,与工位 1:1。', purpose: '该接驳台服务哪个工位', fill: '只读,如 3 表示 3 号工位' },
|
||||
{ name: '托盘状态', source: '系统自动维护(PLC 托盘传感器 / AGV 到位卸货)。', purpose: '看该接驳台当前是否被占用', fill: '只读,实时反映是否有托盘占用' },
|
||||
{ name: '状态', source: '系统预置:启用 / 停用。', purpose: '停用的接驳台不再参与配送与下拉选择', fill: '只读查看' }
|
||||
]
|
||||
}
|
||||
|
||||
export const helpAttachment = {
|
||||
title: '附件中心',
|
||||
overview:
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
HomeFilled, Download, Upload, Search, CircleCheck, List,
|
||||
Box, Tickets, Monitor, EditPen, Fold, Expand, Location, Goods, Key, Operation, Van, Clock, RefreshLeft, Aim, Folder
|
||||
Box, Tickets, Monitor, EditPen, Fold, Expand, Location, Goods, Key, Operation, Van, Clock, RefreshLeft, Folder
|
||||
} from '@element-plus/icons-vue'
|
||||
import { getUser, getToken, logout, setSession } from '../utils/auth'
|
||||
import request from '../utils/request'
|
||||
@@ -93,8 +93,7 @@ const menuGroups = [
|
||||
{
|
||||
title: '基础资料', icon: Goods, children: [
|
||||
{ path: '/material', title: '物料档案', icon: Goods, code: 'material:view' },
|
||||
{ path: '/zone', title: '区域维护', icon: Location, code: 'zone:view' },
|
||||
{ path: '/dock', title: '接驳台维护', icon: Aim, code: 'dock:manage' }
|
||||
{ path: '/zone', title: '区域维护', icon: Location, code: 'zone:view' }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -20,16 +20,6 @@ const props = defineProps({
|
||||
// 帮助文档按菜单各自独立
|
||||
const helpData = computed(() => (props.mode === 'material' ? helpMaterial : helpZone))
|
||||
|
||||
// 默认近3个月起始日期
|
||||
function defaultStart() {
|
||||
const d = new Date()
|
||||
d.setMonth(d.getMonth() - 3)
|
||||
const y = d.getFullYear()
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
/* ---------- 区域维护(库位四级:区域/货架/层/位置号 4 个独立 Tab) ---------- */
|
||||
const zoneLevels = [
|
||||
{ level: 1, name: '区域', codeLabel: '区域编码', nameLabel: '区域名称' },
|
||||
@@ -54,7 +44,7 @@ const regionOptions = ref([])
|
||||
const f2Shelf = ref([]); const f3Shelf = ref([]); const f3Layer = ref([])
|
||||
const f4Shelf = ref([]); const f4Layer = ref([])
|
||||
const cShelf = ref([]); const cLayer = ref([])
|
||||
const bShelf = ref([])
|
||||
const bShelf = ref([]); const bLayer = ref([])
|
||||
const lbShelf = ref([])
|
||||
|
||||
async function picker(level, params) {
|
||||
@@ -71,6 +61,9 @@ async function loadLayerOpts(target, zoneCode, shelfNo) {
|
||||
target.value = (zoneCode && shelfNo) ? await picker(3, { zoneCode, shelfNo }) : []
|
||||
}
|
||||
|
||||
// 下拉框展开即刷新上级选项(方案2):新建区域/货架后无需切页或重进菜单即可选到最新数据。
|
||||
function onDropdownOpen(visible, loader) { if (visible) loader() }
|
||||
|
||||
async function loadNodes(level) {
|
||||
const s = nodeState[level]
|
||||
s.loading = true
|
||||
@@ -97,6 +90,8 @@ async function loadNodes(level) {
|
||||
// 进入某 Tab:首次加载列表,并确保上级下拉选项就绪
|
||||
async function onZoneTabChange(level) {
|
||||
activeZoneTab.value = level
|
||||
// 切 tab 刷新区域下拉(方案1):在「区域」Tab 新建后切到货架/层/位置号,区域下拉立即是最新。
|
||||
await loadRegions()
|
||||
const f = nodeState[level].filter
|
||||
if (level >= 2 && f.zoneCode) await loadShelfOpts(level === 2 ? f2Shelf : level === 3 ? f3Shelf : f4Shelf, f.zoneCode)
|
||||
if ((level === 3 || level === 4) && f.zoneCode && f.shelfNo) {
|
||||
@@ -140,24 +135,22 @@ const nodeSaving = ref(false)
|
||||
|
||||
function openNodeCreate(level) {
|
||||
nodeEditing.value = false
|
||||
cShelf.value = []; cLayer.value = []
|
||||
Object.assign(nodeForm, { level, id: 0, code: '', name: '', remark: '', status: '启用', regionCode: '', shelfCode: '', layerCode: '' })
|
||||
nodeDialog.value = true
|
||||
}
|
||||
function openNodeEdit(row) {
|
||||
async function openNodeEdit(row) {
|
||||
nodeEditing.value = true
|
||||
const f = { level: row.level, id: row.id, code: row.code, name: row.name || row.zoneName || '', remark: row.description || '', status: row.status || '启用', regionCode: '', shelfCode: '', layerCode: '' }
|
||||
if (row.level === 2) f.regionCode = row.zoneCode
|
||||
if (row.level === 3) { f.regionCode = row.zoneCode; f.shelfCode = row.shelfNo }
|
||||
if (row.level === 4) { f.regionCode = row.zoneCode; f.shelfCode = row.shelfNo; f.layerCode = row.layerNo }
|
||||
Object.assign(nodeForm, f)
|
||||
// 编辑态必须预加载上级下拉选项:否则「所属货架 / 所属层」无选项、且当前值无法回显(用户报的编辑无下拉数据)
|
||||
if (row.level >= 3) await loadShelfOpts(cShelf, f.regionCode)
|
||||
if (row.level === 4) await loadLayerOpts(cLayer, f.regionCode, f.shelfCode)
|
||||
nodeDialog.value = true
|
||||
}
|
||||
function nodeParentCode() {
|
||||
if (nodeForm.level === 1) return ''
|
||||
if (nodeForm.level === 2) return nodeForm.regionCode
|
||||
if (nodeForm.level === 3) return nodeForm.shelfCode
|
||||
return nodeForm.layerCode || nodeForm.shelfCode
|
||||
}
|
||||
async function onNodeRegionChange() {
|
||||
nodeForm.shelfCode = ''
|
||||
nodeForm.layerCode = ''
|
||||
@@ -171,9 +164,10 @@ async function onNodeShelfChange() {
|
||||
async function saveNode() {
|
||||
if (!nodeForm.code) { ElMessage.warning('编码必填'); return }
|
||||
if (nodeForm.level === 1 && !nodeForm.name) { ElMessage.warning('区域名称必填'); return }
|
||||
if (nodeForm.level === 2 && !nodeForm.regionCode) { ElMessage.warning('请选择所属区域'); return }
|
||||
if (nodeForm.level === 3 && !nodeForm.shelfCode) { ElMessage.warning('请选择所属货架'); return }
|
||||
if (nodeForm.level === 4 && !nodeForm.shelfCode) { ElMessage.warning('请选择所属货架'); return }
|
||||
// 父级必须不能为空(逐级必选):货架必选区域;层必选区域+货架;位置号必选区域+货架+层
|
||||
if (nodeForm.level >= 2 && !nodeForm.regionCode) { ElMessage.warning('请选择所属区域'); return }
|
||||
if (nodeForm.level >= 3 && !nodeForm.shelfCode) { ElMessage.warning('请选择所属货架'); return }
|
||||
if (nodeForm.level === 4 && !nodeForm.layerCode) { ElMessage.warning('请选择所属层'); return }
|
||||
const okSave = await confirmAction(
|
||||
nodeEditing.value ? `确认保存【${nodeForm.code}】的修改?` : `确认新增【${nodeForm.code}${nodeForm.name ? ' ' + nodeForm.name : ''}】?`,
|
||||
nodeEditing.value ? '编辑确认' : '新增确认'
|
||||
@@ -187,13 +181,16 @@ async function saveNode() {
|
||||
} else {
|
||||
await request.post('/zone/node/create', {
|
||||
level: nodeForm.level, code: nodeForm.code, name: nodeForm.name,
|
||||
parentCode: nodeParentCode(), remark: nodeForm.remark
|
||||
zoneCode: nodeForm.regionCode, shelfNo: nodeForm.shelfCode, layerNo: nodeForm.layerCode,
|
||||
remark: nodeForm.remark
|
||||
})
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
nodeDialog.value = false
|
||||
zoneTabLoaded[nodeForm.level] = false
|
||||
await loadNodes(nodeForm.level)
|
||||
// 新建/修改区域后立刻刷新区域下拉,保证本页及其他 Tab 马上能选到新区域。
|
||||
if (nodeForm.level === 1) await loadRegions()
|
||||
} finally {
|
||||
nodeSaving.value = false
|
||||
}
|
||||
@@ -201,22 +198,31 @@ async function saveNode() {
|
||||
|
||||
/* ---------- 区域维护:位置号批量生成 ---------- */
|
||||
const batchDialog = ref(false)
|
||||
const batchForm = reactive({ zoneCode: '', shelfNo: '', layerStart: 1, layerEnd: 1, posStart: 1, posEnd: 1 })
|
||||
const batchForm = reactive({ zoneCode: '', shelfNo: '', layerNo: '', posStart: 1, posEnd: 1 })
|
||||
const batchPreview = ref([])
|
||||
const batchPreviewing = ref(false)
|
||||
const batchSubmitting = ref(false)
|
||||
|
||||
function openBatchGen() {
|
||||
Object.assign(batchForm, { zoneCode: '', shelfNo: '', layerStart: 1, layerEnd: 1, posStart: 1, posEnd: 1 })
|
||||
Object.assign(batchForm, { zoneCode: '', shelfNo: '', layerNo: '', posStart: 1, posEnd: 1 })
|
||||
bShelf.value = []; bLayer.value = []
|
||||
batchPreview.value = []
|
||||
batchDialog.value = true
|
||||
}
|
||||
async function onBatchRegionChange() {
|
||||
batchForm.shelfNo = ''
|
||||
batchForm.layerNo = ''
|
||||
bLayer.value = []
|
||||
await loadShelfOpts(bShelf, batchForm.zoneCode)
|
||||
}
|
||||
// 选定货架后加载该货架下已存在的层(只能选具体层,批量生成只生成位置、不创建父级层)
|
||||
async function onBatchShelfChange() {
|
||||
batchForm.layerNo = ''
|
||||
await loadLayerOpts(bLayer, batchForm.zoneCode, batchForm.shelfNo)
|
||||
}
|
||||
async function previewBatch() {
|
||||
if (!batchForm.zoneCode || !batchForm.shelfNo) { ElMessage.warning('请选择区域与货架'); return }
|
||||
if (!batchForm.layerNo) { ElMessage.warning('请选择具体的层'); return }
|
||||
batchPreviewing.value = true
|
||||
try {
|
||||
const data = await request.post('/zone/batch-generate', { ...batchForm, preview: true })
|
||||
@@ -286,7 +292,7 @@ const materials = ref([])
|
||||
const materialTotal = ref(0)
|
||||
const materialLoading = ref(false)
|
||||
const matFilter = reactive({
|
||||
materialCode: '', name: '', spec: '', manageMode: '', itemType: '', startDate: defaultStart(), endDate: ''
|
||||
materialCode: '', name: '', spec: '', manageMode: '', itemType: '', startDate: '', endDate: ''
|
||||
})
|
||||
const matPage = reactive({ current: 1, size: 10 })
|
||||
|
||||
@@ -573,7 +579,7 @@ async function onMaterialFile(e) {
|
||||
<el-tab-pane :name="2" label="货架">
|
||||
<el-form inline style="margin-bottom:14px" @submit.prevent="searchNodes(2)">
|
||||
<el-form-item label="区域">
|
||||
<el-select v-model="nodeState[2].filter.zoneCode" placeholder="全部区域" clearable filterable style="width:160px" @change="onFilterRegion(2)">
|
||||
<el-select v-model="nodeState[2].filter.zoneCode" placeholder="全部区域" clearable filterable style="width:160px" @change="onFilterRegion(2)" @visible-change="(v) => onDropdownOpen(v, loadRegions)">
|
||||
<el-option v-for="r in regionOptions" :key="r.code" :value="r.code" :label="r.code + (r.zoneName ? ' '+r.zoneName : '')" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -624,12 +630,12 @@ async function onMaterialFile(e) {
|
||||
<el-tab-pane :name="3" label="层">
|
||||
<el-form inline style="margin-bottom:14px" @submit.prevent="searchNodes(3)">
|
||||
<el-form-item label="区域">
|
||||
<el-select v-model="nodeState[3].filter.zoneCode" placeholder="全部区域" clearable filterable style="width:150px" @change="onFilterRegion(3)">
|
||||
<el-select v-model="nodeState[3].filter.zoneCode" placeholder="全部区域" clearable filterable style="width:150px" @change="onFilterRegion(3)" @visible-change="(v) => onDropdownOpen(v, loadRegions)">
|
||||
<el-option v-for="r in regionOptions" :key="r.code" :value="r.code" :label="r.code + (r.zoneName ? ' '+r.zoneName : '')" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架">
|
||||
<el-select v-model="nodeState[3].filter.shelfNo" placeholder="全部货架" clearable filterable style="width:130px" @change="onFilterShelf(3)">
|
||||
<el-select v-model="nodeState[3].filter.shelfNo" placeholder="全部货架" clearable filterable style="width:130px" @change="onFilterShelf(3)" @visible-change="(v) => onDropdownOpen(v, () => loadShelfOpts(f3Shelf, nodeState[3].filter.zoneCode))">
|
||||
<el-option v-for="s in f3Shelf" :key="s.code" :value="s.code" :label="s.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -674,17 +680,17 @@ async function onMaterialFile(e) {
|
||||
<el-tab-pane :name="4" label="位置号">
|
||||
<el-form inline style="margin-bottom:14px" @submit.prevent="searchNodes(4)">
|
||||
<el-form-item label="区域">
|
||||
<el-select v-model="nodeState[4].filter.zoneCode" placeholder="全部区域" clearable filterable style="width:150px" @change="onFilterRegion(4)">
|
||||
<el-select v-model="nodeState[4].filter.zoneCode" placeholder="全部区域" clearable filterable style="width:150px" @change="onFilterRegion(4)" @visible-change="(v) => onDropdownOpen(v, loadRegions)">
|
||||
<el-option v-for="r in regionOptions" :key="r.code" :value="r.code" :label="r.code + (r.zoneName ? ' '+r.zoneName : '')" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架">
|
||||
<el-select v-model="nodeState[4].filter.shelfNo" placeholder="全部货架" clearable filterable style="width:130px" @change="onFilterShelf(4)">
|
||||
<el-select v-model="nodeState[4].filter.shelfNo" placeholder="全部货架" clearable filterable style="width:130px" @change="onFilterShelf(4)" @visible-change="(v) => onDropdownOpen(v, () => loadShelfOpts(f4Shelf, nodeState[4].filter.zoneCode))">
|
||||
<el-option v-for="s in f4Shelf" :key="s.code" :value="s.code" :label="s.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="层">
|
||||
<el-select v-model="nodeState[4].filter.layerNo" placeholder="全部层" clearable filterable style="width:110px" @change="searchNodes(4)">
|
||||
<el-select v-model="nodeState[4].filter.layerNo" placeholder="全部层" clearable filterable style="width:110px" @change="searchNodes(4)" @visible-change="(v) => onDropdownOpen(v, () => loadLayerOpts(f4Layer, nodeState[4].filter.zoneCode, nodeState[4].filter.shelfNo))">
|
||||
<el-option v-for="l in f4Layer" :key="l.code" :value="l.code" :label="'层 '+l.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -730,25 +736,24 @@ async function onMaterialFile(e) {
|
||||
<!-- 新增/编辑节点弹窗 -->
|
||||
<el-dialog v-model="nodeDialog" :title="(nodeEditing ? '编辑' : '新增') + (zoneLevels.find(z=>z.level===nodeForm.level)?.name || '')" width="560px" append-to-body destroy-on-close>
|
||||
<el-form label-width="90px">
|
||||
<el-form-item :label="zoneLevels.find(z=>z.level===nodeForm.level)?.codeLabel" required>
|
||||
<el-input v-model="nodeForm.code" :placeholder="zoneLevels.find(z=>z.level===nodeForm.level)?.codeLabel" :disabled="nodeEditing && nodeForm.level===1" clearable
|
||||
@input="nodeForm.code = (nodeForm.code || '').toUpperCase()" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="nodeForm.level === 2 || nodeForm.level === 3 || nodeForm.level === 4" label="所属区域" required>
|
||||
<el-select v-model="nodeForm.regionCode" placeholder="请选择区域" filterable style="width:100%" @change="onNodeRegionChange">
|
||||
<el-select v-model="nodeForm.regionCode" placeholder="请选择区域" filterable style="width:100%" @change="onNodeRegionChange" @visible-change="(v) => onDropdownOpen(v, loadRegions)">
|
||||
<el-option v-for="r in regionOptions" :key="r.code" :value="r.code" :label="r.code + (r.zoneName ? ' '+r.zoneName : '')" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="nodeForm.level === 3 || nodeForm.level === 4" label="所属货架" required>
|
||||
<el-select v-model="nodeForm.shelfCode" placeholder="请选择货架" filterable :disabled="!nodeForm.regionCode" style="width:100%" @change="onNodeShelfChange">
|
||||
<el-select v-model="nodeForm.shelfCode" placeholder="请选择货架" filterable :disabled="!nodeForm.regionCode" style="width:100%" @change="onNodeShelfChange" @visible-change="(v) => onDropdownOpen(v, () => loadShelfOpts(cShelf, nodeForm.regionCode))">
|
||||
<el-option v-for="s in cShelf" :key="s.code" :value="s.code" :label="s.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="nodeForm.level === 4" label="所属层">
|
||||
<el-select v-model="nodeForm.layerCode" placeholder="选填(留空=货架默认位置)" filterable :disabled="!nodeForm.shelfCode" style="width:100%">
|
||||
<el-form-item v-if="nodeForm.level === 4" label="所属层" required>
|
||||
<el-select v-model="nodeForm.layerCode" placeholder="请选择层" filterable :disabled="!nodeForm.shelfCode" style="width:100%" @visible-change="(v) => onDropdownOpen(v, () => loadLayerOpts(cLayer, nodeForm.regionCode, nodeForm.shelfCode))">
|
||||
<el-option v-for="l in cLayer" :key="l.code" :value="l.code" :label="'层 '+l.code" />
|
||||
</el-select>
|
||||
<div style="color:#909399;font-size:12px;margin-top:4px">留空则作为该货架的默认位置(无层)</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="zoneLevels.find(z=>z.level===nodeForm.level)?.codeLabel" required>
|
||||
<el-input v-model="nodeForm.code" :placeholder="zoneLevels.find(z=>z.level===nodeForm.level)?.codeLabel" :disabled="nodeEditing && nodeForm.level===1" clearable
|
||||
@input="nodeForm.code = (nodeForm.code || '').toUpperCase()" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="zoneLevels.find(z=>z.level===nodeForm.level)?.nameLabel">
|
||||
<el-input v-model="nodeForm.name" :placeholder="(zoneLevels.find(z=>z.level===nodeForm.level)?.nameLabel || '') + '(可空)'" clearable />
|
||||
@@ -773,19 +778,20 @@ async function onMaterialFile(e) {
|
||||
<el-dialog v-model="batchDialog" title="批量生成位置号" width="720px" append-to-body destroy-on-close>
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="区域" required>
|
||||
<el-select v-model="batchForm.zoneCode" placeholder="请选择区域" filterable style="width:100%" @change="onBatchRegionChange">
|
||||
<el-select v-model="batchForm.zoneCode" placeholder="请选择区域" filterable style="width:100%" @change="onBatchRegionChange" @visible-change="(v) => onDropdownOpen(v, loadRegions)">
|
||||
<el-option v-for="r in regionOptions" :key="r.code" :value="r.code" :label="r.code + (r.zoneName ? ' '+r.zoneName : '')" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架" required>
|
||||
<el-select v-model="batchForm.shelfNo" placeholder="请选择货架" filterable :disabled="!batchForm.zoneCode" style="width:100%">
|
||||
<el-select v-model="batchForm.shelfNo" placeholder="请选择货架" filterable :disabled="!batchForm.zoneCode" style="width:100%" @change="onBatchShelfChange" @visible-change="(v) => onDropdownOpen(v, () => loadShelfOpts(bShelf, batchForm.zoneCode))">
|
||||
<el-option v-for="s in bShelf" :key="s.code" :value="s.code" :label="s.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="层范围">
|
||||
<el-input-number v-model="batchForm.layerStart" :min="0" :step="1" step-strictly controls-position="right" style="width:120px" />
|
||||
<span style="margin:0 8px">至</span>
|
||||
<el-input-number v-model="batchForm.layerEnd" :min="0" :step="1" step-strictly controls-position="right" style="width:120px" />
|
||||
<el-form-item label="层" required>
|
||||
<el-select v-model="batchForm.layerNo" placeholder="请选择具体的层" filterable :disabled="!batchForm.shelfNo" style="width:100%" @visible-change="(v) => onDropdownOpen(v, () => loadLayerOpts(bLayer, batchForm.zoneCode, batchForm.shelfNo))">
|
||||
<el-option v-for="l in bLayer" :key="l.code" :value="l.code" :label="'层 '+l.code" />
|
||||
</el-select>
|
||||
<div style="color:#909399;font-size:12px;margin-top:4px">只能选择已存在的层;批量生成只在该层下生成位置号,不会创建父级层。</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="位置范围">
|
||||
<el-input-number v-model="batchForm.posStart" :min="0" :step="1" step-strictly controls-position="right" style="width:120px" />
|
||||
@@ -814,12 +820,12 @@ async function onMaterialFile(e) {
|
||||
<el-dialog v-model="layerBatchDialog" title="批量生成层" width="640px" append-to-body destroy-on-close>
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="区域" required>
|
||||
<el-select v-model="layerBatchForm.zoneCode" placeholder="请选择区域" filterable style="width:100%" @change="onLayerBatchRegionChange">
|
||||
<el-select v-model="layerBatchForm.zoneCode" placeholder="请选择区域" filterable style="width:100%" @change="onLayerBatchRegionChange" @visible-change="(v) => onDropdownOpen(v, loadRegions)">
|
||||
<el-option v-for="r in regionOptions" :key="r.code" :value="r.code" :label="r.code + (r.zoneName ? ' '+r.zoneName : '')" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架" required>
|
||||
<el-select v-model="layerBatchForm.shelfNo" placeholder="请选择货架" filterable :disabled="!layerBatchForm.zoneCode" style="width:100%">
|
||||
<el-select v-model="layerBatchForm.shelfNo" placeholder="请选择货架" filterable :disabled="!layerBatchForm.zoneCode" style="width:100%" @visible-change="(v) => onDropdownOpen(v, () => loadShelfOpts(lbShelf, layerBatchForm.zoneCode))">
|
||||
<el-option v-for="s in lbShelf" :key="s.code" :value="s.code" :label="s.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -887,7 +893,7 @@ async function onMaterialFile(e) {
|
||||
<el-button v-if="can('material:create')" type="success" @click="openMatCreate">新增物料</el-button>
|
||||
<el-button v-if="can('material:import')" type="warning" :loading="matImporting" @click="pickMaterialFile">导入</el-button>
|
||||
<el-button v-if="can('material:export')" :loading="matExporting" @click="exportMaterials">导出</el-button>
|
||||
<el-tooltip v-if="can('material:import')" content="Excel 模板(首行表头):图号 | 名称 | 规格 | 单位 | 类型(结构件/电气件) | 说明(除「说明」外均为必填)">
|
||||
<el-tooltip v-if="can('material:import')" content="Excel 首行表头按名称识别(列顺序可变、可含多余列):图号 | 名称 | 规格 | 单位 | 类型(结构件/电气件) | 品类(原材料/半成品/成品/其他,可选) | 说明(除「说明」「品类」外均为必填)">
|
||||
<el-link type="info" :underline="false" style="margin-left:4px">导入说明</el-link>
|
||||
</el-tooltip>
|
||||
<input ref="matFileRef" type="file" accept=".xlsx,.xls" style="display:none" @change="onMaterialFile" />
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
<template>
|
||||
<div class="dock-page">
|
||||
<el-card shadow="never">
|
||||
<el-alert type="info" :closable="false" show-icon style="margin-bottom:12px"
|
||||
title="接驳台是产线与库房之间供 AGV 取送货的物理停靠位,为系统预置的只读主数据,本页仅供查看。类型分 产线 / 库房 / 其他:产线接驳台与工位一一对应(DOCK01~20 对应工位 1~20),库房接驳台为收货/发货口(DOCK21),其他为缓存/暂存位;只有产线接驳台绑定工位号。" />
|
||||
|
||||
<!-- 列表页禁止关键字混搜:编码精确、名称模糊、类型/状态各自独立下拉(需求5、N) -->
|
||||
<el-form inline :model="filter">
|
||||
<el-form-item label="接驳台编码">
|
||||
<el-input v-model="filter.dockCode" clearable style="width:160px" placeholder="精确匹配,如 DOCK01" @keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item label="接驳台名称">
|
||||
<el-input v-model="filter.name" clearable style="width:180px" placeholder="名称模糊匹配" @keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-select v-model="filter.dockType" clearable style="width:120px" placeholder="全部">
|
||||
<el-option label="产线" value="line" />
|
||||
<el-option label="库房" value="store" />
|
||||
<el-option label="其他" value="other" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="filter.status" style="width:110px" placeholder="全部">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="启用" value="ENABLED" />
|
||||
<el-option label="停用" value="DISABLED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="search">查询</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table :data="list" border size="small" v-loading="loading">
|
||||
<el-table-column prop="dockCode" label="接驳台编码" width="140" />
|
||||
<el-table-column prop="name" label="接驳台名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="类型" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" :type="tagType(row.dockType)">{{ typeLabel(row.dockType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="绑定工位" width="110" align="center">
|
||||
<template #default="{ row }">{{ row.stationNo > 0 ? '工位' + row.stationNo : '—' }}</template>
|
||||
</el-table-column>
|
||||
<!-- 占用状态:现场调度参考(空闲 / 有托盘) -->
|
||||
<el-table-column label="占用状态" width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" :type="row.hasPallet ? 'warning' : 'info'">{{ row.hasPallet ? '有托盘' : '空闲' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="palletRef" label="托盘关联" min-width="160" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.palletRef || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="启用状态" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" :type="row.status === 'ENABLED' ? 'success' : 'info'">
|
||||
{{ row.status === 'ENABLED' ? '启用' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" width="170">
|
||||
<template #default="{ row }">{{ fmtTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="暂无接驳台数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<el-pagination v-model:current-page="page.current" v-model:page-size="page.size" :page-sizes="[20, 50, 100]"
|
||||
:total="total" background layout="total, sizes, prev, pager, next, jumper" style="margin-top:12px"
|
||||
@size-change="search" @current-change="load" />
|
||||
</el-card>
|
||||
</div>
|
||||
<PageHelp :data="helpDock" page="Dock" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineOptions({ name: 'Dock' })
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import request from '../utils/request'
|
||||
import { fmtTime } from '../utils/format'
|
||||
import PageHelp from '../components/PageHelp.vue'
|
||||
import { helpDock } from '../help'
|
||||
|
||||
const list = ref([])
|
||||
const total = ref(0)
|
||||
const loading = ref(false)
|
||||
const page = reactive({ current: 1, size: 20 })
|
||||
// 默认只看启用;停用需主动选择(需求7 一致的默认口径)
|
||||
const filter = reactive({ dockCode: '', name: '', dockType: '', status: 'ENABLED' })
|
||||
|
||||
const TYPE_LABEL = { line: '产线', store: '库房', other: '其他' }
|
||||
function typeLabel(t) { return TYPE_LABEL[t] || '其他' }
|
||||
function tagType(t) { return t === 'line' ? 'success' : (t === 'store' ? 'warning' : 'info') }
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = { page: page.current, pageSize: page.size }
|
||||
if (filter.dockCode.trim()) params.dockCode = filter.dockCode.trim()
|
||||
if (filter.name.trim()) params.name = filter.name.trim()
|
||||
if (filter.dockType) params.dockType = filter.dockType
|
||||
if (filter.status) params.status = filter.status
|
||||
const data = await request.get('/docks', { params })
|
||||
list.value = data?.list || []
|
||||
total.value = data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function search() {
|
||||
page.current = 1
|
||||
load()
|
||||
}
|
||||
function reset() {
|
||||
filter.dockCode = ''
|
||||
filter.name = ''
|
||||
filter.dockType = ''
|
||||
filter.status = 'ENABLED'
|
||||
search()
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
</script>
|
||||
@@ -617,12 +617,12 @@ 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%" @change="onZoneChange(form1)">
|
||||
<el-select v-model="form1.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%" @change="onZoneChange(form1)" @visible-change="(v) => v && loadDicts(true)">
|
||||
<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="货架 / 层 / 位置">
|
||||
<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" />
|
||||
@@ -705,12 +705,12 @@ onActivated(() => {
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域" prop="zoneCode">
|
||||
<el-select v-model="form2.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%" @change="onZoneChange(form2)">
|
||||
<el-select v-model="form2.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%" @change="onZoneChange(form2)" @visible-change="(v) => v && loadDicts(true)">
|
||||
<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="货架 / 层 / 位置">
|
||||
<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" />
|
||||
@@ -822,12 +822,12 @@ 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%" @change="onZoneChange(form3)">
|
||||
<el-select v-model="form3.zoneCode" placeholder="请选择入库区域(必填)" clearable style="width:100%" @change="onZoneChange(form3)" @visible-change="(v) => v && loadDicts(true)">
|
||||
<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="货架 / 层 / 位置">
|
||||
<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" />
|
||||
|
||||
@@ -318,7 +318,7 @@ onMounted(() => {
|
||||
</el-form-item>
|
||||
<template v-if="viewTab === 'detail'">
|
||||
<el-form-item label="区域">
|
||||
<el-select v-model="filters.zoneCode" placeholder="全部区域" clearable style="width:140px" @change="search">
|
||||
<el-select v-model="filters.zoneCode" placeholder="全部区域" clearable style="width:140px" @change="search" @visible-change="(v) => v && loadZones()">
|
||||
<el-option v-for="z in zoneOptions" :key="z.zoneCode" :label="z.zoneName" :value="z.zoneCode" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
@@ -158,6 +158,10 @@ async function loadDicts() {
|
||||
loadStations()
|
||||
if (zones.value.length) return
|
||||
// 物料下拉由 MaterialSelect 组件按需远程搜索(最近 100 条),此处只加载区域
|
||||
await reloadZones()
|
||||
}
|
||||
// 区域字典强刷:区域维护新建/编辑后,出库页区域下拉展开即重拉,避免看不到最新货位
|
||||
async function reloadZones() {
|
||||
const zs = await request.get('/zone/picker')
|
||||
zones.value = Array.isArray(zs) ? zs : zs?.list || []
|
||||
}
|
||||
@@ -533,11 +537,11 @@ onMounted(loadDicts)
|
||||
</template>
|
||||
|
||||
<el-form-item label="区域">
|
||||
<el-select v-model="genForm.zoneCode" filterable clearable placeholder="选择区域(选物料/批次后自动带出最近库位)" style="width:100%" @change="onGenZoneChange">
|
||||
<el-select v-model="genForm.zoneCode" filterable clearable placeholder="选择区域(选物料/批次后自动带出最近库位)" style="width:100%" @change="onGenZoneChange" @visible-change="(v) => v && reloadZones()">
|
||||
<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="货架 / 层 / 位置">
|
||||
<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" />
|
||||
|
||||
@@ -40,8 +40,9 @@ function search() {
|
||||
|
||||
/* ===================== 库位四级联动(与入库一致,数据来自 /zone/picker) ===================== */
|
||||
const zones = ref([])
|
||||
async function loadZones() {
|
||||
if (zones.value.length) return
|
||||
// force=true 强制重拉:区域维护新建后,退回区域下拉展开/弹窗打开即可见最新货位
|
||||
async function loadZones(force = false) {
|
||||
if (!force && zones.value.length) return
|
||||
const zs = await request.get('/zone/picker')
|
||||
zones.value = Array.isArray(zs) ? zs : zs?.list || []
|
||||
}
|
||||
@@ -91,7 +92,7 @@ async function openConfirm(row) {
|
||||
dlg.snInput = ''
|
||||
dlg.zoneCode = ''; dlg.shelfNo = ''; dlg.layerNo = ''; dlg.positionNo = ''
|
||||
dlg.manageMode = 1
|
||||
await loadZones()
|
||||
await loadZones(true)
|
||||
// 预填:管理粒度 + 原库位建议(库管可手动改)
|
||||
try {
|
||||
const s = await request.get('/return-order/suggest-location', { params: { materialCode: row.materialCode } })
|
||||
@@ -254,12 +255,12 @@ onMounted(load)
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="退回区域">
|
||||
<el-select v-model="dlg.zoneCode" placeholder="请选择退回区域" clearable style="width:100%" @change="onZoneChange">
|
||||
<el-select v-model="dlg.zoneCode" placeholder="请选择退回区域" clearable style="width:100%" @change="onZoneChange" @visible-change="(v) => v && loadZones(true)">
|
||||
<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="货架 / 层 / 位置">
|
||||
<el-form-item label="库位">
|
||||
<div style="display:flex;gap:6px;flex-wrap:wrap">
|
||||
<el-select v-model="dlg.shelfNo" placeholder="货架" clearable style="width:120px" @change="onShelfChange">
|
||||
<el-option v-for="s in zoneShelves(dlg.zoneCode)" :key="s" :label="s + ' 架'" :value="s" />
|
||||
|
||||
@@ -23,7 +23,6 @@ const routes = [
|
||||
{ path: 'agv', name: 'Agv', component: () => import('../pages/Agv.vue'), meta: { title: 'AGV配送', keepAlive: true, componentName: 'Agv' } },
|
||||
{ path: 'zone', name: 'Zone', component: () => import('../pages/BaseData.vue'), props: { mode: 'zone' }, meta: { title: '区域维护', keepAlive: true, componentName: 'BaseData' } },
|
||||
{ path: 'material', name: 'Material', component: () => import('../pages/BaseData.vue'), props: { mode: 'material' }, meta: { title: '物料档案', keepAlive: true, componentName: 'BaseData' } },
|
||||
{ path: 'dock', name: 'Dock', component: () => import('../pages/Dock.vue'), meta: { title: '接驳台维护', keepAlive: true, componentName: 'Dock' } },
|
||||
{ path: 'change-password', name: 'ChangePassword', component: () => import('../pages/ChangePassword.vue'), meta: { title: '修改密码' } },
|
||||
{ path: 'users', name: 'UserManage', component: () => import('../pages/UserManage.vue'), meta: { title: '账号管理', keepAlive: true, componentName: 'UserManage' } },
|
||||
{ path: 'roles', name: 'RoleManage', component: () => import('../pages/RoleManage.vue'), meta: { title: '角色管理', keepAlive: true, componentName: 'RoleManage' } },
|
||||
|
||||
Reference in New Issue
Block a user