先来描述一下整个业务需求吧,文件上传时发送请求,跳转页面,如下图
由于表格内容过长分两部分来裁剪,看着页面很简单是吧,其实里面的逻辑很复杂,首先tab是根据后台传来的数据动态生成的,其次表头中嵌入动态下拉选择年份,先给大家看看后台返回的数据格式
我们针对于此处数据格式来做一个分析,tableData使我们所需要的table数据,里面每一项年份正是动态展示的年份,name如何将动态下拉放入表格来修改呢,此处认真看过elementui文档的同学就发现了有个 render-header 他后面可以跟一个回调,代码如下:
<el-table-column
:render-header="(h) => renderHeaderA(h, index, item)"
v-for="(item, index) in tableHeader"
:key="index"
:prop="item"
align="center">
<template slot-scope="scope">
<el-input
size="small"
v-model="scope.row[item]"
placeholder="请输入内容"
></el-input>
<!-- <span>{{ item }}</span> -->
</template>
</el-table-column>
renderHeaderA(h, index, prop) {
let filters = [
{
text: "2016年",
value: 2016,
},
{
text: "2017年",
value: 2017,
},
{
text: "2018年",
value: 2018,
},
{
text: "2019年",
value: 2019,
},
{
text: "2020年",
value: 2020,
},
];
return h("div", [
h(
"el-select",
{
class: "level-sel",
on: {
input: (value) => {
this.$set(this.chooseHead, prop, value);
this.tableHeader.forEach((item, index) => {
console.log(prop,item);
if (!!parseInt(prop) && prop === item) {
console.log(prop,item);
this.$set(this.tableHeader, index, value + "");
//这里用$set因为修改数据,数据改了试图没有修改
this.tableData.forEach(item => {
item[value] = item[prop]
})
}
})
},
},
props: {
//文字框的内容取决于这个value,如果value不存在,会报错
value: this.chooseHead[prop] || this.startStatus,
},
},
[
filters.map((item) => {
return h("el-option", {
props: {
value: item.value,
label: item.text,
},
});
}),
]
),
]);
},
},
tableHeader: [], //这里是后台传来的年份 已做过处理
chooseHead: {
2016: 2016,
2017: 2017,
2018: 2018,
2019: 2019,
2020: 2020,
}, //这里是用户选择年份并回显
上面的三步我们仅仅只是把表格的th下拉选择做好了,接下来该展示tab切换时做的数据处理
getTableData() {
// 获取表格总数据
this.currentTableData = sesstion.getLocalData("fileTableData");
console.log(this.currentTableData);
this.submitTableData = {...this.currentTableData};
if (this.currentTableData.table_data["资产负债表"]) {
this.tableTextList[0] = {
name: "资产负债表",
tableData:
this.currentTableData.table_data["资产负债表"].tableData || [],
listData:
this.currentTableData.table_data["资产负债表"].listData || [],
};
this.yearData[0] = this.updateYearData(
this.currentTableData.table_data["资产负债表"].tableData
);
}
if (this.currentTableData.table_data["利润表"]) {
this.tableTextList[1] = {
name: "利润表",
tableData: this.currentTableData.table_data["利润表"].tableData || [],
listData: this.currentTableData.table_data["利润表"].listData || [],
};
this.yearData[1] = this.updateYearData(
this.currentTableData.table_data["利润表"].tableData
);
}
if (this.currentTableData.table_data["现金流量表"]) {
this.tableTextList[2] = {
name: "现金流量表",
tableData:
this.currentTableData.table_data["现金流量表"].tableData || [],
listData:
this.currentTableData.table_data["现金流量表"].listData || [],
};
this.yearData[2] = this.updateYearData(
this.currentTableData.table_data["现金流量表"].tableData
);
}
// 此处this.updateYearData是一个处理后台数据的方法,
// 每一个表都要做相同的处理并且传给子组件
},
最麻烦的应该就是处理数据了,我们要把查分开后端数据做显示的数据,在保存时给后台传送回去,刚才我们下拉选择年份时后台有可能传无法识别年份,对于无法识别的年份,前端展示“请选择”,但是这个时候chooseHead里面的数据已经被修改了,无法判断哪个年份是当时“无法识别”的年份,所以需要用原数据去跟修改后的数据作比较,并且将元数据的key替换成修改后的value,代码如下:
saveData() {
console.log(this.$refs.table);
console.log(this.chooseHead);
console.log(this.tableData);
console.log(this.tableLable);
this.obj = {};
this.obj.company_code = this.companyCode || "";
this.obj.table_data = {
[this.tableLable]: {
tableData: { ...this.tableData },
},
};
console.log(this.obj);
var flage = true;
this.tableData.forEach((v, i) => {
for (let i1 in v) {
// arr2 = Object.keys(i1)
if (v[i1] == "") {
flage = false;
break;
}
}
let that = this;
let arr1 = Object.keys(that.chooseHead);
let arr2 = Object.keys(v);
arr2.forEach(function (item2) {
// console.log(arr1);
arr1.forEach((item1) => {
if (item2 === item1) {
v[that.chooseHead[item1] + "NY"] = parseInt(v[item2]) ? parseInt(v[item2]) : v[item2];
//说明一下这里为什么要加NY,因为在前端对象中有key则是修改,没有则是添加因为要循环对比,所以需要加NY来区分
// v[that.chooseHead[item1]] = v[item2];
delete v[item1];
}
});
});
console.log(this.chooseHead);
});
console.log(this.tableData, this.tableLable);
// let currentData = [...this.tableData]
// this.tableData = JSON.parse(
// JSON.stringify(currentData).replace(/NY/g, "")
// );
this.obj = JSON.stringify(this.obj).replace(/NY/g, "");
//这里是处理NY的代码
let tableString = JSON.stringify(this.tableData).replace(/NY/g, "");
// let tableString_data = JSON.stringify(this.tableData).replace(/NY/g, "");
console.log(tableString, this.tableData);
// this.tableData = JSON.parse(tableString_data);
this.totalData = {
tableLable: this.tableLable,
tableData: tableString,
tableHeader: this.tableHeader,
index: this.index
};
if (!flage) {
console.log("lalal");
this.open();
}
},
看似好像完了,其实还没有结束,我们需要将拼接好的数据传回去,刚刚加了NY的年份需要再另一个页面去处理,将所有含NY的去掉,这样又引发了另一个问题,她点击保存后,这正个流程走了,但时用户又不想保存了,还想继续修改,所以整个流程按逻辑需要重新再走一遍,问题来了,没有保存意味着没有提交,没有提交意味着没有处理那个NY,就会发现我们修改了年份后,数据没了,写到这里时我已经崩溃了,但是问题还是要解决的,绞尽脑汁后,我想到了一个错误的方法-修改table值,经过不断的尝试不断地报错,发现没有遵循vue单向数据流(所以提醒大家vue基本不要忘记,否则错都不知道错在哪里),因为连表都是动态的,所以数据还得穿回来再做处理
getCurrentTableData(totalData) {
// totalData 例 {tableLable: "资产负债表", tableData: ...}
console.log(totalData, this.submitTableData);
totalData.tableData = JSON.parse(totalData.tableData);
// this.currentTableData.table_data[totalData.tableLable].tableData = totalData.tableData
this.tableTextList[totalData.index].tableData = totalData.tableData
// 回显
Object.keys(this.submitTableData.table_data).forEach(item => {
if (this.submitTableData.table_data[item].listData) {
this.submitTableData.table_data[item] = {tableData: this.submitTableData.table_data[item].tableData}
}
})
this.submitTableData.table_data[totalData.tableLable] = {tableData: totalData.tableData}
},