Files
workspace/code/fms/.codebuddy/plans/AppTabs_操作按钮组与应用内最大化_6f4058df.md
T
2026-07-22 22:25:10 +08:00

11 KiB
Raw Blame History

name, overview, design, todos
name overview design todos
AppTabs 操作按钮组与应用内最大化 在页签栏 AppTabs 最左侧新增「一体的、带分割线」的三图标按钮组(返回控制台 / 刷新当前路由 / 留空占位),最右侧新增「应用内最大化」按钮;最大化时隐藏侧边栏+顶栏+页签栏,内容区占满窗口,并提供退出浮窗。
styleKeywords fontSystem colorSystem
企业级扁平
一体化分段工具栏
竖向分割线
蓝色主色高亮
轻量 hover
桌面端
fontFamily heading subheading body
PingFang SC
size weight
14px 600
size weight
13px 500
size weight
12px 400
primary background text functional
#1677ff
#0958d9
#ffffff
#f5f7fa
#1f2329
#646a73
#e5e8eb
#f2f3f5
#e6f4ff
#c9cdd4
id content status
store-state 在 app store 新增 contentMaximized 与 routeRefreshKey 状态及切换/刷新方法(不持久化) completed
id content status dependencies
apptabs-buttons AppTabs 新增左侧三按钮一体化组(返回/刷新/占位+分割线)与右侧最大化按钮并接线 completed
store-state
id content status dependencies
default-layout DefaultLayout 应用内最大化隐藏三块布局、加浮动退出按钮、路由刷新 key 接入 completed
store-state
id content status dependencies
verify 校验返回/刷新/最大化/退出交互与各页面正常且未触发整页刷新 completed
apptabs-buttons
default-layout

用户需求

在页签栏 AppTabs 上新增操作按钮:

  • 最左侧新增一组「一体化的三个图标按钮」,按钮之间以分割线分隔,视觉上是一个整体。
  • 第 1 个(最左):返回控制台按钮,点击跳转到 /dashboard(工作台)。
  • 第 2 个(中间):刷新按钮,要求重新挂载当前路由组件(各页面 onMounted 重新执行、重新拉数据),不能刷新整站(router.go(0) / location.reload() 禁止)。
  • 第 3 个(最右):暂不确定功能,先留空占位——保留按钮槽位与分割线,禁用状态、无图标。
  • 最右侧新增一个「收缩全屏」按钮,用户确认行为为应用内最大化:隐藏侧边栏 + 顶栏 + 页签栏,让内容区占满整个窗口(仍是网页,不调用浏览器 Fullscreen API)。该按钮放在 AppTabs 最右侧。

产品概述

为内部管理系统页签栏补充快捷操作:左侧一组统一风格的工具按钮(返回控制台 / 刷新路由 / 占位),右侧一个「应用内最大化」开关。最大化后,侧边栏、顶栏、页签栏全部收起,仅留内容区;因承载开关的页签栏随之隐藏,需在内容区右上角浮动一个「退出最大化」按钮用于恢复。

核心特性

  • 左侧三按钮为「一体容器 + 分割线」的视觉整体,风格对齐现有 tab-nav-button。
  • 返回控制台:router.push('/dashboard')。
  • 刷新路由:通过 appStore.routeRefreshKey 自增,驱动 DefaultLayout 中 <component :key> 变化以重挂载当前路由(非整页刷新)。
  • 应用内最大化:由 appStore.contentMaximized 控制,DefaultLayout 用 v-show 收起三块布局,内容区右上角出现浮动退出按钮。
  • 占位按钮:禁用、无图标、保留分割线,后续可随时接入功能。

技术栈

  • 前端:Vue 3 <script setup> + Vite + antdv-next + Pinia(沿用现有项目栈)
  • 图标:@lucide/vue(复用现有图标习惯,新增 House / RotateCw / Maximize2 / Minimize2)
  • 样式:组件内 scoped lang="scss",复用全局 --fms-* 主题变量,遵循「少量 CSS / 公用集中 / 不兼容移动端」CSS 规范

实现方案

策略

  1. 状态下沉到 useAppStore:新增 contentMaximized(ref(false))+ toggleContentMaximized(),以及 routeRefreshKey(ref(0))+ refreshRoute()(自增计数)。两者均不加入 persist.pick(当前只持久化 locale),避免刷新/最大化状态被持久化。
  2. AppTabs 接线:
  • 标签轨道前插入「左侧操作组」.tab-actions(一体化容器,含 3 个按钮 + 2 条竖向分割线)。按钮 1 调 router.push('/dashboard');按钮 2 调 appStore.refreshRoute();按钮 3 禁用、无图标。
  • 右滚动按钮后插入「最大化」按钮,调 appStore.toggleContentMaximized(),图标按 contentMaximized 在 Maximize2 / Minimize2 间切换(退出时页签栏已隐藏,此图标仅作状态提示,真正退出走浮动按钮)。
  1. DefaultLayout 收起布局 + 路由刷新:
  • AppSidebar / AppToolbar / AppTabs 包裹 v-show="!appStore.contentMaximized"(用 v-show 而非 v-if,保留页签与折叠状态,避免重挂载开销)。
  • 内容区 <component :is="Component" :key="route.fullPath + ':' + appStore.routeRefreshKey">——routeRefreshKey 变化即强制重挂载当前路由组件,达成「刷新当前路由」。
  • 内容区右上角新增 fixed 浮动「退出最大化」按钮(v-if="appStore.contentMaximized"),点击 toggleContentMaximized() 恢复。

关键技术决策

  • 刷新用 key 自增而非整页 reload:keep-alive 下组件按 :key 缓存,route.fullPath + ':' + routeRefreshKey 变化会创建新实例并触发 onMounted,等价于「重进当前页」而不重载网站;原有过渡/缓存结构不变。
  • 最大化用 v-show:与 v-if 相比不销毁 AppTabs/AppSidebar,保留 visitedTabs、sidebarCollapsed 等内存状态,退出后零重新加载;display:none 不影响键盘/焦点无障碍(内部按钮仍可达)。
  • 退出入口与开关解耦:因最大化时 AppTabs 被隐藏,退出动作改由内容区浮动按钮承载,保证「进入必有出口」。
  • 风格对齐:左侧操作组直接复用 tab-nav-button 的尺寸/圆角/配色(26×28、radius 4、--tabs-idle-bg/--fms-text-secondary),仅在外层加统一个边框与 1px 分割线,满足「一体 + 分割线」。

性能与可靠性

  • 路由刷新为低频用户操作:每次刷新在 keep-alive 中产生一个新缓存槽。keep-alive 当前为裸标签(无 max),理论上可无限增长;本场景为人工触发、频率极低,可接受。若后续需要可加 :max 限制缓存数——本次不改以避免影响现有缓存语义。
  • v-show 切换为纯 CSS display 切换,无重渲染、无额外网络请求;最大化状态不持久化,刷新页面后默认恢复常规布局。
  • 不改通用接口、不改其他页面、不改权限逻辑;仅触及 app.js / DefaultLayout.vue / AppTabs.vue 三处。

实现注意

  • app.js 的 persist.pick 保持 ["locale"] 不变,新增状态不持久化。
  • DefaultLayout.vue 当前无 <script setup>,需补 import { useRoute } from 'vue-router' 与 import { useAppStore } 并取 route/appStore,再改 :key 与加 v-show/浮动按钮。
  • 返回控制台按钮在 /dashboard 时点击应无副作用(vue-router 对相同路径 push 静默处理)。
  • 左侧操作组与右侧最大化按钮均需 aria-label,占位按钮加 disabled 与 title="敬请期待"。
  • 样式保持 scoped,与现有 tab-header 高度(34px)、间距(gap 4px)一致;分割线用 border-left + margin。

架构设计

flowchart TD
  A[AppTabs 左侧操作组] -->|返回控制台| B[router.push /dashboard]
  A -->|刷新路由| C[appStore.refreshRoute 自增 routeRefreshKey]
  A -->|占位 禁用| Z[无操作]
  D[AppTabs 右侧最大化按钮] -->|toggleContentMaximized| E[appStore.contentMaximized=true]
  E --> F[DefaultLayout v-show 隐藏 Sidebar/Toolbar/Tabs]
  E --> G[内容区浮动 退出最大化 按钮显示]
  G -->|toggleContentMaximized| H[恢复常规布局]
  C --> I[DefaultLayout :key 变化 重挂载路由组件]

目录结构

fms-vue/src/
├── stores/
│   └── app.js                       # [MODIFY] 新增 contentMaximized/toggleContentMaximized 与
│                                    # routeRefreshKey/refreshRoute;persist.pick 仍为 ["locale"]。
├── layouts/
│   ├── DefaultLayout.vue            # [MODIFY] 引入 useRoute/useAppStore;三块布局加
│                                    # v-show="!contentMaximized";<component :key> 加入
│                                    # routeRefreshKey;内容区加浮动退出最大化按钮。
│   └── components/
│       └── AppTabs.vue              # [MODIFY] 标签轨道前加左侧一体三按钮组(返回/刷新/占位+分割线);
│                                    # 右滚动按钮后加最大化按钮;import 新图标并接线。

关键代码结构

// src/stores/app.js 新增状态
const contentMaximized = ref(false);
const routeRefreshKey = ref(0);
function toggleContentMaximized() { contentMaximized.value = !contentMaximized.value; }
function refreshRoute() { routeRefreshKey.value++; }
// 返回中需导出 contentMaximized, routeRefreshKey, toggleContentMaximized, refreshRoute

// DefaultLayout.vue 中 <component> 的 key
<component :is="Component" :key="route.fullPath + ':' + appStore.routeRefreshKey" />

设计风格

延续现有 FMS 企业级扁平风格(白底、蓝色主色 #1677ff、细边框、轻量 hover)。在 34px 高的页签栏内新增两类控件,与既有 tab-nav-button 视觉一致,不引入新色彩或拟物风格。

左侧一体化按钮组

  • 一个统一的外层容器 .tab-actions:浅边框、4px 圆角、与页签栏同高,内含 3 个等宽图标按钮,按钮之间以 1px 竖向分割线隔开,整体观感如一个「分段工具栏」。
  • 按钮 1(House 图标):返回控制台;hover 时文字/图标转主色蓝、背景转 --tabs-active-bg。
  • 按钮 2(RotateCw 图标):刷新当前路由;hover 态同上。
  • 按钮 3(占位):禁用态、无图标、保留分割线,视觉稍淡(opacity 0.4),title="敬请期待"。
  • 图标尺寸 14px(对齐 .lucide 习惯),按钮 26×28,圆角 4px。

右侧最大化按钮

  • 位于右滚动箭头之后,独立图标按钮(Maximize2 / 退出时 Minimize2),样式复用 tab-nav-button。
  • 最大化激活后:侧边栏、顶栏、页签栏整体 display:none,内容区占满窗口;内容区右上角浮现一个 fixed 圆角胶囊「退出最大化」按钮(退出箭头图标 + 文字),hover 浅色背景,点击恢复三块布局。

交互与响应式

  • 纯桌面端,不做移动端媒体查询(遵循 CSS 规范第 4 条)。
  • 所有按钮带 a-tooltip 文字提示与 aria-label;hover/active 有平滑颜色过渡(0.15s ease)。
  • 分割线与按钮间距使用现有 gap:4px 节奏,保持与页签栏其他元素对齐。