第一章 插入行和合并单元格应用 vue3.0
JvxeTable 是在JEECGBOOT项目中根据VxeTable封装的一个实用性组件,该组件介绍见[JvxeTable文档](https://help.jeecg.com/component/JVxeTable.html)。该组件中封装有新增功能,插入行功能没有实现,下面介绍JvxeTable的插入行功能。
参考[vxe-table api文档](https://vxetable.cn/v4/#/table/api)
此表格分为一级和二级列表(不是树结构显示);一级具有添加二级数据的功能(如图中左侧添加按钮)
代码如下(示例):
<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>
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 };
}
}
}
}