JVxeTable插入行和合并单元格

本文介绍了如何在JEECGBOOT项目中利用JVxeTable组件实现表格的插入行功能,并展示了如何合并单元格以展示一级和二级数据。作者提供了详细的代码示例和实现方法,包括使用Vue3.0的事件处理和组件交互。
摘要由CSDN通过智能技术生成

JVxeTable实践

第一章 插入行和合并单元格应用 vue3.0


前言

JvxeTable 是在JEECGBOOT项目中根据VxeTable封装的一个实用性组件,该组件介绍见[JvxeTable文档](https://help.jeecg.com/component/JVxeTable.html)。该组件中封装有新增功能,插入行功能没有实现,下面介绍JvxeTable的插入行功能。
参考[vxe-table api文档](https://vxetable.cn/v4/#/table/api)

一、实现目标

在这里插入图片描述
此表格分为一级和二级列表(不是树结构显示);一级具有添加二级数据的功能(如图中左侧添加按钮)

二、代码实现

1.JvxeTable标签

代码如下(示例):

<JVxeTable
              class="jtable"
              ref="tableRef1"
              :disabled="disabled"
              keepSource
              toolbar
              asyncRemove
              :loading="loading"
              rowSelection
              :maxHeight="500"
              :columns="columns"
              :dataSource="concreteList"
              @added="addRowHandel"
              @removed="handleTableRemove"
              @valueChange="valueChange"
              :reloadEffect="true"
              :linkageConfig="linkageConfig"
              :toolbarConfig="{ slot: ['prefix', 'suffix'], btn: ['add', 'remove', 'clearSelection'] }"
              :span-method="rowspanMethod"
            >
              <template #addButton="props">
                <a-button v-if="props.row.level === '0'" type="primary" preIcon="ant-design:plus-square-outlined" @click="addNextRow(props)" />
              </template>
              <template #strengthCategory="{ row }">
                <a-select
                  style="width: 150px"
                  show-search
                  :disabled="disabled"
                  v-model:value="row.strengthCategory"
                  allowClear
                  :filter-option="filterOption"
                  placeholder="请选择类别"
                  @change="proChange"
                >
                  <template v-for="item in concreteStrengthData.value" :key="`${item.id}`">
                    <a-select-option :value="item.id" :title="item.name">{{ item.name }}</a-select-option>
                  </template>
                </a-select>
              </template>
              <template #action="props">
                <a @click="handleMx(props)">明细维护</a>
              </template>
            </JVxeTable>

2.实现方法

1)添加子行:

  /**
   * 添加子行 写的不好勿怪 仅参考
   */
  async function addNextRow({ row }) {
    let rowIndex;
    let $table = tableRef1.value;
    let array = $table.getTableData();
    let length = array.length;
    // 因是添加临时数据,方法中传入的rowIndex始终都是-1 此采用vxeTable的getVTRowIndex方法获取行下标
    rowIndex = $table.getXTable().getVTRowIndex(row);
    // 设置需要添加的行数据 和首行数据大部分一致
    let record = {
      level: '1',
      strengthCategory: '',
      strengthCategorySmall: '',
    };
    Object.assign(record, row);
    for (let key in row) {
      if (key != 'id' || key != 'strengthCategory' || key != 'strengthCategorySmall' || key != 'level') {
        record[key] = row[key];
      }
    }
    record.level = '1';
    record.strengthCategory = '';
    record.strengthCategorySmall = '';
    let tagId = row.tagId;
    let childArray = [];
    // 因为在一组中,始终都是按顺序往下插入行,所以每次的rowIndex需由当前行的下标加上下一级的列表长度,这样在一组中依次往下添加
    let num = 0;
    if (tagId) {
      let index = 0;
      for (let element of array) {
        if (element.level === '0' && tagId === element.tagId) {
          num = index;
        }
        if (element.level === '1' && tagId === element.tagId) {
          childArray.push(element);
        }
        index++;
      }
    }
    let childArrayLength = childArray.length;
    rowIndex = num + 1 + childArrayLength;
    // 此判断可为没有 可以都采用else中的内容
    // 因每次生成id都一致 所以又重新生成了下row_id
    // 采用vxe-table中的insertAt方法去插入行 必须同步进行 -1代表在最后一行插入
    if (rowIndex >= length) {
      const { row: newRow } = await $table.getXTable().insertAt(record, -1);
      newRow.id = 'row_' + randomString(32, '123456789');
    } else {
      let index = rowIndex;
      console.log('index', index);
      // insertRows方法是JeecgBoot项目中封装的方法
      const { row: newRow } = await $table.insertRows(record, index);
      newRow.id = 'row_' + randomString(32, '123456789');
    }

    $table.getXTable().reloadData($table.getTableData());
  }

2)insertRows方法(仅参考)

  // 创建新行,自动添加默认值
  function createRow(record: Recordable = {}) {
    let xTable = getXTable();
    // 添加默认值
    xTable.internalData.tableFullColumn.forEach((column) => {
      let col = column.params;
      if (col) {
        if (col.key && (record[col.key] == null || record[col.key] === '')) {
          // 设置默认值
          let createValue = getEnhanced(col.type).createValue;
          let defaultValue = col.defaultValue ?? '';
          let ctx = { context: { row: record, column, $table: xTable } };
          record[col.key] = createValue(defaultValue, ctx);
        }
        // 处理联动列
        if (col.type === JVxeTypes.select && data.innerLinkageConfig.size > 0) {
          // 判断当前列是否是联动列
          if (data.innerLinkageConfig.has(col.key)) {
            let configItem = data.innerLinkageConfig.get(col.key);
            linkageMethods.getLinkageOptionsAsync(configItem, '');
          }
        }
      }
    });
    return record;
  }

  async function addOrInsert(rows: Recordable | Recordable[] = {}, index, triggerName, options?: IAddRowsOptions) {
    let xTable = getXTable();
    let records;
    if (isArray(rows)) {
      records = rows;
    } else {
      records = [rows];
    }
    // 遍历添加默认值
    records.forEach((record) => createRow(record));
    let setActive = options?.setActive ?? props.addSetActive ?? true;
    let result = await pushRows(records, { index: index, setActive });
    // 遍历插入的行
    // online js增强时以传过来值为准,不再赋默认值
    if (!(options?.isOnlineJS ?? false)) {
      if (triggerName != null) {
        for (let i = 0; i < result.rows.length; i++) {
          let row = result.rows[i];
          trigger(triggerName, {
            row: row,
            rows: result.rows,
            insertIndex: index,
            $table: xTable,
            target: instanceRef.value,
            isModalData: options?.isModalData
          });
        }
      }
    }
    return result;
  }

 /**
   * 添加一行或多行临时数据,不会填充默认值,传什么就添加进去什么
   * @param rows
   * @param options 选项
   * @param options.setActive 是否激活最后一行的编辑模式
   */
  async function pushRows(rows: Recordable | Recordable[] = {}, options = { setActive: false, index: -1 }) {
    let xTable = getXTable();
    let { setActive, index } = options;
    index = index === -1 ? index : xTable.internalData.tableFullData[index];
    // 插入行
    let result = await xTable.insertAt(rows, index);
    if (setActive) {
      // 激活最后一行的编辑模式
      xTable.setActiveRow(result.rows[result.rows.length - 1]);
    }
    await recalcSortNumber();
    return result;
  }

  /**
   * 插入一行或多行临时数据
   *
   * @param rows
   * @param index 添加下标,数字,必填
   * @param options 参数
   * @return
   */
  function insertRows(rows: Recordable | Recordable[] = {}, index: number, options?: IAddRowsOptions) {
    if (index < 0) {
      console.warn(`【JVxeTable】insertRows:index必须传递数字,且大于-1`);
      return;
    }
    return addOrInsert(rows, index, 'inserted', options);
  }

3)合并单元格:

  :span-method="rowspanMethod"
  // 通用行合并函数(将相同多列数据合并为一行)
  function rowspanMethod({ row, _rowIndex, column, visibleData }) {
    // 对象中什么字段需要合并就往后面填写
    let fields = [];
    let array = strandList.value;
    if (array.length > 0) {
      array.forEach((element) => {
        fields.push(element.CompressiveStrength);
      });
    }
    fields.push('action');
    // 拿到一行中所有列中的值
    // 一行中只要tagId属性值一样 就合并
    let cellValue = row['tagId'];
    if (cellValue && fields.includes(column.property)) {
      let prevRow = visibleData[_rowIndex - 1];
      let nextRow = visibleData[_rowIndex + 1];
      // 一行中只要tagId属性值一样 就合并
      if (prevRow && prevRow['tagId'] === cellValue) {
        return { rowspan: 0, colspan: 0 };
      } else {
        let countRowspan = 1;
        // 一行中只要tagId属性值一样 就合并
        while (nextRow && nextRow['tagId'] === cellValue) {
          nextRow = visibleData[++countRowspan + _rowIndex];
        }
        if (countRowspan > 1) {
          return { rowspan: countRowspan, colspan: 1 };
        }
      }
    }
  }


  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值