Files
workspace/code/fms/.codebuddy/plans/pagination-component_b3c90f94(未完成).md
T
2026-08-16 22:01:32 +08:00

179 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: pagination-component
overview: 按开发规范并参考 antdv-next 设计,新增 fms-vue 的 Pagination 分页组件(含页码折叠、sizeChanger、quickJumper、showTotal、非受控/受控双 v-model),并在 App.vue 演示页补充导航与示例。
design:
architecture:
framework: vue
styleKeywords:
- 简洁
- 中性色
- 主色强调
- 等宽页码
- 清晰状态
fontSystem:
fontFamily: PingFang SC
heading:
size: 14px
weight: 600
subheading:
size: 14px
weight: 400
body:
size: 14px
weight: 400
colorSystem:
primary:
- "#0f172b"
- "#ffffff"
background:
- "#ffffff"
- "#f5f6f8"
- "#f1f5f9"
text:
- "#1f2329"
- "#86909c"
- "#ffffff"
functional:
- "#e5e6eb"
- "#c9cdd4"
- "#f2f3f5"
todos:
- id: create-pagination-component
content: 使用 [skill:ui-ux-pro-max] 核对分页交互规范后,创建 pagination.vue:props/emits、页码窗口算法、受控/非受控双模式
status: completed
- id: build-pagination-template
content: 完成 pagination.vue 模板:页码/省略号/prev-next、sizeChanger 复用 Select、quickJumper 复用 Input、showTotal 与 ARIA
status: completed
dependencies:
- create-pagination-component
- id: write-pagination-styles
content: 编写 index.scss:页码项各状态、省略号 hover 双箭头、布局间距,全部复用 --fms-* token
status: completed
dependencies:
- build-pagination-template
- id: add-pagination-demo
content: App.vue 新增 Pagination 导航项与演示 section(基础/条数切换/快速跳转/总数/禁用/单页隐藏),静态检查后汇报
status: in_progress
dependencies:
- write-pagination-styles
---
## 产品概述
在 fms-vue 组件库中新增 Pagination 分页组件:参考 antdv-next 的 Pagination 设计(current/pageSize 双 v-model、页码窗口与省略号跳转、每页条数切换、快速跳转、总数显示),按本项目开发规范做轻量化实现,并在演示站 App.vue 中新增展示。
## 核心功能
- 页码导航:首页 / 尾页固定展示,当前页前后各 1 页,中间用省略号折叠;省略号点击跳 ±5 页;上一页 / 下一页箭头按钮
- 每页条数切换(showSizeChanger):复用 Select 组件,选项默认 [10, 20, 50, 100]
- 快速跳转(showQuickJumper):复用 Input 数字输入,Enter 跳转到指定页
- 总数显示(showTotal):默认显示「共 X 条」,支持插槽自定义文案
- 受控 / 非受控双模式:不传 v-model 时组件内部维护 current 与 pageSize(参照 Tabs 先例)
- 边界与禁用:单页时可选隐藏(hideOnSinglePage)、整组禁用、页码越界自动回退、页码 1 时上一页禁用等
- 可访问性:页码按钮原生 disabled、当前页 aria-current、图标按钮带 aria-label、focus-visible 焦点样式
## 视觉效果
- 页码项为 32px 等宽方形按钮,与控件高度 token 一致;当前页主色填充,hover/焦点主色描边,禁用降级为灰
- 整体水平排列、间距 8px,与 Tabs 等现有组件间距体系一致;深色模式自动适配 tokens
## 技术栈
- Vue 3 `<script setup>` + Vite + Sass,与现有组件库一致
- 图标按需导入 Lucide(ChevronLeft / ChevronRight / ChevronsLeft / ChevronsRight / Ellipsis)
- 复用现有 Select(每页条数)、Input type="number"(快速跳转)、Button(无需,页码项为原生 button)
- 样式全部复用 `--fms-*` token,不新增 token(页码项尺寸由 `--fms-control-height` 派生)
## 实现方案
### API 设计
Props(均带类型与默认值,枚举带 validator):
| Prop | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| current | Number | undefined | 当前页(受控时传,非受控不传) |
| pageSize | Number | 10 | 每页条数 |
| total | Number | 0 | 总条数 |
| disabled | Boolean | false | 整组禁用 |
| hideOnSinglePage | Boolean | false | 仅 1 页时隐藏 |
| showSizeChanger | Boolean | false | 显示每页条数切换 |
| pageSizeOptions | Array | [10, 20, 50, 100] | 每页条数选项 |
| showQuickJumper | Boolean | false | 显示快速跳转 |
| showTotal | Boolean | false | 显示「共 X 条」(配合 #showTotal 插槽自定义) |
事件:`update:current`、`update:pageSize`、`change(page, pageSize)`、`showSizeChange(current, size)`(pageSize 变化时触发)。
插槽:`showTotal`(作用域 `{ total, from, to }`,用于自定义总数文案)。
### 页码窗口算法
`totalPages = Math.max(1, Math.ceil(total / pageSize))`;`pageItems` 计算属性生成:
- totalPages ≤ 7:展示全部页码
- 否则:固定含 1 与 totalPages,含 current-1/current/current+1;中间空隙插入 `jump-prev` / `jump-next` 省略号项(点击跳 `current ± 5`,clamp 到 [1, totalPages])
每个项结构:`{ type: 'page'|'jump-prev'|'jump-next'|'prev'|'next', page }`,模板按 type 渲染;全部用 computed 预生成,不在模板中调用创建对象的函数。
### 受控 / 非受控双模式(参照 Tabs 先例)
- `innerCurrent` / `innerPageSize` 两个内部 ref;`current` prop 未传时用内部值
- 变化时统一走 `applyChange(page, pageSize)`:受控模式 emit `update:current` / `update:pageSize`,非受控模式写内部 ref,均 emit `change`;pageSize 变化额外 emit `showSizeChange`
- 越界回退:current 超出 [1, totalPages] 时展示层 clamp 到边界(受控不写回,保持受控语义)
- pageSize 变化导致 current 超界时,非受控模式同步调整 current
### 子部件复用要点
- **sizeChanger**:`<Select :model-value="pageSize" :options="pageSizeOptions" :filterable="false" @update:model-value="onSizeChange" style="width: 76px; min-width: 76px" />`。Select 根默认 `min-width: 200px`,须用内联样式覆盖宽度,浮层仍跟随触发器
- **quickJumper**:`<Input type="number" ...>`,本地 ref 维护输入值,Enter 提交(clamp 到 [1, totalPages] 后触发跳转并清空)、失焦清空;Enter 监听依赖 Input 根元素事件透传,若透传受限则在外层 div 监听 keydown(冒泡兜底)
- 禁用时 Select/Input 同步传 disabled
### 键盘与 ARIA
- 容器 `role="navigation"` + `aria-label="分页"`
- 当前页码项 `aria-current="page"`;prev/next 图标按钮 `aria-label="上一页" / "下一页"`
- 所有页码项为原生 `<button type="button">`,禁用状态同时反映原生 disabled 与视觉(not-allowed)
- `:focus-visible` 主色 outline(复用 Tabs/Button 焦点规范)
### 性能与可靠性
- 页码数组、总页数、显示范围(from/to)均为 computed 缓存,无重复计算
- 无高频事件、无全局监听器、无 watch 深度监听;跳转输入仅本地 ref
- 图标按需导入,样式只定义一套状态选择器,无 !important、无多余包裹层
## 目录结构
```
fms-vue/src/components/ui/pagination/
├── pagination.vue # [NEW] 分页主组件:页码窗口算法、受控/非受控切换、模板(页码/省略号/prev-next/sizeChanger/quickJumper/showTotal)
└── index.scss # [NEW] 样式:页码项各状态(默认/hover/focus/active/disabled)、省略号、布局与间距,全部复用 --fms-* token
fms-vue/src/App.vue # [MODIFY] categories 通用分组新增 { key: 'pagination', label: 'Pagination 分页' };新增演示 section
```
不新增其他文件;分页逻辑单文件承载,无 barrel index。
## 已知风险与规避
- Select 宽度覆盖:内联 style 覆盖根 min-width,已在上文写明
- Input 事件透传:keydown.enter 若未透传则外层包装监听,方案已定
- 省略号 hover 双箭头效果依赖 CSS(hover 切换图标),用两个图标 + CSS 显隐,成本低;`prefers-reduced-motion` 下关闭过渡
## 设计风格
延续项目现有 tokens 驱动的简洁中性风格,参考 antd Pagination 经典形态,保证与 Button / Tabs 等组件视觉一致。
- 布局:整体 inline-flex 水平排列、gap 8px;页码项与箭头按钮等高 32px(复用 --fms-control-height);showTotal 居左、sizeChanger 与 quickJumper 居右;空间不足时允许 flex-wrap 换行
- 页码项:32px 等宽方形(min-width 与 height 同值),圆角 6px;默认白底 1px 边框 + 次级文字;hover 主色描边与文字;当前页主色填充 + 白色文字 + 字重 600(不只靠颜色表达选中);禁用降为灰底灰字 not-allowed
- 省略号项:居中 Ellipsis 图标,hover 时切换为 ChevronsLeft / ChevronsRight 双箭头并显示主色,点击跳 ±5 页
- 交互反馈:hover 与 :focus-visible 均呈现主色描边;过渡仅限颜色/边框低成本属性,prefers-reduced-motion 关闭
- 数字稳定性:页码数字使用 tabular-nums,切换页时不抖动
- 暗色模式:所有颜色走 --fms-* token,.dark 自动适配,无需额外样式
## Agent Extensions
### Skill
- **ui-ux-pro-max**
- 用途:实现前查询分页组件(pagination)的键盘操作、可访问性与视觉细节 UX 规则,核对页码窗口交互是否符合常见实践
- 预期结果:获得分页导航的交互/可访问性指引(如页码按钮焦点、aria-current、省略号跳转习惯);若查询无有效输出,则回退到开发规范内置的交互底线(focus-visible、ARIA、禁用语义)