1、在 components 中创建 HeaderTable 文件夹,在创建 ColumnItem.vue 和 index.vue。
如下:
2、index.vue 代码内容,如下:
<template><div><el-table:data="dataTableData"style="width: 100%"max-height="700":cell-style="{'border-right': '1px solid #C4C6CB','border-bottom': '1px solid #C4C6CB',}":header-cell-style="{'background-color': '#f8f8f9','border-right': '1px solid #C4C6CB','border-bottom': '1px solid #C4C6CB',}"><el-table-columnprop="date"label="时间"width="150"align="center"v-if="flag"></el-table-column><!-- 递归组件 --><template v-if="flag"><ColumnItemv-for="(item,index) in dataHeaders":key="item.label":col="item":maxLength="maxLength"></ColumnItem></template><el-table-columnprop=""width="150"align="center"v-if="showAddBut && flag"><template slot="header" slot-scope="scope"><i class="el-icon-plus" @click="getAdd({})"/></template></el-table-column></el-table><el-drawer:title="title":visible.sync="drawer":size="350"direction="ltr":before-close="handleClose"><el-form:inline="true":model="column"label-position="right"label-width="auto"ref="ruleFormRef":rules="rules"class="demo-form-inline form-padding"><el-form-item label="名称" prop="label"><el-input v-model="column.label" placeholder="请输入名称" clearable /></el-form-item><el-form-item label="宽度" prop="width"><el-inputv-model="column.width"type="number"placeholder="请输入列宽度(不填为自适应)"clearable/></el-form-item><el-form-item label="对齐方式" prop="align"><el-selectv-model="column.align"placeholder="请选择对齐方式"clearable><el-option label="左对齐" value="left" /><el-option label="居中对齐" value="center" /><el-option label="右对齐" value="right" /></el-select></el-form-item><el-form-item label="映射变量" prop="prop"><el-cascaderv-model="column.prop":options="options":props="optionProps"@change="handleChange"></el-cascader></el-form-item></el-form><div class="drawer-footer"><el-button @click="handleClose">取消</el-button><el-button type="primary" :loading="loading" @click="handleSubmit">{{ submitText }}</el-button></div></el-drawer></div>
</template><script>
import { EventBus } from "../../utils/event-bus.js";
import ColumnItem from './ColumnItem.vue';
import { apiEditHeaderTable, apiGetList, apiGetTreeselect } from "@/api/headerTable/index.js";
export default {name: 'CustomElTable',components: {ColumnItem},props: {// 表头数据headers: {type: Array,required: true},// 表格列表数据tableData: {type: Array,required: true},// 区分哪个页面下的列表tablekey: {type: String,required: true},// 限制新增最大列maxLength: {type: Number,required: false},},data() {return {dataHeaders: this.headers,dataTableData: this.tableData,dataNum: this.num,flag: true, // 为了更新子组件的状态drawer: false,loading: false,column: {label: "",width: "",align: "center",prop: "",},optionProps: { expandTrigger: 'click',value: "id",label: "label",children: "children",},copyCol: {},rules: {label: [{ required: true, message: "请输入名称", trigger: "blur" }],align: [{ required: true, message: "请选择对齐方式", trigger: "blur" }],},title: '新增列',submitText: '新增',options: [],}},computed: {showAddBut() {return this.$store.state.common.headerEditBut}},watch: {headers: {handler(newValue,oldValue) {this.dataHeaders = newValue;}},},methods: {// 删除getDelete(col) {this.$confirm('是否删除?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(_ => {let newHeaders = this.getRecursion(this.dataHeaders,col);console.log("处理完数据的", newHeaders);this.dataHeaders = newHeaders;// 数据更新,更新子组件状态this.flag = false;this.$nextTick(() => {this.flag = true;})EventBus.$emit("getHeaders",this.headers)}).catch(() => {});},// 递归删除getRecursion(arr,col) {arr.map((item,index) => {if(item.label === col.label && item.deep === col.deep) {arr.splice(index,1);return;}if(item.children && item.children.length > 0) {this.getRecursion(item.children,col)}})return arr;},// 新增getAdd(col) {this.drawer = true;this.title = '新增列';this.submitText = '新增';this.column.label = '新增列';this.copyCol = col;},// 编辑getEdit(col) {this.drawer = true;this.title = '编辑列',this.submitText = '保存',this.column.label = col.label;this.copyCol = col;},// 编辑,新增里的取消handleClose() {this.$confirm('内容未保存,确认关闭?','提示',{confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(_ => {this.drawer = false;}).catch(_ => {});},// 编辑,新增里的保存handleSubmit() {let col = this.copyColthis.loading = true;let item = {label: this.column.label,prop: "",width: this.column.width,align: this.column.align,deep: 1,selected: false,children: []}if(this.title === '新增列') {if(!Object.keys(col).length == 0){item.deep = col.deep + 1;col.children.push(item);}else {this.dataHeaders.push(item);}}else {this.flag = false;this.$nextTick(() => {this.flag = true;col.label = this.column.label;col.width = this.column.width;col.align = this.column.align;col.prop = this.column.prop;})}this.loading = false;this.drawer = false;console.log("dataHeaders", this.dataHeaders);// this.handleApi();},// 请求接口,保存表头数据handleApi() {let data = {tableKey: this.tablekey,tableJson: JSON.stringify(this.dataHeaders)}apiEditHeaderTable(data).then(() => {this.loading = false;this.drawer = false;this.$message({message: '编辑成功',type: 'success'});}).catch(() => {this.loading = false;this.drawer = false;this.$message({message: '编辑失败',type: 'error'});})},handlePreserve() {console.log("保存");this.handleApi();},//handleChange(val) {let aa = val[val.length-1]apiGetList({deptId: aa}).then(res => {console.log(">>>>",res);})},handleList() {let data = {}apiGetTreeselect(data).then((res) => {this.options = res.data;})}},mounted() {this.handleList();console.log("tablekey",this.tablekey);EventBus.$on("getDelete",(col) => {this.getDelete(col)});EventBus.$on("getAdd",(col) => {this.getAdd(col)});EventBus.$on("getEdit",(col) => {this.getEdit(col)});EventBus.$on("handlePreserve",() => {this.handlePreserve()});}
}
</script><style lang="scss" scoped>
.scope_p {margin: 0;
}
.i_margin {margin: 0 10px;
}.content-main {.table-title {display: flex;justify-content: space-around;margin-bottom: 10px;> p {flex: 1;font-weight: bold;font-size: 18px;}}.el-input {width: 250px;}.el-select {width: 280px;}
}
.form-padding {padding: 0 20px;
}
.drawer-footer {display: flex;align-items: center;justify-content: center;
}.header-btn {display: flex;align-items: center;justify-content: center;.el-icon-plus {margin-left: 10px;cursor: pointer;}.el-icon-edit {margin-left: 10px;cursor: pointer;}.el-icon-delete {margin-left: 10px;cursor: pointer;}
}.selected {color: #409eff;
}.header-scroll::v-deep {.el-table__header-wrapper {overflow-x: auto;}/* 修改滚动条样式 */::-webkit-scrollbar {height: 8px; /* 设置滚动条宽度 */}::-webkit-scrollbar-track {background-color: #ffffff; /* 设置滚动条轨道背景色 */}::-webkit-scrollbar-thumb {background-color: #ececec; /* 设置滚动条滑块颜色 */border-radius: 4px; /* 设置滚动条滑块圆角 */}::-webkit-scrollbar-thumb:hover {background-color: #e2e2e2; /* 设置滚动条滑块鼠标悬停时颜色 */}
}
.error_label {color: #f56c6c !important;
}
</style>
3、ColumnItem.vue 代码内容,如下:
<template><el-table-column:prop="col.prop":width="col.width":align="col.align"min-width="150"><template slot="header" slot-scope="scope"><p class="scope_p">{{col.label}}</p><div v-if="showAddBut"><i class="el-icon-plus" v-if="col.deep < maxLength" @click="Add(col)"/><i class="el-icon-edit-outline i_margin" @click="Edit(col)"/><i class="el-icon-delete" @click="Delete(col)"/></div></template><!-- 遍历递归 --><template v-for="(item,index) in col.children"><ColumnItem v-if="item.children" :col="item" :key="item.label" :maxLength="maxLength"/></template></el-table-column>
</template><script>
import { EventBus } from "../../utils/event-bus.js";
export default {name: "ColumnItem",props: {col: {type: Object,required: true},maxLength: {type: Number,required: false},},methods: {Add(col) {EventBus.$emit("getAdd",col)},Edit(col) {EventBus.$emit("getEdit",col)},Delete(col) {console.log(col);EventBus.$emit("getDelete",col)}},computed: {showAddBut() {return this.$store.state.common.headerEditBut}},mounted() {},
}
</script><style lang="scss" scoped>
.scope_p {margin: 0;
}
i {cursor: pointer;
}
.i_margin {margin: 0 10px;
}
</style>
4、在 .vue 文件中使用和数据,如下:
<HeaderTable :headers="headers" :tableData="tableData" :tablekey="tablekey" :maxLength="4"/>
data() {return {headers: [{label: "1",prop: "name",width: "150",align: "center",deep: 1,selected: false,children: [{label: "1-1",prop: "",width: "",align: "center",deep: 2,selected: false,children: [{label: "1-1-1",prop: "",width: "",align: "center",deep: 3,selected: false,children: []}]},{label: "1-2",prop: "",width: "",align: "center",deep: 2,selected: false,children: []}]},{label: "2",prop: "name",width: "150",align: "center",deep: 1,selected: false,children: [{label: "2-1",prop: "",width: "",align: "center",deep: 2,selected: false,children: [{label: "2-1-1",prop: "",width: "",align: "center",deep: 3,selected: false,children: []},{label: "2-1-2",prop: "",width: "",align: "center",deep: 3,selected: false,children: []}]},{label: "2-2",prop: "",width: "",align: "center",deep: 2,selected: false,children: []}]}],tableData: [{date: '2016-05-03',}, {date: '2016-05-02',}, {date: '2016-05-04',}, {date: '2016-05-01',}, {date: '2016-05-08',}, {date: '2016-05-06',}, {date: '2016-05-07', }],}
}