业务需求
导入excel表单,导入成功后预览表单数据。根据表单首行字段,动态生成预览表单的表头。
excel表单格式:

技术栈
vue,ts,elementUI
实现
页面布局,调用接口获取到excel表格中数据,存入 fields 中。
<el-table :data="tableList"><el-table-column label="行号" width="100"><template slot-scope="scope"><div>{{scope.row.index}}</div></template></el-table-column><el-table-column v-for="(item, index) in fields" :key="index" :label="item.label"><template slot-scope="scope"><div>{{scope.row[item.field]}}</div></template></el-table-column></el-table>
逻辑实现
1、上传的表格中数据都是后端返回给前端的,这里是调用了getFileData 接口,返回值中 mapList 是个对象数组。
getFileData(params: any) {MyForm.getFileData(params).then((res) => {if (res.status === 0) {this.setTableList(res.data);} else {this.$message({message: res.data.msg,type: "error",});}});},

2、setTableList 方法就是动态生成表头数据。
但在此之前,需要明白前后端传值中后端需要的参数格式,这里表单的后端实现逻辑中关键的字段有三个:attrName,attrColumn和value。上图中拿到了attrName和value的对应关系:

后端还提供了一个attrName和attrColumn对应关系的接口,在页面加载的时候来调用。

最终生成的表单的数据是attrColumn和value的对应关系,以这样的数据格式传给后端,那就需要前端处理一下数据格式。
interface IField {label: string;field: string;}// methodsgetDetail() {UserForm.detail(this.id).then((res) => {if (res.status === 0) {const list = res.data.formAttrList;const fields: IField[] = [];const fieldMap: {[k: string]: IField } = {};list.forEach((d: any) => {const attr = {label: d.formAttrName,field: d.formAttrColumn,};fields.push(attr);fieldMap[d.formAttrName] = attr;});this.fields = fields;this.fieldMap = fieldMap;}});},
先定义空的数组fields,map对象fieldMap。循环返回值列表,把需要的attrName和attrColumn字段拿出来组成数组fields。以attrName为key,fields的Item为value,组成map对象fieldMap。
赋值好这两个变量之后,就可以实现setTableList 方法。
3、回到最上边,拿到那个mapList的数据,先做一个校验。当mapList存在的时候,取数组mapList中的第一项,检查表头数据是否存在fieldMap中,如果不存在的话给出提示直接return。
if (mapList && mapList.length > 0) {const item = mapList[0];let check = true;Object.keys(item).forEach((key) => {if (!this.fieldMap[key]) {check = false;}});if (!check) {this.$message({message: "表单格式已变动,请下载最新模版",type: "warning",});return;}// 。。。}
开始组装表单数据。先定义一个数组用来存放最终结果,循环mapList,返回值中的rowNumber数组里的数据是对应着mapList每一项在excel中的行号。
const tableList: any[] = [];mapList.forEach((d: {[k: string]: any}, index: number) => {const row: {[k: string]: any} = {index: rowNumber[index],};Object.keys(d).forEach((name) => {const field = this.fieldMap[name].field;row[field] = d[name];});tableList.push(row);});this.tableList = tableList;
整体 setTableList 方法如下:
setTableList(data: any) {this.tableList = [];this.errorColumn = "";const { mapList, rowNumber, errorColumn } = data;if (mapList && mapList.length > 0) {const item = mapList[0];let check = true;Object.keys(item).forEach((key) => {if (!this.fieldMap[key]) {check = false;}});if (!check) {this.$message({message: "表单格式已变动,请下载最新模版",type: "warning",});return;}// 组装表格数据const tableList: any[] = [];mapList.forEach((d: {[k: string]: any}, index: number) => {const row: {[k: string]: any} = {index: rowNumber[index],};Object.keys(d).forEach((name) => {const field = this.fieldMap[name].field;row[field] = d[name];});tableList.push(row);});this.tableList = tableList;}// 错误信息if (errorColumn) {errorColumn.forEach((el: string) => {const row = Number(el.split(",")[0]) + 1;const column = Number(el.split(",")[1]) + 1;this.errorColumn = `${row}行${column}列`;});}},
4、最终效果

关注我吧


1034

被折叠的 条评论
为什么被折叠?



