2026-10-02-list-toolbar-overflow.md 16 KB

web-admin 列表工具栏「更多」溢出收纳 Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 在 HIGH/MEDIUM 列表页复用 ListToolbarOverflow,窄屏将次要操作收入「更多」;编辑/删除优先平铺,导出与清空列过滤最后收纳。

Architecture: 复用现有 ListToolbarOverflow 测量算法;新增纯函数工厂 list-toolbar-overflow-items.ts 统一 edit/delete/export/clearFilters;各列表页将次要按钮改为 toolbarOverflowItems + 可选 #export slot。主操作与 ListToolbarEndActions 留在溢出组件外。运输计划把 clearFilters 挪到溢出池末尾以对齐新约定。

Tech Stack: Vue 3、Element Plus、ListToolbarOverflow、Node node:test(与现有 *.test.ts 一致)

规格: docs/superpowers/specs/2026-10-02-list-toolbar-overflow-design.md

Commit 约定: 仅在用户明确要求时执行 git commit;计划中的 Commit 步骤表示「可提交的逻辑切点」,执行时默认跳过 unless 用户要求提交。


File structure

文件 职责
web-admin/src/utils/list-toolbar-overflow-items.ts 新建:edit/delete/clearFilters/export 工厂
web-admin/src/utils/list-toolbar-overflow-items.test.ts 新建:工厂单元测试
web-admin/src/utils/list-toolbar-overflow.ts 已有算法,本变更不改逻辑
web-admin/src/components/business/list-toolbar-overflow/* 已有组件,本变更原则上不改
web-admin/src/views/pl/plan/index.vue 样板:clearFilters 移末尾
规格清单中的各 views/**/index.vue 等 工具栏改造成 Overflow

标准页改造清单(每页 Task 都执行)

对目标页:

  1. import ListToolbarOverflow 与 ListToolbarOverflowItem(若尚未导入)。
  2. import 工厂:overflowEditItem / overflowDeleteItem / overflowClearFiltersItem / overflowExportPlaceholder(按需)。
  3. 模板:保留日期快捷、快捷搜索、唯一 btn-main、末尾 ListToolbarEndActions;其余次要按钮删除,改为:
<ListToolbarOverflow :items="toolbarOverflowItems">
  <template #export>
    <ListExportDropdown …原有 props… />
  </template>
</ListToolbarOverflow>

若该页导出已是 children 项(无 ListExportDropdown),则不要 #export slot,在 items 里放带 children 的 export 项。

  1. script 增加 toolbarOverflowItems computed;顺序 = 编辑/删除等行级 → 业务次要 → export → clearFilters(最末)。
  2. 若有日期 pills + 搜索导致挤占:给 list-toolbar-row 增加与 pl-plan-list-toolbar-row 等价的 flex-wrap: nowrap; overflow: hidden; min-width: 0 及子项 flex-shrink: 0(主按钮、搜索、EndActions),Overflow 根已 flex: 1; min-width: 0。
  3. 手工验收:宽屏平铺;缩窄后右侧先入「更多」;主按钮与刷新始终可见。

Task 1: 溢出项工厂 + 单元测试

Files:

  • Create: web-admin/src/utils/list-toolbar-overflow-items.ts
  • Create: web-admin/src/utils/list-toolbar-overflow-items.test.ts

  • [ ] Step 1: 写失败测试

import assert from 'node:assert/strict'
import { describe, it } from 'node:test'
import { Edit, Delete, Filter, Download } from '@element-plus/icons-vue'
import {
  overflowEditItem,
  overflowDeleteItem,
  overflowClearFiltersItem,
  overflowExportPlaceholder
} from './list-toolbar-overflow-items'

describe('overflowEditItem', () => {
  it('uses key edit and wires onClick/disabled', () => {
    let clicked = false
    const item = overflowEditItem({
      disabled: true,
      onClick: () => {
        clicked = true
      }
    })
    assert.equal(item.key, 'edit')
    assert.equal(item.label, '编辑')
    assert.equal(item.disabled, true)
    assert.equal(item.icon, Edit)
    item.onClick?.()
    assert.equal(clicked, true)
  })
})

describe('overflowDeleteItem', () => {
  it('uses danger type and key delete', () => {
    const item = overflowDeleteItem({ onClick: () => {} })
    assert.equal(item.key, 'delete')
    assert.equal(item.type, 'danger')
    assert.equal(item.icon, Delete)
  })
})

describe('overflowClearFiltersItem', () => {
  it('hides when no active filters', () => {
    const hidden = overflowClearFiltersItem(false, () => {})
    assert.equal(hidden.key, 'clearFilters')
    assert.equal(hidden.hidden, true)
    assert.equal(hidden.icon, Filter)
    const shown = overflowClearFiltersItem(true, () => {})
    assert.equal(shown.hidden, false)
  })
})

describe('overflowExportPlaceholder', () => {
  it('returns export key for slot rendering', () => {
    const item = overflowExportPlaceholder()
    assert.equal(item.key, 'export')
    assert.equal(item.label, '导出')
    assert.equal(item.icon, Download)
  })
})
  • Step 2: 跑测试确认失败

Run:

cd web-admin && node --import tsx --test src/utils/list-toolbar-overflow-items.test.ts

Expected: FAIL(模块不存在)。若项目惯用其它 runner,查同目录其它 *.test.ts 的跑法并对齐(例如 pnpm exec tsx --test …)。

  • Step 3: 实现工厂

创建 web-admin/src/utils/list-toolbar-overflow-items.ts:

import type { Component } from 'vue'
import { Delete, Download, Edit, Filter } from '@element-plus/icons-vue'
import type { ListToolbarOverflowItem } from '@/components/business/list-toolbar-overflow/types'

type ClickOpts = {
  disabled?: boolean
  loading?: boolean
  label?: string
  icon?: Component
  onClick: () => void
}

export function overflowEditItem(opts: ClickOpts): ListToolbarOverflowItem {
  return {
    key: 'edit',
    label: opts.label ?? '编辑',
    icon: opts.icon ?? Edit,
    disabled: opts.disabled,
    loading: opts.loading,
    onClick: opts.onClick
  }
}

export function overflowDeleteItem(opts: ClickOpts): ListToolbarOverflowItem {
  return {
    key: 'delete',
    label: opts.label ?? '删除',
    icon: opts.icon ?? Delete,
    type: 'danger',
    disabled: opts.disabled,
    loading: opts.loading,
    onClick: opts.onClick
  }
}

export function overflowClearFiltersItem(
  hasActive: boolean,
  onClear: () => void
): ListToolbarOverflowItem {
  return {
    key: 'clearFilters',
    label: '清空列过滤',
    icon: Filter,
    hidden: !hasActive,
    onClick: onClear
  }
}

export function overflowExportPlaceholder(
  label = '导出'
): ListToolbarOverflowItem {
  return {
    key: 'export',
    label,
    icon: Download
  }
}
  • Step 4: 跑测试确认通过

同一命令,Expected: PASS。

  • Step 5: Commit 切点(仅用户要求时)

feat(web-admin): add list toolbar overflow item factories


Task 2: 运输计划 — clearFilters 移到溢出池末尾

Files:

  • Modify: web-admin/src/views/pl/plan/index.vue(toolbarOverflowItems computed)

  • [ ] Step 1: 调整 items 顺序

在 toolbarOverflowItems 中:

  1. 删除数组开头的 clearFilters 项。
  2. 在数组最末(export 项之后)追加:
overflowClearFiltersItem(hasActiveFilters.value, () => clearAllFilters())

或等价手写:

{
  key: 'clearFilters',
  label: '清空列过滤',
  icon: Filter,
  hidden: !hasActiveFilters.value,
  onClick: () => clearAllFilters()
}

最终顺序应为:copy → arrange → waitNotice → print → void → pasteCreate → export → clearFilters。

若采用工厂,增加 import:

import { overflowClearFiltersItem } from '@/utils/list-toolbar-overflow-items'
  • Step 2: 浏览器抽查

打开 /#/pl/plan-module/plan:有列过滤时「清空列过滤」仍可用;缩窄窗口时它应比「复制/安排运输」更早进入「更多」。

  • Step 3: Commit 切点(仅用户要求时)

fix(web-admin): move plan toolbar clear-filters to overflow end


Task 3: plan-cert 接入 Overflow

Files:

  • Modify: web-admin/src/views/pl/plan-cert/index.vue

主操作(外): 保留现有「证书齐备」「上传证书」按钮及主色切换逻辑(均在 Overflow 外)。

溢出池顺序:

  1. cancelReady — 取消齐备(现有 handleToolbarUnmarkCertReady,hidden/v-if 对齐 canCertReady)
  2. export — #export + 现有 ListExportDropdown
  3. clearFilters — overflowClearFiltersItem
  • Step 1: 模板 — 去掉工具栏内「清空列过滤」「取消齐备」「ListExportDropdown」平铺;在主操作按钮后插入 ListToolbarOverflow;EndActions 不动。
  • Step 2: script — 增加 toolbarOverflowItems;import 组件与工厂。
  • Step 3: 样式 — 已有 pl-plan-list-toolbar-row 则确认 Overflow 能收缩;否则按标准清单第 5 步补。
  • Step 4: 抽查 /#/…/plan-cert 宽/窄屏。
  • Step 5: Commit 切点 feat(web-admin): overflow toolbar on plan-cert list

Task 4: plan-archive 接入 Overflow

Files:

  • Modify: web-admin/src/views/pl/plan-archive/index.vue

主操作(外): 「归档」/「调整」等现有 primary。

溢出池: 业务次要(如 ERP 录入)→ export → clearFilters。不要把主归档按钮放进池。

  • 执行标准页改造清单;抽查归档列表宽/窄屏。
  • Commit 切点:feat(web-admin): overflow toolbar on plan-archive list

Task 5: 报销申请 / 备用金申请

Files:

  • Modify: web-admin/src/views/bx/reimburse/apply/index.vue
  • Modify: web-admin/src/views/bx/advance/apply/index.vue

报销 toolbarOverflowItems 顺序(主操作「新增报销申请」在外):

  1. overflowEditItem — 原编辑 disabled/handler
  2. overflowDeleteItem — 原删除
  3. downloadTemplate — 下载模板
  4. import — 批量导入
  5. submit — 提交审批
  6. withdraw — 撤回
  7. viewFlow — 查看审批流
  8. overflowExportPlaceholder + #export
  9. overflowClearFiltersItem

备用金: 无模板/导入则省略对应项;其余同构(编辑、删除、提交、撤回、查看审批流、导出、清空)。

  • 两页按标准清单改造并抽查。
  • Commit 切点:feat(web-admin): overflow toolbar on bx apply lists

Task 6: CRM 线索 / 产品

Files:

  • Modify: web-admin/src/views/crm/clue/index.vue
  • Modify: web-admin/src/views/crm/product/index.vue

线索顺序: 编辑 → 跟进 → 删除 → 批量分配 → 转为客户 → 标为无效 → export → clearFilters

产品顺序: 编辑 → 删除 → 批量上架 → 批量下架 → 导入 → 产品分类 → export → clearFilters

  • 改造 + 抽查 /#/crm/... 对应路由。
  • Commit 切点:feat(web-admin): overflow toolbar on crm clue and product

Task 7: 合同列表 / 报价列表

Files:

  • Modify: web-admin/src/views/crm/contract/ContractListPage.vue
  • Modify: web-admin/src/views/crm/quote/QuoteListPage.vue

注意: 管理模式与审批态按钮用 hidden 控制,勿用破坏测量的零散 v-if 平铺按钮。

合同(示例顺序): 合同复制 → 提交审批 → 作废/恢复 → 审批通过 → 驳回 → 上传扫描件 → export → clearFilters(按页现有按钮裁剪,编辑若存在则放最前)。

报价: 复制新增 → 提交审批 → 生成报价单 → 作废 → 审批(审批页)→ export → clearFilters。

  • 改造 + 抽查管理/审批两种入口(若共用同一组件)。
  • Commit 切点:feat(web-admin): overflow toolbar on contract and quote lists

Task 8: 其余 HIGH 页

对下表每一文件执行标准改造;主操作列在外,其余进池(编辑/删除靠前,export、clearFilters 最末)。

文件 主操作(外)
web-admin/src/views/crm/contract/change/index.vue 新增变更
web-admin/src/views/crm/price-letter/index.vue 新增调价函
web-admin/src/views/pl/personnel/index.vue 新增人员
web-admin/src/views/pl/vehicle/index.vue 新增车辆
web-admin/src/views/pl/vehicle-recharge-apply/index.vue 新增申请
web-admin/src/views/pl/freight/components/SettlementBillPanel.vue 现有主色按钮
web-admin/src/views/bx/expense-item/index.vue 新增一级项目
web-admin/src/views/system/role/index.vue 新增角色
web-admin/src/views/system/dict/index.vue 新增(主表;子栏按钮多则同样接入)
web-admin/src/views/system/post/index.vue 新增职位
  • 逐文件改造;每 2~3 个文件做一次宽/窄屏抽查。
  • Commit 切点:feat(web-admin): overflow toolbar on remaining high-density lists

Task 9: MEDIUM 页

对下表执行标准改造;若打开文件后次要操作实际 ≤2,跳过该文件并在 PR/说明中注明。

文件 主操作(外)
web-admin/src/views/crm/customer/index.vue 新增客户
web-admin/src/views/crm/opportunity/index.vue 新增商机
web-admin/src/views/crm/customer/pool/RuleIndex.vue 新增规则
web-admin/src/views/crm/contract/template/index.vue 新增模板
web-admin/src/views/pl/self-vehicle/index.vue 新增自有车辆
web-admin/src/views/pl/vehicle-fuel-register/FuelRegisterListPage.vue 新增登记
web-admin/src/views/pl/vehicle-maintenance-process/index.vue 处理
web-admin/src/views/pl/vehicle-recharge-record/index.vue 发放
web-admin/src/views/pl/vehicle-urea-disburse/index.vue 发放
web-admin/src/views/system/user/index.vue 新增用户
web-admin/src/views/system/tenant/index.vue 新增租户
web-admin/src/views/system/leave/index.vue 新增请假
web-admin/src/views/system/workflow/process/index.vue 新增流程
web-admin/src/views/db/plans/index.vue 新增计划
web-admin/src/views/db/inventory/index.vue 新增记录
web-admin/src/views/db/weighing/index.vue 新增地磅单
web-admin/src/views/pl/vehicle-maintenance-apply/index.vue 新增申请
web-admin/src/views/pl/vehicle-urea-apply/index.vue 新增申请
web-admin/src/views/system/dept/index.vue 新增
web-admin/src/views/system/menu/index.vue 新增
  • 逐文件改造 + 抽查抽样页(建议:客户、用户、地磅)。
  • Commit 切点:feat(web-admin): overflow toolbar on medium-density list pages

Task 10: 文档与图谱

Files:

  • Modify(可选一句): docs/web-admin-ui-pattern-index.md 或 docs/web-admin-ui-spec-fresh-mint.md 列表工具栏小节:注明次要操作使用 ListToolbarOverflow,顺序约定见设计文档。
  • Modify: docs/superpowers/specs/2026-10-02-list-toolbar-overflow-design.md 状态改为「已落地」或「实现中」。
  • Run: ./scripts/update-graph.sh frontend(或仓库约定的 graphify 更新命令)。

  • [x] 补一句 UI 约定文档(避免大段重写)。

  • [x] 更新图谱。

  • [ ] Commit 切点:docs: note list toolbar overflow pattern


Spec coverage checklist

规格要求 Task
方案 B 工厂 Task 1
clearFilters 最末 + 对齐 pl/plan Task 2
plan-cert / plan-archive Task 3–4
最挤业务(报销/线索/产品/合同/报价) Task 5–7
其余 HIGH Task 8
MEDIUM Task 9
主操作在外、EndActions/日期/搜索不动 标准清单
编辑/删除靠前 各页 items 顺序
导出 slot 标准清单 + 各 Task
LOW / 流程配置跳过 未列入 Task
验收宽/窄屏 各 Task 抽查步骤

Placeholder scan

无 TBD/TODO;工厂与测试代码完整;各页给出明确主操作与 items 顺序要点。


Execution handoff

Plan complete and saved to docs/superpowers/plans/2026-10-02-list-toolbar-overflow.md.

Two execution options:

  1. Subagent-Driven(推荐) — 每 Task 派生子代理,Task 间复核
  2. Inline Execution — 本会话按 executing-plans 连续执行,批次检查点停顿

Which approach?