- 需求说明: 后端接口会返回日志信息,并且日志是以一整个字符串返回,其中你需要将日志信息展示在页面上,或者是弹窗/抽屉,同时考虑到日志信息量过大,不能一次性渲染在当前页面/弹窗,会导致浏览器卡顿,性能差,体验感不好,需要尽量满足用户快速查看日志结果和日志输出所有信息。并且优化处理上全部是给到前端处理,后端返回的数据结构固定。数据如下图:
- 思考方向: 在考虑到性能,数据量大问题时,我们会考虑说日志做分页或者说直接给出加载更多去请求后端,或者说下载日志文件,那么下载的链接怎么来呢?这里是用前端来实现。
- 前端实现日志导出 1、安装 FileSaver包
npm install file-saver --save
2、在.vue组件中局部引入或在main.js中全文引入
import {saveAs} from 'file-saver';
3、将返回的字符串先转为Blob对象,然后导出.txt文本
const strData = '要导出的文本内容'
const result= new Blob([strData], {type: 'text/plain;charset=utf-8'});
// 导出
saveAs(result, 导出文件时的名字.txt
);
- 具体实现: 1.基本结构和数据处理
弹出的日志抽屉展示框
<el-drawer v-model="drawer" title="日志信息" size="50%" :withHeader="false" show-close>
<div>
<el-tabs v-model="tabActiveName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane v-for="item in tabList" :key="item.name" :label="item.label" :name="item.name">
<div>
<el-button type="primary" plain @click="downLoadLog(item)">下载日志文件</el-button>
</div>
<h3>输入语句:</h3>
<div v-if="item.step_command" v-html="item.step_command" class="log_sty"></div>
<h3>日志显示:</h3>
<div class="log_sty">
<div v-for="(ite,idx) in item.fmessage" :key="idx">{{ite}}</div>
</div>
<div class="load_more" @click="clickMore"
v-if="multiFmessage.length>1 && more_index+1<multiFmessage.length">
<span>点击加载更多......</span>
</div>
</el-tab-pane>
</el-tabs>
</div>
</el-drawer>
数据定义
// 备份任务查看日志窗口
const multiFmessage = ref([])
const more_index = ref(0);
const drawer = ref(false)
const tabActiveName = ref(1)
const tabList = reactive([
{
label: '备份日志',
name: 1,
step_command: "",
fmessag: [],
table: [],
},
{
label: '解压缩日志',
name: 2,
step_command: "",
fmessag: [],
table: [],
},
{
label: 'applylog日志',
name: 3,
step_command: "",
fmessag: [],
table: [],
},
{
label: '备份压缩日志日志',
name: 4,
step_command: "",
fmessag: [],
table: [],
},
{
label: '传输磁带日志',
name: 5,
step_command: "",
fmessag: [],
table: [],
},
{
label: '传输异地日志',
name: 6,
step_command: "",
fmessag: [],
table: [],
},
])
const ftaskid = ref('')
const drawer_loading = ref(false)
拿到日志文件并且处理数据
import { dts_log } from '@/api/mysql';
//查看日志
const lookLog = (row) => {
tabList[0].step_command = '';
tabList[0].fmessage = ''
tabActiveName.value = 1;
drawer.value = true;
ftaskid.value = row.ftaskid;
more_index.value = 0;
drawer_loading.value = true;
dts_log({
task_id: row.ftaskid,
step_level: 1
}).then(async (res) => {
drawer_loading.value = false;
if (res.code == 200 && res.data.length != 0) {
let fstep_command = res.data[0].fstep_command.split("")
let log = res.data[0].fmessage.split(" ");
let fmessage = res.data[0].fmessage.split("\n");
multiFmessage.value = getNewArray(fmessage, 3000); //这是一段分割后的数组
let splitP = multiFmessage.value[0].map((item) => {
return item + '\n'
})
tabList[0].fmessage = splitP;
tabList[0].step_command = fstep_command.map((item) => {
return item === "\n" ? "<br>" : item
}).join("")
tabList[0].table = log.map((item) => {
return item === "\n" ? "<br>" : item
}).join(" ")
// tabList[0].fmessage = fmessage.map((item) => {
// return item === "\n" ? "<br>" : item
// }).join("")
} else {
//清楚上一个tab下的内容
tabList[0].step_command = "";
tabList[0].fmessage = "";
}
}).catch(() => { });
}
//tab页切换时方法,处理数据
const handleClick = (tab, event) => {
let index = tab.index;
tabList[index].step_command = "";
tabList[index].fmessage = "";
multiFmessage.value = [];
more_index.value = 0;
dts_log({
task_id: ftaskid.value,
step_level: tab.props.name
}).then(async (res) => {
if (res.code == 200 && res.data.length != 0) {
let fstep_command = res.data[0].fstep_command.split("")
let fmessage = res.data[0].fmessage.split("\n");
let log = res.data[0].fmessage.split(" ");
multiFmessage.value = getNewArray(fmessage, 3000); //这是一段分割后的数组
let splitP = multiFmessage.value[0].map((item) => {
return item + '\n'
})
tabList[index].fmessage = splitP;
tabList[index].step_command = fstep_command.map((item) => {
return item === "\n" ? "<br>" : item
}).join("")
tabList[index].table = log.map((item) => {
return item === "\n" ? "<br>" : item
}).join(" ")
// tabList[index].fmessage = fmessage.map((item) => {
// return item === "\n" ? "<br>" : item
// }).join("")
} else {
//清楚上一个tab下的内容
tabList[index].step_command = "";
tabList[index].fmessage = "";
}
}).catch(() => { });
}
// 切割数组
const getNewArray = (array, subGroupLength) => {
let index = 0;
let newArray = [];
while (index < array.length) {
newArray.push(array.slice(index, index += subGroupLength));
}
return newArray;
}
2.点击加载更多
//点击加载更多 备份信息
const clickMore = () => {
more_index.value++;
let splitP = multiFmessage.value[more_index.value].map((item) => {
return item + '\n'
})
let splitPStr = splitP.toString()
tabList[tabActiveName.value - 1].fmessage.push(splitPStr);
}
3.新增一个按钮,点击下载日志文件,输出txt日志文件。
import { saveAs } from 'file-saver';
//下载日志 备份信息
const downLoadLog = (item) => {
let list = item.table
const result = new Blob([list], { type: 'text/plain;charset=utf-8' });
// 导出
saveAs(result, `${item.label}_${ftaskid.value}`);
}