需求:
1.某些特定列需要合并
2.某几个列循环渲染
3.表格需要可点击行编辑单元格,
4.单元格需要行数据两值的对比来动态展示样式
因此用jsx能更好更快的解决
代码:
<template>
<!-- 表格 -->
<div class="table-page">
<!-- span-method:el-table组件对列合并的事件-->
<el-table
class="table"
ref="tablePage"
v-bind="_attrs"
v-loading="isLoading"
element-loading-text="数据加载中,请稍候"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(255,255,255,0.8)"
:span-method="arraySpanMethod"
>
<el-table-column fixed prop="prjDeptName" label="部门" width="150" align="center">
</el-table-column>
<el-table-column fixed prop="projectNumber" label="项目编号" width="220" align="center">
</el-table-column>
<el-table-column fixed prop="fundName" label="资金" width="150" align="center">
</el-table-column>
<el-table-column
fixed
prop="budgetForYear"
:label="currentYear + '年预算金额'"
width="150"
align="center"
>
</el-table-column>
<el-table-column
fixed
prop="budgetToLeave"
:label="currentYear - 1 + '年结转金额'"
width="150"
align="center"
>
</el-table-column>
<!-- 这里只能用template 用div或者别的标签会让循环前的列跑到最后 -->
<template v-for="(month, index) in 10">
<el-table-column :label="'1-' + [month + 2] + '月支出'" :key="month" align="center">
<el-table-column :prop="planCountArr[index]" label="预计支出" width="120" align="center">
<template slot-scope="scope">
<!-- 数据为-1的置为空字符串 -->
<span>{{
scope.row[planCountArr[index]] == -1 ? '' : scope.row[planCountArr[index]]
}}</span>
</template>
</el-table-column>
<el-table-column
:prop="realCountArrange[index]"
label="实际支出"
width="120"
align="center"
class-name="realCountStyle"
>
<template slot-scope="scope">
<div
:class="
cellColor(scope.row[planCountArr[index]], scope.row[realCountArrange[index]])
"
>
<template v-if="canEdit">
{{ renderToInput(scope.row, index) }}
<!-- 这个slot必须要定义 不然render不生效,name要和table-cloumn的prop一致 -->
<slot :name="realCountArrange[index]"></slot>
</template>
<template v-else>
{{
scope.row[realCountArrange[index]] == -1
? ''
: scope.row[realCountArrange[index]]
}}
</template>
</div>
</template>
</el-table-column>
</el-table-column>
</template>
<el-table-column prop="remark" label="备注" width="150" align="center"> </el-table-column>
</el-table>
</div>
</template>
<script>
import { listProjectBudgetPayCount } from '@/api/budgetManagement' //接口
export default {
name: 'excelPreview',
props: {
params: {
type: Object,
default: () => {}
},
//实际支出是否可编辑
canEdit: {
type: Boolean,
default: false
},
//当前年
currentYear: {
type: String,
default: String(new Date().getFullYear())
}
},
data() {
return {
// 预计支出字段集
planCountArr: [
'payPlanJanMarCount',
'payPlanJanAprCount',
'payPlanJanMayCount',
'payPlanJanJunCount',
'payPlanJanJulCount',
'payPlanJanAugCount',
'payPlanJanSepCount',
'payPlanJanOctCount',
'payPlanJanNovCount',
'payPlanJanDecCount'
],
// 实际支出字段集
realCountArrange: [
'payRealJanMarCount',
'payRealJanAprCount',
'payRealJanMayCount',
'payRealJanJunCount',
'payRealJanJulCount',
'payRealJanAugCount',
'payRealJanSepCount',
'payRealJanOctCount',
'payRealJanNovCount',
'payRealJanDecCount'
],
isLoading: false,
tableData: []
}
},
computed: {
_attrs() {
return {
data: this.tableData,
stripe: false,
border: true,
height: 'calc(100% - 48px)'
}
}
},
mounted() {
this.initData()
},
methods: {
// 初始化数据
async initData() {
let res = await listProjectBudgetPayCount(this.params)
this.tableData = res.data ?? []
},
// 合并列
arraySpanMethod(data) {
const { row, columnIndex } = data
if (row.mergeCol) {
if (columnIndex == 0) {
// 第一列合并
return [1, 3]
} else if (columnIndex > 0 && columnIndex < 3) {
// 合并的其他列不展示
return [0, 0]
}
}
},
//单元格的样式
cellColor(planCount, realCount) {
if (planCount > realCount) {
return 'countWarning'
} else {
return 'countNormal'
}
},
//jsx语法
renderToInput(row, index) {
// 使用js动态新增一个slot实现render函数jsx语法渲染
this.$slots[this.realCountArrange[index]] = (
<div>
{
<el-input
v-model={row[this.realCountArrange[index]]}
placeholder="请输入"
clearable
vOn:class={this.cellColor(
row[this.planCountArr[index]],
row[this.realCountArrange[index]]
)}
></el-input>
}
</div>
)
}
}
}
</script>
<style lang="scss" scoped>
.table-page {
position: relative;
flex-grow: 1;
margin-left: 24px;
margin-right: 24px;
.el-table {
position: absolute;
background-color: transparent;
}
}
::v-deep .el-table__row .realCountStyle {
padding: unset;
.cell {
padding: unset;
}
}
.countWarning {
display: inline-block;
width: 100%;
height: 100%;
line-height: 47px;
background-color: #ff4444;
color: #fff;
::v-deep .el-input__inner {
background-color: #ff4444;
color: #fff;
}
// 清除按钮样式更改
::v-deep .el-input__suffix {
.el-input__suffix-inner {
border-color: none;
.el-icon-circle-close:before {
color: #fff;
}
}
}
}
::v-deep {
.el-table__body-wrapper {
@include scrollBar;
}
// 解决固定列后滚动条无效的问题
.el-table__fixed {
height: auto !important;
bottom: 12px;
}
.el-input__inner {
padding: 0 15px !important;
text-align: center;
border: unset;
&::placeholder {
color: #fff;
}
}
}
</style>