用户自定义表格列

9/7/2022

# 一、背景与问题

对于中后台系统,表格一般列会非常多、而且每个人关注的列又不一样,有些列中的文字太挤的话会换行,用户希望每个表格都可以自定义,并且在下次打开的时候还是保持原样,拆分下需求的问题:

  • 1、列可以设置隐藏于显示
  • 2、列可以设置自定义宽度
  • 3、列可以设置自定义顺序
  • 4、将以上自定义设置存入后端

# 二、架构与思想

;后端一件事:保存用户和表格列信息

# 2.1、前端分析

通过需求与整理的问题,再拆解下,前端三件事情:显示与隐藏、宽度、顺序,同时又需要每个table都要使用,那么前端就需要一个通用的组件来解决这三点。
我们在使用table组件的时候,columns属性中记录着所有的列信息,包含:列名、字段、顺序、宽度,所以这些信息我们可以直接使用。
初步定义如下:

  • 组件名称为: table-operator
  • 组件``table-operator`中可以进行: 列的显示与隐藏、宽度、顺序
  • 原来table的columns信息可以传递给 table-operator 进行使用
  • table-operator中修改完 “列的显示与隐藏、宽度、顺序” 之后,回传给原table的columns,用于显示

但是我们的需求是,“用户希望每次打开都是我上次操作过的列信息”,那么怎么解决这个需求呢?
这个需求点说明,必须将 table-operator中操作的列信息 存储到后端。有如下几点:

  • table-operator 有保存到后端的功能
  • table-operator 有从后端获取列信息的功能
  • table-operator 要有一个唯一table id用于保存用户的“这个表”的列信息

# 2.2、后端分析

通过需求,了解到所有的操作都是前端进行的,后端只需记录 用户的表格列信息,那么有几个关键数据:

  • 用户id
  • 表格 table id
  • 列信息 columns info

那么表结构有两种设计思路: 第一种,列铺开的形式,每个用户的一个表列设置 会对应多条数据记录

table 't_table_column' {
  user_id,                用户id
  table_id,               表格id
  column_name,            列名
  column_field,           列字段
  column_sort,            列排序
  column_show_flag,       列显示与隐藏
  column_width            列宽
}

1
2
3
4
5
6
7
8
9
10

第二种,存储json的形式,每个用户的一个表列设置 会对应 一条 数据记录

table 't_table_column' {
  user_id,            用户id
  table_id,           表格id
  columns,            所有列信息(json形式)
}

1
2
3
4
5
6

简单对比下

项目 优点 缺点
铺开第一种 满足sql范式 数据量稍微多一点,因为一个系统中 table会比较多
json第二种 数据量会少很多 不满足sql范式,字段用了json存储

最终我们选择了 第二种,具体原因:

  • 1、 sql范式是为么满足 数据库的复杂功能,增删查改等,但是对于此功能,我只需要存储,并不需要其他sql复杂语句
  • 2、 不存在 任何的sql复杂操作
  • 3、 无需将来在 navicat 端进行 数据查询排查问题
  • 4、 数据量少点,数据库操作也不频繁

# 三、具体使用

1)在 src/components/support 顶级组件目录中有table-operator 组件目录;
2)在 src/constants/support/table-id-const.jstable-id的常量文件中 找到(或添加)新的 table 的唯一id
3)在具体的页面vue文件中,直接引入 table-operator组件,引入第二步的 table-id,如下:

  template 中
  <div class="smart-table-setting-block">
    <TableOperator v-model="columns" :tableId="TABLE_ID_CONST.BUSINESS.OA.ENTERPRISE" :refresh="ajaxQuery" />
  </div>

  <script> js 中
  import TableOperator from '/@/components/support/table-operator/index.vue';
  import { TABLE_ID_CONST } from '/@/constants/support/table-id-const';
  const columns = ref([
    {
      title: '企业名称',
      dataIndex: 'enterpriseName',
      minWidth: 180,
      ellipsis: true,
    },
    ....
    ....
    ]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

是不是很简单呢?

# 四、实现原理

# 4.1、 table-operator

第一步先定义通用组件 table-operator,因为是通用组件,同时又是支撑support业务,我们定义到src/components/support 顶级组件目录中。
具体可以查看 table-operator (opens new window)

table-operator组件中有三个参数:

  const props = defineProps({
    // 表格列数组
    modelValue: {
      type: Array,
      default: new Array(),
    },
    // 刷新表格函数
    refresh: {
      type: Function,
      required: true,
    },
    // 表格id
    tableId: {
      type: Number,
      require: true,
    },
  });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

第一个组件参数modelValue 对应着原table中的 columns字段,为了达到响应式,所以在原table中,必须将 columns中定义为 ref

# 4.2、 table-id-const.js

根据上面的组件参数中有一个是 tableId,表示表格id,并且要 前端全局唯一,所以呢,这也时候需要在顶级常量目录src/constants/support中创建一个table-id的常量文件,即table-id-const.js

//system系统功能表格初始化id
let systemInitTableId = 10000;
//support支撑功能表格初始化id
let supportInitTableId = 20000;
//业务表格初始化id
let businessOAInitTableId = 30000;
let businessERPInitTableId = 40000;

export const TABLE_ID_CONST = {
  /**
   * 业务
   */
  BUSINESS: {
    OA: {
      NOTICE: businessOAInitTableId + 1, //通知公告
      ENTERPRISE: businessOAInitTableId + 2, //企业信息
    },
    ERP: {
      GOODS: businessERPInitTableId + 1, //商品管理
    },
  },
  /**
   * 系统
   */
  SYSTEM: {
    EMPLOYEE: systemInitTableId + 1, //员工
    MENU: systemInitTableId + 2, //菜单
  },
  /**
   * 支撑
   */
  SUPPORT: {
    CONFIG: supportInitTableId + 1, //参数配置
    DICT: supportInitTableId + 2, //字典
    SERIAL_NUMBER: supportInitTableId + 3, //单号
    OPERATE_LOG: supportInitTableId + 4, //请求监控
    HEART_BEAT: supportInitTableId + 5, //心跳
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 4.3、java代码

对于后端而言,我们采用的是第二种存储json的表结构,所以就比较简单了,就是普通的增删查改。
由于table-operator是一个支撑业务,各个项目中都可能会用到,所以我们写到了 sa-common项目中的 supoort包;
具体可以查看 代码 (opens new window)


# 联系我们

1024创新实验室-主任:卓大 (opens new window),混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。
1024创新实验室(河南·洛阳) (opens new window) 致力于成为中原领先、国内一流的技术团队,以技术创新为驱动,合作各类项目。

加 主任 “卓大” 微信
拉你入群,一起学习
关注 “小镇程序员”
分享代码与生活、技术与赚钱
请 “1024创新实验室” 喝咖啡
支持我们的开源与分享

告白气球 (钢琴版)
JESSE T