handsonetable+vue 表格在线编辑

<template>
  <div>
    <div id="example-container" class="wrapper">
      <HotTable ref="testHot" :root="root" :settings="hotSettings"/>
      <el-button type="primary" size="small" @click="saveData">{{ '保存' }}</el-button>
      <el-button size="small" @click="goBack">{{ '返回' }}</el-button>
      <!--<el-button size="small" @click="goBack">{{ $t('task.next_step') }}</el-button>-->
    </div>
  </div>
</template>
<script>
import HotTable from 'vue-handsontable-official'
export default {
  name: 'SampleApp',
  components: {
    HotTable
  },
  props: {
    taskid: {
      type: String,
      default: ''
    },
    createTaskType: {
      type: Boolean,
      default: false
    },
    createTaskForm: {
      type: String,
      default: ''
    }
  },
  data: function() {
    return {
      root: 'test-hot',
      hotSettings: {
        data: [],
        // startRows: 11, //行列范围
        // startCols: 11,
        minRows: 1, // 最小行列
        // minCols: 6,
         '100%',
        // maxRows: 30, //最大行列
        // maxCols: 30,
        rowHeaders: true, // 行表头
        height: 320,
        rowHeights: 23,
        colHeaders: true, // 行表头
        // colHeaders: ["时间", "Kia", "Nissan", "Toyota", "Honda", "123"], //自定义列表头or 布尔值
        // minSpareCols: 2, //列留白
        // minSpareRows: 2, //行留白
        currentRowClassName: 'currentRow', // 为选中行添加类名,可以更改样式
        currentColClassName: 'currentCol', // 为选中列添加类名
        autoWrapRow: true, // 自动换行
        contextMenu: {
          // 自定义右键菜单,可汉化,默认布尔值
          items: {
            row_above: {
              name: '上方插入一行'
            },
            row_below: {
              name: '下方插入一行'
            },
            // col_left: {
            //   name: "左方插入列"
            // },
            // col_right: {
            //   name: "右方插入列"
            // },
            hsep1: '---------', // 提供分隔线
            remove_row: {
              name: '删除行'
            }
            // remove_col: {
            //   name: "删除列"
            // },
            // make_read_only: {
            //   name: "只读"
            // },
            // borders: {
            //   name: "表格线"
            // },
            // commentsAddEdit: {
            //   name: "添加备注"
            // },
            // commentsRemove: {
            //   name: "取消备注"
            // },
            // freeze_column: {
            //   name: "固定列"
            // },
            // unfreeze_column: {
            //   name: "取消列固定"
            // },
            // hsep2: "---------"
          }
        }, // 右键效果
        fillHandle: true, // 选中拖拽复制 possible values: true, false, "horizontal", "vertical"
        fixedColumnsLeft: 0, // 固定左边列数
        fixedRowsTop: 0, // 固定上边列数
        columns: [
          // 添加每一列的数据类型和一些配置
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          // {},
          // {},
          // {},
          // {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {}
        ],
        manualColumnFreeze: true, // 手动固定列
        manualColumnMove: true, // 手动移动列
        manualRowMove: true, // 手动移动行
        manualColumnResize: true, // 手工更改列距
        manualRowResize: true, // 手动更改行距
        comments: true, // 添加注释
        customBorders: [], // 添加边框
        columnSorting: true, // 排序
        stretchH: 'none' // 根据宽度横向扩展,last:只扩展最后一列,none:默认不扩展
      }
    }
  },

  mounted() {
    // 获取任务详情
    console.log(this.taskid)
    if (this.taskid) {
      this.$store.dispatch('GET_Field_LIST', this.taskid).then(data => {
        // 拼column
        var columnSize = data.data.columnLargestSize
        if (columnSize === 0) {
          columnSize = 30
        }
        var size = []
        for (var i = 0; i < columnSize; i++) {
          var col = {}
          size.push(col)
        }
        console.log(size)
        // this.hotSettings.columns = size;
        // 放数据
        this.hotSettings.data = data.data.result
      })
    }
  },
  methods: {
    goBack() {
      this.$parent.goback()
      // this.$router.push('/integration/task')
    },
    submit() {
      this.postData()
    },
    transformTf(str) {
      return str.replace(/([A-Z])/g, '_$1').toLowerCase()
    },
    transformStr3(str) {
      const re = /_(w)/g
      return str.replace(re, function($0, $1) {
        return $1.toUpperCase()
      })
    },
    saveData() {
      var examData = this.$refs.testHot.table.getData() // 这里要注意,如果使用this.hotSettings.data 保存表格数据,拖拽完以后数据的顺序将不会更新,因此使用 this.$refs.testHot.table.getData(); 来获取数据,获取的数据格式为二维数组。
      var param = []
      param.push(examData)
      param.push(this.taskid)
      this.$store.dispatch('SAVE_Field_LIST', param).then(data => {
        this.$notify({
          title: '操作成功',
          dangerouslyUseHTMLString: true,
          type: 'success'
        })
        console.log(data)
        this.goBack()
      })
    }
  }
}
</script>

<style>
button {
  margin: 20px 20px;
}
.handsontable .currentRow {
  background-color: #e7e8ef;
}

.handsontable .currentCol {
  background-color: #f9f9fb;
}
#test-hot {
  width: 800px;
  height: 800px;
  overflow: hidden;
}
</style>

效果 

 后端代码 一个用来回显 一个是修改数据

 Resource方法

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/template/table/{id}", method = {
            RequestMethod.GET }, produces = "application/json;charset=UTF-8")
    @ResponseBody
    @ApiOperation("给在线模版编辑准备的数据")
    public ResponseEntity<RestResponse<List<ImportField>>> getTemplateTableField(
            @ApiParam(required = true, name = "Authorization", value = "jwt凭证") @RequestHeader(value = "Authorization", required = true) String Authorization,
            @PathVariable(value = "id", required = true) String id) throws URISyntaxException, WebException, Exception {
        TableTemplateField result = importFieldService.getTableFieldByTemplateId(id);
        return ResponseEntity.ok().body(RestResponse.getRestResponse(CommonCodeMessageEnum.SUCCESS.getBizCode(),
                CommonCodeMessageEnum.SUCCESS.getMessage(), result));
    }
    
    
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/template/table/{id}", method = {
            RequestMethod.POST }, produces = "application/json;charset=UTF-8")
    @ResponseBody
    @ApiOperation("编辑在线模版")
    public ResponseEntity<RestResponse<List<ImportField>>> editTemplateTableField(
            @ApiParam(required = true, name = "Authorization", value = "jwt凭证") @RequestHeader(value = "Authorization", required = true) String Authorization,@RequestBody List<String[]> json,
            @PathVariable(value = "id", required = true) String id){
        System.out.println(json.toString());
        importFieldService.editTemplateTableField(json,id);
        return ResponseEntity.ok().body(RestResponse.getRestResponse(CommonCodeMessageEnum.SUCCESS.getBizCode(),
                CommonCodeMessageEnum.SUCCESS.getMessage(), "success"));
    }

 数据格式,类似一个list<<string>>的格式,返回和接收都是这个格式

[
["20080101", 10, 11, 12, 13, true],
["20090101", 20, 11, 14, 13, true],
["20010101", 30, 15, 12, 13, true],
["20010101", 32, 213, 21, 312, true],
["20010201", 32, 213, 21, 312, true],
["20010301", 32, 213, 21, 312, true],
["20010401", 32, 213, 21, 312, true],
["20010501", 32, 213, 21, 312, true],
["20010601", 32, 213, 21, 312, true]
],

 service方法

    /**
     * 获取模版字段,转成table
     * 
     * @param id
     * @return
     */
    public TableTemplateField getTableFieldByTemplateId(String id) {
        List<List<String>> datalist = new ArrayList<>();
        List<ImportField> list = importFieldRepository.findFieldByTemplateId(id);
        // 根据rowNumber 分类column
        Map<Integer, List<ImportField>> map = list.stream().sorted(Comparator.comparing(ImportField::getColumnNo))
                .collect(Collectors.groupingBy(ImportField::getRowNo,
                        Collectors.mapping(java.util.function.Function.identity(), Collectors.toList())));
        for (Integer i : map.keySet()) {
            List<String> contentlist = new ArrayList<>();
            for (ImportField field : map.get(i)) {
                contentlist.add(field.getName() + "(" + field.getLabel() + ")");
            }
            datalist.add(contentlist);
        }
        System.out.println(datalist.toString());
        TableTemplateField tableTemplateField = new TableTemplateField();
        tableTemplateField.setResult(datalist);
        // 获取最大的column
        Optional<ImportField> importField = list.stream().max(Comparator.comparingInt(ImportField::getColumnNo));
        Integer columSize = importField.isPresent() ? importField.get().getColumnNo() : 0;
        tableTemplateField.setColumnLargestSize(columSize);
        return tableTemplateField;
    }

    /**
     * 修改模版field 全删全增
     * 
     * @param json
     * @param id
     */
    public void editTemplateTableField(List<String[]> dataList, String id) {
        ImportTemplate template = importTemplateRepository.findOne(id);
        Set<ImportField> fields = new HashSet<ImportField>();
        if (dataList.size() > 0) {
            for (int i = 1; i <= dataList.size(); i++) {
                String[] heads = dataList.get(i - 1);
                for (int b = 1; b <= heads.length; b++) {
                    ImportField field = new ImportField();
                    String fieldcontent = heads[b - 1];
                    field.setRowNo(i);
                    field.setColumnNo(b);
                    // 可能存在空字段
                    if (!StringUtils.isEmpty(fieldcontent)) {
                        if (fieldcontent.contains("rowkey")) {
                            field.setIsRowKey(1);
                        }
                        int a = fieldcontent.indexOf("(");
                        int c = fieldcontent.indexOf(")");
                        if (a == -1 || c == -1) {
                            throw new WebException(ErrorEnum.ERR_FIELDNAME_UNFORMATTER);
                        }
                        String label = fieldcontent.substring(a + 1, c);
                        String name = fieldcontent.substring(0, a);
                        field.setName(name);
                        field.setLabel(label);
                        fields.add(field);
                    }
                }
            }
            if (dataList.size() > 1) {
                template.setIsMutipartTitle(1);
            }
            template.setTitleLine(dataList.size());
            template.setImportField(fields);
            importTemplateRepository.save(template);
        }
    }

原文地址:https://www.cnblogs.com/chenyangwang/p/11095755.html