docs: add DB weighbridge date column dual-caret sort design.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-09-08 22:31:35 +08:00
1 parent 9ead177dc3
commit 9e1862f4e7
1 file changed
+154
@@ -0,0 +1,154 @@
# 地磅域日期列头双三角排序(出入库 / 地磅单)
**日期**:2026-09-08
**状态**:待审阅
**对齐**:`docs/superpowers/specs/2026-09-08-crm-date-column-sort-design.md`、`docs/superpowers/specs/2026-09-08-bx-date-column-sort-design.md`
**Demo**:`docs/crm-date-column-sort-demo.html`(样式 2 · 双三角)
---
## 1. 背景与目标
地磅管理下「地磅出入库」「地磅单管理」已具备列头 `datetime` 漏斗,但日期列无法升/降序切换。交互需与 CRM / 报销一致。
### 目标
1. 仅对已有 `ColumnHeaderFilter` 且 `type === 'datetime'` 的列显示双三角。
2. 整表(拉全量后的全集)按该列 `asc` / `desc`;取消后恢复现网默认倒序。
3. 列表与导出顺序一致:导出走同一 `_fetch_*`,须识别 `sortField` / `sortOrder`。
4. 参数与 inject 与报销相同:`useColumnSort` + `provide('crmColumnSort')`。
### 非目标
- **地磅计划**(本批无 datetime 漏斗列;起始/截止日期不加)
- 地磅单 `grossWeightTime` / `tareWeightTime`(无漏斗)
- 文本 / 枚举 / 数字列排序
- 排序状态 URL / localStorage 持久化
- 工作台 `db/dashboard`
---
## 2. 已确认产品决策
| # | 决策 |
|---|------|
| D1 | 范围方案 **A**:只给已有 datetime 漏斗的列加双三角 |
| D2 | 页面:出入库 + 地磅单;**计划本批跳过** |
| D3 | 交互与 CRM/报销相同:双三角;同向再点取消;空值升序前、降序后 |
| D4 | 架构:复用 `ColumnHeaderFilter`(已支持 inject)+ `useColumnSort` + 后端白名单(方案 1) |
---
## 3. 本批页面与日期列
| 菜单 | 前端路径 | 日期列 prop | 后端映射 |
|------|----------|-------------|---------|
| 地磅出入库 | `web-admin/src/views/db/inventory/index.vue` | `date` | `DbInboundOutbound.date` |
| 地磅单管理 | `web-admin/src/views/db/weighing/index.vue` | `inventoryDate` | 关联出入库 `DbInboundOutbound.date`(经 `inbound_outbound_id`;展示字段非地磅单本表列) |
**跳过**:`views/db/plans/index.vue`、`views/db/dashboard/index.vue`。
---
## 4. 产品与交互
与 CRM / 报销 §4 一致:
- 列头:标题 → 双三角(仅 datetime) → 漏斗。
- 同一时刻仅一列排序;藏列若为当前排序列则清除。
- 过滤、快捷搜索与排序 AND。
- 导出 filter/body 合并 `toSortQueryParams()`。
---
## 5. 架构
### 5.1 现网列表形态(约束)
两页均为:
1. 后端 `_fetch_inventory` / `_fetch_weighing` **一次拉全量**(含列过滤);
2. 前端再 **固定按日期倒序**(出入库 `applySortAndPage`;地磅单 `loadData` 内对 `getRecordDate` 排序);
3. 前端切片分页。
因此:
- **列表 UI 排序**:改前端现有固定倒序,接入 `useColumnSort`(无参时保持现网默认 `desc`)。
- **导出 / 与后端默认序对齐**:`_fetch_*` 按 `sortField`/`sortOrder` 应用白名单 `order_by`,避免导出仍按硬编码序。
### 5.2 前端
`ColumnHeaderFilter` 已在报销任务中支持 `inject('crmColumnSort')` + `type==='datetime'` 显示双三角,**本批无需再改组件**。
各页:
```ts
const { setSort, clearSort, isSortActive, sortField, sortOrder,
toQueryParams: toSortQueryParams, watchVisibleColumns: watchSortVisibleColumns } =
useColumnSort({ onChange: () => { /* 出入库:applySortAndPage;地磅单:重排 allData 或 loadData */ } })
provide('crmColumnSort', { setSort, clearSort, isSortActive, sortField, sortOrder })
```
- `buildListQueryParams` / 导出 `getFilterParams` 合并 `...toSortQueryParams()`。
- `watchSortVisibleColumns(visibleFilterProps)`。
- 出入库:`applySortAndPage` 按 `sortField`(仅 `date`)与 `sortOrder` 排;缺省 `date` + `desc`。
- 地磅单:替换现网固定 `getRecordDate` 倒序;缺省仍按展示日期 `desc`;有 `inventoryDate`+`asc|desc` 时按该序(空串按空值规则)。
### 5.3 后端
新建薄封装(对齐 `app/services/bx/list_sort.py`):
- `app/services/db/list_sort.py`
- `INVENTORY_WHITELIST = {"date": DbInboundOutbound.date}`
- `WEIGHING_WHITELIST`:`inventoryDate` → 需 **outerjoin** 出入库表后对 `DbInboundOutbound.date` 排序(见下)
- 复用 `resolve_datetime_order_by`;`parse_sort_params` 可复用 bx 或同文件复制一行。
**出入库** `_fetch_inventory`:
- 默认:`date.desc(), id.desc()`(现网)。
- 有合法 sort:`order_by(resolve(...))`;建议次键仍 `id.desc()` 保稳定。
**地磅单** `_fetch_weighing`:
- 默认:`gross_weight_time.desc()`(现网;与列头「日期」展示字段不完全同一列,保持取消排序后行为不变)。
- 排序 `inventoryDate`:`outerjoin(DbInboundOutbound, ...)` 后按 `DbInboundOutbound.date` asc/desc;无关联单时 date 为空,依赖 MySQL NULL 次序(升序前、降序后)。
- 注意 join 后勿重复行:按 `inbound_outbound_id` 一对一关联即可。
导出 body(若已有 export schema)显式或 `extra=allow` 透传 `sortField`/`sortOrder`。
### 5.4 测试
- `backend/tests/test_db_list_sort.py`:白名单 / 非法回退。
- 前端:复用已有 `useColumnSort.test.ts`,无需新测除非抽纯函数。
- 手工:出入库 `date` 升/降/取消;地磅单 `inventoryDate`;导出序与列表一致;计划页无三角。
---
## 6. 风险与注意
| 风险 | 处理 |
|------|------|
| `inventoryDate` 非本表列 | JOIN 排序;禁止臆造 `inventory_date` 列名 |
| 前端已拉全量 | 列表改客户端排序即可;仍须后端排序服务导出 |
| 取消排序后默认序 | 出入库回 `date desc`;地磅单回 `gross_weight_time desc`(后端)与展示日期 desc(前端,与现网 loadData 一致) |
| 与未提交的 BX 排序改动并存 | 本能力独立;提交时勿混入无关 dirty 文件 |
---
## 7. 验收
1. 出入库「日期」列头有双三角;升/降/取消行为正确。
2. 地磅单「日期」列头有双三角;按关联出入库日期排序。
3. 地磅计划无双三角。
4. 导出顺序与当前列表排序一致。
5. 列过滤 + 排序可叠加。
---
## 8. 实现顺序(摘要)
1. `services/db/list_sort.py` + 单测
2. `_fetch_inventory` / `_fetch_weighing`(及 export params)接排序
3. 接线 `inventory/index.vue`、`weighing/index.vue`
4. 回归 + `./scripts/update-graph.sh`