<template>
<el-scrollbar style="height: 100%">
<div
v-loading="loading"
:element-loading-svg="svg"
element-loading-svg-view-box="-10, -10, 50, 50"
element-loading-text="加载中"
class="right-card"
:style="{ height: heights, width: '100%' }"
element-loading-background="rgba(255, 255, 255, 0.6)"
>
<!-- 普通表格 + 树形表格 -->
<!-- lu 把stripe删了,row-class-name="row-style"改为“tableRowClolor” -->
<!-- style="border: none !important;"-->
<!-- row-key=ID ,这个ID必须跟表格数据中的ID匹配上 -->
<div
v-if="isOrdinary"
class="table-style"
>
<el-table
@expand-change="handleExpandChange"
:row-class-name="tableRowColor"
class="mainHeight"
:key="itemKey"
:height="heights"
row-key="ID"
:data="tableData"
header-row-class-name="row-style"
@row-click="rowToggleSelection"
@select="select"
@select-all="selectAll"
@selection-change="handleSelectionChange"
ref="TableRef"
:tree-props="{ children: 'Children', hasChildren: 'hasChildren' }"
:table-layout="auto"
:default-expand-all="defaultall"
@row-dblclick="dblclick"
:header-cell-style="{background:'#a6c5f8'}"
highlight-current-row
>
<!-- 多选 -->
<el-table-column
v-if="isMultiple == 1"
type="selection"
width="55"
></el-table-column>
<!-- <el-table-column type="index" label="序号" width="55" /> 单选 -->
<!-- show-over...,min-with lu 下拉-->
<template v-for="(item, index) in tableHeader">
<el-table-column
v-if="item.ispass"
:key="index"
:label="item.label"
:prop="item.fieldName"
:align="item.iscenter"
:sortable="item.sortable"
show-overflow-tooltip
min-width="110px"
header-align="center"
>
<!-- 此处通过插槽的形式动态将值赋予新的表单 逻辑稍微有些恶心 FormOption[index].option-->
<template
v-if="item.isTransition"
v-slot="scope"
>
<!-- 递归组件 -->
<Recursion
:list="FormOption[index].oldOption !== undefined
? FormOption[index].oldOption
: FormOption[index].option
"
:rows="scope"
/>
</template>
<!-- 图片 -->
<template
v-if="item.isImages"
v-slot="scope"
>
<!-- <el-button @click="Test(scope.row.Files)"></el-button> -->
<!-- this.$FWurl + i -->
<!-- <el-image
:initial-index="4"
:preview-teleported="true"
hide-on-click-modal
v-for="(item, indexFiles) in scope.row.Files"
:key="indexFiles"
style="width: 30px; height: 30px"
:src="item"
:preview-src-ProcessInfo="[item]"
></el-image> -->
<template v-if="scope.row.Files != null">
<el-image
fit="cover"
:initial-index="0"
:preview-teleported="true"
style="width: 40px; height: 40px"
:src="scope.row.Files[0]"
:preview-src-list="scope.row.Files"
></el-image>
</template>
</template>
</el-table-column>
</template>
<!-- Table中的控制 -->
<!-- <el-table-column align="center" width="60px" label="操作">
<template #default="scope">
<div class="btn-option" @click="submitData(scope)">
<el-button class="el-icon-tickets"></el-button>
</div>
</template>
</el-table-column> -->
</el-table>
<!-- 分页 -->
<div
class="pagination"
v-if="showFenYe"
style="margin-top: 10px"
>
<el-pagination
:key="itemKeyFy"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[1, 3, 5, 10, 20, 30, 40]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next"
:total="total"
popper-class="select_bottom"
>
</el-pagination>
</div>
</div>
<!-- 表格嵌套表格 -->
<!-- 如果isOrdinary=false,执行这个 -->
<!-- 我把这个删了 row-class-name="row-style" -->
<div v-if="!isOrdinary">
<el-table
:table-layout="auto"
:row-class-name="tableRowColor"
class="tableIntable"
:key="itemKey"
:height="heights"
border
row-key="id"
:data="tableData"
@row-click="rowToggleSelection"
@select="select"
@select-all="selectAll"
@selection-change="handleSelectionChange"
ref="TableRef"
:tree-props="{ children: 'Children', hasChildren: 'hasChildren' }"
:default-expand-all="false"
:align="textCenter"
>
<!-- 多选 -->
<el-table-column
v-if="isMultiple == 1"
type="selection"
width="55"
></el-table-column>
<!-- 子表格 -->
<!-- 我把这个删了 row-class-name="row-style" -->
<el-table-column type="expand">
<template #default="props">
<el-table
:table-layout="auto"
class="bqqqb"
:data="props.row.sonData"
style="width: 90%; margin-left: 20px;margin-right;: 20px"
:key="itemKey"
border
row-key="id"
:show-summary="isOpenSums"
:summary-method="getSummaries"
>
<!-- :align="item.label == '备注' ? 'left':'center'" -->
<template v-for="(item, index) in sonColumns">
<el-table-column
class="ccc"
v-if="item.ispass"
:key="index"
:label="item.label"
:prop="item.fieldName"
:sortable="item.sortable"
header-align="center"
:align="Test(item)"
min-width="110px"
>
<template
class="aaaaaaaaaa"
v-if="item.isTransition"
v-slot="scope"
>
<!-- <el-button @click="Test(item, FormOption)">用于测试</el-button> -->
<!-- 递归组件 -->
<Recursion
:list="SonFormOption[index].oldOption !== undefined
? SonFormOption[index].oldOption
: SonFormOption[index].option
"
:rows="scope"
/>
</template>
<!-- 图片 -->
<template
v-if="item.isImages"
v-slot="scope"
>
<template v-if="scope.row.Files != null">
<el-image
fit="cover"
:initial-index="0"
:preview-teleported="true"
style="width: 40px; height: 40px"
:src="scope.row.Files[0]"
:preview-src-list="scope.row.Files"
></el-image>
</template>
</template>
</el-table-column>
</template>
<el-table-column
min-width="110px"
label="操作"
header-align="center"
v-if="isOpenOperation"
>
<template v-slot="scope">
<el-button
type="success"
plain
size="mini"
@click="SonhandleEdit(scope.$index, scope.row)"
>编辑</el-button>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<!-- 外层表头,父表头 -->
<template
v-for="(item, index) in tableHeader"
class="aaa"
>
<el-table-column
v-if="item.ispass"
:key="index"
:label="item.label"
:prop="item.fieldName"
:sortable="item.sortable"
header-align="center"
:align="Test(item)"
min-width="160px"
>
<!-- 此处通过插槽的形式动态将值赋予新的表单 逻辑稍微有些恶心 -->
<template
class="aaaaaaaaaa"
v-if="item.isTransition"
v-slot="scope"
>
<!-- 递归组件 FormOption[index].option-->
<Recursion
:list="FormOption[index].oldOption !== undefined
? FormOption[index].oldOption
: FormOption[index].option
"
:rows="scope"
/>
</template>
<!-- 图片 -->
<template
v-if="item.isImages"
v-slot="scope"
>
<template v-if="scope.row.Files != null">
<el-image
fit="cover"
:initial-index="0"
:preview-teleported="true"
style="width: 40px; height: 40px"
:src="scope.row.Files[0]"
:preview-src-list="scope.row.Files"
></el-image>
</template>
</template>
</el-table-column>
</template>
</el-table>
<!-- 分页 -->
<div
class="pagination"
v-if="showFenYe"
style="margin-top: 10px"
>
<el-pagination
:key="itemKeyFy"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next"
:total="total"
popper-class="select_bottom"
>
</el-pagination>
</div>
</div>
</div>
</el-scrollbar>
</template>
<script>
import { inject, reactive, ref, toRefs, defineExpose } from "@vue/runtime-core";
import { watchEffect, getCurrentInstance, nextTick } from "vue";
import SvgIcon from "../../components/SvgIcon.vue";
import Recursion from "../components/TableDialogTreeCol.vue";
import tableStyle from "../../assets/css/tableStyle.css";
//选中的数据
let listData = [];
export default {
components: { SvgIcon, Recursion, tableStyle },
name: "TableDialog",
emits: ["tableMessage"],
props: {
showFenYe: {
default: true,
type: Boolean,
},
// 接收的是:树结构是否展开,默认不展开
defaultall: {
default: false,
type: Boolean,
},
},
setup(props, context) {
//是否为普通表格
let isOrdinary = true;
//默认不开启子表格操作
let isOpenOperation = false;
//默认不开启合计行
let isOpenSums = false;
const loading = ref(true);
const svg = `
<path class="path" d="
M 30 15
L 28 17
M 25.61 25.61
A 15 15, 0, 0, 1, 15 30
A 15 15, 0, 1, 1, 27.99 7.5
L 15 15
" style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
`;
//表头设置,是否为多选,默认为多选
let isMultiple = 0;
// 表头配置
let tableHeader = ref([]);
// 数据及配置
// let tableData = reactive([]);
let tableData = ref([]);
const multipleSelection = ref([]);
const TableRef = ref(null);
const instance = getCurrentInstance();
const tableHeaderConfig = inject("tableHeaderConfig");
const tableDataConfig = inject("tableDataConfig");
// 监听表单配置数据
watchEffect(() => {
tableHeader = tableHeaderConfig;
tableData = tableDataConfig ? tableDataConfig.tableData : [];
//默认普通表格,true
isOrdinary =
tableDataConfig.isOrdinary != undefined
? tableDataConfig.isOrdinary
: true;
//默认不开启子表格操作
isOpenOperation =
tableDataConfig.isOpenOperation != undefined
? tableDataConfig.isOpenOperation
: false;
//默认不开启合计操作
isOpenSums =
tableDataConfig.isOpenSums != undefined
? tableDataConfig.isOpenSums
: false;
});
//#region 表单监听事件
//表格内部操作按钮,目前不用
function submitData(scope) {
context.emit("tableMessage", { page: page, type: scope });
}
//lu table背景色
function tableRowColor({ row, rowIndex }) {
if (
(row.sonData && row.sonData.length > 0) ||
(row.children && row.children.length > 0)
) {
return "success-row";
}
}
//复选框监听事件,值变化 定义方法可以这么写:const handleSelectionChange = (val) => 也可以 function
const handleSelectionChange = (val) => {
multipleSelection.value = val;
listData = val;
debugger;
context.emit("tableMessage", { listData: listData, type: "列表选择" });
};
//#endregion
//公共方法,用于子集选择
// nextTick(() => {
// otherParam.showA = true;
// });
//选择事件 需要注意,此处位置在部署服务器上后,失效,体现在 toRefs(instance.refs.TableRef);
// ultipleTabInstance.toggleRowSelection.value(row, select); 最终为空,需要找寻其他方法实现!,另外还有一个在form表单的动态生成,估计是响应参数出了问题!周一记得解决
//注册
return {
listData,
tableHeader,
tableData,
isMultiple, //默认为1,多选
loading,
svg,
submitData,
tableRowColor,
handleSelectionChange, //行事件
TableRef, //ref参数,用于选中取消
isOrdinary, //是否为普通表格
isOpenOperation, // 是否开启子表格操作
isOpenSums, // 是否开启合计
};
},
data() {
return {
// defaultall: false, //是否默认展开所有行(用于有树状结构的表格)
heights: 1,
itemKey: "",
itemKeyFy: "",
pageNum: 1, //当前页
pageSize: 10, //页大小
total: 0, //总数
FormOption: null, //父表表单Option
SonFormOption: null, //子表表单Option
sonColumns: [], //内层table的表头
textCenter: "", //文字居中
flag: 1, //判断表格高度的时候使用
expandRows: [],
expandRowKeys: [],
};
},
created() {
// this.heights = window.innerHeight - 200;
this.TimeoutOpen();
// 监听事件
// window.addEventListener('resize', this.onresize)
},
beforeDestroy() {
// 取消监听事件
// window.removeEventListener('resize', this.onresize)
},
mounted() {
this.$nextTick(() => {
this.$refs.TableRef.$el.getBoundingClientRect().top; //表格距离浏览器的高度
let height;
switch (this.flag) {
case 1:
height = 0;
break;
case 2:
height = 80;
break;
case 3:
height = 110;
break;
case 4:
height = -30;
break;
case 5:
height = -65;
break;
case 6:
height = 125;
break;
case 7:
height = 90;
break;
case 8:
height = 30;
break;
case 9:
height = 135;
break;
default:
break;
}
// 根据浏览器高度设置初始高度
this.heights =
window.innerHeight - this.$refs.TableRef.$el.offsetTop - 280 - height;
// 监听浏览器高度变化,修改表格高度
window.onresize = () => {
this.heights =
window.innerHeight - this.$refs.TableRef.$el.offsetTop - 280 - height;
};
});
},
methods: {
//展开行只能展开一行
handleExpandChange(row, expanded) {
if (expanded) {
this.expandRows.forEach((item) => {
this.$refs.TableRef.toggleRowExpansion(item, false);
});
this.expandRows.push(row);
} else {
this.expandRows = this.expandRowKeys.filter(
(item) => item.ID !== row.ID
);
}
},
Test(item) {
var test = item.iscenter ? "center" : "left";
if (item.label.indexOf("费") > 0 || item.label.indexOf("金额") > 0) {
test = "right";
}
if (item.label.indexOf("备注") > 0) {
test = "left";
}
return test;
},
//自定义合计方法
getSummaries(param) {
const { columns, data } = param;
const sums = {};
const HJJE = {}; // 合计金额 = 数量 * 单价金额
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = "合计";
return;
}
// // if (index === 3) {
// // sums[index] = '';
// // return;
// // }
const values = data.map((item) => Number(item[column.property]));
if (column.label == "数量" || column.label == "单价金额") {
if (!values.every((value) => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
if (column.label == "数量") {
HJJE.sl = values;
}
if (column.label == "单价金额") {
HJJE.dj = values;
}
// sums[index] += ' kg';
} else {
// sums[index] = 'N/A';
}
}
});
let rowsHJ = 0;
//合计总价 = 数量 * 单价金额
if (HJJE.sl !== undefined && HJJE.dj !== undefined) {
for (let index = 0; index < HJJE.sl.length; index++) {
rowsHJ += HJJE.sl[index] * HJJE.dj[index];
}
}
sums[0] = "合计总金额\n SUM(数量 * 单价金额) = " + rowsHJ;
return sums;
},
//子表格中按钮事件
SonhandleEdit(index, row) {
//按钮事件,暂时维护编辑按钮,后续有需要添加
this.$emit("SonButtonChange", row);
},
//嵌套表格下的样式 —— 貌似不生效
tableRowClassName({ row, rowIndex }) {
if (row.sonData.length > 0) {
return "success-row";
}
return "";
},
//#region 数据表格事件
//清空表格全部选择
ClearSelect() {
this.$nextTick(() => {
this.$refs.TableRef.clearSelection();
});
},
setChildren(children, type) {
// 编辑多个子层级
children.map((j) => {
this.toggleSelection(j, type);
if (j.children) {
this.setChildren(j.children, type);
}
});
},
toggleSelection(row, select) {
this.$nextTick(() => {
this.$refs.TableRef.toggleRowSelection(row, select);
});
},
//行点击事件
rowToggleSelection(rows) {
this.$emit("rowClick", rows); //传给父组件行点击数据
const selected = listData.some((item) => item.id === rows.id);
if (!selected) {
if (rows.children) {
// 解决子组件没有被勾选到
this.setChildren(rows.children, true);
}
this.toggleSelection(rows, true);
} else {
if (rows.children) {
// 解决子组件没有被勾选到
this.setChildren(rows.children, false);
}
this.toggleSelection(rows, false);
}
},
//#endregion
handleSizeChange(val) {
this.pageSize = val;
// 调用自定义事件,传入参数
this.$emit("getPage", { pageSize: this.pageSize, pageNum: this.pageNum });
this.TimeoutOpen();
},
/**
* 切换页码
* @param {*} val
*/
handleCurrentChange(val) {
this.pageNum = val;
this.$emit("getPage", { pageSize: this.pageSize, pageNum: this.pageNum });
this.TimeoutOpen();
},
/**
* 获取父组件传递过来的新的数据表头
* @param {} GetDataLists
*/
SetDataTableHeader(GetDataLists, flag) {
//重新渲染,itemKey用于处理Table不渲染的问题
this.itemKey = Math.random();
this.flag = flag ? flag : this.flag;
//重新渲染数据表
this.tableHeader = GetDataLists.lstSubset[0].Headers;
this.FormOption = GetDataLists.lstSubset[0].Froms;
this.FormOption.forEach((item) => {
if (item.oldOption === undefined) {
//存储旧集合
item.oldOption = item.option;
}
});
//清空选择
this.ClearSelect();
},
/**
* 获取父组件传递过来的新的数据表头,仅对于子表格使用
* @param {} GetDataLists
*/
SetDataTableHeaderByZiTable(GetDataLists) {
//重新渲染,itemKey用于处理Table不渲染的问题
this.itemKey = Math.random();
//重新渲染数据表
this.sonColumns = GetDataLists.lstSubset[0].Headers;
this.SonFormOption = GetDataLists.lstSubset[0].Froms;
this.SonFormOption.forEach((item) => {
if (item.oldOption === undefined) {
//存储旧集合
item.oldOption = item.option;
}
});
//清空选择
this.ClearSelect();
},
/**
* 用于父组件获取子组件当前Table数据信息,最终用于勾选选择使用
*/
GetDataTable() {
return this.tableData;
},
/**
* 获取父组件传递过来的新的数据Data进行重新赋值
* @param {*} GetDataLists 新增、修改、删除后,重新查询的数据
*/
SetDataTable(GetDataLists) {
//重新渲染,itemKey用于处理Table不渲染的问题
this.itemKey = Math.random();
this.itemKeyFy = Math.random();
let dataList =
typeof GetDataLists.rows == "string"
? JSON.parse(GetDataLists.rows)
: GetDataLists.rows;
this.SetTreeDataTableIds(dataList, 1);
//重新渲染数据表
this.tableData = dataList;
this.total = GetDataLists.total;
//清空选择
this.ClearSelect();
this.$forceUpdate();
this.TimeoutOpen();
},
//递归算法动态赋值
SetTreeDataTableIds(GetDataLists, AllIndex) {
//此处添加Id是为了保证每一条的唯一性,因为很多表中的ID命名规则不统一,所以在此自行规定,实质上此id无其他作用
GetDataLists.forEach((element, index) => {
element.id = AllIndex * 1000 + (index + 1);
if (element.children) {
if (element.children.length > 0) {
this.SetTreeDataTableIds(element.children, element.id);
}
}
});
},
//切换表格
SetTableType(val) {
//普通表格为True,嵌套表格为false
this.isOrdinary = val;
},
//#region 关于树形列表复选框事件组
/**
* 选中父节点时,子节点一起选中取消
* @param {*} selection
* @param {*} row
*/
select(selection, row) {
const hasSelect = selection.some((el) => {
return row.id === el.id;
});
if (hasSelect) {
if (row.children) {
// 解决子组件没有被勾选到
this.setChildren(row.children, true);
}
} else {
if (row.children) {
this.setChildren(row.children, false);
}
}
},
//双击
dblclick(row, column, cell, event) {
this.$emit("doubleClick", row);
},
/**
* 选择全部
* @param {*} selection
*/
selectAll(selection) {
// tabledata第一层只要有在selection里面就是全选
const isSelect = selection.some((el) => {
const tableDataIds = this.tableData.map((j) => j.id);
return tableDataIds.includes(el.id);
});
// tableDate第一层只要有不在selection里面就是全不选
const isCancel = !this.tableData.every((el) => {
const selectIds = selection.map((j) => j.id);
return selectIds.includes(el.id);
});
if (isSelect) {
selection.map((el) => {
if (el.children) {
// 解决子组件没有被勾选到
this.setChildren(el.children, true);
}
});
}
if (isCancel) {
this.tableData.map((el) => {
if (el.children) {
// 解决子组件没有被勾选到
this.setChildren(el.children, false);
}
});
}
},
//#endregion
TimeoutOpen() {
this.loading = true;
setTimeout(() => {
//需要定时执行的代码
this.loading = false;
}, 800);
},
setCurrent() {
this.$refs.TableRef.setCurrentRow();
},
},
};
</script>
<style scoped>
.el-table .warning-row {
--el-table-tr-bg-color: var(--el-color-warning-light-9);
}
/*最外层透明*/
.el-table,
.el-table__expanded-cell {
/*border: none !important;*/
background-color: transparent;
}
/* 表格内背景颜色 */
::v-deep .el-table th,
::v-deep .el-table tr,
::v-deep .el-table td {
background-color: transparent;
}
.el-table .success-row {
--el-table-tr-bg-color: var(--el-color-success-light-9);
}
.el-table {
--el-table-row-hover-bg-color: #409effab;
/* 去除表格线 */
}
::v-deep .cell {
color: black;
/* text-align: center; */
}
::v-deep .el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border: 1px solid #a5c4f7;
/* line-height: 3rem; */
font-size: 16px;
}
::v-deep .el-table__inner-wrapper::before {
background-color: transparent !important;
}
</style>
vue3 表格嵌套表格
最新推荐文章于 2024-08-19 09:56:27 发布