20260816220132
This commit is contained in:
1 parent
b6f9a4c912
commit
72993ecdcd
179 files changed
+20050
-633
No files matched your search
@@ -0,0 +1,154 @@
|
||||
---
|
||||
name: migrate-default-layout
|
||||
overview: 将 fms-vue-old2 的 DefaultLayout 布局体系(AppSidebar/AppTopbar/AppTabs/NavMain/NavMenuItem)整体迁移到 fms-vue,tailwind 改为 scoped scss + --fms-* token,不引入新依赖,动态菜单/页签/主题/权限逻辑与 old2 保持一致。
|
||||
todos:
|
||||
- id: migrate-utils-stores
|
||||
content: 迁移 utils/tree.js、utils/lucideIcons.js 与 stores/permissions.js,扩展 stores/app.js(页签/折叠/语言/刷新状态)
|
||||
status: completed
|
||||
- id: layout-shell
|
||||
content: 创建 DefaultLayout.vue 与 scss 布局骨架:拖拽调宽、keep-alive、页面过渡,手写事件替代 @vueuse/core
|
||||
status: completed
|
||||
dependencies:
|
||||
- migrate-utils-stores
|
||||
- id: sidebar-menu
|
||||
content: 自研 NavMain/NavMenuItem 递归菜单与 AppSidebar(团队切换 + 动态权限菜单),参考 [skill:ui-ux-pro-max] 视觉规则
|
||||
status: completed
|
||||
dependencies:
|
||||
- layout-shell
|
||||
- id: topbar-tabs
|
||||
content: 实现 AppTopbar(面包屑/主题/语言/用户下拉,复用 ThemeToggle/ColorThemePicker/Dropdown/Message)与 AppTabs 页签栏
|
||||
status: completed
|
||||
dependencies:
|
||||
- layout-shell
|
||||
- id: router-dashboard
|
||||
content: 改造路由挂 DefaultLayout 承载子路由并加权限守卫,调整 dashboard 为布局内内容页
|
||||
status: completed
|
||||
dependencies:
|
||||
- sidebar-menu
|
||||
- topbar-tabs
|
||||
---
|
||||
|
||||
## 产品概述
|
||||
|
||||
将 fms-vue-old2 的整个布局体系(DefaultLayout 及其 menu/topbar/tabs/content/navmain)迁移到 fms-vue 业务项目,样式从 tailwindcss 改写为自研 scss(基于 --fms-* token),不需要响应式。菜单组件自研并放置于 src/layouts/components(不进 components/ui)。同步迁移权限 store、树/图标工具,扩展 app store 以支持页签、路由刷新、侧栏折叠、语言状态,路由改造为布局壳承载子路由。
|
||||
|
||||
## 核心功能
|
||||
|
||||
- 布局壳 DefaultLayout:左侧可拖拽调宽侧边栏(180-400px)+ 右侧内容区(topbar + 页签栏 + router-view),页面过渡动画 + keep-alive 缓存
|
||||
- AppSidebar:顶部团队切换 + 动态菜单(基于权限模块数据构建树,仅保留有权限的菜单项),可折叠为图标栏
|
||||
- AppTopbar:侧栏折叠按钮、面包屑(路由 meta.title/section)、语言切换、主题色板与深浅色切换(复用 ThemeToggle/ColorThemePicker)、通知、用户下拉(头像/退出登录,退出用 Message 提示)
|
||||
- AppTabs:多页签栏(跟随访问路由自动添加、可关闭、溢出滚动、双击刷新),dashboard 固定不可关
|
||||
- 权限体系:permissions store(loadDataApi 拉取模块/用户权限数据,g3soft 提权,canAccess/canPower),路由守卫在 moduleId 存在时做权限拦截
|
||||
- 路由改造:/login 独立;/ 父路由挂 DefaultLayout(redirect /dashboard),dashboard 为子路由;/demo 保持独立不进布局;catchAll 不变
|
||||
|
||||
## 边界
|
||||
|
||||
- 不引入任何新 npm 依赖:@vueuse/core(useEventListener/usePreferredReducedMotion/useResizeObserver)全部手写;vue-sonner toast 用自研 Message 替代;shadcn sidebar/dropdown-menu/avatar/breadcrumb/separator/collapsible 一律不迁移
|
||||
- 无响应式:移除所有断点类,布局固定桌面形态
|
||||
- 主题沿用 fms-vue 现有体系(--fms-primary + .dark),不迁移 old2 的 oklch scheme 面板,色板复用 ColorThemePicker
|
||||
|
||||
## 技术栈
|
||||
|
||||
- Vue 3.5 + Vite 8(现有),纯 JavaScript,自研 scss 样式(sass 已安装)
|
||||
- 现有依赖复用:@lucide/vue(图标)、pinia + pinia-plugin-persistedstate、vue-router、nprogress、自研组件库(button/dropdown/message/popover/tooltip/spin)
|
||||
- 不新增依赖;@vueuse/core / vue-sonner / shadcn-vue 相关代码以手写或现有组件替代
|
||||
|
||||
## 实现方案
|
||||
|
||||
分层架构与 old2 一致:layouts(布局壳)→ stores(app/permissions/auth)→ services(http/api)→ utils(tree/lucideIcons)。
|
||||
|
||||
关键决策:
|
||||
|
||||
1. **组件替换映射**(tailwind/shadcn → 自研):
|
||||
|
||||
- SidebarProvider/SidebarInset/SidebarTrigger → 自研 flex scss 布局 + 折叠状态存 app store(sidebarCollapsed),侧栏宽 240px(展开)/ 64px(折叠)
|
||||
- DropdownMenu(topbar 用户菜单/色板、sidebar 团队切换)→ fms-vue Dropdown(items 数组或 #menu 插槽),icon/shortcut/divider 均已支持
|
||||
- Avatar → 自研圆形首字母头像(CSS)
|
||||
- Breadcrumb/Separator → 自研面包屑(flex + span)与 CSS 分隔线
|
||||
- toast → Message.info/success/error(已有命令式 API)
|
||||
- Collapsible(菜单展开)→ NavMenuItem 自研递归组件 + 手写展开状态
|
||||
|
||||
2. **手写 composables**(替代 @vueuse/core):onMounted/onBeforeUnmount 注册移除 window 事件(mousemove/mouseup 拖拽调宽)、matchMedia('(prefers-reduced-motion: reduce)')、ResizeObserver(页签溢出检测);组件卸载时全部清理,避免内存泄漏
|
||||
3. **菜单自研**:NavMain 渲染 NavMenuItem 递归(depth 递归):有 children 的目录项 → 可展开/收起(默认展开含激活子项的父级,hasActiveChild 判断);叶子项 → router-link + isActive 高亮(route.path === url 或 startsWith url + '/');折叠态下目录项点击展开、叶子仅图标 + tooltip 悬浮提示
|
||||
4. **app store 扩展**(保持现有 options API 兼容):新增 sidebarCollapsed、visitedTabs(初始含 dashboard)、routeRefreshKeys + addVisitedTab/removeVisitedTab/getRouteRefreshKey/refreshRoute/toggleSidebar;现有 darkMode/primaryColor/initThemeSync 不变(ThemeToggle/ColorThemePicker 依赖它们)
|
||||
5. **权限 store 迁移**:JS 版逻辑与 old2 完全一致(load 去重加载、g3soft 提权、resolvePageId/canAccess/canPower、watch auth 变化 clear),依赖已有 loadDataApi
|
||||
6. **路由改造**:/ 父路由 `component: DefaultLayout, redirect: '/dashboard', meta: { requiresAuth: true }`,子路由 /dashboard(title 工作台,id 固定);beforeEach 保留登录守卫 + 新增 moduleId 权限校验(await permissionStore.load() 后 canAccess 失败跳 /dashboard);/demo 独立路由不进布局
|
||||
7. **dashboard 页面**:移除原独立全屏占位样式,改为 layout 内容区内的简单内容页(标题 + 建设中提示,删除退出登录按钮——退出已由 topbar 负责)
|
||||
8. **性能与可靠性**:keep-alive max 8 + routeInstanceKey(fullPath:refreshKey)保持;拖拽调宽用 rAF 节流避免频繁重排;页签滚动按钮按需渲染(scrollWidth > clientWidth 判定);所有手写监听在 onBeforeUnmount 清理
|
||||
|
||||
## 实施要点
|
||||
|
||||
- DefaultLayout 的页面过渡 CSS(.page-enter-active 等)写在非 scoped style,并包裹 @media (prefers-reduced-motion: reduce) 禁用
|
||||
- 拖拽 rail 交互:mousedown 记录 startX/startWidth,mousemove 计算 180-400px 夹逼,直接写 inline width 到侧栏根元素;mouseup 移除监听
|
||||
- AppTabs 的 wheel 横向滚动需 e.preventDefault()(非 passive 监听),overflow 检测用 ResizeObserver + scroll 事件
|
||||
- topbar 语言切换仅切换 store.locale 状态(项目暂无 i18n 文案,按钮保留占位),通知按钮保留占位
|
||||
- 面包屑从 route.meta.title/section 派生;dashboard 无 section 时显示单级"工作台"
|
||||
- 用户下拉:Dropdown #menu 插槽自定义内容(用户名/orgId/退出登录),退出调 authStore.clearSession + Message.info + router.replace('/login')
|
||||
- 删除项:old2 的 oklch scheme 面板、shadcn sidebar 相关选择器(data-slot、group-data 等)不迁移;@vueuse/core/vue-sonner import 全部移除
|
||||
- 不主动执行构建/测试;交付后 lint 检查 + 说明手动验证路径(pnpm dev → 登录 → dashboard 布局/页签/菜单/退出)
|
||||
|
||||
## 架构与数据流
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[访问 /] --> B{router.beforeEach}
|
||||
B -->|未登录| C[/login/]
|
||||
B -->|已登录| D[DefaultLayout]
|
||||
D --> E[AppSidebar]
|
||||
D --> F[AppTopbar]
|
||||
D --> G[AppTabs]
|
||||
D --> H[router-view + keep-alive]
|
||||
E --> I[permissions store]
|
||||
I --> J[loadDataApi 拉取模块]
|
||||
E --> K[NavMain/NavMenuItem 递归菜单]
|
||||
F --> L[退出登录 clearSession]
|
||||
G --> M[app store visitedTabs]
|
||||
H --> N[子路由 dashboard 等]
|
||||
```
|
||||
|
||||
## 目录结构(变更清单)
|
||||
|
||||
```
|
||||
fms-vue/
|
||||
├── src/
|
||||
│ ├── layouts/
|
||||
│ │ ├── DefaultLayout.vue # [NEW] 布局壳:侧栏 + 内容区 + keep-alive/过渡 + 拖拽调宽
|
||||
│ │ ├── index.scss # [NEW] 布局壳 scss(非 scoped 全局布局样式 + 页面过渡)
|
||||
│ │ └── components/
|
||||
│ │ ├── AppSidebar.vue # [NEW] 团队切换 + 动态菜单容器(权限数据构建树)
|
||||
│ │ ├── AppTopbar.vue # [NEW] 折叠/面包屑/语言/主题/通知/用户下拉
|
||||
│ │ ├── AppTabs.vue # [NEW] 页签栏(添加/关闭/滚动/双击刷新)
|
||||
│ │ ├── NavMain.vue # [NEW] 菜单列表容器
|
||||
│ │ ├── NavMenuItem.vue # [NEW] 递归菜单项(展开/折叠/高亮/图标)
|
||||
│ │ └── index.scss # [NEW] 侧栏/菜单/topbar/页签 scss(--fms-* token)
|
||||
│ ├── stores/
|
||||
│ │ ├── app.js # [MODIFY] 新增 sidebarCollapsed/visitedTabs/routeRefreshKeys/locale + actions
|
||||
│ │ ├── permissions.js # [NEW] 权限 store(load/canAccess/canPower/resolvePageId/clear)
|
||||
│ │ └── auth.js # 不变
|
||||
│ ├── utils/
|
||||
│ │ ├── tree.js # [NEW] buildTree(b_id/b_parent_id)/sortTree(b_xh,b_id)
|
||||
│ │ └── lucideIcons.js # [NEW] getIcon(name) 按名取 @lucide/vue 图标
|
||||
│ ├── router/
|
||||
│ │ └── index.js # [MODIFY] / 挂 DefaultLayout + dashboard 子路由 + 权限守卫
|
||||
│ ├── views/
|
||||
│ │ ├── dashboard/index.vue # [MODIFY] 改为布局内内容页(去掉独立全屏壳/退出按钮)
|
||||
│ │ ├── login/index.vue # 不变
|
||||
│ │ └── demo/index.vue # 不变
|
||||
│ ├── App.vue # 不变(router-view)
|
||||
│ └── main.js # 不变(initThemeSync 保持)
|
||||
└── package.json # 不变(不新增依赖)
|
||||
```
|
||||
|
||||
## 关键约定
|
||||
|
||||
- 所有组件 props/事件命名沿用自研组件库现有 API(如 Button type/block/loading、Dropdown items/#menu(close))
|
||||
- 页面过渡与全局布局样式放 DefaultLayout 非 scoped style;组件内布局细节用 scoped scss
|
||||
- 不使用 TS 类型标注;复杂接口用 JSDoc 注释说明(如 NavItem:{ title, url, icon?, items?, moduleId? })
|
||||
|
||||
## Agent Extensions
|
||||
|
||||
### Skill
|
||||
|
||||
- **ui-ux-pro-max**
|
||||
- 用途:查询企业后台管理布局(侧边栏导航/顶栏/页签)的视觉与交互规则,指导自研菜单与 topbar 的 scss 样式细节(hover/active 态、间距、层级),确保迁移后视觉符合现代企业 SaaS 标准
|
||||
- 预期结果:自研 NavMain/NavMenuItem/AppTopbar/AppTabs 的 scss 达到与 old2 视觉质量相当的水平(若脚本无法执行则读取其 references 规则文档落地)
|
||||
Reference in new issue
Block a user