feat: 完成表格行操作

master
shengwen.chen 2 months ago
parent 9a82c26ace
commit 9b44a03ad0

@ -1,13 +1,16 @@
<!-- eslint-disable @typescript-eslint/no-explicit-any -->
<script setup lang="ts">
import { inject } from 'vue'
import { addTableRow, addTableCol } from "@/utils/table";
import { addTableRow, addTableCol, mergeRightCol, mergeRow, cancelMergeCol, } from "@/utils/table";
import { handleFindDomById } from "@/utils/index";
import type { IWidget, IWidgetJson } from '@/types/widgetsConfigInterface'
import RendererDom from '@/components/RendererDom.vue'
const props = defineProps<{
itemData: IWidget
itemData: IWidget,
rowIndex: number,
colIndex: number,
colLength: number
}>()
//
@ -83,7 +86,8 @@ const handleDelDom = (node: any = widgetJson) => {
<table border="1" cellpadding="10" cellspacing="0" class="w-full">
<template v-for="(row, rowIndex) in itemData['subDomList']" :key="rowIndex">
<tr>
<RendererDom v-for="subData in row" :key="subData['id']" :itemData="subData" />
<RendererDom v-for="(subData, index) in row" :key="subData['id']" :itemData="subData" :rowIndex="rowIndex"
:colIndex="index" :colLength="Array.isArray(row) ? row['length'] : 1" />
</tr>
</template>
</table>
@ -93,10 +97,10 @@ const handleDelDom = (node: any = widgetJson) => {
<div @click.stop="handleFindLastDom" title="选中父组件">
<Icon icon="ion:return-up-back" />
</div>
<div @click.stop="addTableRow(widgetJson, 'table-cell')" title="插入新行">
<div @click.stop="addTableRow(widgetJson, rowIndex, true, false, 'table-cell')" title="插入新行">
<Icon icon="iconoir:arrow-separate-vertical" />
</div>
<div @click.stop="addTableCol(widgetJson, 'table-cell')" title="插入新列">
<div @click.stop="addTableCol(widgetJson, colIndex, true, false, 'table-cell')" title="插入新列">
<Icon icon="iconoir:arrow-separate" />
</div>
<div @click.stop="() => { debugger; handleDelDom() }" title="移除组件">
@ -109,10 +113,12 @@ const handleDelDom = (node: any = widgetJson) => {
<!-- 针对表格列 -->
<template v-if="itemData['type'] == 'table-cell'">
<td v-if="!itemData['merged']" :colspan="itemData['options']['colspan']" :rowspan="itemData['options']['rowspan']"
:data-id="itemData['id']" :class="{ activeDom: widgetJson['activeConfig']['activeId'] == itemData['id'] }"
<td v-if="!itemData['options']['merged']" :colspan="itemData['options']['colspan']"
:rowspan="itemData['options']['rowspan']" :data-id="itemData['id']"
:class="{ activeDom: widgetJson['activeConfig']['activeId'] == itemData['id'] }"
@click.stop="handleSelectDom(itemData['id'])">
<RendererDom v-for="subData in itemData['subDomList'] as IWidget[]" :key="subData['id']" :itemData="subData" />
<RendererDom v-for="(subData, index) in itemData['subDomList'] as IWidget[]" :key="subData['id']"
:itemData="subData" :rowIndex="rowIndex" :colIndex="index" :colLength="1" />
<template v-if="itemData['id'] == widgetJson['activeConfig']['activeId']">
<div class="activeDomWrapper">{{ widgetJson['activeConfig']['activeDisplayName'] }}</div>
<div class="fnArea">
@ -123,20 +129,23 @@ const handleDelDom = (node: any = widgetJson) => {
<Icon icon="hugeicons:menu-square" />
<div class="actionBox">
<ul>
<li>插入左侧列</li>
<li>插入右侧列</li>
<li>插入上方行</li>
<li>插入下方行</li>
<li @click.stop="addTableCol(widgetJson, colIndex, false, true, 'table-cell')">插入左侧列</li>
<li @click.stop="addTableCol(widgetJson, colIndex, true, true, 'table-cell')">插入右侧列</li>
<li @click.stop="addTableRow(widgetJson, rowIndex, false, true, 'table-cell')">插入上方行</li>
<li @click.stop="addTableRow(widgetJson, rowIndex, true, true, 'table-cell')">插入下方行</li>
<el-divider />
<li>合并左侧单元格</li>
<li>合并右侧单元格</li>
<li>合并整行</li>
<li :class="{ readOnly: colIndex == colLength - 1 || itemData['options']['colspan'] == colLength }"
@click="mergeRightCol(widgetJson, rowIndex, colIndex)">合并右侧单元格</li>
<li :class="{ readOnly: colLength == 1 || colIndex > 0 || itemData['options']['colspan'] == colLength }"
@click="mergeRow(widgetJson, rowIndex)">合并整行
</li>
<el-divider />
<li>合并上方单元格</li>
<li>合并下方单元格</li>
<li>合并整列</li>
<el-divider />
<li>撤销行合并</li>
<li :class="{ readOnly: itemData['options']['colspan'] && itemData['options']['colspan'] == 1 }"
@click="cancelMergeCol(widgetJson, rowIndex, colIndex)">撤销行合并
</li>
<li>撤销列合并</li>
<el-divider />
<li>删除整列</li>

@ -17,6 +17,8 @@ export interface IOption {
colspan?: number
// 列合并
rowspan?: number
// 单元格是否被合并
merged?: boolean
}
export type ICategory = 'container' | 'formItem'
@ -38,8 +40,6 @@ export interface IWidget {
options: IOption
// 子结构
subDomList?: IWidget[] | IWidget[][]
// 单元格是否被合并
merged?: boolean
// X轴坐标
axisX?: number
// Y轴坐标

@ -51,8 +51,8 @@ export const addTable = (widgetJson: IWidgetJson, addItemTypeName: any) => {
* @param addItemTypeName
* @param fatherId
*/
export const addTableRow = (widgetJson: IWidgetJson, addItemTypeName = 'table-cell') => {
const tableJson = handleFindDomById(widgetJson['subDomList'], widgetJson['activeConfig']['activeId'], false);
export const addTableRow = (widgetJson: IWidgetJson, rowIndex: number, isPush: boolean, returnParent: boolean, addItemTypeName = 'table-cell') => {
const tableJson = handleFindDomById(widgetJson['subDomList'], widgetJson['activeConfig']['activeId'], returnParent);
if (tableJson) {
const newRow: IWidget[] = []
for (let index = 0; index < tableJson['subDomList'][0]['length']; index++) {
@ -61,24 +61,119 @@ export const addTableRow = (widgetJson: IWidgetJson, addItemTypeName = 'table-ce
newRow.push(addItemData);
}
}
(tableJson['subDomList'] as IWidget[][]).push(newRow)
if (isPush) {
(tableJson['subDomList'] as IWidget[][]).splice(rowIndex + 1, 0, newRow)
} else {
(tableJson['subDomList'] as IWidget[][]).splice(rowIndex, 0, newRow)
}
}
}
/**
*
* @param widgetJson
* @param addItemTypeName
* @param fatherId
* @param widgetJson
* @param colIndex
* @param isPush
* @param returnParent
* @param addItemTypeName
*/
export const addTableCol = (widgetJson: IWidgetJson, addItemTypeName = 'table-cell') => {
const tableJson = handleFindDomById(widgetJson['subDomList'], widgetJson['activeConfig']['activeId'], false);
export const addTableCol = (widgetJson: IWidgetJson, colIndex: number, isPush: boolean, returnParent: boolean, addItemTypeName = 'table-cell') => {
const tableJson = handleFindDomById(widgetJson['subDomList'], widgetJson['activeConfig']['activeId'], returnParent);
if (tableJson && tableJson['subDomList']) {
for (let index = 0; index < tableJson['subDomList']['length']; index++) {
const { addItemData } = formatAddItem(addItemTypeName);
if (addItemData) {
const row: IWidget[] = tableJson['subDomList'][index];
row.push(addItemData);
if (isPush) {
row.splice(colIndex + 1, 0, addItemData);
} else {
row.splice(colIndex, 0, addItemData);
}
}
}
}
}
/**
*
* @param widgetJson
* @param rowIndex
* @param colIndex
*/
export const mergeRightCol = (widgetJson: IWidgetJson, rowIndex: number, colIndex: number) => {
const tableJson = handleFindDomById(widgetJson['subDomList'], widgetJson['activeConfig']['activeId'], true);
if (tableJson && tableJson['subDomList']) {
let isStartmerge = false;
let mergeIndexArr: number[] = [];
let targetItem = { colspan: 0 };
const rowData = tableJson['subDomList'][rowIndex];
for (let index = 0; index < rowData['length']; index++) {
if (isStartmerge) {
if (mergeIndexArr.includes(index)) {
const nextItem = rowData[index]['options'] as any;
if (nextItem['merged']) {
targetItem['colspan'] = targetItem['colspan'] + nextItem['colspan']
}
nextItem['colspan'] = 1;
nextItem['merged'] = true;
}
}
if (colIndex == index) {
isStartmerge = true;
targetItem = rowData[index]['options'];
rowData[index]['options']['colspan']++;
mergeIndexArr = Array.from({ length: rowData[index]['options']['colspan'] }, (_, i) => index + i);
}
}
}
}
/**
*
* @param widgetJson
* @param rowIndex
*/
export const mergeRow = (widgetJson: IWidgetJson, rowIndex: number) => {
const tableJson = handleFindDomById(widgetJson['subDomList'], widgetJson['activeConfig']['activeId'], true);
if (tableJson && tableJson['subDomList']) {
const rowData = tableJson['subDomList'][rowIndex];
for (let index = 0; index < rowData['length']; index++) {
if (index == 0) {
rowData[index]['options']['colspan'] = rowData['length'];
} else {
const nextItem = rowData[index]['options'] as any;
nextItem['colspan'] = 1;
nextItem['merged'] = true;
}
}
}
}
/**
*
* @param widgetJson
* @param rowIndex
* @param colIndex
*/
export const cancelMergeCol = (widgetJson: IWidgetJson, rowIndex: number, colIndex: number) => {
const tableJson = handleFindDomById(widgetJson['subDomList'], widgetJson['activeConfig']['activeId'], true);
if (tableJson && tableJson['subDomList']) {
let isStartmerge = false;
let mergeIndexArr: number[] = [];
const rowData = tableJson['subDomList'][rowIndex];
for (let index = 0; index < rowData['length']; index++) {
if (isStartmerge) {
if (mergeIndexArr.includes(index)) {
(rowData[index]['options'] as any)['merged'] = false;
(rowData[index]['options'] as any)['colspan'] = 1;
}
}
if (colIndex == index) {
isStartmerge = true;
mergeIndexArr = Array.from({ length: rowData[index]['options']['colspan'] }, (_, i) => index + i);
(rowData[index]['options'] as any)['colspan'] = 1;
}
}
}

@ -17,9 +17,9 @@ export const containers: IWidget[] = [
type: 'table-cell',
displayName: '子单元格',
icon: 'Monitor',
merged: false,
options: {
name: '',
merged: false,
hidden: false,
colspan: 1,
rowspan: 1,

@ -16,8 +16,8 @@ provide('docForm', docForm)
<section class="editWrapper">
<h1 class="text-sky-300">{{ widgetJson }}</h1>
<el-form :model="docForm" label-width="80px">
<template v-for="item in widgetJson['subDomList']" :key="item['id']">
<RendererDom :itemData="item" />
<template v-for="(item, index) in widgetJson['subDomList']" :key="item['id']">
<RendererDom :itemData="item" :rowIndex="index" :colIndex="index" :colLength="1" />
</template>
</el-form>
</section>
@ -56,9 +56,9 @@ provide('docForm', docForm)
left: 50%;
transform: translateX(-50%);
padding-top: 12px;
z-index: 10;
ul {
list-style: none;
padding-left: 0;
background-color: #fff;
@ -72,10 +72,15 @@ provide('docForm', docForm)
font-size: 12px;
padding: 4px 8px;
&:hover {
&:not(.readOnly):hover {
background-color: #c9effd;
color: var(--el-color-primary);
}
&.readOnly {
color: #c0c4cc;
cursor: not-allowed;
}
}
}
}

Loading…
Cancel
Save