设备与库位聚合页拆分为设备接入与库位管理

将“设备与库位”聚合页拆分为“设备接入”和“库位管理”两个独立页面,调整相关菜单、路由、权限、页面定义及映射。FacilityConfigView.vue 仅保留设备接入,库位管理内容移除,LocationView.vue 删除,新增 WarehouseManagementView.vue。同步精简聚合页 tab 逻辑及重定向,后端 PageCatalog、DeploymentCatalog 和前端 rbac.ts、AppShell.vue、index.ts 等均已更新。
This commit is contained in:
ArtoriasWu
2026-06-24 16:21:31 +08:00
parent 5529883b9c
commit 60b3afb954
7 changed files with 17 additions and 104 deletions
+3 -2
View File
@@ -44,7 +44,8 @@ public static class PageCatalog
// ── 管理端 / Platform:平台配置中心(聚合页,每个 Key 对齐前端聚合路由 route.name) ──
new("admin-config-strategy", "调度策略", "平台配置中心", ScopePlatform),
new("admin-vehicle-hub", "车辆运维", "平台配置中心", ScopePlatform),
new("admin-config-facility", "设备与库位", "平台配置中心", ScopePlatform),
new("admin-config-facility", "设备接入", "平台配置中心", ScopePlatform),
new("admin-config-warehouse", "库位管理", "平台配置中心", ScopePlatform),
new("admin-config-business", "业务与集成", "平台配置中心", ScopePlatform),
new("admin-config-ops-center", "运维与回放", "平台配置中心", ScopePlatform),
new("admin-config-system-center", "系统与权限", "平台配置中心", ScopePlatform),
@@ -72,7 +73,7 @@ public static class PageCatalog
["admin-config-traffic"] = "admin-config-strategy",
["admin-config-charge"] = "admin-config-strategy",
["admin-config-device"] = "admin-config-facility",
["admin-config-location"] = "admin-config-facility",
["admin-config-location"] = "admin-config-warehouse",
["admin-config-integrations"] = "admin-config-business",
["admin-config-scenario"] = "admin-config-business",
["admin-config-widget"] = "admin-config-business",
+1 -1
View File
@@ -31,7 +31,7 @@ public static class DeploymentCatalog
public static readonly IReadOnlyDictionary<string, string[]> ModuleToPages =
new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
["wms"] = new[] { "admin-config-location" },
["wms"] = new[] { "admin-config-warehouse" },
};
/// <summary>所有「可被选型控制」的页面 Key(Module → 页 映射值的并集)。</summary>
@@ -162,7 +162,8 @@ const ADMIN_MENU: MenuItem[] = [
children: [
{ path: '/admin/config/strategy', label: '调度策略', key: 'admin-config-strategy' },
{ path: '/admin/config/vehicle-hub', label: '车辆运维', key: 'admin-vehicle-hub' },
{ path: '/admin/config/facility', label: '设备与库位', key: 'admin-config-facility' },
{ path: '/admin/config/facility', label: '设备接入', key: 'admin-config-facility' },
{ path: '/admin/config/warehouse', label: '库位管理', key: 'admin-config-warehouse' },
{ path: '/admin/config/business', label: '业务与集成', key: 'admin-config-business' },
{ path: '/admin/config/ops-center', label: '运维与回放', key: 'admin-config-ops-center' },
{ path: '/admin/config/system-center', label: '系统与权限', key: 'admin-config-system-center' }
@@ -22,7 +22,8 @@ const PAGES: PageDef[] = [
{ key: 'admin-task-templates', label: '任务编排', group: '设计与编排', scope: 'Platform' },
{ key: 'admin-config-strategy', label: '调度策略', group: '平台配置中心', scope: 'Platform' },
{ key: 'admin-vehicle-hub', label: '车辆运维', group: '平台配置中心', scope: 'Platform' },
{ key: 'admin-config-facility', label: '设备与库位', group: '平台配置中心', scope: 'Platform' },
{ key: 'admin-config-facility', label: '设备接入', group: '平台配置中心', scope: 'Platform' },
{ key: 'admin-config-warehouse', label: '库位管理', group: '平台配置中心', scope: 'Platform' },
{ key: 'admin-config-business', label: '业务与集成', group: '平台配置中心', scope: 'Platform' },
{ key: 'admin-config-ops-center', label: '运维与回放', group: '平台配置中心', scope: 'Platform' },
{ key: 'admin-config-system-center', label: '系统与权限', group: '平台配置中心', scope: 'Platform' },
@@ -143,7 +144,7 @@ function sanitizePages(pages: string[]): string[] {
'admin-config-traffic': 'admin-config-strategy',
'admin-config-charge': 'admin-config-strategy',
'admin-config-device': 'admin-config-facility',
'admin-config-location': 'admin-config-facility',
'admin-config-location': 'admin-config-warehouse',
'admin-config-integrations': 'admin-config-business',
'admin-config-scenario': 'admin-config-business',
'admin-config-widget': 'admin-config-business',
@@ -38,11 +38,11 @@ const routes: RouteRecordRaw[] = [
{ path: 'scripts', name: 'admin-scripts', component: () => import('@/views/admin/ScriptPanelView.vue'), meta: { title: '脚本管理' } },
{ path: 'task-templates', name: 'admin-task-templates', component: () => import('@/views/admin/TaskTemplateView.vue'), meta: { title: '任务编排' } },
{ path: 'project-properties', name: 'admin-project-properties', component: () => import('@/views/admin/ProjectPropertiesView.vue'), meta: { title: '项目属性' } },
// ── 平台配置中心:聚合页(每个聚合页一个 page key = route.name,对齐后端 PageCatalog)。
// 原十余个独立配置页按业务收敛为下列 6 个入口,子页改为聚合页内的 tab。 ──
// ── 平台配置中心:聚合页 + 独立业务页(page key = route.name,对齐后端 PageCatalog)。 ──
{ path: 'config/strategy', name: 'admin-config-strategy', component: () => import('@/views/admin/config/StrategyConfigView.vue'), meta: { title: '调度策略' } },
{ path: 'config/vehicle-hub', name: 'admin-vehicle-hub', component: () => import('@/views/shared/VehicleHubView.vue'), meta: { title: '车辆运维' } },
{ path: 'config/facility', name: 'admin-config-facility', component: () => import('@/views/admin/config/FacilityConfigView.vue'), meta: { title: '设备与库位' } },
{ path: 'config/facility', name: 'admin-config-facility', component: () => import('@/views/admin/config/FacilityConfigView.vue'), meta: { title: '设备接入' } },
{ path: 'config/warehouse', name: 'admin-config-warehouse', component: () => import('@/views/admin/WarehouseManagementView.vue'), meta: { title: '库位管理' } },
{ path: 'config/business', name: 'admin-config-business', component: () => import('@/views/admin/config/BusinessConfigView.vue'), meta: { title: '业务与集成' } },
{ path: 'config/ops-center', name: 'admin-config-ops-center', component: () => import('@/views/admin/config/OpsCenterView.vue'), meta: { title: '运维与回放' } },
{ path: 'config/system-center', name: 'admin-config-system-center', component: () => import('@/views/admin/config/SystemCenterView.vue'), meta: { title: '系统与权限' } },
@@ -56,8 +56,8 @@ const routes: RouteRecordRaw[] = [
{ path: 'config/task', redirect: { path: '/admin/config/strategy', query: { tab: 'task' } } },
{ path: 'config/traffic', redirect: { path: '/admin/config/strategy', query: { tab: 'traffic' } } },
{ path: 'config/charge', redirect: { path: '/admin/config/strategy', query: { tab: 'charge' } } },
{ path: 'config/device', redirect: { path: '/admin/config/facility', query: { tab: 'device' } } },
{ path: 'config/location', redirect: { path: '/admin/config/facility', query: { tab: 'location' } } },
{ path: 'config/device', redirect: '/admin/config/facility' },
{ path: 'config/location', redirect: '/admin/config/warehouse' },
{ path: 'config/integrations', redirect: { path: '/admin/config/business', query: { tab: 'integrations' } } },
{ path: 'config/scenario', redirect: { path: '/admin/config/business', query: { tab: 'scenario' } } },
{ path: 'config/widget', redirect: { path: '/admin/config/business', query: { tab: 'widget' } } },
@@ -1,39 +1,11 @@
<template>
<div class="config-hub-page">
<el-tabs v-model="activeTab" class="hub-tabs">
<el-tab-pane name="device" label="设备接入">
<div class="config-pane"><DeviceHubView /></div>
</el-tab-pane>
<el-tab-pane name="location" label="库位管理" lazy>
<div class="config-pane"><LocationView /></div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import DeviceHubView from '@/views/admin/config/DeviceHubView.vue'
import LocationView from '@/views/admin/config/LocationView.vue'
// 聚合页:第三方设备接入与库位管理。Tab 与 URL ?tab= 同步。
const route = useRoute()
const router = useRouter()
const TAB_NAMES = ['device', 'location'] as const
type TabName = (typeof TAB_NAMES)[number]
function readTab(): TabName {
const q = route.query.tab
return typeof q === 'string' && (TAB_NAMES as readonly string[]).includes(q) ? (q as TabName) : 'device'
}
const activeTab = ref<TabName>(readTab())
watch(activeTab, (t) => {
if (route.query.tab !== t) router.replace({ query: { ...route.query, tab: t } })
})
watch(() => route.query.tab, () => {
const next = readTab()
if (next !== activeTab.value) activeTab.value = next
})
</script>
<style scoped>
@@ -44,32 +16,9 @@ watch(() => route.query.tab, () => {
flex-direction: column;
overflow: hidden;
}
.hub-tabs {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
:deep(.el-tabs__content) {
flex: 1;
min-height: 0;
overflow: auto;
}
:deep(.el-tab-pane) { height: 100%; }
.config-pane {
height: 100%;
flex: 1;
min-height: 0;
overflow: auto;
}
:deep(.el-tabs__item) {
color: var(--mg-text-muted, rgba(255, 255, 255, 0.65));
}
:deep(.el-tabs__item.is-active) {
color: var(--mg-text-light, #fff);
}
:deep(.el-tabs__active-bar) {
background-color: var(--mg-accent, var(--el-color-primary));
}
:deep(.el-tabs__nav-wrap::after) {
background-color: rgba(255, 255, 255, 0.08);
}
</style>
@@ -1,39 +0,0 @@
<template>
<ConfigPageBase
section="location"
title="库位管理"
description="出入库、库存、库位可视化(LocationManagement"
:defaults="DEFAULT_LOCATION">
<template #default="{ payload }">
<el-tabs model-value="locs">
<el-tab-pane name="locs" label="库位">
<el-table :data="payload.locations" size="small" border>
<el-table-column label="ID" prop="id" width="100" />
<el-table-column label="编码" prop="code" width="120" />
<el-table-column label="名称" prop="name" />
<el-table-column label="站点" prop="siteId" width="100" />
<el-table-column label="容量" prop="capacity" width="100" />
<el-table-column label="占用">
<template #default="s">
<el-progress :percentage="Math.round((s.row.occupied / s.row.capacity) * 100)" :stroke-width="10" />
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="rules" label="库存规则">
<el-table :data="payload.inventoryRules" size="small" border>
<el-table-column label="ID" prop="id" width="100" />
<el-table-column label="物料类型" prop="itemType" />
<el-table-column label="下限" prop="minQty" width="100" />
<el-table-column label="上限" prop="maxQty" width="100" />
</el-table>
</el-tab-pane>
</el-tabs>
</template>
</ConfigPageBase>
</template>
<script setup lang="ts">
import ConfigPageBase from '@/components/ConfigPageBase.vue'
import { DEFAULT_LOCATION } from '@/mock/data/configs'
</script>