通用明细列表控件设计与开发文档(一)---升鲜宝生鲜配送供应链管理软件重构方案
通用明细列表控件设计与开发文档(一)---升鲜宝生鲜配送供应链管理软件重构方案
适用于商品、采购、销售、WMS、门店、财务、日志等所有明细列表页面
版本:V1.0
技术栈:Vue3 + Element Plus + Spring Boot + MyBatis-Plus + MySQL 8.0 + Redis
文档性质:研发设计说明 / 通用组件规范 / 可落地开发方案
文档目录
1. 建设背景与目标
2. 组件定位与边界
3. 适用业务场景
4. 总体架构设计
5. 前端控件设计
6. 列设置弹窗设计
7. 后端服务设计
8. 数据库表结构设计
9. 接口设计
10. 权限、缓存与多语言设计
11. 关键业务流程
12. 代码骨架
13. 异常处理与校验规则
14. 测试用例与验收标准
15. 实施路线图
1. 建设背景与目标
在升鲜宝供应链管理系统中,商品明细、订单明细、入库明细、出库明细、盘点明细、采购明细、销售明细、客户账单明细等页面都存在大量表格列。不同岗位、不同业务场景、不同门店和不同用户对列表字段的关注点并不一致。
因此需要建设一套通用的明细列表控件,将“列表渲染、列显示控制、列宽设置、对齐方式、冻结列、拖拽排序、字段权限、数据权限、导入导出、打印、缓存、默认配置、用户个性化配置”等能力统一沉淀为系统基础组件。
1.1 核心目标
- 所有明细类页面统一使用同一套表格控件和列配置规范,减少重复代码。
- 支持每个用户独立配置显示列、列顺序、列宽、对齐方式和冻结列。
- 支持系统默认配置、角色默认配置、用户个人配置三层覆盖。
- 支持与字段权限、数据权限、导出权限、打印模板联动。
- 支持后端统一保存,用户更换电脑后仍然保留个人配置。
- 支持未来扩展多语言列名、低代码列表配置、动态查询条件和移动端适配。
1.2 参考原型
下图为列设置弹窗参考形态:包含列名称、冻结、显示、对齐方式、展示顺序、展示宽度、恢复默认、保存、关闭等能力。

图 1:升鲜宝明细列表列设置参考原型
2. 组件定位与边界
组件名称建议为 SxbDetailTable,列设置子组件命名为 SxbColumnSetting。SxbDetailTable 是列表渲染主体;SxbColumnSetting 是配置弹窗;useColumnSetting 是前端组合式 Hook;后端 system-column-setting 模块负责默认配置、用户配置和权限过滤。
|
组件/模块 |
职责 |
是否通用 |
|
SxbDetailTable.vue |
统一封装 Element Plus 表格、分页、加载、空状态、汇总行、操作列、动态列渲染 |
是 |
|
SxbColumnSettingDialog.vue |
列设置弹窗:显示/隐藏、冻结、对齐、排序、宽度、恢复默认 |
是 |
|
SxbColumnSettingButton.vue |
列表右上角列设置入口按钮,可嵌入 toolbar |
是 |
|
useColumnSetting.ts |
获取、合并、保存、重置列配置,处理本地缓存和后端同步 |
是 |
|
system-column-setting 后端服务 |
保存用户个性化列配置,维护系统默认列配置,执行权限过滤 |
是 |
|
业务页面 |
只声明 tableKey、defaultColumns、查询接口和业务操作列 |
否 |
2.1 组件不应该承担的职责
- 不直接写死任何业务字段,例如 SKU、客户、供应商、订单状态等字段都由业务页面声明。
- 不直接处理复杂业务流程,例如审核、反审核、生成入库单、生成出库单等。
- 不绕过后端权限控制,前端列隐藏只是一种体验优化,安全控制必须以后端为准。
- 不将数据权限和列权限混为一谈,数据权限控制行,字段权限控制列,列设置控制用户偏好。
3. 适用业务场景
|
业务域 |
典型页面 |
建议 tableKey 示例 |
|
商品 PMS |
商品列表、SKU列表、商品单位关系、商品价格明细 |
pms_goods_list / pms_sku_list / pms_sku_unit_detail |
|
采购 PUR |
采购订单明细、采购入库计划、供应商报价明细 |
pur_order_detail / pur_stockin_plan_detail |
|
销售 OMS |
销售订单明细、销售出库明细、客户价格明细 |
oms_order_detail / oms_stockout_detail |
|
仓库 WMS |
入库单明细、出库单明细、盘点单明细、调拨单明细 |
wms_stockin_detail / wms_stocktake_detail |
|
门店 HWMS |
门店库存明细、门店盘点明细、门店销售扣减明细 |
hwms_inventory_detail / hwms_stocktake_detail |
|
财务 FIN |
应收明细、应付明细、客户账单、供应商账单 |
fin_ar_detail / fin_ap_detail |
|
日志 LOG |
操作日志、接口日志、审计日志、异常日志 |
log_operation_list / log_api_list |
4. 总体架构设计
整体采用“业务页面声明列 + 通用组件渲染 + 后端保存配置 + 权限引擎过滤 + 缓存加速”的架构。业务页面不再关心列配置弹窗的实现,只需要提供 tableKey 和默认列定义。
业务页面
├─ 声明 tableKey
├─ 声明 defaultColumns
├─ 绑定查询接口
└─ 声明业务操作列
↓
SxbDetailTable 通用明细列表控件
├─ 动态列渲染
├─ 分页/排序/选择/汇总
├─ 空状态/加载状态
├─ 列设置入口
└─ 导入/导出/打印扩展点
↓
SxbColumnSetting 列设置组件
├─ 显示/隐藏
├─ 冻结列
├─ 对齐方式
├─ 拖拽排序
├─ 列宽设置
└─ 恢复默认
↓
后端 ColumnSettingService
├─ 系统默认配置
├─ 角色默认配置
├─ 用户个人配置
├─ 字段权限过滤
└─ Redis 缓存
↓
MySQL 配置表
├─ sys_table_column_default
├─ sys_role_column_setting
└─ sys_user_column_setting
4.1 三层配置覆盖规则
|
层级 |
说明 |
优先级 |
|
系统默认配置 |
由研发或系统管理员预置,保证页面首次打开有合理列结构 |
最低 |
|
角色默认配置 |
按采购员、仓管员、财务、店长等岗位设置默认列 |
中 |
|
用户个人配置 |
用户自行设置的显示列、顺序、宽度、对齐方式等 |
最高 |
最终返回给前端之前,还必须经过字段权限过滤。即使用户配置了某个敏感字段为显示,只要没有字段权限,后端也不能返回该字段配置。
5. 前端控件设计
5.1 目录结构
src/components/sxb-detail-table/
├─ SxbDetailTable.vue # 通用明细列表主体
├─ SxbColumnSettingDialog.vue # 列设置弹窗
├─ SxbColumnSettingButton.vue # 列设置按钮
├─ SxbTableToolbar.vue # 工具栏:刷新、导出、打印、列设置
├─ SxbTablePagination.vue # 分页封装
├─ hooks/
│ ├─ useColumnSetting.ts # 列配置 Hook
│ ├─ useTableQuery.ts # 查询 Hook
│ ├─ useTableSelection.ts # 多选 Hook
│ └─ useTableExport.ts # 导出 Hook
├─ types/
│ └─ table-column.ts # TypeScript 类型定义
└─ api/
└─ column-setting-api.ts # 后端接口封装
5.2 前端列定义模型
export interface SxbColumnConfig {
columnKey: string; // 字段编码,例如 skuCode
columnName: string; // 显示名称,例如 SKU编码
prop?: string; // Element Plus prop,默认等于 columnKey
visible: boolean; // 是否显示
frozen: boolean; // 是否冻结
fixed?: 'left' | 'right' | boolean; // Element Plus fixed
align: 'left' | 'center' | 'right'; // 对齐方式
headerAlign?: 'left' | 'center' | 'right'; // 表头对齐方式
sortNo: number; // 显示顺序
width: number; // 列宽
minWidth?: number; // 最小宽度
required?: boolean; // 是否必显示
sortable?: boolean | 'custom'; // 是否支持排序
formatter?: string; // 格式化器编码,例如 money/date/status
permissionCode?: string; // 字段权限编码
summaryFlag?: boolean; // 是否参与汇总
exportFlag?: boolean; // 是否允许导出
printFlag?: boolean; // 是否允许打印
tooltipFlag?: boolean; // 超长内容是否显示 tooltip
}
5.3 业务页面使用示例
<template>
<SxbDetailTable
table-key="pms_sku_suggest_detail"
row-key="id"
:default-columns="defaultColumns"
:query-api="querySkuSuggestDetail"
:query-params="queryParams"
show-selection
show-index
show-summary
>
<template #toolbar>
<el-button type="primary" @click="handleAdd">新增</el-button>
<el-button @click="handleExport">导出</el-button>
</template>
<template #operation="{ row }">
<el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
</template>
</SxbDetailTable>
</template>
5.4 defaultColumns 示例
const defaultColumns: SxbColumnConfig[] = [
{ columnKey: 'orgName', columnName: '机构', visible: false, frozen: false, align: 'left', sortNo: 10, width: 100 },
{ columnKey: 'shopName', columnName: '门店', visible: true, frozen: false, align: 'left', sortNo: 20, width: 100 },
{ columnKey: 'suggestDate', columnName: '建议日期', visible: true, frozen: false, align: 'left', sortNo: 30, width: 100, formatter: 'date' },
{ columnKey: 'skuCode', columnName: 'SKU编码', visible: true, frozen: false, align: 'left', sortNo: 40, width: 120 },
{ columnKey: 'barcode', columnName: '国际条码', visible: true, frozen: false, align: 'left', sortNo: 50, width: 130 },
{ columnKey: 'skuName', columnName: 'SKU名称', visible: true, frozen: false, align: 'center', sortNo: 60, width: 180, required: true },
{ columnKey: 'processStatusName', columnName: '处理状态', visible: true, frozen: false, align: 'left', sortNo: 70, width: 100 },
{ columnKey: 'suggestQty', columnName: '建议件数', visible: true, frozen: false, align: 'right', sortNo: 80, width: 100, summaryFlag: true },
{ columnKey: 'unitRelation', columnName: '单位关系', visible: true, frozen: false, align: 'right', sortNo: 90, width: 120 }
];
6. 列设置弹窗设计
列设置弹窗用于维护当前表格的展示偏好。弹窗内每一行对应一个列配置项,支持勾选显示、勾选冻结、选择对齐方式、拖拽排序、输入展示宽度。
|
字段 |
控件 |
规则 |
|
列名称 |
文本 |
来自 columnName,一般不允许用户修改。 |
|
冻结 |
Checkbox |
设置 fixed。冻结列建议限制数量,避免横向滚动异常。 |
|
显示 |
Checkbox |
控制 visible。required=true 的列不允许取消显示。 |
|
对齐方式 |
Select |
允许 left、center、right,对应居左、居中、居右。 |
|
展示顺序 |
拖拽图标 |
拖拽后重新计算 sortNo,建议间隔 10 保存。 |
|
展示宽度 |
InputNumber |
建议 60 到 600,特殊列可配置更大。 |
|
恢复默认 |
Button |
清空用户配置,重新加载系统默认配置。 |
|
保存 |
Button |
提交当前用户配置到后端。 |
|
关闭 |
Button |
关闭弹窗,不保存未提交修改。 |
6.1 列设置交互规则
- 弹窗打开时复制一份临时配置,用户点击保存后才覆盖表格当前配置。
- 勾选显示时,如果该字段被字段权限过滤,则前端不应展示该列配置项。
- 冻结列推荐只允许连续靠左冻结;如支持右侧冻结,需要在列配置中明确 fixed=right。
- 拖拽排序只影响展示顺序,不影响后端查询 SQL 字段。
- 列宽输入需要做数字校验,非法值回退到默认宽度。
- 恢复默认需要二次确认,防止误操作覆盖用户配置。
7. 后端服务设计
7.1 后端包结构
com.sxb.system.columnsetting
├─ controller
│ └─ SysColumnSettingController.java
├─ service
│ ├─ SysColumnSettingService.java
│ └─ impl/SysColumnSettingServiceImpl.java
├─ mapper
│ ├─ SysTableColumnDefaultMapper.java
│ ├─ SysRoleColumnSettingMapper.java
│ └─ SysUserColumnSettingMapper.java
├─ entity
│ ├─ SysTableColumnDefaultEntity.java
│ ├─ SysRoleColumnSettingEntity.java
│ └─ SysUserColumnSettingEntity.java
├─ dto
│ ├─ ColumnSettingQueryDTO.java
│ ├─ ColumnSettingSaveDTO.java
│ └─ ColumnSettingItemDTO.java
├─ vo
│ └─ ColumnSettingVO.java
└─ enums
├─ ColumnAlignEnum.java
└─ ColumnFixedTypeEnum.java
7.2 后端核心服务职责
|
方法 |
说明 |
|
getUserColumnSetting(tableKey) |
获取当前用户最终列配置,执行系统默认、角色默认、用户配置合并,并进行字段权限过滤。 |
|
saveUserColumnSetting(dto) |
保存当前用户列配置,按 userId + tableKey + columnKey 做新增或更新。 |
|
resetUserColumnSetting(tableKey) |
删除当前用户个人配置,重新返回默认配置。 |
|
initDefaultColumnSetting(dto) |
系统管理员初始化或维护某个 tableKey 的默认列配置。 |
|
refreshColumnSettingCache(tableKey) |
刷新 Redis 缓存,避免配置变更后用户仍看到旧配置。 |
8. 数据库表结构设计
第一版建议至少落地两张表:系统默认列配置表和用户列配置表。角色默认配置表可作为第二阶段扩展。如果升鲜宝系统已经有 RBAC 角色体系,角色列配置表可以很自然地接入。
8.1 系统默认列配置表
CREATE TABLE sys_table_column_default (
id BIGINT NOT NULL COMMENT '主键ID',
tenant_id BIGINT DEFAULT NULL COMMENT '租户ID;纯运营系统可为空',
table_key VARCHAR(100) NOT NULL COMMENT '表格业务编码,例如 pms_sku_suggest_detail',
table_name VARCHAR(100) NOT NULL COMMENT '表格名称',
column_key VARCHAR(100) NOT NULL COMMENT '列字段编码',
column_name VARCHAR(100) NOT NULL COMMENT '列显示名称',
prop_name VARCHAR(100) DEFAULT NULL COMMENT '前端绑定属性名,默认等于 column_key',
visible_flag TINYINT NOT NULL DEFAULT 1 COMMENT '默认是否显示:0否,1是',
frozen_flag TINYINT NOT NULL DEFAULT 0 COMMENT '默认是否冻结:0否,1是',
fixed_type VARCHAR(20) NOT NULL DEFAULT 'none' COMMENT '冻结方向:none/left/right',
align_type VARCHAR(20) NOT NULL DEFAULT 'left' COMMENT '对齐方式:left/center/right',
header_align_type VARCHAR(20) DEFAULT NULL COMMENT '表头对齐方式',
sort_no INT NOT NULL DEFAULT 0 COMMENT '默认顺序',
width INT NOT NULL DEFAULT 100 COMMENT '默认宽度',
min_width INT DEFAULT NULL COMMENT '最小宽度',
required_flag TINYINT NOT NULL DEFAULT 0 COMMENT '是否必显示:0否,1是',
sortable_flag TINYINT NOT NULL DEFAULT 0 COMMENT '是否支持排序:0否,1是',
formatter_type VARCHAR(50) DEFAULT NULL COMMENT '格式化类型:date/money/qty/status等',
summary_flag TINYINT NOT NULL DEFAULT 0 COMMENT '是否参与汇总:0否,1是',
export_flag TINYINT NOT NULL DEFAULT 1 COMMENT '是否允许导出:0否,1是',
print_flag TINYINT NOT NULL DEFAULT 1 COMMENT '是否允许打印:0否,1是',
tooltip_flag TINYINT NOT NULL DEFAULT 1 COMMENT '超长内容是否提示:0否,1是',
permission_code VARCHAR(150) DEFAULT NULL COMMENT '字段权限编码',
enable_flag TINYINT NOT NULL DEFAULT 1 COMMENT '启用状态:0停用,1启用',
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
create_user BIGINT DEFAULT NULL COMMENT '创建人',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_user BIGINT DEFAULT NULL COMMENT '更新人',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted_flag TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记:0正常,1删除',
PRIMARY KEY (id),
UNIQUE KEY uk_table_column (table_key, column_key),
KEY idx_table_key (table_key),
KEY idx_permission_code (permission_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统默认表格列配置表';
8.2 用户列配置表
CREATE TABLE sys_user_column_setting (
id BIGINT NOT NULL COMMENT '主键ID',
tenant_id BIGINT DEFAULT NULL COMMENT '租户ID;纯运营系统可为空',
user_id BIGINT NOT NULL COMMENT '用户ID',
table_key VARCHAR(100) NOT NULL COMMENT '表格业务编码',
column_key VARCHAR(100) NOT NULL COMMENT '列字段编码',
column_name VARCHAR(100) NOT NULL COMMENT '列显示名称快照',
visible_flag TINYINT NOT NULL DEFAULT 1 COMMENT '是否显示:0否,1是',
frozen_flag TINYINT NOT NULL DEFAULT 0 COMMENT '是否冻结:0否,1是',
fixed_type VARCHAR(20) NOT NULL DEFAULT 'none' COMMENT '冻结方向:none/left/right',
align_type VARCHAR(20) NOT NULL DEFAULT 'left' COMMENT '对齐方式:left/center/right',
sort_no INT NOT NULL DEFAULT 0 COMMENT '显示顺序',
width INT NOT NULL DEFAULT 100 COMMENT '展示宽度',
required_flag TINYINT NOT NULL DEFAULT 0 COMMENT '是否必显示:0否,1是',
version INT NOT NULL DEFAULT 1 COMMENT '配置版本号',
create_user BIGINT DEFAULT NULL COMMENT '创建人',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_user BIGINT DEFAULT NULL COMMENT '更新人',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted_flag TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记:0正常,1删除',
PRIMARY KEY (id),
UNIQUE KEY uk_user_table_column (user_id, table_key, column_key),
KEY idx_user_table (user_id, table_key),
KEY idx_table_key (table_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表格列配置表';
8.3 角色列配置表(增强版)
CREATE TABLE sys_role_column_setting (
id BIGINT NOT NULL COMMENT '主键ID',
tenant_id BIGINT DEFAULT NULL COMMENT '租户ID;纯运营系统可为空',
role_id BIGINT NOT NULL COMMENT '角色ID',
table_key VARCHAR(100) NOT NULL COMMENT '表格业务编码',
column_key VARCHAR(100) NOT NULL COMMENT '列字段编码',
visible_flag TINYINT NOT NULL DEFAULT 1 COMMENT '是否显示:0否,1是',
frozen_flag TINYINT NOT NULL DEFAULT 0 COMMENT '是否冻结:0否,1是',
fixed_type VARCHAR(20) NOT NULL DEFAULT 'none' COMMENT '冻结方向:none/left/right',
align_type VARCHAR(20) NOT NULL DEFAULT 'left' COMMENT '对齐方式:left/center/right',
sort_no INT NOT NULL DEFAULT 0 COMMENT '显示顺序',
width INT NOT NULL DEFAULT 100 COMMENT '展示宽度',
enable_flag TINYINT NOT NULL DEFAULT 1 COMMENT '启用状态:0停用,1启用',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted_flag TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记:0正常,1删除',
PRIMARY KEY (id),
UNIQUE KEY uk_role_table_column (role_id, table_key, column_key),
KEY idx_role_table (role_id, table_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表格列配置表';
9. 接口设计
9.1 获取列配置
GET /api/system/column-setting/get?tableKey=pms_sku_suggest_detail
返回示例:
{
"code": 0,
"msg": "success",
"data": [
{
"columnKey": "skuName",
"columnName": "SKU名称",
"prop": "skuName",
"visible": true,
"frozen": false,
"fixed": "none",
"align": "center",
"sortNo": 60,
"width": 180,
"required": true,
"sortable": false,
"formatter": null,
"summaryFlag": false,
"exportFlag": true,
"printFlag": true,
"tooltipFlag": true
}
]
}
9.2 保存列配置
POST /api/system/column-setting/save
Content-Type: application/json
{
"tableKey": "pms_sku_suggest_detail",
"columns": [
{
"columnKey": "skuName",
"columnName": "SKU名称",
"visible": true,
"frozen": false,
"fixed": "none",
"align": "center",
"sortNo": 60,
"width": 180,
"required": true
}
]
}
9.3 恢复默认配置
POST /api/system/column-setting/reset
Content-Type: application/json
{
"tableKey": "pms_sku_suggest_detail"
}
10. 权限、缓存与多语言设计
10.1 字段权限联动
列设置控制的是“用户想不想看”,字段权限控制的是“用户能不能看”。最终返回列配置时,后端必须先按用户权限过滤字段。比如成本价、毛利、供应商结算价、客户授信额度、客户余额等敏感字段,不能只靠前端隐藏。
最终列 = 合并后的列配置 - 当前用户无字段权限的列
10.2 数据权限关系
数据权限控制行,例如只能看本门店、本机构、本仓库、本客户经理的数据;列配置控制列,例如 SKU编码、单位关系、建议件数是否显示。两者必须解耦。
10.3 Redis 缓存设计
|
缓存 Key |
说明 |
建议 TTL |
|
sxb:column:user:{userId}:{tableKey} |
用户最终列配置缓存 |
30 分钟 |
|
sxb:column:default:{tableKey} |
系统默认列配置缓存 |
2 小时 |
|
sxb:field-permission:{userId} |
用户字段权限缓存 |
30 分钟 |
|
sxb:column:version:{tableKey} |
配置版本,用于前端判断是否需要刷新 |
长期 |
10.4 多语言列名
如果升鲜宝后续启用多语言,列名不建议直接写死在用户配置表中。用户配置表的 column_name 只作为快照,正式显示应优先从 sys_table_column_default_i18n 或前端 i18n 资源中获取。
11. 关键业务流程
11.1 页面加载流程
用户打开业务页面
↓
前端根据 tableKey 调用 /column-setting/get
↓
后端查询用户配置
↓
没有用户配置则查询角色配置
↓
没有角色配置则查询系统默认配置
↓
执行字段权限过滤
↓
返回最终列配置
↓
SxbDetailTable 按列配置渲染表格
↓
调用业务查询接口加载数据
11.2 保存配置流程
用户点击列设置
↓
弹出 SxbColumnSettingDialog
↓
用户调整显示、冻结、对齐、顺序、宽度
↓
点击保存
↓
前端校验 required 字段、宽度、冻结数量
↓
提交后端 save 接口
↓
后端再次校验合法性
↓
批量 upsert 用户配置
↓
删除 Redis 用户列配置缓存
↓
返回保存成功
↓
前端刷新表格列
12. 代码骨架
12.1 DTO
@Data
public class ColumnSettingSaveDTO {
@NotBlank(message = "表格编码不能为空")
private String tableKey;
@NotEmpty(message = "列配置不能为空")
private List<ColumnSettingItemDTO> columns;
}
@Data
public class ColumnSettingItemDTO {
@NotBlank(message = "列字段编码不能为空")
private String columnKey;
@NotBlank(message = "列名称不能为空")
private String columnName;
@NotNull(message = "显示状态不能为空")
private Boolean visible;
@NotNull(message = "冻结状态不能为空")
private Boolean frozen;
private String fixed;
@NotBlank(message = "对齐方式不能为空")
private String align;
@NotNull(message = "排序号不能为空")
private Integer sortNo;
@NotNull(message = "列宽不能为空")
private Integer width;
private Boolean required;
}
12.2 Controller
@RestController
@RequestMapping("/api/system/column-setting")
public class SysColumnSettingController {
@Resource
private SysColumnSettingService sysColumnSettingService;
@GetMapping("/get")
public Result<List<ColumnSettingVO>> get(@RequestParam String tableKey) {
return Result.ok(sysColumnSettingService.getUserColumnSetting(tableKey));
}
@PostMapping("/save")
public Result<Void> save(@Valid @RequestBody ColumnSettingSaveDTO dto) {
sysColumnSettingService.saveUserColumnSetting(dto);
return Result.ok();
}
@PostMapping("/reset")
public Result<List<ColumnSettingVO>> reset(@RequestBody ColumnSettingResetDTO dto) {
return Result.ok(sysColumnSettingService.resetUserColumnSetting(dto.getTableKey()));
}
}
12.3 Service 关键逻辑伪代码
@Override
public List<ColumnSettingVO> getUserColumnSetting(String tableKey) {
Long userId = LoginUserContext.getUserId();
// 1. 查询缓存
String cacheKey = ColumnCacheKey.user(userId, tableKey);
List<ColumnSettingVO> cached = redisCache.get(cacheKey);
if (CollectionUtils.isNotEmpty(cached)) {
return cached;
}
// 2. 查询用户配置
List<ColumnSettingVO> columns = userColumnSettingMapper.selectByUserAndTable(userId, tableKey);
// 3. 用户配置不存在,则查询角色配置
if (CollectionUtils.isEmpty(columns)) {
columns = roleColumnSettingMapper.selectByUserRoleAndTable(userId, tableKey);
}
// 4. 角色配置不存在,则查询系统默认配置
if (CollectionUtils.isEmpty(columns)) {
columns = tableColumnDefaultMapper.selectByTableKey(tableKey);
}
// 5. 字段权限过滤
columns = fieldPermissionEngine.filterColumns(userId, tableKey, columns);
// 6. 排序并缓存
columns = columns.stream()
.sorted(Comparator.comparing(ColumnSettingVO::getSortNo))
.collect(Collectors.toList());
redisCache.set(cacheKey, columns, Duration.ofMinutes(30));
return columns;
}
13. 异常处理与校验规则
|
校验项 |
规则 |
错误提示 |
|
tableKey |
不能为空,长度不超过 100 |
表格编码不能为空或长度超限 |
|
columnKey |
不能为空,长度不超过 100 |
列字段编码不能为空或长度超限 |
|
align |
只能是 left、center、right |
对齐方式不合法 |
|
fixed |
只能是 none、left、right |
冻结方向不合法 |
|
width |
建议 60 到 600 |
列宽必须在 60 到 600 之间 |
|
required |
必显示列不允许隐藏 |
必显示列不能取消显示 |
|
frozen count |
冻结列建议不超过 5 个 |
冻结列数量超过限制 |
|
permission |
无字段权限的列不能保存为可见 |
无权限显示该字段 |
14. 测试用例与验收标准
14.1 核心测试用例
|
编号 |
测试场景 |
预期结果 |
|
TC001 |
首次打开没有用户配置的页面 |
加载系统默认列配置并正常展示。 |
|
TC002 |
用户隐藏某一列并保存 |
刷新页面后该列仍保持隐藏。 |
|
TC003 |
用户调整列顺序并保存 |
刷新页面后列顺序保持调整后的顺序。 |
|
TC004 |
用户修改列宽并保存 |
刷新页面后列宽保持调整后的宽度。 |
|
TC005 |
用户设置 SKU名称居中 |
表格 SKU名称列内容居中显示。 |
|
TC006 |
用户点击恢复默认 |
删除个人配置并恢复系统默认列。 |
|
TC007 |
用户无成本价字段权限 |
列设置弹窗和表格都不出现成本价列。 |
|
TC008 |
必显示列取消显示 |
前端禁止取消,后端也拒绝保存。 |
|
TC009 |
多端登录同一用户 |
配置保存后另一端刷新可加载最新配置。 |
|
TC010 |
导出跟随当前列配置 |
导出字段与当前可见列一致,且不导出无权限字段。 |
14.2 验收标准
- 至少接入一个商品明细页面、一个订单明细页面、一个 WMS 明细页面进行验证。
- 列显示、隐藏、排序、宽度、对齐、冻结、恢复默认全部可用。
- 刷新浏览器、重新登录、更换电脑后用户配置仍然生效。
- 无字段权限的列不能通过接口返回,也不能通过前端列配置绕过。
- 表格数据量较大时,列配置加载不应明显拖慢页面,建议接口耗时小于 200ms。
- 配置表具有唯一索引和必要查询索引,支持长期扩展。
15. 实施路线图
|
阶段 |
目标 |
交付内容 |
|
第一阶段:MVP |
完成通用列设置能力 |
SxbColumnSettingDialog、useColumnSetting、两张配置表、get/save/reset 接口。 |
|
第二阶段:组件化 |
完成 SxbDetailTable 主控件 |
统一分页、排序、选择、汇总、空状态、工具栏、操作列插槽。 |
|
第三阶段:权限联动 |
接入字段权限和数据权限 |
字段权限过滤、敏感字段控制、权限缓存刷新。 |
|
第四阶段:生态联动 |
导入导出、打印、低代码配置 |
导出字段跟随列配置、打印字段跟随列配置、系统默认列后台维护。 |
|
第五阶段:高级能力 |
角色配置、多语言、移动端适配 |
角色默认列配置、多语言列名、移动端列折叠策略。 |
附录 A:tableKey 命名规范
建议采用“模块_业务对象_使用场景”的命名方式,全部使用小写字母、数字和下划线。
|
模块 |
命名示例 |
|
商品 |
pms_goods_list、pms_sku_list、pms_sku_unit_detail |
|
采购 |
pur_order_list、pur_order_detail、pur_stockin_plan_detail |
|
销售 |
oms_order_list、oms_order_detail、oms_stockout_detail |
|
仓库 |
wms_stockin_detail、wms_stockout_detail、wms_stocktake_detail |
|
门店仓 |
hwms_inventory_detail、hwms_stocktake_detail、hwms_pick_task_detail |
|
财务 |
fin_customer_bill_detail、fin_supplier_bill_detail |
|
日志 |
log_operation_list、log_api_list |
附录 B:推荐开发原则
- 业务页面只声明列,不实现列设置逻辑。
- 前端隐藏不是安全手段,敏感字段必须由后端过滤。
- 组件必须支持插槽,避免为不同业务页面写多个变体。
- 配置数据必须可恢复默认,避免用户误配置后无法找回。
- 字段编码 columnKey 一旦上线应保持稳定,避免用户配置失效。
- 列配置不应该参与业务 SQL 拼接,避免引入 SQL 注入和字段泄露风险。
- 所有 deleted_flag、enable_flag、visible_flag 等字段统一使用 flag 后缀,不使用 is_ 前缀。
结论
通用明细列表控件是升鲜宝供应链管理系统非常重要的基础能力。它可以显著降低各业务模块的列表开发成本,统一用户体验,并为字段权限、数据权限、导入导出、打印、多语言和低代码配置打下基础。建议优先按照 MVP 版本落地,再逐步扩展角色配置、权限联动和生态能力。

浙公网安备 33010602011771号