共计 6595 个字符,预计需要花费 17 分钟才能阅读完成。
需要
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> |
正文完