先描述一下需求,看下图
1:动态合并行,如图所示,第一列全部合并,第二列和第三列第四列根据名称进行合并
2:可以动态编辑第三列和第四列,并且只能编辑属于此合并行的第三列和第四列,比如第一个编辑按钮点击后,只有前三行可以编辑
3:第一列的数据是根据第三列相加得来的
4:点击快捷填写,可以快速填写第三列和第四列
思路
1:第二列和第三列第四列根据名称进行合并,后台根据名称进行排序,前台通过循环解析名称来知道哪一行需要合并,这个从网上找了一个自己改了下。
第一列特殊情况根据上面的思路做简单修改
element代码: span-method="cellMerge"
<el-table
border
:data="tableData3"
height="100%"
width="100%"
:cell-style="cellStyle"
:row-style="getRowClass"
:header-row-style="getRowClass"
:header-cell-style="getRowClass"
:span-method="cellMerge"
>
vue代码:
//合并单元格,此方法需要后台进行名字进行排序
cellMerge({ row, column, rowIndex, columnIndex }) {
let length = this.tableData3.length;
//第0列比较特殊,单独合并
if (columnIndex === 0) {
const _row = this.spanArrOne[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
};
}
//1 2 5列进行合并
if (columnIndex === 1 || columnIndex === 2 || columnIndex === 5) {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
};
}
},
//1 2 5列合并的数据
getSpanArr(data) {
for (var i = 0; i < data.length; i++) {
if (i === 0) {
this.spanArr.push(1);
this.pos = 0;
} else {
// 判断当前元素与上一个元素是否相同
if (data[i].name === data[i - 1].name) {
this.spanArr[this.pos] += 1; //需要合并的行数
this.spanArr.push(0); //新增被合并的行
} else {
this.spanArr.push(1);
this.pos = i; //新的需要合并的第几行数
}
}
}
},
//0列合并的数据
getSpanArrOne(data) {
for (var i = 0; i < data.length; i++) {
if (i === 0) {
this.spanArrOne.push(1);
this.posOne = 0;
} else {
this.spanArrOne[this.posOne] += 1; //需要合并的行数
this.spanArrOne.push(0); //新增被合并的行
}
}
console.log(this.spanArrOne, " this.spanArrOne");
},
2:可以动态编辑第三列和第四列解决:
0-2行是0 3到5行是3 6到9行是6以此类推,可以发现其规律就是第一个开头的行,当你点击第一个编辑按钮的时候,传的index就是0,所以根据flagNum匹配0-2行可以编辑,下面的是一样的逻辑
element代码;
<el-table-column prop="value1" label="XXX" min-width="15%" align="center">
<template slot-scope="scope">
<template v-if="scope.row.editing">
<el-input class="edit-input" v-model="scope.row.value1"></el-input>
</template>
<span v-else>{{ scope.row.value1 }}</span>
</template>
</el-table-column>
vue代码:
//判断可编辑作用域 用到的数据spanArr4Edit
getSpanArr4Edit(data) {
let ctx = this;
var flagNum = 0;
for (var i = 0; i < data.length; i++) {
//首先不能编辑
ctx.$set(data[i], "editing", false);
if (i === 0) {
ctx.spanArr4Edit.push(flagNum);
} else {
// 判断当前元素与上一个元素是否相同
if (data[i].name === data[i - 1].name) {
ctx.spanArr4Edit.push(flagNum); //还是同一个记录
} else {
ctx.spanArr4Edit.push(i);
flagNum = i;
}
}
//与编辑相对应
ctx.$set(data[i], "flagNum", flagNum);
}
//最终赋值
ctx.tableData3 = data;
console.log(ctx.spanArr4Edit, "this.spanArr4Edit");
},
handleEdit(index, row) {
let ctx = this;
this.setEditFlag(index, 1);
console.log(index);
},
/编辑输入框显示与隐藏0 隐藏 1显示
setEditFlag: function(index, flag) {
let ctx = this;
let datalength = ctx.tableData3.length;
let flagNum = ctx.spanArr4Edit[index];
for (let i = 0; i < datalength; i++) {
if (flag == 1) {
if (flagNum === ctx.tableData3[i].flagNum) {
//循环遍历改变可编辑的标记
this.$set(ctx.tableData3[i], "editing", true);
}
} else {
//循环遍历改变可编辑的标记
this.$set(ctx.tableData3[i], "editing", false);
}
}
}
3:第一列的数据是根据第三列相加得来的
可以用监听器深度监听后台传过来的数据
代码:
watch: {
tableData3: {
handler(newValue, oldValue) {
let ctx = this;
let length = oldValue.length;
var num = 0;
if (length > 0) {
for (let i = 0; i < length; i++) {
//取出编辑后的对象数据
num = Number(num) + Number(ctx.tableData3[i].value1);
}
if (num != 0) {
//赋值对象数据
ctx.tableData3[0].all = num;
} else {
ctx.tableData3[0].all = "";
}
}
},
deep: true //深度监听对象里面的属性
}
},
4;此逻辑比较简单,就是弹出个输入框,点击确认把值带到这个页面进行填写
直接上代码:
//快捷填写保存
addSubmit: function() {
let ctx = this;
//赋值数据,取出哪一行需要进行赋值
let idx = this.quickFlag;
let datalength = ctx.tableData3.length;
//每次快捷填写某一个区域,所以此变量在此定义
var initFlag = 0;
for (let i = 0; i < datalength; i++) {
if (idx === ctx.tableData3[i].flagNum) {
if (initFlag == 0) {
//value1 只赋值一次就行
this.$set(ctx.tableData3[i], "value1", this.addform.w);
}
initFlag++;
this.$set(ctx.tableData3[i], "value2", this.addform.q);
}
}
this.dialogQuick = false;
ctx.$message.success("操作成功");
console.log(this.addform, "this.addform");
},
-----------------------------------分割线------------------------------------------------
贴上完整代码
<template>
<div class="waterApplyTable">
<el-table
border
:data="tableData3"
height="100%"
width="100%"
:cell-style="cellStyle"
:row-style="getRowClass"
:header-row-style="getRowClass"
:header-cell-style="getRowClass"
:span-method="cellMerge"
>
<el-table-column prop="title" :label="title" align="center">
<el-table-column prop="all" label="xx" min-width="20%">
<template slot-scope="scope">
<span>{{ scope.row.all }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="xx" min-width="15%" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="value1" label="xx" min-width="15%" align="center">
<template slot-scope="scope">
<template v-if="scope.row.editing">
<el-input class="edit-input" v-model="scope.row.value1"></el-input>
</template>
<span v-else>{{ scope.row.value1 }}</span>
</template>
</el-table-column>
<el-table-column prop="value2" label="xx" min-width="15%" align="center">
<template slot-scope="scope">
<template v-if="scope.row.editing">
<el-input class="edit-input" v-model="scope.row.value2"></el-input>
</template>
<span v-else>{{ scope.row.value2 }}</span>
</template>
</el-table-column>
<el-table-column prop="value3" label="xx" min-width="15%" align="center"></el-table-column>
<el-table-column prop="editing" label="操作" min-width="20%" align="center">
<template slot-scope="scope">
<el-button
type="primary"
v-if="!scope.row.editing"
@click.native="handleEdit(scope.$index, scope.row)"
>编辑</el-button>
<el-button type="primary" v-else @click.native="savemodify(scope.$index, scope.row)">保存</el-button>
<el-button type="primary" @click.native="clickTodo(scope.$index, scope.row)">快捷填写</el-button>
</template>
</el-table-column>
</el-table-column>
</el-table>
<el-dialog
class="dialog"
:visible="dialogQuick"
top="15vh"
@close="dialogQuickClose"
width="20%"
title="快捷填写"
:append-to-body="true"
>
<el-form :model="addform" class="demo-form-inline">
<el-form-item label="x">
<el-input v-model.trim="addform.w"></el-input>
</el-form-item>
<el-form-item label="xx">
<el-input v-model.trim="addform.q"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click.native="addSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "waterApplyTable",
props: {
total: {
type: Number,
default: 100
}
},
data() {
return {
rules: {},
page: 1,
pageSize: 20,
pageCount: 10,
formInline: {
area: "青岛市",
year: "2018-2019"
},
tableData3: [],
dialogQuick: false,
addform: {},
spanArr: [],
pos: "",
spanArrOne: [],
posOne: "",
spanArr4Edit: [],
pos4Edit: "",
//快捷填写flag,记录哪一行数据的快捷填写
quickFlag: "",
title:'我是表头',
};
},
watch: {
tableData3: {
handler(newValue, oldValue) {
let ctx = this;
let length = oldValue.length;
var num = 0;
if (length > 0) {
for (let i = 0; i < length; i++) {
num = Number(num) + Number(ctx.tableData3[i].value1);
}
if (num != 0) {
ctx.tableData3[0].all = num;
} else {
ctx.tableData3[0].all = "";
}
}
},
//immediate: true,
deep: true //深度监听对象里面的属性
}
},
created() {
this.getData();
},
mounted() {
// this.getData();
},
methods: {
getData() {
this.getTableDataList();
},
// 列表,
getTableDataList() {
let ctx = this;
// ctx.$api
// .getTableDataList()
// .then(res => {
// ctx.total = res.totalRows;
// ctx.pageCount = ctx.total / ctx.pageSize + 1;
// ctx.tableData = res.rows;
// })
// .catch(() => {
// });
let _data = [
{
all: "",
name: "名字1",
value1: "",
value2: "",
value3: "2017年-10月"
},
{
all: "",
name: "名字1",
value1: "",
value2: "",
value3: "2017年-11月"
},
{
all: "",
name: "名字1",
value1: "",
value2: "",
value3: "2017年-12月"
},
{
all: "",
name: "名字2",
value1: "",
value2: "",
value3: "2017年-10月"
},
{
all: "",
name: "名字2",
value1: "",
value2: "",
value3: "2017年-11月"
},
{
all: "",
name: "名字2",
value1: "",
value2: "",
value3: "2017年-12月"
},
{
all: "",
name: "名字3",
value1: "",
value2: "",
value3: "2017年-10月"
},
{
all: "",
name: "名字3",
value1: "",
value2: "",
value3: "2017年-11月"
},
{
all: "",
name: "名字3",
value1: "",
value2: "",
value3: "2017年-12月"
},
{
all: "",
name: "名字4",
value1: "",
value2: "",
value3: "2017年-10月"
},
{
all: "",
name: "名字4",
value1: "",
value2: "",
value3: "2017年-11月"
},
{
all: "",
name: "名字4",
value1: "",
value2: "",
value3: "2017年-12月"
}
];
//进行赋值,为了后面编辑用,此方法位置不要动
ctx.getSpanArr4Edit(_data);
console.log(ctx.tableData3, "ctx.tableData3");
ctx.getSpanArr(ctx.tableData3);
ctx.getSpanArrOne(ctx.tableData3);
},
//改变分页事件已办理
clickChangePage(currPage) {
this.getGateStationList(currPage);
},
cellStyle({ row, column, rowIndex, columnIndex }) {
return "padding:0px";
},
getRowClass({ row, column, rowIndex, columnIndex }) {
return "height:0";
},
searchData: function() {
let searchVal = this.formInline.searchVal;
},
setClass(gateState) {
if (gateState == 0) {
return "stateClass-a";
}
return "stateClass-b";
},
dialogQuickClose: function() {
this.dialogQuick = false;
},
//前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性
//index 0开始
objectSpanMethod: function({ row, column, rowIndex, columnIndex }) {
let length = this.tableData3.length - 1;
// //合并第一列
// if (columnIndex === 0) {
// console.log(columnIndex, "columnIndex");
// alert(columnIndex);
// if (rowIndex % length === 0) {
// return {
// rowspan: length + 1,
// colspan: 1
// };
// } else {
// return {
// rowspan: 0,
// colspan: 0
// };
// }
// }
//合并第一列
if (columnIndex === 0) {
alert(columnIndex);
if (rowIndex % 2 === 0) {
return {
rowspan: 2,
colspan: 1
};
} else {
return {
rowspan: 0,
colspan: 0
};
}
}
//合并第二三列
},
//合并单元格,此方法需要后台进行名字进行排序
cellMerge({ row, column, rowIndex, columnIndex }) {
let length = this.tableData3.length;
//第0列比较特殊,单独合并
if (columnIndex === 0) {
const _row = this.spanArrOne[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
};
}
//1 2 5列进行合并
if (columnIndex === 1 || columnIndex === 2 || columnIndex === 5) {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
};
}
},
//1 2 5列合并的数据
getSpanArr(data) {
for (var i = 0; i < data.length; i++) {
if (i === 0) {
this.spanArr.push(1);
this.pos = 0;
} else {
// 判断当前元素与上一个元素是否相同
if (data[i].name === data[i - 1].name) {
this.spanArr[this.pos] += 1; //需要合并的行数
this.spanArr.push(0); //新增被合并的行
} else {
this.spanArr.push(1);
this.pos = i; //新的需要合并的第几行数
}
}
}
},
//0列合并的数据
getSpanArrOne(data) {
for (var i = 0; i < data.length; i++) {
if (i === 0) {
this.spanArrOne.push(1);
this.posOne = 0;
} else {
this.spanArrOne[this.posOne] += 1; //需要合并的行数
this.spanArrOne.push(0); //新增被合并的行
}
}
console.log(this.spanArrOne, " this.spanArrOne");
},
//编辑用到的数据
getSpanArr4Edit(data) {
let ctx = this;
var flagNum = 0;
for (var i = 0; i < data.length; i++) {
//首先不能编辑
ctx.$set(data[i], "editing", false);
if (i === 0) {
ctx.spanArr4Edit.push(flagNum);
} else {
// 判断当前元素与上一个元素是否相同
if (data[i].name === data[i - 1].name) {
ctx.spanArr4Edit.push(flagNum); //还是同一个记录
} else {
ctx.spanArr4Edit.push(i);
flagNum = i;
}
}
//与编辑相对应
ctx.$set(data[i], "flagNum", flagNum);
}
//最终赋值
ctx.tableData3 = data;
console.log(ctx.spanArr4Edit, "this.spanArr4Edit");
},
//快捷填写
clickTodo: function(index, row) {
this.dialogQuick = true;
this.quickFlag = index;
this.addform = {};
},
//快捷填写保存
addSubmit: function() {
let ctx = this;
//赋值数据,取出哪一行需要进行赋值
let idx = this.quickFlag;
let datalength = ctx.tableData3.length;
//每次快捷填写某一个分水口,所以此变量在此定义
var initFlag = 0;
for (let i = 0; i < datalength; i++) {
if (idx === ctx.tableData3[i].flagNum) {
if (initFlag == 0) {
//value1 只赋值一次就行
this.$set(ctx.tableData3[i], "value1", this.addform.w);
}
initFlag++;
this.$set(ctx.tableData3[i], "value2", this.addform.q);
}
}
this.dialogQuick = false;
ctx.$message.success("操作成功");
console.log(this.addform, "this.addform");
},
handleEdit(index, row) {
let ctx = this;
this.setEditFlag(index, 1);
console.log(index);
// this.prevValue = JSON.parse(JSON.stringify(row));//保存之前的数据
},
handleCancle(index, row) {
row.editing = false;
// let prevContent = this.prevValue.bookname;
// this.$set(row,"bookname",prevContent);
},
savemodify(index, row) {
this.setEditFlag(index, 0);
console.log(row, "row");
console.log(this.tableData3, "改变后的table数据");
console.log(
JSON.stringify(this.tableData3),
"JSON.stringify(this.tableData3)"
);
},
//提交数据到后台
submitToServe() {
let ctx = this;
let dataResult = JSON.parse(JSON.stringify(this.tableData3));
var result = 0;
//调用后台保存方法
// ctx.$api.addWaterApply(dataResult).then(res => {
// if (res.code == "0") {
// result =1;
// }
// });
console.log(dataResult, "提交到后台的数据");
//return result;
return 1;
},
//编辑输入框显示与隐藏0 隐藏 1显示
setEditFlag: function(index, flag) {
let ctx = this;
let datalength = ctx.tableData3.length;
let flagNum = ctx.spanArr4Edit[index];
for (let i = 0; i < datalength; i++) {
if (flag == 1) {
if (flagNum === ctx.tableData3[i].flagNum) {
//循环遍历改变可编辑的标记
this.$set(ctx.tableData3[i], "editing", true);
}
} else {
//循环遍历改变可编辑的标记
this.$set(ctx.tableData3[i], "editing", false);
}
}
}
},
filters: {
iswarnFlt(val) {
return val == 0 ? "否" : "是";
}
}
};
</script>
<style lang="scss" scoped>
.waterApplyTable {
height: 100%;
}
</style>