项目需要做一个评分表,涉及到单元格合并,就简单记录一下。(大佬勿喷)
效果图:
参考文档:Element UI Table 表格https://element.eleme.cn/#/zh-CN/component/table
通过给table
传入span-method
方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row
、当前列column
、当前行号rowIndex
、当前列号columnIndex
四个属性。该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan
,第二个元素代表colspan
。 也可以返回一个键名为rowspan
和colspan
的对象。
代码如下:
<template>
<div>
<el-table :data="scoreList" border :span-method="objectSpanMethod" emptyText='暂无评分规则,请添加'
:header-cell-style="{background:'#e8e8e8',color:'#4c5058',fontWeight: '600',textAlign: 'center'}">
<el-table-column type="index" align="center" label="序号" :index="indexMethod" width="50">
</el-table-column>
<el-table-column align="center" prop="parentName">
<template slot="header">
<span><i style="color: red;margin-right: 1px;">*</i>项目/主要内容</span>
</template>
</el-table-column>
<el-table-column align="center" label="考核内容" prop="name">
<template slot="header">
<span><i style="color: red;margin-right: 1px;">*</i>考核内容</span>
</template>
</el-table-column>
<el-table-column align="center" label="配分" prop="score">
<template slot="header">
<span><i style="color: red;margin-right: 1px;">*</i>配分</span>
</template>
</el-table-column>
<el-table-column align="center" label="评分标准/考核要点" prop="remark">
</el-table-column>
<el-table-column align="center" label="扣分" prop="loseScore">
</el-table-column>
<el-table-column align="center" label="得分" prop="getScore">
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="editTable(scope)">编辑</el-button>
<el-button type="text" size="small" @click="delTable(scope.row.parentName)">移除</el-button>
</template>
</el-table-column>
</el-table>
<el-button size="small" type="text" @click="addTable">+添加项目/主要内容</el-button>
<el-dialog class="dialogxx" append-to-body :close-on-click-modal="false" :title="dialogTitle"
:visible.sync="dialogTableVisible" :before-close="handleClose">
<div class="tableinput">
<span style="width:120px"><span style="color: red;">*</span>项目/主要内容:</span>
<el-input :disabled="dialogType === 'edit'" size="small" class="xxinput" v-model="parentName"></el-input>
</div>
<el-table :data="gridData"
:header-cell-style="{background:'#e8e8e8',color:'#4c5058',fontWeight: '600',textAlign: 'center'}">
<el-table-column label="考核内容">
<template slot="header">
<span><i style="color: red;margin-right: 1px;">*</i>考核内容</span>
</template>
<template slot-scope="scope">
<el-input v-model="scope.row.name" :controls="false"></el-input>
</template>
</el-table-column>
<el-table-column label="配分">
<template slot="header">
<span><i style="color: red;margin-right: 1px;">*</i>配分</span>
</template>
<template slot-scope="scope">
<el-input-number :min="0" :precision='0' v-model="scope.row.score" :controls="false"></el-input-number>
</template>
</el-table-column>
<el-table-column width="150" label="评分标准/考核要点">
<template slot-scope="scope">
<el-input v-model="scope.row.remark" :controls="false"></el-input>
</template>
</el-table-column>
<el-table-column label="扣分" prop="loseScore">
<!-- <template slot-scope="scope">
<el-input v-model="scope.row.loseScore" :controls="false"></el-input>
</template> -->
</el-table-column>
<el-table-column label="得分" prop="getScore">
<!-- <template slot-scope="scope">
<el-input v-model="scope.row.getScore" :controls="false"></el-input>
</template> -->
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="delnr(scope)">移除</el-button>
</template>
</el-table-column>
</el-table>
<el-button size="small" type="text" @click="addnr">+添加考核内容</el-button>
<div class="dialogfooter">
<el-button size="small" @click="handleClose">取消</el-button>
<el-button size="small" type="primary" @click="sureScore">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: '',
components: {},
data() {
return {
dialogTitle: '添加项目/主要内容',
dialogTableVisible: false,
dialogType: '',
parentName: '',
scoreList: [],
gridData: [
{
parentName: '',
name: '',
score: 0,
remark: '',
loseScore: '',
getScore: '',
},
],
spanArr: [], //存放整合数据
position: 0, //记录下标
};
},
computed: {},
watch: {},
created() {},
mounted() {
// 实际项目中可能初始的时候就有数据,所以需要渲染的时候调用
this.$nextTick(() => {
this.rowspan();
});
},
destroyed() {},
methods: {
rowspan() {
//每次调用清空数据
this.spanArr = [];
this.position = 0;
//存放表格数据数组
this.scoreList.forEach((item, index) => {
if (index === 0) {
this.spanArr.push(1);
this.position = 0;
} else {
if (
//scoreList 判断合并列的索引字段
this.scoreList[index].parentName ===
this.scoreList[index - 1].parentName
) {
this.spanArr[this.position] += 1;
this.spanArr.push(0);
} else {
this.spanArr.push(1);
this.position = index;
}
}
});
},
// 添加项目/主要内容
addTable() {
this.dialogType = 'add';
this.dialogTableVisible = true;
this.dialogTitle = '添加项目/主要内容';
},
// 编辑
editTable(scope) {
const name = scope.row.parentName;
const arr = [];
for (let i = 0; i < this.scoreList.length; i++) {
if (this.scoreList[i].parentName === name) {
arr.push(this.scoreList[i]);
}
}
this.gridData = arr;
this.parentName = name;
this.editIndex = scope.$index;
this.dialogType = 'edit';
this.dialogTableVisible = true;
this.dialogTitle = '编辑项目/主要内容';
},
// 移除
delTable(name) {
const arr = [];
for (let i = 0; i < this.scoreList.length; i++) {
if (this.scoreList[i].parentName === name) {
arr.push(i);
}
}
this.scoreList.splice(arr[0], arr.length);
this.rowspan();
},
indexMethod(index) {
if (index === 0) {
return 1;
} else {
let zeroCount = 0;
for (let i = 0; i < index; i++) {
if (this.spanArr[i] === 0) {
zeroCount++;
}
}
return index + 1 - zeroCount;
}
},
sureScore() {
const isIncomplete =
this.parentName === '' ||
this.gridData.some((item) => item.name === '');
if (isIncomplete) {
this.$message.error('请完善项目/主要内容、考核内容、配分');
return;
}
this.gridData.forEach((item) => {
item.parentName = this.parentName;
});
const data = JSON.parse(JSON.stringify(this.gridData));
if (this.dialogType === 'add') {
const hasDuplicate = this.scoreList.some(
(item) => item.parentName === this.parentName
);
if (hasDuplicate) {
this.$message.warning(
'已有此项目/考核内容,请修改或退出点击对应编辑'
);
return;
}
this.scoreList.push(...data);
} else {
const indices = [];
this.scoreList.forEach((item, index) => {
if (item.parentName === this.parentName) {
indices.push(index);
}
});
this.scoreList.splice(indices[0], indices.length, ...data);
}
this.rowspan();
this.dialogTableVisible = false;
this.parentName = '';
this.gridData = [
{
parentName: '',
name: '',
score: 0,
remark: '',
loseScore: '',
getScore: '',
},
];
},
handleClose() {
this.gridData = [
{
parentName: '',
name: '',
score: '',
remark: '',
loseScore: '',
getScore: '',
},
];
this.parentName = '';
this.dialogTableVisible = false;
},
addnr() {
this.gridData.push({
parentName: '',
name: '',
score: 0,
remark: '',
loseScore: '',
getScore: '',
});
},
delnr(scope) {
this.gridData.length > 1
? this.gridData.splice(scope.$index, 1)
: this.$message.warning('需要保留至少一条');
},
objectSpanMethod({ rowIndex, columnIndex }) {
// 需要作处理的对应列
if (columnIndex === 0 || columnIndex === 1 || columnIndex === 7) {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
},
},
};
</script>
<style lang='scss' scoped>
/deep/.w-e-text-container {
resize: vertical;
}
/deep/.avue-crud__header {
display: none;
}
/deep/.el-table__header {
.el-table__cell {
background-color: #e8e8e8;
color: #4c5058;
padding: 5px 0;
}
}
.tableinput {
margin-bottom: 15px;
display: flex;
align-items: center;
.xxinput {
flex: 1;
}
}
/deep/.el-dialog__body {
padding-top: 0;
}
.dialogfooter {
text-align: right;
}
.dialogxx {
/deep/.el-table .el-table__body-wrapper .el-table__cell {
padding: 0;
text-align: center;
}
/deep/.el-table .cell {
padding: 0;
}
/deep/.el-input__inner {
width: 100%;
}
/deep/.el-input-number {
width: 100%;
}
}
</style>
注:可能代码不是那么优雅,但是能跑就行,简单记录一下,不要要求那么严格~~