包含多个会话的累积代码变更: - backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔 - admin-web: ETL 状态页、任务管理、调度配置、登录优化 - miniprogram: 看板页面、聊天集成、UI 组件、导航更新 - etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强 - tenant-admin: 项目初始化 - db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8) - packages/shared: 枚举和工具函数更新 - tools: 数据库工具、报表生成、健康检查 - docs: PRD/架构/部署/合约文档更新 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
138 lines
6.5 KiB
Markdown
138 lines
6.5 KiB
Markdown
# P10-NS4-06:表格组件的统一规范
|
||
|
||
## 简要结论
|
||
- 状态:⚠️ 部分解决
|
||
- tenant-admin 各页面表格在分页大小、loading 状态、筛选器位置上已形成事实一致的模式,但缺少显式的统一配置抽象层;排序交互完全缺失;空数据展示未统一;部分表格分页大小不一致(20 vs 10)。
|
||
|
||
## 详细审查
|
||
|
||
### 前端代码
|
||
|
||
#### 1. 分页大小
|
||
|
||
| 页面/组件 | 默认 pageSize | showSizeChanger | showTotal | 后端分页 |
|
||
|-----------|:---:|:---:|:---:|:---:|
|
||
| UserApproval | 20 | ✅ | ✅ `共 N 条` | ✅ page/page_size |
|
||
| UserManagement | 20 | ✅ | ✅ `共 N 条` | ✅ page/page_size |
|
||
| ExcelUpload — 上传记录 | 20 | ✅ | ✅ `共 N 条` | ✅ page/page_size |
|
||
| ExcelUpload — 校验详情 | **10** | ❌ | ❌ | 前端分页 |
|
||
| RetentionClues — 客户搜索 | `false` | — | — | 无分页(LIMIT 50) |
|
||
| RetentionClues — 线索列表 | **10** | ❌ | ❌ | 无分页(全量返回) |
|
||
| DiffTable — 冲突表 | `false` | — | — | 前端数据 |
|
||
|
||
结论:主列表页统一为 20 条/页 + showSizeChanger + showTotal,但子表格(校验详情、线索列表)使用 10 条/页且缺少 showSizeChanger 和 showTotal,**不一致**。
|
||
|
||
#### 2. 排序交互
|
||
|
||
所有 5 个表格组件均未配置 `sorter` 属性,前端不支持列排序。后端 SQL 统一使用 `ORDER BY created_at DESC`(固定倒序),无动态排序参数。
|
||
|
||
结论:**完全缺失**。用户无法按任意列排序。
|
||
|
||
#### 3. 筛选器位置
|
||
|
||
| 页面 | 筛选器位置 | 筛选方式 |
|
||
|------|-----------|---------|
|
||
| UserApproval | 表格上方独立区域 | Select(状态筛选) |
|
||
| UserManagement | 表格上方独立区域 | Select(角色)+ Input.Search(关键词) |
|
||
| ExcelUpload — 上传记录 | 无筛选 | — |
|
||
| RetentionClues | Card title 区域 + Card extra 区域 | Input.Search + SiteSelector(上方);Select×2(Card extra 右侧) |
|
||
|
||
结论:筛选器统一放在表格上方(非表格内 column filter),**位置一致**。但 RetentionClues 的线索筛选器放在 Card extra 右侧,与其他页面的左对齐布局略有差异。
|
||
|
||
#### 4. loading 状态
|
||
|
||
所有带后端请求的表格均通过 `loading={loading}` 传入 Ant Design Table 的 loading 属性,**统一且正确**。
|
||
|
||
#### 5. 空数据展示
|
||
|
||
| 页面 | 空数据处理 |
|
||
|------|-----------|
|
||
| UserApproval | Ant Design Table 默认空状态(无自定义) |
|
||
| UserManagement | Ant Design Table 默认空状态(无自定义) |
|
||
| ExcelUpload | Ant Design Table 默认空状态(无自定义) |
|
||
| RetentionClues — 客户搜索 | `<Empty description="未找到匹配客户" />` ✅ 自定义 |
|
||
| RetentionClues — 线索列表 | Ant Design Table 默认空状态(无自定义) |
|
||
| DiffTable | Ant Design Table 默认空状态(无自定义) |
|
||
|
||
结论:仅 RetentionClues 客户搜索有自定义空状态文案,其余均依赖 Ant Design 默认的英文 "No Data"。**未统一**,且未做中文化。
|
||
|
||
对比 admin-web:`TaskManager` 页面使用了 `locale={{ emptyText: <Empty description="队列为空" /> }}` 自定义空状态,tenant-admin 未跟进。
|
||
|
||
#### 6. 统一配置抽象
|
||
|
||
- tenant-admin 中**不存在**统一的表格配置文件、常量定义或封装组件
|
||
- 每个页面独立定义 `pageSize`、`pagination` 配置、`handleTableChange` 等
|
||
- 分页响应结构 `{ items, total, page, pageSize }` 在前后端已统一,但属于隐式约定
|
||
|
||
### 后端代码
|
||
|
||
#### 分页参数统一性
|
||
|
||
| 路由 | 参数名 | 默认值 | 范围约束 |
|
||
|------|--------|--------|---------|
|
||
| `GET /applications` | `page` + `page_size` | 1 / 20 | ge=1 / ge=1,le=100 |
|
||
| `GET /users` | `page` + `page_size` | 1 / 20 | ge=1 / ge=1,le=100 |
|
||
| `GET /excel/logs` | `page` + `page_size` | 1 / 20 | ge=1 / ge=1,le=100 |
|
||
| `GET /customers/search` | 无分页 | — | LIMIT 50 硬编码 |
|
||
| `GET /customers/{id}/clues` | 无分页 | — | 全量返回 |
|
||
|
||
结论:三个主列表接口的分页参数**完全统一**(`page`/`page_size`,默认 20,上限 100)。客户搜索和线索列表不分页,属于业务设计选择(数据量可控),但线索列表在数据量增长后可能需要补充分页。
|
||
|
||
响应格式统一为 `{ items: T[], total: int, page: int, pageSize: int }`,**一致**。
|
||
|
||
### 差距分析
|
||
|
||
与 P10 标杆文件要求的差距:
|
||
|
||
| 规范项 | P10 要求(推断) | 当前状态 | 差距 |
|
||
|--------|-----------------|---------|------|
|
||
| 默认分页大小 | 统一值(如 20) | 主表 20,子表 10 | 🟡 子表不一致 |
|
||
| showSizeChanger | 所有分页表格启用 | 仅主表启用 | 🟡 子表缺失 |
|
||
| showTotal | 所有分页表格显示 | 仅主表显示 | 🟡 子表缺失 |
|
||
| 排序交互 | 至少关键列支持排序 | 完全缺失 | 🔴 缺失 |
|
||
| 筛选器位置 | 统一在表格上方 | 基本一致 | ✅ |
|
||
| loading 状态 | 统一 loading 属性 | 全部已配置 | ✅ |
|
||
| 空数据展示 | 统一中文空状态 | 仅 1 处自定义,其余默认 | 🟡 未统一 |
|
||
| 统一配置抽象 | 提取公共 Table 配置 | 不存在 | 🔴 缺失 |
|
||
|
||
### 建议
|
||
|
||
1. **提取统一表格配置常量**(优先级:高)
|
||
|
||
在 `apps/tenant-admin/src/constants/table.ts` 中定义:
|
||
```ts
|
||
export const DEFAULT_PAGE_SIZE = 20;
|
||
export const PAGE_SIZE_OPTIONS = ['10', '20', '50'];
|
||
export const TABLE_LOCALE = {
|
||
emptyText: '暂无数据',
|
||
};
|
||
export const defaultPagination = (total: number, page: number, pageSize: number) => ({
|
||
current: page,
|
||
pageSize,
|
||
total,
|
||
showSizeChanger: true,
|
||
showTotal: (t: number) => `共 ${t} 条`,
|
||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||
});
|
||
```
|
||
|
||
2. **统一空数据展示**(优先级:高)
|
||
|
||
通过 Ant Design ConfigProvider 全局设置中文 locale 和空状态:
|
||
```tsx
|
||
import zhCN from 'antd/locale/zh_CN';
|
||
<ConfigProvider locale={zhCN} renderEmpty={() => <Empty description="暂无数据" />}>
|
||
```
|
||
|
||
3. **子表格分页对齐**(优先级:中)
|
||
|
||
ExcelUpload 校验详情和 RetentionClues 线索列表的 pageSize 改为 20,并补充 showSizeChanger 和 showTotal。
|
||
|
||
4. **排序交互**(优先级:低)
|
||
|
||
对时间列(申请时间、上传时间、记录时间)添加前端 `sorter` 支持。如数据量增长需后端排序,可在 API 中增加 `sort_by` + `sort_order` 参数。当前数据量下前端排序即可。
|
||
|
||
5. **线索列表补充分页**(优先级:低)
|
||
|
||
`GET /customers/{member_id}/clues` 当前全量返回,建议在数据量可能超过 50 条时补充后端分页。
|