10 KiB
web-admin 列表工具栏「更多」溢出收纳设计
日期:2026-10-02
状态:已落地(实现计划见 docs/superpowers/plans/2026-10-02-list-toolbar-overflow.md)
参考实现:web-admin/src/views/pl/plan/index.vue + web-admin/src/components/business/list-toolbar-overflow/
范围:web-admin HIGH + MEDIUM 列表页工具栏;不含小程序、不含 LOW 页、不含流程节点配置条。
背景与目标
运输计划列表已用 ListToolbarOverflow:宽度不足时,次要操作收入「更多」下拉。其它业务列表仍把大量 el-button / ListExportDropdown 平铺在工具栏,窄屏拥挤。
已确认决策
| 项 | 决策 |
|---|---|
| 覆盖范围 | HIGH + MEDIUM(约 30+ 页);LOW(次要操作 ≤2)跳过 |
| 落地方式 | 方案 B:复用现有 ListToolbarOverflow,抽公共工厂函数统一常见项;页面组装业务特有项 |
| 主操作 | 唯一 btn-main / type="primary" 固定在溢出组件外 |
| 编辑/删除 | 进溢出池,但排在靠前位置(宽屏优先平铺,窄屏较晚收入「更多」) |
| 清空列过滤 | 溢出池最末(最易进「更多」);运输计划现有顺序一并调整对齐 |
| 导出 | 用 key: 'export' + #export slot 挂 ListExportDropdown(与运输计划一致;若页内已是 children 式导出可保留 children) |
| 不动 | 日期快捷、快捷搜索、ListToolbarEndActions(刷新/列设置) |
| 本批不做 | 流程配置条(上移/下移/保存配置);仅 1~2 个次要按钮的 LOW 页 |
布局约定
工具栏从左到右:
[日期快捷?] → [快捷搜索?] → [唯一主操作] → [ListToolbarOverflow] → [ListToolbarEndActions]
- 主操作始终外显(如「新增*」「归档」「发放」「处理」;plan-cert 等互斥主按钮按页保留其现有主色切换逻辑,主色者在外、次要进池)。
- 溢出池内从左到右 = 优先保留;算法从右侧收入「更多」(见
calcListToolbarOverflowVisibleCount)。
溢出池推荐顺序
- 行级高频:编辑、删除、复制、处理/发放/归档调整等
- 业务次要:提交审批、撤回、批量上/下架、导入、下载模板、证书 ZIP、查看审批流等
- 导出(slot 或 children)
- 清空列过滤(
hidden: !hasActiveFilters,始终排最末)
公共能力
已有(不改算法,仅复用)
| 路径 | 职责 |
|---|---|
components/business/list-toolbar-overflow/index.vue |
测量宽度、平铺可见项、「更多」菜单 |
components/business/list-toolbar-overflow/types.ts |
ListToolbarOverflowItem |
components/business/list-toolbar-overflow/ToolbarOverflowAction.vue |
默认按钮/子下拉渲染 |
utils/list-toolbar-overflow.ts |
calcListToolbarOverflowVisibleCount |
新增工厂(建议路径)
web-admin/src/utils/list-toolbar-overflow-items.ts(纯函数,无 Vue 生命周期依赖)
提供可组合工厂,页面 computed 内组装数组,例如:
| 工厂 | 约定 |
|---|---|
overflowEditItem(opts) |
key: 'edit',图标 Edit/EditPen 由 opts 传入,默认 Edit |
overflowDeleteItem(opts) |
key: 'delete',type: 'danger' |
overflowClearFiltersItem(hasActive, onClear) |
key: 'clearFilters',hidden: !hasActive |
overflowExportPlaceholder() |
{ key: 'export', label: '导出' },配合 #export slot;若不用 slot 可不调用 |
不做成强制「一个 composable 管全页」:特殊页(证件双主按钮、合同审批态按钮)可手写 items,只遵守顺序约定与类型。
运输计划可继续手写 toolbarOverflowItems,但须把 clearFilters 移到数组末尾以符合本约定。
页面改造模板
<div class="list-toolbar-row">
<!-- 日期 / 搜索(若有) -->
<el-button class="btn-main" type="primary" @click="handleAdd">…新增…</el-button>
<ListToolbarOverflow :items="toolbarOverflowItems">
<template #export>
<ListExportDropdown … />
</template>
</ListToolbarOverflow>
<ListToolbarEndActions … />
</div>
const toolbarOverflowItems = computed<ListToolbarOverflowItem[]>(() => [
overflowEditItem({ disabled: selectedRows.value.length !== 1, onClick: handleToolbarEdit }),
overflowDeleteItem({ disabled: selectedRows.value.length === 0, onClick: handleDelete }),
// 业务特有项插在导出之前
overflowExportPlaceholder(),
overflowClearFiltersItem(hasActiveFilters.value, clearAllFilters)
])
行级 list-toolbar-row 若与运输计划同骨架(日期 pills + 搜索),须保证工具栏行 min-width: 0(可复用或对齐 pl-plan-list-toolbar-row),让 ListToolbarOverflow 的 flex: 1 吃到剩余宽度,避免整行换行导致测量失真。
目标页面清单
计数口径:业务操作(含条件性清空列过滤、导出);不含日期快捷、快捷搜索、EndActions。
批次 0 — 基建
- 新增
list-toolbar-overflow-items.ts - 调整
pl/plan/index.vue:clearFilters移至溢出池末尾
批次 1 — PL 兄弟页(与 plan 同骨架)
| 路径 | 主操作(外) | 溢出池要点 |
|---|---|---|
views/pl/plan-cert/index.vue |
「证书齐备」/「上传证书」主色切换逻辑保留在外 | 取消齐备、导出、清空列过滤 |
views/pl/plan-archive/index.vue |
归档/调整 | 导出、ERP 录入、清空列过滤等次要 |
批次 2 — 最挤业务列表
| 路径 | 主操作(外) | 溢出池要点(编辑/删除靠前) |
|---|---|---|
views/bx/reimburse/apply/index.vue |
新增报销申请 | 编辑、删除、下载模板、批量导入、提交/撤回、查看审批流、导出、清空 |
views/bx/advance/apply/index.vue |
新增备用金申请 | 同报销结构(无导入模板则省略) |
views/crm/clue/index.vue |
新增线索 | 编辑、跟进、删除、批量分配、转为客户、标无效、导出、清空 |
views/crm/product/index.vue |
新增产品 | 编辑、删除、批量上/下架、导入、产品分类、导出、清空 |
views/crm/contract/ContractListPage.vue |
新增 | 复制、提交审批、作废恢复、审批通过/驳回(审批态)、上传扫描件、导出、清空 |
views/crm/quote/QuoteListPage.vue |
新增 | 复制新增、提交审批、生成报价单、作废、审批(审批页)、导出、清空 |
批次 3 — 其余 HIGH
| 路径 | 主操作(外) |
|---|---|
views/crm/contract/change/index.vue |
新增变更 |
views/crm/price-letter/index.vue |
新增调价函 |
views/pl/personnel/index.vue |
新增人员 |
views/pl/vehicle/index.vue |
新增车辆 |
views/pl/vehicle-recharge-apply/index.vue |
新增申请 |
views/pl/freight/components/SettlementBillPanel.vue |
编辑/发票信息(现有主色) |
views/bx/expense-item/index.vue |
新增一级项目 |
views/system/role/index.vue |
新增角色 |
views/system/dict/index.vue |
新增(主表;字典数据子栏若按钮多可同样接入) |
views/system/post/index.vue |
新增职位 |
批次 4 — MEDIUM
| 路径 | 主操作(外) |
|---|---|
views/crm/customer/index.vue |
新增客户 |
views/crm/opportunity/index.vue |
新增商机 |
views/crm/customer/pool/RuleIndex.vue |
新增规则 |
views/crm/contract/template/index.vue |
新增模板 |
views/pl/self-vehicle/index.vue |
新增自有车辆 |
views/pl/vehicle-fuel-register/FuelRegisterListPage.vue |
新增登记 |
views/pl/vehicle-maintenance-process/index.vue |
处理 |
views/pl/vehicle-recharge-record/index.vue |
发放 |
views/pl/vehicle-urea-disburse/index.vue |
发放 |
views/system/user/index.vue |
新增用户 |
views/system/tenant/index.vue |
新增租户 |
views/system/leave/index.vue |
新增请假 |
views/system/workflow/process/index.vue |
新增流程 |
views/db/plans/index.vue |
新增计划 |
views/db/inventory/index.vue |
新增记录 |
views/db/weighing/index.vue |
新增地磅单 |
views/pl/vehicle-maintenance-apply/index.vue |
新增申请 |
views/pl/vehicle-urea-apply/index.vue |
新增申请 |
views/system/dept/index.vue |
新增 |
views/system/menu/index.vue |
新增 |
实施时可按实际按钮数微调:若某页次要操作已 ≤2,降为跳过。
明确跳过(本设计)
pl/plan-contract等 LOWbx/*/approve、bx/view/*等审批只读向、按钮少的页(除非验收时发现仍挤)bx/workflow/*、pl/vehicle-recharge-workflow流程节点配置条- Demo 页(
views/demo/*)可选,非必须
实施约束
- 最小改动:只改工具栏模板与
toolbarOverflowItems(及工厂文件);不重构列表查询/权限。 - 图标:溢出项按钮须带前置
el-icon(与 OpenSpec UI「按钮须携带图标」一致);工厂默认带图标。 - 主色唯一:工具栏行仍仅一个
type="primary"(在外);溢出池内默认btn-ghost。 - 样式:需要收缩时给工具栏行
min-width: 0,保证ListToolbarOverflow的flex: 1能拿到剩余宽度。 - 文档:落地后可在
docs/web-admin-ui-pattern-index.md或 Fresh Mint 列表工具栏小节补一句「次要操作使用 ListToolbarOverflow」;OpenSpecui-conventions若有工具栏 SHALL,同步一句(实现计划阶段再定是否写入)。
验收标准
- 宽屏:编辑/删除等优先平铺;无「更多」或「更多」项很少。
- 逐步缩窄窗口:导出、清空列过滤先入「更多」;编辑/删除较晚。
- 主操作与 EndActions 始终可见。
- 「更多」内导出、带子菜单项可点击且 disabled 态正确。
pl/plan清空列过滤位于溢出池末尾,行为与改造前一致(仅收纳优先级变化)。
风险与缓解
| 风险 | 缓解 |
|---|---|
| 自定义导出组件测量宽度不准 | 与 plan 相同:measure/button 模式走 #export slot |
条件 v-if 按钮导致宽度抖动 |
用 hidden 进 items,由组件过滤,避免 DOM 突然增减难测 |
| 页太多易漏测 | 按批次改 + 每批抽查 1 个宽屏/窄屏;优先 visual 验收 plan-cert / 报销申请 / 产品 |
非目标
- 不引入新的第三套工具栏组件。
- 不把操作列按钮迁入工具栏(已外置的保持外置)。
- 不在本变更修改后端 API。