vue3实现点击导出后端接口返回的日志信息(日志是一串字符串)

578 阅读3分钟
  • 需求说明: 后端接口会返回日志信息,并且日志是以一整个字符串返回,其中你需要将日志信息展示在页面上,或者是弹窗/抽屉,同时考虑到日志信息量过大,不能一次性渲染在当前页面/弹窗,会导致浏览器卡顿,性能差,体验感不好,需要尽量满足用户快速查看日志结果和日志输出所有信息。并且优化处理上全部是给到前端处理,后端返回的数据结构固定。数据如下图:

image.png

image.png

image.png

  • 思考方向: 在考虑到性能,数据量大问题时,我们会考虑说日志做分页或者说直接给出加载更多去请求后端,或者说下载日志文件,那么下载的链接怎么来呢?这里是用前端来实现。
  • 前端实现日志导出 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}`);
    }