docs: add design for reimburse apply server-side column filters.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
45ed795501
commit
3fa1f8e312
1 file changed
+217
@@ -0,0 +1,217 @@
|
||||
# 报销申请:列头漏斗整库服务端筛选
|
||||
|
||||
**日期**:2026-09-06
|
||||
**状态**:待审阅
|
||||
**范围(本轮)**:`web-admin` 【报销申请】`src/views/bx/reimburse/apply/index.vue` + 后端 `GET /reimburses/my`(及同页导出)
|
||||
**后续**:CRM 及其他列表按本标杆推广(不在本轮实现)
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与问题
|
||||
|
||||
【报销申请】已落地 Excel 风格列头漏斗(`ColumnHeaderFilter` + `useClientColumnFilters`),但过滤仅作用于**当前页已加载行**,不传给后端。换页后条件只作用于新页;文本列「本页可选值」也无法代表全库。
|
||||
|
||||
目标:改为**整库服务端筛选**,并统一四类列交互,作为后续全站列表/弹窗列表推广的标杆。
|
||||
|
||||
---
|
||||
|
||||
## 2. 产品决策(已确认)
|
||||
|
||||
### 2.1 检索入口
|
||||
|
||||
- **去掉**顶部 `filter-block`。
|
||||
- 检索只走:**列头漏斗** + **工具栏快捷搜索**。
|
||||
- 多列条件之间 **AND**;快捷搜索 `keyword` 与列条件 **AND**。
|
||||
|
||||
### 2.2 原顶部条件迁移
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| 有列则挂漏斗 | 原顶部有过的检索字段,列表必须有对应数据列;若无,**先补列再加漏斗**。 |
|
||||
| 默认值迁移 | 原顶部筛若有默认值,写入对应列漏斗的**初始生效条件**;首屏即按该条件请求。漏斗按钮呈 active。 |
|
||||
| 本页现状 | 【报销申请】原顶部字段(单号/费用项目/状态/申请时间)均已有列;`filterForm` 初始均为空,**无默认值可迁**。 |
|
||||
|
||||
### 2.3 列类型交互
|
||||
|
||||
| 类型 | 适用列(本页) | 交互 |
|
||||
|------|----------------|------|
|
||||
| `datetime` | 申请时间 | 开始日期 + 结束日期,闭区间(含起止当天) |
|
||||
| `number` | 报销金额(元) | 运算符(介于/等于/大于/…)+ 单值或区间 |
|
||||
| `enum` | 状态 | 固定选项多选勾选(待提交/审批中/审批通过/审批驳回) |
|
||||
| `text`(新语义) | 报销单号、报销标题、费用项目、当前节点 | **单行输入模糊检索**(废除「本页可选值」勾选) |
|
||||
|
||||
勾选列、序号列不加漏斗。
|
||||
|
||||
### 2.4 列显示与筛选绑定
|
||||
|
||||
**隐藏某列时:自动清空该列已生效的漏斗条件,并立即重查。**
|
||||
|
||||
- 再显示该列:**不**自动恢复默认值或原条件;漏斗为空,需用户重设。
|
||||
- 「重置列显示」恢复默认可见列时:**一并恢复**列漏斗的初始默认值(与重置语义一致)。本页无默认,影响为清空全部列条件即可。
|
||||
- 理由:看不见的列不允许仍挂筛选,避免「无故变少」且无法从列头改条件。
|
||||
|
||||
### 2.5 清空与导出
|
||||
|
||||
- 「清空列过滤」:清空全部列条件并重查;**不**清快捷搜索(快捷搜索自带清空)。
|
||||
- 导出(`exportMy`):与当前列表同一套 `keyword` + 列条件参数。
|
||||
|
||||
### 2.6 不在本轮
|
||||
|
||||
- CRM / 其他 BX 列表、弹窗内列表推广。
|
||||
- 将约定写入 OpenSpec 基线(可在标杆验收后另开变更)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 架构方案
|
||||
|
||||
**选定:扩展现有 GET 扁平查询参数**(与已有 `applyDateFrom` / `applyDateTo` 风格一致)。
|
||||
|
||||
备选未选:
|
||||
|
||||
- 单一 `columnFilters` JSON:灵活但本页过重。
|
||||
- 改 POST 查询体:与现网列表 GET 习惯不一致。
|
||||
|
||||
前端引入(或演进)`useServerColumnFilters`:管理列条件 state、`toQueryParams()`、隐藏列清条件、触发 `page=1` 重查。表格直接绑定服务端 `rows`,**不再**对当前页做二次 `filter`。
|
||||
|
||||
保留近期修复:日期面板 teleport 导致 popover 误关时的抑制关闭逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 4. API 约定
|
||||
|
||||
### 4.1 `GET /api/.../reimburses/my`
|
||||
|
||||
在现有分页、租户、数据权限、软删之上增加/明确:
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `page` / `pageSize` | int | 已有 |
|
||||
| `keyword` | string | **仅工具栏快捷搜索**:单号 / 标题 / 费用项目名联合模糊(保持现网 OR 语义) |
|
||||
| `applyDateFrom` / `applyDateTo` | `YYYY-MM-DD` | 申请时间(`create_time`)闭区间;已有 |
|
||||
| `applyCode` | string | 报销单号模糊 |
|
||||
| `title` | string | 报销标题模糊 |
|
||||
| `expenseName` | string | 费用项目模糊;复用 `build_expense_name_condition` |
|
||||
| `amountOp` | string | `between` \| `eq` \| `gt` \| `gte` \| `lt` \| `lte` |
|
||||
| `amount` | string/number | 单值运算时使用 |
|
||||
| `amountMin` / `amountMax` | string/number | `between` 时使用;只填一端则只约束一端 |
|
||||
| `statusIn` | string | 状态多选,逗号分隔,如 `draft,pending`;空则不按状态筛 |
|
||||
| `currentNode` | string | 当前节点名模糊 |
|
||||
|
||||
兼容:若仍收到单值 `status`,可视为仅含该值的 `statusIn`。前端本页以 `statusIn` 为准。
|
||||
|
||||
列表 `total` 必须反映过滤后全量条数。
|
||||
|
||||
### 4.2 导出
|
||||
|
||||
`POST /reimburses/my/export`(或现有导出体)须接受与列表相同的过滤字段,过滤逻辑与 list **共用同一拼装函数**,避免漏参。
|
||||
|
||||
### 4.3 校验
|
||||
|
||||
- 日期:`from > to` 由前端拦截;后端可防御性忽略或 400。
|
||||
- 金额:`between` 且 min>max 前端拦截;非法 `amountOp` 后端忽略或 400。
|
||||
- 所有业务查询继续强制 `tenant_no` + 数据权限;不信任客户端改租户。
|
||||
|
||||
---
|
||||
|
||||
## 5. 前端改造要点
|
||||
|
||||
### 5.1 `ColumnHeaderFilter`
|
||||
|
||||
- `text`:单行输入 + 确定/取消/清空本列;文案提示「模糊匹配」。
|
||||
- `enum` / `number` / `datetime`:保持面板能力;确定后由页面触发服务端查询。
|
||||
- 继续处理日期选择器与 popover 的误关问题。
|
||||
|
||||
### 5.2 `useServerColumnFilters`(建议新建)
|
||||
|
||||
职责:
|
||||
|
||||
- `filters`:已生效条件;`initialFilters` 支持默认值。
|
||||
- `toQueryParams()` → 请求/导出。
|
||||
- `setFilter` / `clearColumn` / `clearAll` → 回调 `onChange` → 页面 `search(1)`。
|
||||
- `onColumnHidden(prop)`:清空该 prop 条件并 `onChange`。
|
||||
- `isFilterActive(prop)`:驱动漏斗 active 样式。
|
||||
- 与 `useClientColumnFilters` 并存一段时间;本页切换到服务端版。客户端版可留给纯本地小表,或后续废弃。
|
||||
|
||||
### 5.3 页面 `reimburse/apply/index.vue`
|
||||
|
||||
- 删除 `filter-block` 与 `filterForm` 驱动的顶部搜索。
|
||||
- `useServerPaged` 的请求参数 = 快捷搜索 + `toQueryParams()`。
|
||||
- 列 `v-if="isColumnVisible(...)"` 变为隐藏时调用 `onColumnHidden`。
|
||||
- 工具栏保留「清空列过滤」(`hasActiveFilters` 时显示)。
|
||||
- 快捷搜索清空/搜索不自动清列条件。
|
||||
|
||||
### 5.4 本页列定义一览
|
||||
|
||||
| prop | label | type | 默认可见 | 初始条件 |
|
||||
|------|-------|------|----------|----------|
|
||||
| applyTime | 申请时间 | datetime | 是 | 无 |
|
||||
| applyCode | 报销单号 | text | 是(固定列) | 无 |
|
||||
| title | 报销标题 | text | 是 | 无 |
|
||||
| expenseName | 费用项目 | text | 是 | 无 |
|
||||
| amount | 报销金额(元) | number | 是 | 无 |
|
||||
| status | 状态 | enum | 是 | 无 |
|
||||
| currentNode | 当前节点 | text | 否(现有 defaultVisible: false) | 无 |
|
||||
|
||||
`currentNode` 默认隐藏:首屏无该列条件。用户打开列后再筛。若将来为该列配置默认条件,则须默认可见,或首屏强制带参且列默认可见(遵循「有条件则列应可操作」;本设计选「藏列清条件」,故默认条件列必须默认可见)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据流
|
||||
|
||||
```text
|
||||
进入页
|
||||
→ 应用 initialFilters(本页为空)
|
||||
→ GET /reimburses/my (page, pageSize, keyword?, column params?)
|
||||
|
||||
列漏斗确定
|
||||
→ 更新 filters → page=1 → 同上 GET
|
||||
|
||||
藏列
|
||||
→ 若该列有生效条件:删除该条件 → 重查
|
||||
→ 再显示:条件为空
|
||||
|
||||
清空列过滤
|
||||
→ filters={} → 重查(保留 keyword)
|
||||
|
||||
导出
|
||||
→ 与当前列表相同的 keyword + column params
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 验收标准
|
||||
|
||||
1. 页面无顶部筛选区;有列头漏斗 + 工具栏快捷搜索。
|
||||
2. 日期/数字/状态/文本四类行为符合 §2.3,且过滤结果跨页、跨 pageSize 一致;`total` 正确。
|
||||
3. 换页不丢失已生效列条件与快捷搜索。
|
||||
4. 隐藏带条件的列 → 该条件消失且列表刷新;再显示后漏斗为空。
|
||||
5. 「重置列显示」后列可见性恢复默认,列漏斗恢复为 initial(本页即全空)。
|
||||
6. 导出 Excel 与当前筛选结果一致(在权限范围内)。
|
||||
7. 租户隔离与「我的申请」数据范围与改造前一致。
|
||||
8. 选择申请时间起止时,过滤弹窗不因点选日期面板而提前关闭。
|
||||
|
||||
---
|
||||
|
||||
## 8. 风险与注意
|
||||
|
||||
- `keyword` 与列上 `applyCode`/`title`/`expenseName` 同时存在时为 AND,可能比旧「顶部单号」更严;属预期。
|
||||
- 费用项目展示可能来自明细多行,服务端模糊须与现 `build_expense_name_condition` 一致,避免只匹配主表名。
|
||||
- `statusIn` 多选后,旧单选 `status` 调用方需兼容。
|
||||
- 推广 CRM 时复用参数命名与 `useServerColumnFilters`,按页补齐缺列与后端字段。
|
||||
|
||||
---
|
||||
|
||||
## 9. 实现顺序(建议)
|
||||
|
||||
1. 后端:抽取/扩展 my 列表与导出的过滤拼装;支持上表参数。
|
||||
2. 前端 composable + `ColumnHeaderFilter` 文本模式改造。
|
||||
3. 改造 `apply/index.vue`:去顶部筛、接线服务端列筛、藏列清条件。
|
||||
4. 手工验收 §7;必要时补 API 单测覆盖 amount/statusIn/日期组合。
|
||||
|
||||
---
|
||||
|
||||
## 10. 修订记录
|
||||
|
||||
| 日期 | 说明 |
|
||||
|------|------|
|
||||
| 2026-09-06 | 初稿:整库服务端列筛;去顶部筛;藏列清条件;四类交互;本页无默认值 |
|
||||
Reference in new issue
Block a user