需要
1.表头数据不固定
2.表头数据多层级
3.表格跨行跨列
4.表格可编辑
5.编辑反对根本表单框
子组件代码
dynamic-header.vue
<template> <div> <el-form size="medium" class="horizontal" inline> <slot name="search"></slot> </el-form> <div class="title" v-if="title">{{title}}</div> <el-table v-loading="listLoading" :data="list" :stripe="true" class="flexible" :border="true" :span-method="arraySpanMethod" style="overflow: auto" :height="height" ref="table" width="100%" > <template v-for="(item,index) in tableHeader"> <table-column v-if="item.children && item.children.length" :key="Math.random()" :coloumn-header="item"></table-column> <el-table-column v-else class-name="custom" :width="item.width?item.width:'auto'" :fixed="item.fixed" :key="Math.random()" :label="item.tableHeadName" align="center"> <template slot-scope="scope"> <template v-if="item.isEdit"> <el-select filterable v-if='(item.htmlType == "select" || item.htmlType == "radio") && item.dictData' v-model.lazy="scope.row[item.tableFiled]"> <el-option v-for="dict in item.dictData" :key="dict[item.options.value] || dict.value" :label="dict[item.options.label] || dict.label" :value="parseInt(dict[item.options.value] || dict.value)" /> </el-select> <el-date-picker v-else-if='item.htmlType == "datetime" && item.queryType != "BETWEEN"' clearable size="small" v-model.lazy="scope.row[item.tableFiled]" type="date" value-format="yyyy-MM-dd"> </el-date-picker> <el-date-picker v-else-if='item.htmlType == "datetime" && item.queryType == "BETWEEN"' v-model.lazy="scope.row[item.tableFiled]" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="完结日期" ></el-date-picker> <el-input-number v-else-if='item.htmlType == "number"' v-model.lazy="scope.row[item.tableFiled]" clearable size="small" /> <el-input v-else v-model.lazy="scope.row[item.tableFiled]" clearable size="small" /> </template> <template v-else-if="item.template"> {{getTemplate(item.template,scope)}} </template> <template v-else> <dict-tag v-if="item.dictData" :options="item.dictData" :value="scope.row[item.tableFiled]" /> <tempalte v-else-if="item.dictDataArray" > <dict-tag v-for="(it,itIndex) in item.dictDataArray" v-if="scope.row[it.props] == it.value" :key="itIndex" :options="it.dictData" :value="scope.row[item.tableFiled]" /> </tempalte> <template v-else>{{scope.row[item.tableFiled]}}</template> </template> </template> </el-table-column> </template> <el-table-column v-if="pageParamInfo.oper" label="操作" :key="index" fixed="right" width="150"> <template slot-scope="scope"> <slot name="oper" :scope="scope.row"></slot> </template> </el-table-column> </el-table> <slot name="tableFooter" :scope="pageParamInfo.req"></slot> </div></template><script> import TableColumn from './table-column' export default { props: { pageParamInfo: { type: Object, default(){ return {} } }, tableHeader: { type: Array, default(){ return [] } }, RowRules: { type: Array, default(){ return [] } }, list: { type: Object, default(){ return {} } }, title: { type: String, default: "" }, listLoading: { type: Boolean, default: false }, height: { type: String, default: "70vh" }, }, // pageParamInfo 页面列表参数:url req等等; // tableHeader 表头信息 components: { TableColumn, }, data() { return { } }, watch: { tableHeight(val) { this.height = val } }, created() { }, mounted() { }, methods: { getTemplate(template,scope){ return eval(template) }, arraySpanMethod({ row, column, rowIndex, columnIndex }) { let returnMap = { rowspan: 1, colspan: 1 } const data = this.RowRules if (data instanceof Array && data.length > 0) { data.forEach(item => { if (item.col === (columnIndex + 1)) { if (rowIndex % item.row === 0) { returnMap = { rowspan: item.row, colspan: 1 } } else { returnMap = { rowspan: 0, colspan: 0 } } } }) } return returnMap }, // 列表 getList() { this.listLoading = true this.$http.post(this.pageParamInfo.url, this.pageParamInfo.req).then(res => { this.listLoading = false // this.list = res.data.list }) }, // 文件上传中解决 handleExceed(event, file, fileList) { this.upload.isUploading = true }, // 文件上传胜利解决 handleSuccess(response, file, fileList) { this.upload.open = false this.upload.isUploading = false this.$refs.upload.clearFiles() this.$alert(response.message, '导入后果', { dangerouslyUseHTMLString: true, }) this.getList() }, // 重置 reset() { /* this.listLoading = true this.$http.post('busprojecttask/findTaskList', this.req).then(res => { this.listLoading = false this.getList(this.req.MONTH) })*/ }, // 批改 save() { /* this.listLoading = true this.$http.post('busprojecttask/findTaskList', this.req).then(res => { this.listLoading = false this.getList(this.req.MONTH) })*/ } } }</script><style lang="scss" scoped> h1{ color: black !important; text-align: center; padding: 20px; } table{ margin-top: 20px; } .tableClass{ ::v-deep .el-table__fixed{ height: 100% !important; //设置高优先,以笼罩内联款式 } }</style>
table-column.vue
<template> <el-table-column :label="coloumnHeader.tableHeadName" :prop="coloumnHeader.tableFiled" align="center"> <template v-for="item in coloumnHeader.children"> <tableColumn v-if="item.children && item.children.length" :key="Math.random()" :coloumn-header="item"></tableColumn> <el-table-column :fixed="item.fixed" :width="item.width?item.width:'auto'" v-else :key="Math.random()" :label="item.tableHeadName" :prop="item.tableFiled" align="center"> <template slot-scope="scope"> <template v-if="item.isEdit"> <el-select v-if='(item.htmlType == "select" || item.htmlType == "radio") && item.dictData' v-model.lazy="scope.row[item.tableFiled]"> <el-option v-for="dict in item.dictData" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)" /> </el-select> <el-date-picker v-else-if='item.htmlType == "datetime" && item.queryType != "BETWEEN"' clearable size="small" v-model.lazy="scope.row[item.tableFiled]" type="date" value-format="yyyy-MM-dd"> </el-date-picker> <el-date-picker v-else-if='item.htmlType == "datetime" && item.queryType == "BETWEEN"' v-model.lazy="scope.row[item.tableFiled]" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="完结日期" ></el-date-picker> <el-input-number v-else-if='item.htmlType == "number"' v-model.lazy="scope.row[item.tableFiled]" clearable size="small" /> <el-input v-else v-model.lazy="scope.row[item.tableFiled]" clearable size="small" /> </template> <template v-else-if="item.template"> {{getTemplate(item.template,scope)}} </template> <template v-else> <dict-tag v-if="item.dictData" :options="item.dictData" :value="scope.row[item.tableFiled]" /> <tempalte v-else-if="item.dictDataArray" > <dict-tag v-for="(it,itIndex) in item.dictDataArray" v-if="scope.row[it.props] == it.value" :key="itIndex" :options="it.dictData" :value="scope.row[item.tableFiled]" /> </tempalte> <template v-else>{{scope.row[item.tableFiled]}}</template> </template> </template> </el-table-column> </template> </el-table-column></template><script>export default { name: 'TableColumn', props: { coloumnHeader: { type: Object, required: true } }}</script><style scoped></style>
父组件
list为表格数据,tableHeader为表头数据
<template> <dynamicHeaderEdit :tableHeader="tableHeader" :list="list" ref="table"> </dynamicHeaderEdit></template>