9.3 KiB
9.3 KiB
name, overview, design, todos
| name | overview | design | todos | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| pagination-component | 按开发规范并参考 antdv-next 设计,新增 fms-vue 的 Pagination 分页组件(含页码折叠、sizeChanger、quickJumper、showTotal、非受控/受控双 v-model),并在 App.vue 演示页补充导航与示例。 |
|
|
产品概述
在 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;currentprop 未传时用内部值- 变化时统一走
applyChange(page, pageSize):受控模式 emitupdate:current/update:pageSize,非受控模式写内部 ref,均 emitchange;pageSize 变化额外 emitshowSizeChange - 越界回退: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、禁用语义)