Files
shanxia2.0/docs/superpowers/specs/2026-10-02-list-toolbar-overflow-design.md
T
2026-10-05 12:57:51 +08:00

10 KiB
Raw Blame History

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)。

溢出池推荐顺序

  1. 行级高频:编辑、删除、复制、处理/发放/归档调整等
  2. 业务次要:提交审批、撤回、批量上/下架、导入、下载模板、证书 ZIP、查看审批流等
  3. 导出(slot 或 children)
  4. 清空列过滤(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 等 LOW
  • bx/*/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」;OpenSpec ui-conventions 若有工具栏 SHALL,同步一句(实现计划阶段再定是否写入)。

验收标准

  1. 宽屏:编辑/删除等优先平铺;无「更多」或「更多」项很少。
  2. 逐步缩窄窗口:导出、清空列过滤先入「更多」;编辑/删除较晚。
  3. 主操作与 EndActions 始终可见。
  4. 「更多」内导出、带子菜单项可点击且 disabled 态正确。
  5. pl/plan 清空列过滤位于溢出池末尾,行为与改造前一致(仅收纳优先级变化)。

风险与缓解

风险 缓解
自定义导出组件测量宽度不准 与 plan 相同:measure/button 模式走 #export slot
条件 v-if 按钮导致宽度抖动 用 hidden 进 items,由组件过滤,避免 DOM 突然增减难测
页太多易漏测 按批次改 + 每批抽查 1 个宽屏/窄屏;优先 visual 验收 plan-cert / 报销申请 / 产品

非目标

  • 不引入新的第三套工具栏组件。
  • 不把操作列按钮迁入工具栏(已外置的保持外置)。
  • 不在本变更修改后端 API。