Vue3 用户自定义表格列且持久化保存

一、背景与问题

希望用户对于每个表格都可以自定义,并且在下次打开的时候还是保持原样,如张三和李四 对于同一个表格的顺序,隐藏,宽度是不一样的。拆分下需求的问题:

  • 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            列宽
}

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

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

简单对比下

项目优点缺点
铺开第一种满足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,
    },
    ....
    ....
    ]);

是不是很简单呢?

四、实现原理

4.1、 table-operator

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

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

  const props = defineProps({
    // 表格列数组
    modelValue: {
      type: Array,
      default: new Array(),
    },
    // 刷新表格函数
    refresh: {
      type: Function,
      required: true,
    },
    // 表格id
    tableId: {
      type: Number,
      require: true,
    },
  });

第一个组件参数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, //心跳
  },
};

4.3、java代码

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

/**
 * 表格自定义列(前端用户自定义表格列,并保存到数据库里)
 *
 * @Author 1024创新实验室-主任: 卓大
 * @Date 2022-08-12 22:52:21
 * @Wechat zhuoda1024
 * @Email lab1024@163.com
 * @Copyright  <a href="https://1024lab.net">1024创新实验室</a>
 */
@Service
public class TableColumnService {

    @Resource
    private TableColumnDao tableColumnDao;

    /**
     * 获取 - 表格列
     *
     * @return
     */
    public String getTableColumns(RequestUser requestUser, Integer tableId) {
        TableColumnEntity tableColumnEntity = tableColumnDao.selectByUserIdAndTableId(requestUser.getUserId(), requestUser.getUserType().getValue(), tableId);
        return tableColumnEntity == null ? null : tableColumnEntity.getColumns();
    }

    /**
     * 更新表格列
     *
     * @return
     */
    public ResponseDTO<String> updateTableColumns(RequestUser requestUser, TableColumnUpdateForm updateForm) {
        if (CollectionUtils.isEmpty(updateForm.getColumnList())) {
            return ResponseDTO.ok();
        }
        Integer tableId = updateForm.getTableId();
        TableColumnEntity tableColumnEntity = tableColumnDao.selectByUserIdAndTableId(requestUser.getUserId(), requestUser.getUserType().getValue(), tableId);
        if (tableColumnEntity == null) {
            tableColumnEntity = new TableColumnEntity();
            tableColumnEntity.setTableId(tableId);
            tableColumnEntity.setUserId(requestUser.getUserId());
            tableColumnEntity.setUserType(requestUser.getUserType().getValue());

            tableColumnEntity.setColumns(JSONArray.toJSONString(updateForm.getColumnList()));
            tableColumnDao.insert(tableColumnEntity);
        } else {
            tableColumnEntity.setColumns(JSONArray.toJSONString(updateForm.getColumnList()));
            tableColumnDao.updateById(tableColumnEntity);
        }
        return ResponseDTO.ok();
    }

    /**
     * 删除表格列
     *
     * @return
     */
    public ResponseDTO<String> deleteTableColumn(RequestUser requestUser, Integer tableId) {
        tableColumnDao.deleteTableColumn(requestUser.getUserId(), requestUser.getUserType().getValue(), tableId);
        return ResponseDTO.ok();
    }
}

五、看下效果

5.1 表格上操作

在这里插入图片描述

5.2 设置列

在这里插入图片描述

六、代码

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 要设置EasyExcel中的宽,可以使用`Sheet.setColumnWidth()`方法。这个方法接受两个参数:的索引和宽。例如,要将第一的宽度设置为15个字符宽度,可以使用以下代码: ``` Sheet sheet = ...; // 获取要操作的sheet sheet.setColumnWidth(0, 15 * 256); ``` 其中,第一个参数是的索引,从0开始计数,第二个参数是的宽度,以1/256个字符为单位。在这个例子中,15 * 256表示15个字符的256倍,即15个字符的宽度。 ### 回答2: EasyExcel是一款开源的Java工具,用于操作Excel文件。设置宽是EasyExcel中常用的操作之一。 在EasyExcel中,我们可以使用`SheetBuilder`和`ColumnWidthBuilder`来设置宽。首先,我们需要创建一个`SheetBuilder`对象来构建Sheet,并指定要操作的Sheet的名称和索引。然后,我们可以使用`ColumnWidthBuilder`来设置宽。 假设我们要将第1宽设置为20,第2宽设置为30,我们可以按照以下步骤进行操作: ```java // 创建一个SheetBuilder对象 SheetBuilder sheetBuilder = EasyExcel.write("path/to/excel.xlsx").sheet("Sheet1").build(); // 创建一个ColumnWidthBuilder对象 ColumnWidthBuilder columnWidthBuilder = new ColumnWidthBuilder(); // 设置第1宽为20 columnWidthBuilder.columnWidth(0, 20); // 设置第2宽为30 columnWidthBuilder.columnWidth(1, 30); // 将设置的宽应用到Sheet中 sheetBuilder.columnWidths(columnWidthBuilder); // 写入Excel文件 sheetBuilder.doWrite(dataList); ``` 在上述代码中,`EasyExcel.write("path/to/excel.xlsx")`用于指定要操作的Excel文件路径。`sheet("Sheet1")`用于指定要操作的Sheet名称。`columnWidths(columnWidthBuilder)`用于将设置的宽应用到Sheet中。最后,`doWrite(dataList)`用于将数据写入Excel文件。 通过以上步骤,我们可以轻松地使用EasyExcel设置宽。需要注意的是,设置宽的索引从0开始计数,表示的索引位置。 ### 回答3: EasyExcel是一款优秀的Java处理Excel的开源框架,提供了丰富的API来操作Excel文件。要设置宽,可以按照以下步骤进行操作: 1. 首先,创建一个ExcelWriter对象,用来操作Excel文件。可以使用`EasyExcel.write`方法来创建。 2. 然后,创建一个Sheet对象,表示Excel中的一个工作表。可以使用`sheet`方法来创建。 3. 使用`registerWriteHandler`方法,注册一个自定义的写处理器。可以使用`MyColumnWidthStyleStrategy`作为一个例子,并实现`ColumnWidthStyleStrategy`接口,在`setDefaultColumnWidth`方法中设置宽,然后在写入Excel文件时生效。 4. 使用`write`方法写入数据到Excel文件。可以根据需求,使用`write`方法写入不同类型的数据,如List、Map等。 5. 最后,使用`finish`方法,保存并关闭Excel文件。这个方法会将数据写入到磁盘中。 下面是一个简单的例子: ```java public class EasyExcelDemo { public static void main(String[] args) { // 1. 创建ExcelWriter对象 ExcelWriter excelWriter = EasyExcel.write("test.xlsx").build(); // 2. 创建Sheet对象 WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build(); // 3. 注册自定义的写处理器,设置宽 MyColumnWidthStyleStrategy columnWidthStyleStrategy = new MyColumnWidthStyleStrategy(); writeSheet.setWriteHandler(columnWidthStyleStrategy); // 4. 写入数据到Excel文件 excelWriter.write(dataList, writeSheet); // 5. 保存并关闭Excel文件 excelWriter.finish(); } } // 自定义的写处理器 public class MyColumnWidthStyleStrategy implements ColumnWidthStyleStrategy { @Override public void setColumnWidthAndStyle(CellStyle cellStyle, Integer columnIndex, Integer width) { // 设置宽 sheet.setColumnWidth(columnIndex, width * 256); } } ``` 使用上述步骤,就可以方便地使用EasyExcel设置宽。需要注意的是,`setDefaultColumnWidth`方法中的宽参数单位是1/256个字符宽度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六边形工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值