功能如下
<template>
<div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="80%"
>
<dl class="multi-level-table">
<dt>
<div
v-for="(column, c1) in columnsSimulation"
:key="c1"
class="th"
:style="`width: ${column.width}px`"
>
<span v-text="column.label"></span>
</div>
</dt>
<dd
v-for="(item, i) in dataSimulation.firstOrder"
:key="`${i}_1`"
>
<!-- 第一行的第一个表格 后台类目-->
<div
class="td p10"
:style="`width: ${columnsSimulation[1].width}px`"
>
<el-input
v-model="item.compSkuNum"
/>
<!-- 这个是添加删除组件,,, 只有一条数据禁止删除 -->
<AddDelButtonGroup
:index-list="[i]"
:disabled="dataSimulation.firstOrder.length === 1"
@operator="operatorRow"
/>
</div>
<!-- 第一行的第二个表格 -->
<div
v-for="(strategy, s) in item.SecondLevel"
:key="`${s}_2`"
class="td-line"
>
<!-- 竞对类型 -->
<div
class="td p10"
:style="`width: ${columnsSimulation[1].width}px`"
>
<el-input
v-model="strategy.compSkuNum"
/>
<AddDelButtonGroup
:index-list="[i, s]"
:disabled="item.SecondLevel.length === 1"
@operator="operatorRow"
/>
</div>
<!-- 竞争品类型 -->
<div
class="td p10"
:style="`width: ${columnsSimulation[1].width}px`"
>
<div
v-for="(threeLevel, cIndex) in strategy.threeLevel"
:key="`${cIndex}_3`"
class="td-line"
>
<!-- 竞对类型 -->
<div
class="td p10"
:style="`width: ${columnsSimulation[1].width}px`"
>
<el-input
v-model="threeLevel.compSkuNum"
/>
<AddDelButtonGroup
:index-list="[i, s, cIndex]"
:disabled="strategy.threeLevel.length === 1"
@operator="operatorRow"
/>
</div>
</div>
</div>
</div>
</dd>
</dl>
<span
slot="footer"
class="dialog-footer"
>
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button
type="primary"
@click="confirmDialogVisible"
>确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import {
defineComponent, toRefs, getCurrentInstance, reactive,
} from '@vue/composition-api';
import AddDelButtonGroup from './AddDelButtonGroup';
export default defineComponent({
name: 'ConventionalPricingTableRef',
components: { AddDelButtonGroup },
props: {
query: {
type: Object,
default: () => ({}),
},
},
setup() {
const { proxy } = getCurrentInstance();
const initData = reactive({
dialogVisible: true,
// 表头
columnsSimulation: [{
label: '组织',
width: 200,
},
{
label: '竞对',
width: 200,
},
{
label: '标签',
width: 200,
}],
// 模拟的接口数据
dataSimulation: {
firstOrder: [
{
compSkuNum: '生鲜',
SecondLevel: [{
compSkuNum: 'DD',
threeLevel: [{
cptType: 1,
compSkuNum: 'MB1',
}, {
cptType: 1,
compSkuNum: '新品',
}],
}, {
compSkuNum: 'HM',
threeLevel: [{
cptType: 1,
compSkuNum: '强跟价商品',
}],
}],
},
{
compSkuNum: '物流',
SecondLevel: [{
compSkuNum: 'PP',
threeLevel: [{
cptType: 2,
compSkuNum: '非MB1',
}],
}],
},
],
},
// 添加的数据列
defaultDataSimulation: {
firstOrder: [
{
SecondLevel: [{
threeLevel: [{
cptType: '',
compSkuNum: '',
}],
compSkuNum: '',
cptType: '',
}],
compSkuNum: '',
cptType: '',
},
],
},
});
const operatorRow = (obj) => {
// 这个深拷贝是封装好的, 可以用其他深拷贝
const { cloneDeep } = proxy.$tools;
const { isAdd, indexList } = obj || {};
const indexLen = indexList.length;
const sourceData = proxy.$tools.deepClone(initData.dataSimulation.firstOrder); // 拷贝一下原数据,等下操作这个数据的增删
console.log('isAdd', isAdd);
console.log('indexList', indexList);
console.log('sourceData', sourceData);
switch (indexLen) {
case 1: // 添加第一列
if (isAdd === 'copy') {
// 实现逻辑是如果复制的是组织,那么需要将组织项清空,如果不深拷贝的话,会影响原数据
const copyValue = sourceData[indexList[0]];
const deepCloneCopy = proxy.$tools.deepClone(copyValue);
deepCloneCopy.compSkuNum = null;
sourceData.splice(+indexList[0] + 1, 0, cloneDeep(deepCloneCopy));
} else if (isAdd) {
sourceData.splice(+indexList[0] + 1, 0, cloneDeep(initData.defaultDataSimulation.firstOrder[0]));
} else {
sourceData.splice(+indexList[0], 1);
}
break;
case 2:// 添加第二列
if (isAdd === 'copy') {
// 要复制的数据
const copyValue = sourceData[indexList[0]].SecondLevel[indexList[1]];
const deepCloneCopy = proxy.$tools.deepClone(copyValue);
deepCloneCopy.compSkuNum = null;
sourceData[+indexList[0]].SecondLevel.splice(+indexList[1] + 1, 0, cloneDeep(deepCloneCopy));
} else if (isAdd) {
sourceData[+indexList[0]].SecondLevel.splice(+indexList[1] + 1, 0, cloneDeep(initData.defaultDataSimulation.firstOrder[0].SecondLevel[0]));
} else {
sourceData[+indexList[0]].SecondLevel.splice(+indexList[1], 1);
}
break;
case 3:// 添加第三列
if (isAdd === 'copy') {
// 要复制的数据
const copyValue = sourceData[indexList[0]].SecondLevel[indexList[1]].threeLevel[indexList[2]];
const deepCloneCopy = proxy.$tools.deepClone(copyValue);
deepCloneCopy.compSkuNum = null;
sourceData[+indexList[0]].SecondLevel[+indexList[1]].threeLevel.splice(+indexList[2] + 1, 0, cloneDeep(deepCloneCopy));
} else if (isAdd) {
sourceData[+indexList[0]].SecondLevel[+indexList[1]].threeLevel.splice(+indexList[2] + 1, 0, cloneDeep(initData.defaultDataSimulation.firstOrder[0].SecondLevel[0].threeLevel[0]));
} else {
sourceData[+indexList[0]].SecondLevel[+indexList[1]].threeLevel.splice(+indexList[2], 1);
}
break;
default:
break;
}
initData.dataSimulation.firstOrder = sourceData;
};
// 点击确认
const confirmDialogVisible = () => {
console.log(initData.dataSimulation.firstOrder);
};
return {
operatorRow,
...toRefs(initData),
confirmDialogVisible,
};
},
});
</script>
<style lang="scss" scoped>
// 一些样式
$tBorderColor: #edf0f5;
.multi-table-wrapper {
width: 100%;
overflow-x: auto;
}
.multi-level-table {
min-width: 100%;
display: table;
border: $tBorderColor 1px solid;
border-bottom: none;
dt,
dd {
width: 100%;
margin: 0;
padding: 0;
border-bottom: $tBorderColor 1px solid;
display: table;
table-layout: fixed;
line-height: 20px;
.th,
.td {
display: table-cell;
vertical-align: middle!important;
font-size: 12px;
border-right: $tBorderColor 1px solid;
&:last-child {
border-right: none;
}
line-height: 22px;
box-sizing: border-box;
&.p10 {
padding: 0 10px;
}
&.inner {
padding: 0 10px;
height: 120px;
}
&.inner-mini {
padding: 0 10px;
height: 80px;
}
}
.th {
padding: 10px;
}
.td-line {
width: 100%;
display: table;
table-layout: fixed;
border-bottom: $tBorderColor 1px solid;
&:last-child {
border-bottom: none;
}
}
.error-tips {
margin: 0;
padding: 5px 0;
color: #ff0000;
}
}
dt {
background: #f5f6f7;
font-weight: bold;
}
.border-box {
box-sizing: border-box
}
.table {
display: table;
}
}
</style>
AddDelButtonGroup组件
<template>
<div class="btn-wrapper">
<el-button
type="text"
@click="operatorRow('copy')"
>
复制
</el-button>
<el-button
type="text"
@click="operatorRow(true)"
>
添加
</el-button>
<el-button
type="text"
v-bind="$attrs"
class="del-btn"
@click="operatorRow(false)"
>
删除
</el-button>
</div>
</template>
<script>
export default {
name: 'AddDelButtonGroup',
props: {
indexList: {
type: Array,
required: true,
},
},
data() {
return {
};
},
methods: {
// 添加\删除行
operatorRow(isAdd) {
this.$emit('operator', { isAdd, indexList: this.indexList.map((index) => `${index}`) });
},
},
};
</script>
<style lang="scss" scoped>
.btn-wrapper {
margin-top: 10px;
}
.del-btn {
color: #ff0000;
&:disabled {
color: #B0B3B8;
}
}
</style>