13 KiB
13 KiB
web-admin 门户化布局改造 — 设计文档
日期: 2026-06-20
状态: 已实现(2026-06-20)
范围:web-admin管理端框架(布局 + 菜单展示 + 权限联动)
UI 规范:docs/web-admin-ui-spec-fresh-mint.md(主色#10b981、Fresh Mint Token)
目标
将 web-admin 从「左侧全量菜单 + 顶栏工具条」改为 一体化门户布局:
- 顶栏展示 Logo、「一体化门户」、6 个一级模块卡片(icon 上 / 名称下),选中态绿底白字。
- 下方分左右:左侧为当前模块的二/三级菜单;右侧为 WorkTab + 内容区。
- 移除顶栏的菜单折叠、面包屑、刷新按钮;移除【控制台】一级菜单。
- 一级 / 二级 / 三级菜单仍按角色与
menuCode权限过滤显示。
已确认决策
| # | 决策 | 说明 |
|---|---|---|
| D1 | 实现方式 | 新增 MenuTypeEnum.PORTAL 专用布局模式(方案 A),不魔改 TOP_LEFT / DUAL_MENU |
| D2 | 权限边界(0/1 模块) | 始终保留顶栏卡片区域:0 个可见模块时展示「暂无可用模块」空态;1 个模块时仍展示 1 张卡片 |
| D3 | 一级菜单清单 | CRM 管理、报销管理、地磅管理、运输管理、工作流管理、系统管理(共 6 个,不含控制台) |
| D4 | 一级展示顺序 | CRM → 报销 → 地磅 → 运输 → 工作流 → 系统(前端常量排序,不依赖路由文件注册顺序) |
| D5 | 控制台 | 从侧栏与顶栏卡片中移除;默认首页改为第一个有权限模块的首个可访问叶子页 |
| D6 | 顶栏右侧 | 保留用户菜单;全屏按钮保留;折叠 / 面包屑 / 刷新移除 |
| D7 | 侧栏 | 去掉 Logo 与「一体化门户」品牌区;去掉顶栏式折叠 icon;侧栏本身不新增折叠按钮(固定展开,宽度沿用 menuOpenWidth 默认 230px) |
| D8 | OpenSpec 侧栏 icon | 一级卡片有 icon;左侧二/三级菜单仍遵守「仅一级有 icon、更深层仅文字」(SidebarSubmenu 现有 level === 0 规则) |
非目标(本期不做)
- 设置面板中保留/切换 Left、Top、Mixed、Dual 等旧布局(PORTAL 为唯一产品布局,设置项可隐藏或锁定)
- 小程序端布局改造
- 权限后端 API 改造(沿用
MenuProcessor+fetchGetMenuCodes) - 移动端完整适配(本期仅保证
<800px不严重错位;横滑卡片 + 抽屉侧栏可作为 follow-up) - Demo 菜单独立提升为一级模块
一、目标布局
┌────────────────────────────────────────────────────────────────────────┐
│ [Logo] 一体化门户 [CRM] [报销] [地磅] [运输] [工作流] [系统] [用户] │ ← ArtPortalHeader(全宽)
│ ↑ 卡片:icon 上 / 名称下;选中 #10b981 底 + 白字 │
├──────────────┬─────────────────────────────────────────────────────────┤
│ 二级 / 三级 │ ArtWorkTab(标签页) │
│ 菜单树 ├─────────────────────────────────────────────────────────┤
│ ArtPortal │ ArtPageContent(业务页面) │
│ Sidebar │ │
└──────────────┴─────────────────────────────────────────────────────────┘
DOM 结构(views/index/index.vue)
.app-layout-portal
├── #app-portal-header → ArtPortalHeader
└── #app-portal-body → flex row
├── #app-sidebar → ArtPortalSidebar(改造 art-sidebar-menu)
└── #app-workspace → flex column
├── #app-worktab → ArtWorkTab(从 art-header-bar 迁出)
└── #app-content → ArtPageContent
二、一级模块卡片(ArtPortalTopNav)
2.1 数据来源
- 输入:
menuStore.menuList经 门户一级过滤器 处理后的列表。 - 过滤器职责:
- 排除控制台(
path === '/dashboard'或meta.title === '控制台')。 - 排除
meta.isHide === true的项。 - 按 D4 常量顺序排序。
- 若项无可见子节点且自身不可导航 → 不渲染卡片(与
MenuProcessor.filterEmptyMenus结果一致)。
- 排除控制台(
2.2 卡片 UI
| 属性 | 值 |
|---|---|
| 布局 | 纵向 flex,居中;icon 在上(20–24px),标题在下(12–13px) |
| 间距 | 卡片之间 gap: 8–12px;卡片内 padding 约 8px 12px |
| 圆角 | 8px(与规范按钮/输入圆角一致) |
| 默认 | 透明底;icon/文字 --text / --text-muted |
| 选中 | background: var(--primary);icon 与文字 #fff |
| 激活判定 | 复用 ArtMixedMenu.isMenuItemActive:当前路由(或 meta.activePath)落在该模块子树内 |
2.3 交互
- 点击卡片:
router.push(module.redirect || firstAccessibleChildPath(module))。 - 若当前路由已属于该模块:仅更新选中态,不强制跳转。
- 0 个可见模块:顶栏卡片区展示 muted 文案「暂无可用模块」(不隐藏顶栏)。
- 1 个可见模块:仍展示 1 张卡片(D2)。
2.4 一级模块与路由前缀映射
| 卡片名称 | 路由 path 前缀 | 路由模块 |
|---|---|---|
| CRM 管理 | /crm |
sqxp.ts |
| 报销管理 | /bx |
sqxp.ts |
| 地磅管理 | /db |
sqxp.ts |
| 运输管理 | /pl |
pl.ts |
| 工作流管理 | /workflow |
sqxp.ts |
| 系统管理 | /system |
sqxp.ts |
三、左侧菜单(ArtPortalSidebar)
3.1 渲染范围
- 仅渲染 当前激活一级模块 的
children(二/三级)。 - 激活模块解析:
const top = '/' + route.path.split('/')[1],在过滤后的一级列表中匹配。 - iframe 路由:沿用
art-sidebar-menu现有findIframeMenuList逻辑。
3.2 移除内容
- 侧栏 header 区(Logo + 系统名)。
- 双列菜单 / 折叠按钮 /
menu-model遮罩(PORTAL 模式不启用DUAL_MENU/LEFT分支)。 - 顶栏菜单折叠联动(
visibleMenu/menuOpen切换对 PORTAL 无 UI 入口;menuOpen保持true)。
3.3 子菜单组件
- 继续复用
SidebarSubmenu+filterSidebarRoutes。 ElMenu默认展开:保留现有syncExpandedMenus/defaultOpenedMenus逻辑。
四、顶栏(ArtPortalHeader)
4.1 左侧
ArtLogo(点击跳转默认首页,见 §五)。- 文案「一体化门户」(
AppConfig.systemInfo.name,已为该值)。
4.2 中间
ArtPortalTopNav(flex-1,卡片可横向滚动;模块多时可加ElScrollbar)。
4.3 右侧
- 全屏按钮(可选保留)。
ArtUserMenu。- 不渲染:折叠、刷新、面包屑、快速入口、通知、语言、主题切换(与现 header 隐藏项一致)。
4.4 WorkTab 迁移
- 从
art-header-bar/index.vue移除<ArtWorkTab />。 - 挂载到
#app-workspace顶部(ArtWorkTab组件本身不改业务逻辑)。 - 样式:
worktab-strip的mb-3与 workspace padding 对齐 Fresh Mint 内容区 rhythm。
五、菜单数据与权限
5.1 现有链路(保持不变)
beforeEach → MenuProcessor.getMenuList()
→ filterMenuByRoles / filterMenuByCodes
→ filterEmptyMenus
→ menuStore.setMenuList
→ RouteRegistry.register
5.2 前端增强
| 位置 | 增强 |
|---|---|
MenuProcessor.processFrontendMenu |
过滤掉 Dashboard / 控制台节点 |
新建 utils/router/portal-menu.ts |
PORTAL_TOP_MODULE_ORDER、filterPortalTopModules()、resolveActivePortalModule()、getFirstAccessiblePath() |
menuStore.setMenuList |
设置 homePath 时跳过 /dashboard,使用 getFirstSecondLevelMenuPath(已有) |
5.3 三级权限行为
| 层级 | 机制 |
|---|---|
| 一级卡片 | MenuProcessor 输出 + filterPortalTopModules;filterMenuByCodes level=1 保留「有可见子节点」的父级 |
| 二级 | filterSidebarRoutes |
| 三级 | SidebarSubmenu 递归 + filterSidebarRoutes |
5.4 后端菜单(backend 模式)
- SQL 隐藏或删除 Dashboard 对应
sys_menu记录(与前端路由同步)。 - 确认 6 个一级菜单在
sys_menu中parent_id指向门户 Web 根节点;运输管理已更名见docs/sql/20260620_pl_menu_rename_hide.sql。 - 新增迁移脚本:
docs/sql/20260620_portal_hide_dashboard.sql(建议)。
六、配置与枚举
| 文件 | 变更 |
|---|---|
enums/appEnum.ts |
新增 MenuTypeEnum.PORTAL = 'portal' |
config/setting.ts |
默认 menuType: MenuTypeEnum.PORTAL;showMenuButton/showRefreshButton/showCrumbs: false |
config/modules/headerBar.ts |
menuButton/refreshButton/breadcrumb.enabled: false |
store/modules/setting.ts |
支持 PORTAL 分支(若 layout 判断分散在各组件,统一用 isPortalLayout computed) |
views/index/index.vue |
PORTAL 时使用新 DOM 结构;旧 LEFT 结构可保留供模板升级对比或后续删除 |
七、路由与首页
7.1 控制台处理
sqxp.ts:Dashboard 路由设meta.isHide: true或整段注释/删除(与 SQL 同步)。- 登录后默认跳转:第一个有权限模块的首个叶子页(如
/crm/...)。
7.2 路由顺序
routeModules合并顺序不影响 UI(由PORTAL_TOP_MODULE_ORDER控制)。- 文档注释更新:
sqxp.ts头部说明去掉「控制台」。
八、样式要点
- 顶栏高度:建议
64–72px(略高于现h-15以容纳卡片)。 - 顶栏背景:
var(--default-bg-color)/ 白底 + 底部分割线var(--art-card-border)。 - 一级卡片选中色:
var(--primary)#10b981,勿使用小程序色#0a9f6d。 - 下方 body:
height: calc(100vh - 顶栏高度);workspace 内容区 padding 沿用--mint-content-padding。 - 侧栏宽度:230px(
menuOpenWidth默认值)。
九、测试计划
| 场景 | 预期 |
|---|---|
| super_admin | 6 张卡片 + 对应侧栏全量 |
| admin 仅有 bx 权限 | 顶栏仅 1 张「报销管理」卡片;侧栏仅 bx 子菜单 |
| admin 无任何业务 menuCode | 顶栏卡片区显示「暂无可用模块」 |
| 点击 CRM 卡片 | 路由进入 CRM 首个可访问页;卡片选中;侧栏切换为 CRM 树 |
| 从 CRM 页内跳转 bx 页 | 顶栏选中态自动切到报销 |
直接 URL 访问 /pl/plan |
运输卡片选中;侧栏为 pl 子树 |
控制台 /dashboard |
不可从菜单进入;直接访问按路由守卫处理(404 或重定向首页) |
| WorkTab | 开/关/切换标签正常;位置在内容区上方 |
| 侧栏二/三级 | 无 icon,仅文字(OpenSpec) |
十、影响文件清单
新建
components/core/layouts/art-portal-header/index.vuecomponents/core/layouts/art-portal-top-nav/index.vueutils/router/portal-menu.tsdocs/sql/20260620_portal_hide_dashboard.sql(建议)
修改
views/index/index.vue、views/index/style.scsscomponents/core/layouts/art-menus/art-sidebar-menu/index.vue(PORTAL 分支)components/core/layouts/art-header-bar/index.vue(移除 WorkTab;或 PORTAL 下不再使用此组件)enums/appEnum.ts、config/setting.ts、config/modules/headerBar.tsrouter/core/MenuProcessor.tsrouter/modules/sqxp.ts
可选
components/core/layouts/art-settings-panel:隐藏菜单布局切换或锁定 PORTAL
十一、风险
- WorkTab 样式错位:迁移后需目视检查 tab-card / tab-google 两种
tabStyle。 - 跨模块 deep link:书签直达子页时,顶栏选中态依赖
isMenuItemActive,需覆盖meta.activePath。 - 模板升级:Art Design Pro 上游更新 layout 时,PORTAL 为独立分支,合并冲突集中在
index.vue。 - 窄屏:6 卡片可能溢出,顶栏需横向滚动;侧栏
<800px现有 fixed 策略待 follow-up。
十二、后续(非本期)
- 移动端:顶栏卡片横滑 + 侧栏抽屉。
- 设置面板清理旧 layout 选项。
- OpenSpec
ui-conventions补充「门户布局」章节(若需长期规范)。