20260722222510

This commit is contained in:
oneao committed 2026-07-22 22:25:10 +08:00
1 parent d04fad24ed
commit 59b3ccfb1c
36 files changed
+2753 -3064

No files matched your search

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