11 KiB
11 KiB
name, overview, design, todos
| name | overview | design | todos | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AppTabs 操作按钮组与应用内最大化 | 在页签栏 AppTabs 最左侧新增「一体的、带分割线」的三图标按钮组(返回控制台 / 刷新当前路由 / 留空占位),最右侧新增「应用内最大化」按钮;最大化时隐藏侧边栏+顶栏+页签栏,内容区占满窗口,并提供退出浮窗。 |
|
|
用户需求
在页签栏 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 规范
实现方案
策略
- 状态下沉到
useAppStore:新增contentMaximized(ref(false))+toggleContentMaximized(),以及routeRefreshKey(ref(0))+refreshRoute()(自增计数)。两者均不加入persist.pick(当前只持久化locale),避免刷新/最大化状态被持久化。 AppTabs接线:
- 标签轨道前插入「左侧操作组」
.tab-actions(一体化容器,含 3 个按钮 + 2 条竖向分割线)。按钮 1 调router.push('/dashboard');按钮 2 调appStore.refreshRoute();按钮 3 禁用、无图标。 - 右滚动按钮后插入「最大化」按钮,调
appStore.toggleContentMaximized(),图标按contentMaximized在Maximize2/Minimize2间切换(退出时页签栏已隐藏,此图标仅作状态提示,真正退出走浮动按钮)。
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切换为纯 CSSdisplay切换,无重渲染、无额外网络请求;最大化状态不持久化,刷新页面后默认恢复常规布局。- 不改通用接口、不改其他页面、不改权限逻辑;仅触及
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节奏,保持与页签栏其他元素对齐。