6.4 KiB
6.4 KiB
地磅域日期列头双三角排序(出入库 / 地磅单)
日期: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 / 报销一致。
目标
- 仅对已有
ColumnHeaderFilter且type === 'datetime'的列显示双三角。 - 整表(拉全量后的全集)按该列
asc/desc;取消后恢复现网默认倒序。 - 列表与导出顺序一致:导出走同一
_fetch_*,须识别sortField/sortOrder。 - 参数与 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 现网列表形态(约束)
两页均为:
- 后端
_fetch_inventory/_fetch_weighing一次拉全量(含列过滤); - 前端再 固定按日期倒序(出入库
applySortAndPage;地磅单loadData内对getRecordDate排序); - 前端切片分页。
因此:
- 列表 UI 排序:改前端现有固定倒序,接入
useColumnSort(无参时保持现网默认desc)。 - 导出 / 与后端默认序对齐:
_fetch_*按sortField/sortOrder应用白名单order_by,避免导出仍按硬编码序。
5.2 前端
ColumnHeaderFilter 已在报销任务中支持 inject('crmColumnSort') + type==='datetime' 显示双三角,本批无需再改组件。
各页:
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.pyINVENTORY_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.dateasc/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. 验收
- 出入库「日期」列头有双三角;升/降/取消行为正确。
- 地磅单「日期」列头有双三角;按关联出入库日期排序。
- 地磅计划无双三角。
- 导出顺序与当前列表排序一致。
- 列过滤 + 排序可叠加。
8. 实现顺序(摘要)
services/db/list_sort.py+ 单测_fetch_inventory/_fetch_weighing(及 export params)接排序- 接线
inventory/index.vue、weighing/index.vue - 回归 +
./scripts/update-graph.sh