docs(deployment): 更新部署手册和业务架构说明
- 更新MES和WMS服务端口配置说明 - 详细说明产线工位设备配置(扫码枪+拧紧枪) - 明确AGV配送和接驳台的模拟模式与真实对接方案 - 更新WMS中AGV配送默认模拟模式说明 - 完善厂内物流(AGV/接驳台)的业务架构约束 - 修订临时文档为详细的项目问题和解决方案规划
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
<script setup>
|
||||
defineOptions({ name: 'BaseData' })
|
||||
import { computed, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import request from '../utils/request'
|
||||
import { fmtTime } from '../utils/format'
|
||||
import { can } from '../utils/perm'
|
||||
import { confirmAction } from '../utils/confirm'
|
||||
import { exportXlsxFetch } from '../utils/export'
|
||||
import { getToken } from '../utils/auth'
|
||||
import PageHelp from '../components/PageHelp.vue'
|
||||
@@ -32,8 +33,8 @@ function defaultStart() {
|
||||
/* ---------- 区域维护(库位四级:区域/货架/层/位置号 4 个独立 Tab) ---------- */
|
||||
const zoneLevels = [
|
||||
{ level: 1, name: '区域', codeLabel: '区域编码', nameLabel: '区域名称' },
|
||||
{ level: 2, name: '货架', codeLabel: '货架号' },
|
||||
{ level: 3, name: '层', codeLabel: '层号' },
|
||||
{ level: 2, name: '货架', codeLabel: '货架号', nameLabel: '货架名称' },
|
||||
{ level: 3, name: '层', codeLabel: '层号', nameLabel: '层名称' },
|
||||
{ level: 4, name: '位置号', codeLabel: '位置号', nameLabel: '位置名称' }
|
||||
]
|
||||
const activeZoneTab = ref(1)
|
||||
@@ -43,7 +44,7 @@ function makeNodeState() {
|
||||
return reactive({
|
||||
list: [], total: 0, loading: false,
|
||||
page: { current: 1, size: 10 },
|
||||
filter: { zoneCode: '', shelfNo: '', layerNo: '', keyword: '', status: '' }
|
||||
filter: { zoneCode: '', shelfNo: '', layerNo: '', code: '', name: '', status: '' }
|
||||
})
|
||||
}
|
||||
const nodeState = { 1: makeNodeState(), 2: makeNodeState(), 3: makeNodeState(), 4: makeNodeState() }
|
||||
@@ -77,7 +78,8 @@ async function loadNodes(level) {
|
||||
level,
|
||||
page: s.page.current,
|
||||
pageSize: s.page.size,
|
||||
keyword: (s.filter.keyword || '').trim(),
|
||||
code: (s.filter.code || '').trim(),
|
||||
name: (s.filter.name || '').trim(),
|
||||
status: s.filter.status
|
||||
}
|
||||
if (level >= 2) params.zoneCode = (s.filter.zoneCode || '').trim().toUpperCase()
|
||||
@@ -142,7 +144,7 @@ function openNodeCreate(level) {
|
||||
}
|
||||
function openNodeEdit(row) {
|
||||
nodeEditing.value = true
|
||||
const f = { level: row.level, id: row.id, code: row.code, name: row.name || '', remark: row.description || '', status: row.status || '启用', regionCode: '', shelfCode: '', layerCode: '' }
|
||||
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 }
|
||||
@@ -171,6 +173,11 @@ async function saveNode() {
|
||||
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 }
|
||||
const okSave = await confirmAction(
|
||||
nodeEditing.value ? `确认保存【${nodeForm.code}】的修改?` : `确认新增【${nodeForm.code}${nodeForm.name ? ' ' + nodeForm.name : ''}】?`,
|
||||
nodeEditing.value ? '编辑确认' : '新增确认'
|
||||
)
|
||||
if (!okSave) return
|
||||
nodeSaving.value = true
|
||||
try {
|
||||
if (nodeEditing.value) {
|
||||
@@ -218,6 +225,8 @@ async function previewBatch() {
|
||||
}
|
||||
}
|
||||
async function submitBatch() {
|
||||
const go = await confirmAction(`已预检 ${batchPreview.value.length} 个位置,确认批量生成到库位表?(已存在的自动跳过)`, '批量生成确认')
|
||||
if (!go) return
|
||||
batchSubmitting.value = true
|
||||
try {
|
||||
const data = await request.post('/zone/batch-generate', { ...batchForm, preview: false })
|
||||
@@ -329,15 +338,11 @@ async function saveMaterial() {
|
||||
ElMessage.warning('类型为必填项')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm('确认保存该物料档案吗?保存后将写入数据库。', '操作确认', {
|
||||
confirmButtonText: '确认保存',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
const okSave = await confirmAction(
|
||||
mEditingId.value ? `确认保存物料「${mForm.code}」的修改?` : `确认新增物料「${String(mForm.code || '').trim()}」?保存后可继续上传图纸/附件。`,
|
||||
mEditingId.value ? '编辑确认' : '新增确认'
|
||||
)
|
||||
if (!okSave) return
|
||||
mSaving.value = true
|
||||
try {
|
||||
// 「其他」类(品类=4)不做 SN,管理粒度固定结构件(1),与后端收敛口径一致
|
||||
@@ -424,6 +429,8 @@ async function onMaterialFile(e) {
|
||||
const file = e.target.files?.[0]
|
||||
e.target.value = '' // 允许重复选择同一文件
|
||||
if (!file) return
|
||||
const go = await confirmAction(`确认导入物料文件「${file.name}」?导入将批量写入物料档案(任一行错误则整体回退)。`, '批量导入确认')
|
||||
if (!go) return
|
||||
matImporting.value = true
|
||||
try {
|
||||
const fd = new FormData()
|
||||
@@ -467,8 +474,11 @@ async function onMaterialFile(e) {
|
||||
<!-- 区域 -->
|
||||
<el-tab-pane :name="1" label="区域">
|
||||
<el-form inline style="margin-bottom:14px" @submit.prevent="searchNodes(1)">
|
||||
<el-form-item label="关键字">
|
||||
<el-input v-model="nodeState[1].filter.keyword" placeholder="区域编码/名称" clearable style="width:160px" @keyup.enter="searchNodes(1)" />
|
||||
<el-form-item label="区域编码">
|
||||
<el-input v-model="nodeState[1].filter.code" placeholder="区域编码" clearable style="width:140px" @keyup.enter="searchNodes(1)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="区域名称">
|
||||
<el-input v-model="nodeState[1].filter.name" placeholder="区域名称" clearable style="width:140px" @keyup.enter="searchNodes(1)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="nodeState[1].filter.status" placeholder="全部" clearable style="width:110px" @change="searchNodes(1)">
|
||||
@@ -482,22 +492,25 @@ async function onMaterialFile(e) {
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="nodeState[1].list" border size="small" v-loading="nodeState[1].loading" row-key="id" empty-text="暂无区域,请点击【新增区域】">
|
||||
<el-table-column prop="code" label="区域编码" min-width="120" />
|
||||
<el-table-column label="区域名称" min-width="150">
|
||||
<el-table-column prop="code" label="区域编码" min-width="110" />
|
||||
<el-table-column label="区域名称" min-width="140">
|
||||
<template #default="{ row }">{{ row.zoneName || row.name || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<el-table-column label="实时库存" width="100" align="center">
|
||||
<template #default="{ row }"><el-tag size="small" :type="row.stockQty > 0 ? 'success' : 'info'">{{ row.stockQty || 0 }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '停用' ? 'info' : 'success'" size="small">{{ row.status || '启用' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="description" label="说明" min-width="180">
|
||||
<el-table-column prop="description" label="备注" min-width="160" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.description || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" width="155" align="center">
|
||||
<template #default="{ row }">{{ fmtTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<el-table-column label="操作" width="90" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="can('zone:edit')" link type="primary" size="small" @click="openNodeEdit(row)">编辑</el-button>
|
||||
</template>
|
||||
@@ -520,7 +533,10 @@ async function onMaterialFile(e) {
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="货架号">
|
||||
<el-input v-model="nodeState[2].filter.keyword" placeholder="货架号" clearable style="width:130px" @keyup.enter="searchNodes(2)" />
|
||||
<el-input v-model="nodeState[2].filter.code" placeholder="货架号" clearable style="width:120px" @keyup.enter="searchNodes(2)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="nodeState[2].filter.name" placeholder="货架名称" clearable style="width:120px" @keyup.enter="searchNodes(2)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="nodeState[2].filter.status" placeholder="全部" clearable style="width:110px" @change="searchNodes(2)">
|
||||
@@ -534,17 +550,20 @@ async function onMaterialFile(e) {
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="nodeState[2].list" border size="small" v-loading="nodeState[2].loading" row-key="id" empty-text="暂无货架">
|
||||
<el-table-column label="区域" min-width="140">
|
||||
<el-table-column label="区域" min-width="130">
|
||||
<template #default="{ row }">{{ row.zoneName || row.zoneCode || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="code" label="货架号" min-width="120" />
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<el-table-column prop="code" label="货架号" width="110" align="center" />
|
||||
<el-table-column label="货架名称" min-width="130"><template #default="{ row }">{{ row.name || '-' }}</template></el-table-column>
|
||||
<el-table-column label="实时库存" width="100" align="center"><template #default="{ row }"><el-tag size="small" :type="row.stockQty > 0 ? 'success' : 'info'">{{ row.stockQty || 0 }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="状态" width="80" align="center">
|
||||
<template #default="{ row }"><el-tag :type="row.status === '停用' ? 'info' : 'success'" size="small">{{ row.status || '启用' }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="140" show-overflow-tooltip><template #default="{ row }">{{ row.description || '-' }}</template></el-table-column>
|
||||
<el-table-column label="创建时间" width="155" align="center">
|
||||
<template #default="{ row }">{{ fmtTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<el-table-column label="操作" width="90" align="center" fixed="right">
|
||||
<template #default="{ row }"><el-button v-if="can('zone:edit')" link type="primary" size="small" @click="openNodeEdit(row)">编辑</el-button></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -570,7 +589,10 @@ async function onMaterialFile(e) {
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="层号">
|
||||
<el-input v-model="nodeState[3].filter.keyword" placeholder="层号" clearable style="width:110px" @keyup.enter="searchNodes(3)" />
|
||||
<el-input v-model="nodeState[3].filter.code" placeholder="层号" clearable style="width:100px" @keyup.enter="searchNodes(3)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="nodeState[3].filter.name" placeholder="层名称" clearable style="width:110px" @keyup.enter="searchNodes(3)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="nodeState[3].filter.status" placeholder="全部" clearable style="width:110px" @change="searchNodes(3)">
|
||||
@@ -584,12 +606,15 @@ async function onMaterialFile(e) {
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="nodeState[3].list" border size="small" v-loading="nodeState[3].loading" row-key="id" empty-text="暂无层">
|
||||
<el-table-column label="区域" min-width="130"><template #default="{ row }">{{ row.zoneName || row.zoneCode || '-' }}</template></el-table-column>
|
||||
<el-table-column label="货架号" width="120" align="center"><template #default="{ row }">{{ row.shelfNo || '-' }}</template></el-table-column>
|
||||
<el-table-column prop="code" label="层号" width="100" align="center" />
|
||||
<el-table-column label="状态" width="90" align="center"><template #default="{ row }"><el-tag :type="row.status === '停用' ? 'info' : 'success'" size="small">{{ row.status || '启用' }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="区域" min-width="120"><template #default="{ row }">{{ row.zoneName || row.zoneCode || '-' }}</template></el-table-column>
|
||||
<el-table-column label="货架号" width="100" align="center"><template #default="{ row }">{{ row.shelfNo || '-' }}</template></el-table-column>
|
||||
<el-table-column prop="code" label="层号" width="90" align="center" />
|
||||
<el-table-column label="层名称" min-width="120"><template #default="{ row }">{{ row.name || '-' }}</template></el-table-column>
|
||||
<el-table-column label="实时库存" width="100" align="center"><template #default="{ row }"><el-tag size="small" :type="row.stockQty > 0 ? 'success' : 'info'">{{ row.stockQty || 0 }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="状态" width="80" align="center"><template #default="{ row }"><el-tag :type="row.status === '停用' ? 'info' : 'success'" size="small">{{ row.status || '启用' }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="备注" min-width="130" show-overflow-tooltip><template #default="{ row }">{{ row.description || '-' }}</template></el-table-column>
|
||||
<el-table-column label="创建时间" width="155" align="center"><template #default="{ row }">{{ fmtTime(row.createdAt) }}</template></el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center"><template #default="{ row }"><el-button v-if="can('zone:edit')" link type="primary" size="small" @click="openNodeEdit(row)">编辑</el-button></template></el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center" fixed="right"><template #default="{ row }"><el-button v-if="can('zone:edit')" link type="primary" size="small" @click="openNodeEdit(row)">编辑</el-button></template></el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
<el-pagination background layout="total, sizes, prev, pager, next" :total="nodeState[3].total"
|
||||
@@ -617,8 +642,11 @@ async function onMaterialFile(e) {
|
||||
<el-option v-for="l in f4Layer" :key="l.code" :value="l.code" :label="'层 '+l.code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="位置号/名称">
|
||||
<el-input v-model="nodeState[4].filter.keyword" placeholder="位置号或名称" clearable style="width:150px" @keyup.enter="searchNodes(4)" />
|
||||
<el-form-item label="位置号">
|
||||
<el-input v-model="nodeState[4].filter.code" placeholder="位置号" clearable style="width:130px" @keyup.enter="searchNodes(4)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="nodeState[4].filter.name" placeholder="位置名称" clearable style="width:130px" @keyup.enter="searchNodes(4)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="nodeState[4].filter.status" placeholder="全部" clearable style="width:110px" @change="searchNodes(4)">
|
||||
@@ -633,14 +661,16 @@ async function onMaterialFile(e) {
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="nodeState[4].list" border size="small" v-loading="nodeState[4].loading" row-key="id" empty-text="暂无位置号">
|
||||
<el-table-column label="区域" min-width="120"><template #default="{ row }">{{ row.zoneName || row.zoneCode || '-' }}</template></el-table-column>
|
||||
<el-table-column label="货架号" width="100" align="center"><template #default="{ row }">{{ row.shelfNo || '-' }}</template></el-table-column>
|
||||
<el-table-column label="层" width="80" align="center"><template #default="{ row }">{{ row.layerNo || '-' }}</template></el-table-column>
|
||||
<el-table-column prop="code" label="位置号" width="110" align="center" />
|
||||
<el-table-column label="位置名称" min-width="160"><template #default="{ row }">{{ row.name || '-' }}</template></el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center"><template #default="{ row }"><el-tag :type="row.status === '停用' ? 'info' : 'success'" size="small">{{ row.status || '启用' }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="区域" min-width="110"><template #default="{ row }">{{ row.zoneName || row.zoneCode || '-' }}</template></el-table-column>
|
||||
<el-table-column label="货架号" width="90" align="center"><template #default="{ row }">{{ row.shelfNo || '-' }}</template></el-table-column>
|
||||
<el-table-column label="层" width="70" align="center"><template #default="{ row }">{{ row.layerNo || '-' }}</template></el-table-column>
|
||||
<el-table-column prop="code" label="位置号" width="90" align="center" />
|
||||
<el-table-column label="位置名称" min-width="140"><template #default="{ row }">{{ row.name || '-' }}</template></el-table-column>
|
||||
<el-table-column label="实时库存" width="100" align="center"><template #default="{ row }"><el-tag size="small" :type="row.stockQty > 0 ? 'success' : 'info'">{{ row.stockQty || 0 }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="状态" width="80" align="center"><template #default="{ row }"><el-tag :type="row.status === '停用' ? 'info' : 'success'" size="small">{{ row.status || '启用' }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="备注" min-width="120" show-overflow-tooltip><template #default="{ row }">{{ row.description || '-' }}</template></el-table-column>
|
||||
<el-table-column label="创建时间" width="155" align="center"><template #default="{ row }">{{ fmtTime(row.createdAt) }}</template></el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center"><template #default="{ row }"><el-button v-if="can('zone:edit')" link type="primary" size="small" @click="openNodeEdit(row)">编辑</el-button></template></el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center" fixed="right"><template #default="{ row }"><el-button v-if="can('zone:edit')" link type="primary" size="small" @click="openNodeEdit(row)">编辑</el-button></template></el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
<el-pagination background layout="total, sizes, prev, pager, next" :total="nodeState[4].total"
|
||||
@@ -674,10 +704,10 @@ async function onMaterialFile(e) {
|
||||
</el-select>
|
||||
<div style="color:#909399;font-size:12px;margin-top:4px">留空则作为该货架的默认位置(无层)</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="nodeForm.level === 1 || nodeForm.level === 4" :label="zoneLevels.find(z=>z.level===nodeForm.level)?.nameLabel">
|
||||
<el-input v-model="nodeForm.name" :placeholder="(zoneLevels.find(z=>z.level===nodeForm.level)?.nameLabel || '') + (nodeForm.level===4 ? '(可空)' : '')" clearable />
|
||||
<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 />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="nodeForm.level === 1" label="说明">
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="nodeForm.remark" type="textarea" :rows="2" placeholder="备注(可空)" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="nodeEditing" label="状态">
|
||||
@@ -773,7 +803,7 @@ async function onMaterialFile(e) {
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :loading="materialLoading" @click="searchMaterials">查询</el-button>
|
||||
<el-button type="success" @click="openMatCreate">新增物料</el-button>
|
||||
<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 模板(首行表头):图号 | 名称 | 规格 | 单位 | 类型(结构件/电气件) | 说明(除「说明」外均为必填)">
|
||||
@@ -813,7 +843,7 @@ async function onMaterialFile(e) {
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="openMatEdit(row)">编辑</el-button>
|
||||
<el-button v-if="can('material:edit')" link type="primary" size="small" @click="openMatEdit(row)">编辑</el-button>
|
||||
<el-button link type="success" size="small" @click="openMatAttach(row)">附件</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
Reference in New Issue
Block a user