一、需求
项目中在线sql页面有个新需求,需要对执行sql的结果进行展示,每执行一次需要展示一个结果tab页面,最多不超过10个,方便查看执行的结果,如图所示:
二、思路及功能实现
既然是动态增删,而且在Log tab后面,所以使用数组来存放结果tab,使用Element-UI的el-tabs组件进行展示。而结果tab页面里面展示后台返回的很多条列表数据,用Element-UI的el-table组件来展示。
代码如下:
<el-tabs
type="border-card"
v-model="editableTabsValue"
@tab-click="handleTabLogClick"
@tab-remove="removeTab"
class="inner-tabs"
>
<el-tab-pane name="log">
<span slot="label"> Log</span>
<el-table
class="logTable"
:data="logData"
>
<el-table-column
type="index"
width="50"
label="*"
>
</el-table-column>
<el-table-column label="command">
<template slot-scope="scope">
<el-popover
trigger="hover"
placement="top"
:visible-arrow="false"
>
<div
class="popover-content"
v-html="scope.row.command"
></div>
<template #reference>
<span>{{ scope.row.command | formaterEllipsis(7) }}</span>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column label="exec">
<template slot-scope="scope">
<el-popover
trigger="hover"
placement="top"
:visible-arrow="false"
>
<div
class="popover-content"
v-html="scope.row.exec"
></div>
<template #reference>
<span>{{ scope.row.exec | formaterEllipsis(7) }}</span>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column label="message">
<template slot-scope="scope">
<span>{{ scope.row.message | formaterEllipsis(7) }}</span>
</template>
</el-table-column>
<el-table-column label="operUserCode">
<template slot-scope="scope">
<span>{{ scope.row.operUserCode }}</span>
</template>
</el-table-column>
<el-table-column label="status">
<template slot-scope="scope">
<span>{{ scope.row.status }}</span>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<Pagination
:child-msg="logPageparm"
@callFather="callLogFather"
/>
</el-tab-pane>
<el-tab-pane
v-for="(tab, index) in editableTabs"
:closable="tab.closable"
:key="tab.name"
:label="tab.label"
:name="tab.name"
>
<el-table
class="resultTable"
:data="tab.tableData"
max-height="500"
>
<el-table-column
type="index"
width="80"
>
<template slot="header">
<span>*</span><el-button
type="text"
@click="handleDownload(tab.code)"
class="downloadBtn"
>下载</el-button>
</template>
</el-table-column>
<el-table-column
v-for="(v, ind) in tab.dynamicCols"
:key="ind"
:prop="v"
>
<template slot-scope="scope">
<span>{{ scope.row[v] }}</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
// 调用执行sql接口
executeSql(params)
.then((res) => {
if (res.data.code === 200) {
let dataArray = res.data.data;
// 把字符数组转为对象数组
let tempArray = [];
let obj = {};
dataArray.forEach(function (item, index) {
obj = Object.assign({}, item); //Object.assign将源对象中的所有属性分配到目标对象,返回目标对象
tempArray.push(obj);
});
if (tempArray) {
// this.editableTabsValue = 'result1';
// 找到最长的属性列
const longestColumn = tempArray.reduce(
(longest, obj) => {
const columns = Object.keys(obj);
const longestColumnLength =
Object.keys(longest).length;
if (
columns.length > longestColumnLength
) {
return obj;
} else {
return longest;
}
},
{}
);
console.log(longestColumn);
let dynamicCols = Object.keys(longestColumn);
// console.log(dynamicCols)
//添加tab
this.addTab(
tempArray,
deleteEnterCode,
dynamicCols
);
}
}
})
.catch((error) => {
console.log(error);
});
// 新增tab页事件
addTab(arr, code, columns) {
// let newTabName = ++this.tabIndex + '';
// name: newTabName,
// 每次执行一次executionCount+1
this.executionCount++;
// 限制只显示10个tab
if (this.executionCount > 10) {
return false;
}
let obj = {
label: "结果" + (this.editableTabs.length + 1),
name: "result" + (this.editableTabs.length + 1),
closable: true,
tableData: arr, //每次执行的列表数据
code: code, //每次执行的sql
dynamicCols: columns, //动态列
};
this.editableTabs.push(obj);
this.editableTabsValue = obj.name;
},
// 关闭tab页事件
removeTab(targetName) {
// console.log('remove', targetName)
let tabs = this.editableTabs;
if (tabs.length <= 1) {
return false;
}
let activedTabName = this.editableTabsValue;
if (activedTabName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activedTabName = nextTab.name;
}
}
});
}
this.editableTabsValue = activedTabName;
this.editableTabs = tabs.filter((tab) => tab.name !== targetName);
},
三、遇到的问题
每个结果tab标签中的列表数据的列显示错误
四、原因分析
排查后发现后台返回的列表数据的列不是固定的,我显示是按照固定列进行展示
五、解决方案
把后台返回的二维字符数组转为一维对象数组,遍历对象数组,找到最长的属性列,根据最长的属性列动态显示列表数据