今天收到客户的改进意见,原本我们有一个批量上传excel文档的功能,后台进行数据验证,验证数据某行某列有错误时,会将错误信息以数组的形式返回给前端。
原本我的实现方法是在前端直接遍历后端返回的报错消息,进行拼接,将某行、某列的错误信息这样直接用NoticeProvider中封装好的方法展示出来,实现的代码如下(typescript):
......
import { NoticeProvider } from '../../../../../../providers/common/utils/notice';
@Component({
selector: 'app-add',
templateUrl: './add.component.html',
styleUrls: ['./add.component.scss']
})
export class AddComponent implements OnInit {
......
fileList = [];
fileInfoList = [];
constructor(
......
private notice: NoticeProvider,
) {
......
}
ngOnInit() {
......
}
/**
* 开始、上传进度、完成、失败都会调用这个函数。
*/
handleChange({ file, fileId, fileName, filePath }): void {
const status = file.status;
if (status === 'done') {
if (file.response.status === 0) {
this.notice.info('上传成功');
this.fileList.forEach(item => {
fileId = item.response.data.id;
fileName = item.name;
filePath = item.response.data.url;
});
this.fileInfoList.push({ fileId, fileName, filePath });
file.response.data.successList.forEach(item => {
this.priceConfirmReqs.push(item); // 保存上传的文件内容
});
} else if (file.response.status === 90001) {
this.notice.error(file.response.message);
} else {
const errorRowMes = [];
file.response.data.errorList.forEach(element => {
const errorCloMes = [];
element.errorFields.forEach(element1 => {
errorCloMes.push('第' + (element1.cellIndex + 1) + '列:' + element1.column + element1.errorMessage);
});
errorRowMes.push('第' + (element.rowIndex) + '行:' + '【' + errorCloMes + '】' + '<br>');
});
this.notice.error('上传失败,原因:' + errorRowMes);
this.fileList.splice(this.fileList.length - 1, 1);
}
}
}
......
}
其中this.notice.error的效果是直接在网页上方弹出提示信息,几秒种后就会消失。
客户提出意见,说网页上方弹出提示的效果不是很方便,当上传了几百几千条数据,提示框中的内容会非常多,往往还没有看清楚所有的报错消息,提示框就消失了,这样不利于他们的修改。
原本我们的最优解决方案是将用户导入的Excel表格,在每一个错的单元格中标红,再返回给用户,但是后端小哥哥说现在这个功能没时间实现,所以提出第二个解决方案,就是前端使用模态框弹出报错信息,因为模态框弹出后,用户自己点击关闭才会消失,而且模态框中想要有一个一键复制的按钮,点击后就可以将错误信息拷贝出来供修改。
这样就要用到NzModalService的功能了,我们新写一个页面,用作模态框的内容展示,在导入的页面上(上级页面)将报错信息传给模态框:
首先上级页面,也就是导入页面我们这样处理:
......
import { NzModalService, UploadFile } from 'ng-zorro-antd';
import { ErrorRowMesComponent } from './error-row-mes/error-row-mes.component';
@Component({
selector: 'app-add',
templateUrl: './add.component.html',
styleUrls: ['./add.component.scss']
})
export class AddComponent implements OnInit {
......
fileList = [];
fileInfoList = [];
constructor(
private modalService: NzModalService,
......
) {
}
ngOnInit() {
......
}
......
/**
* 开始、上传进度、完成、失败都会调用这个函数。
*/
handleChange({ file, fileId, fileName, filePath }): void {
const status = file.status;
if (status === 'done') {
if (file.response.status === 0) {
this.notice.info('上传成功');
this.fileList.forEach(item => {
fileId = item.response.data.id;
fileName = item.name;
filePath = item.response.data.url;
});
this.fileInfoList.push({ fileId, fileName, filePath });
file.response.data.successList.forEach(item => {
this.priceConfirmReqs.push(item); // 保存上传的文件内容
});
} else if (file.response.status === 90001) {
this.notice.error(file.response.message);
} else {
const errorRowMes = [];
file.response.data.errorList.forEach(element => {
const errorCloMes = [];
element.errorFields.forEach(element1 => {
errorCloMes.push('第' + (element1.cellIndex + 1) + '列:' + element1.column + element1.errorMessage);
});
errorRowMes.push('第' + (element.rowIndex) + '行:' + '【' + errorCloMes + '】' + '<br>');
});
// 弹窗提示报错信息
this.modalService.create({
nzTitle: '上传失败',
nzContent: ErrorRowMesComponent,
nzWidth: 600,
nzFooter: null,
nzComponentParams: {
data: {
errorRowMes: errorRowMes
}
},
});
this.fileList.splice(this.fileList.length - 1, 1);
}
}
}
......
}
弹出的模态框即显示ErrorRowMesComponent组件中的内容,这个弹出的页面我们这样处理:
import {
Component,
OnInit,
Input
} from '@angular/core';
import * as _ from 'lodash';
import { NzModalRef } from 'ng-zorro-antd';
import { NoticeProvider } from '../../../../../../../providers/common/utils/notice';
@Component({
selector: 'app-error-row-mes',
templateUrl: './error-row-mes.component.html',
styleUrls: ['./error-row-mes.component.scss']
})
export class ErrorRowMesComponent
implements OnInit {
errorRowMes = '';
@Input()
set data(value: any) {
this.errorRowMes = value.errorRowMes;
}
constructor(
private modal: NzModalRef,
private notice: NoticeProvider
) {
}
ngOnInit(): void {
}
doCopy(errorRowMes) {
const oInput = document.createElement('input');
oInput.value = errorRowMes;
document.body.appendChild(oInput);
oInput.select();
document.execCommand('Copy');
oInput.style.display = 'none';
this.notice.success('复制成功');
}
/**
* 取消
* @param e
*/
handleCancel() {
this.modal.destroy({ data: null });
}
}
其中:
@Input()
set data(value: any) {
this.errorRowMes = value.errorRowMes;
}
是从上级页面接收了报错的消息到模态框页面中。
一键复制的方法我们这样实现,将以下方法绑定到按钮即可:
doCopy(errorRowMes) {
const oInput = document.createElement('input');
oInput.value = errorRowMes;
document.body.appendChild(oInput);
oInput.select();
document.execCommand('Copy');
oInput.style.display = 'none';
this.notice.success('复制成功');
}
注意我们在html中,想要实现上级传过来的一些展示的样式,最好使用innerHTML进行展示:
<div class="ql-editor" [innerHTML]="errorRowMes"></div>
实现的效果如下图所示: