admin管理员组

文章数量:1574563

需求

用户上传execl,前端解析excel ,解析之后,将excel的json数据,传给后端,后端通过关键字检测算法,返回你之前传的数据,并且附件敏感字。然后前端渲染数据只table。并且用户以到excel形式下载table表格数据。没看错,全程后端就是对敏感词检测,excel 解析 ,下载,都是前端来做。我们一步一步来分析

步骤一 界面编写

界面编写 就是element一梭子

   <!-- 上传文件按钮界面 -->
    <div class="buttonBox">
      <el-upload
        :show-file-list="false"
        class="upload-demo"
        action=""
        :on-change="handleChange"
        :auto-upload="false">
        <el-button size="small" type="primary">点击上传</el-button>
      </el-upload> 
      <el-button size="small" type="primary" @click="downloadTemplate">下载检查模板</el-button>
      <el-button size="small" type="primary" @click="downloadResult">下载检查结果</el-button>
    </div>
    <!-- table界面 -->
    <el-table  v-loading = "isLoading" element-loading-background = "rgba(255, 255, 255, .5)" element-loading-text = "加载中,请稍后..." element-loading-spinner = "el-icon-loading" :data="listData" stripe width=100%>
      <el-table-column prop="goods_id" label="商品ID" width="180"></el-table-column>
      <el-table-column label="商品图" width="180">
        <template slot-scope="scope">
          <img :src="scope.row.goods_img" class="shop_pic"/>
        </template>
      </el-table-column>
      <el-table-column prop="goods_name" label="商品名称" width="180"></el-table-column>
      <el-table-column prop="contents" label="视频文案内容" width="500">
        <template slot-scope="scope">
          <div class="overflow-style">
            <span v-html="sensitiveWords(scope.row.contents, scope.row.ad_values)"></span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="违禁词">
        <template slot-scope="scope">
          <div class="overflow-style">
            <span class="key-words" v-for="item in scope.row.ad_arr">
              {{item[0]}}&nbsp;({{item[1]}})&nbsp;&nbsp;&nbsp;
            <span>
          </div>
        </template>
      </el-table-column>
    </el-table>

步骤二: 使用XLSX进行execl解析,接续成json格式

    // 把文件按照二进制进行读取
    async handleChange(file) {
      this.FileName = file.name
      let dataBinary = await this.readFile(file.raw)
      let workBook = XLSX.read(dataBinary, {type: 'binary', cellDates: true})
      let workSheet = workBook.Sheets[workBook.SheetNames[0]] // 获取Sheets中第一个Sheet的名字
      const upLoadData = XLSX.utils.sheet_to_json(workSheet) //  生成 JSON 格式的数组对象
      console.log('data', upLoadData)
      const interfaceData = this.dataFormat(upLoadData) // 这里的代码快在下面
      this.adWordsCheck(interfaceData) // 传给后端,后端接收数组对象,经过敏感词算法,返回需要的数组对象
    },
    readFile(file) {
      return new Promise(resolve => {
        let reader = new FileReader()
        reader.readAsBinaryString(file) // 将文件读取为二进制字符串
        reader.onload = ev => {
          resolve(ev.target.result)
        }
      })
    },
这里有必要解释一下
  1. xlsx 实现基本功能没问题(解析excel数据,根据json数据下载成excel ),但是样式什么的,比较费劲,所以下载我选择了excelJS
  2. xlsx
    地址 xlsx地址 https://github/SheetJS/sheetjs
    安装依赖 npm install xlsx
    使用cdn <script src="https://cdn.jsdelivr/npm/xlsx@0.14.3/dist/xlsx.core.min.js"></script>
    excelJS
    地址 exceljs地址 https://github/exceljs/exceljs
    安装依赖 npm install exceljs
    使用cdn <script src="https://cdn.jsdelivr/npm/exceljs@4.3.0/dist/exceljs.min.js"></script>
  3. 代码解释
    3.1 readFile
    使用浏览器的FileReader接口,把文件内容读出来交给js-xlsx解析,最终生成关键的workbook实例。
    3.2 workBook 是什么: workbook是一个工作簿对象
    3.3 workBook.Sheets[workBook.SheetNames[0]] // 获取Sheets中第一个Sheet的名字
    3.4 XLSX.utils.sheet_to_json(workSheet) // 将excel里的数据生成 JSON 格式的数组对象
    3.5 至此XLSX解析就完成了,但是excel是给用户看的,解析出来的数据是要给后端的,所以解析出来的数据,得有一个映射
    3.6 比如 excel里的 商品ID, 文案内容,对应的字段可能是goods_id, contents. 要做一个映射

映射代码

let character = {
    goods_id: {
        text: "商品ID",
    },
    contents: {
        text: "视频文案内容",
    }
};

dataFormat(upLoadData) {
      let arr = [];
      upLoadData.forEach(item => {
      let obj = {};
      for (let key in character) {
      if (!character.hasOwnProperty(key)) break;
       let v = character[key],
         text = v.text,
         type = v.type;
       v = item[text] || "";
       type === "string" ? (v = String(v)) : null;
       type === "number" ? (v = Number(v)) : null;
       obj[key] = v;
        }
      arr.push(obj);
      });
      return arr
    }

现在数据准备完毕,然后传给后端

this.adWordsCheck(interfaceData) // 传给后端,后端接收数组对象,经过敏感词算法,返回需要的数组对象

// 导入检查文案接口
    adWordsCheck(interfaceData){
      this.isLoading = true
      let parent = JSON.stringify(interfaceData)
      $.post('/Tools/ajaxAdWordsCheck', {data: parent}).then(res=>{
        if (res.errno == 0) {
          this.adWordList = res.data
          this.isLoading = false;
        } else {
          this.isLoading = false;
        }
      })
    },

接收后端返回的数据,并且进行数据处理

这里需要对数据进行处理
后端返回的关键字是

{
obj: {
	"最"2"最好的"3"最棒的"4
	}
}

这个需要转化成数组。并且需要一个变量专门用来存放key,为后面敏感词标红做准备

 computed: {
    listData: function ({adWordList}) {
      adWordList.forEach(item=>{
        item.ad_arr = Object.entries(item.ad_words) // 将对象转为数据
        item.ad_values = Object.keys(item.ad_words) // 对关键字进行抽取
      }) 
      return adWordList
    }
  },

现在数据准备完毕,然后渲染

关键点1
将之前的adWordList 转为计算属性listData
关键点2
将敏感词单独渲染
<el-table-column label="违禁词">
        <template slot-scope="scope">
          <div class="overflow-style">
            <span class="key-words" v-for="item in scope.row.ad_arr">
              {{item[0]}}&nbsp;({{item[1]}})&nbsp;&nbsp;&nbsp;
            <span>
          </div>
        </template>
      </el-table-column>

至此el-table渲染完毕。开始进行敏感词标红

敏感词标红

匹配敏感词,如果内容中有敏感词,将content中的敏感词标红,核心就是正则,

 <el-table-column prop="contents" label="视频文案内容" width="500">
        <template slot-scope="scope">
          <div class="overflow-style">
            <span v-html="sensitiveWords(scope.row.contents, scope.row.ad_values)"></span>
          </div>
        </template>
      </el-table-column>

// 敏感词高亮
    sensitiveWords(content, keyWords){
      let keyWordsSort = keyWords
      keyWordsSort.sort(function (a, b) {
        return b.length - a.length;
      }); // 这里为什么要排序?
      keyWordsSort.map(item=>{
        let reg = new RegExp(item, 'g')
        content = content.replaceAll(reg, `<font color="red">${item}</font>`)
      })
      return content
    }, 

为什么要对关键词排序,比如

{
obj: {
	"最"2"最好的"3"最棒的"4
	}
}

全局匹配“最” ,如果是以下内容,
最,最棒,最好的。并且都是关键字

就会出现一次匹配 最

<font color="red"></font>
<font color="red"></font><font color="red"></font>好的

第二次匹配 最棒
但是目前最棒是 <font color="red">最</font> 棒 无法匹配到 “最棒”
所以排序,是为了将字数长的,放在前面,大集合包括小集合

至此 excel 解析,敏感字标红,已经处理完,看效果

下面看下载功能

下载模板

就是一个链接,直接用window.location.href

// 下载检查模板
   downloadTemplate(){
     window.location.href = `oss地址`
   },

根据table ,下载成excel

// 下载检查结果
   async downloadResult(){
     console.log('this.listData111', this.listData) //  
     var worksheet = workbook.addWorksheet();
     worksheet.columns = [
     { header: '商品id', key: 'goods_id', width: 20 },
     { header: '商品图', key: 'goods_img', width: 50 },
     { header: '商品名称', key: 'goods_name', width: 50 },
     { header: '视频文案内容', key: 'contents', width: 50 },
     { header: '违禁词', key: 'ad_words', width: 50, style: { font: { color: { argb: 'ff0000' } } } },
     ];
     worksheet.addRows(this.listData);
     // 通过键,字母和基于1的列号访问单个列
     const dobCol = worksheet.getColumn('contents');
     // 遍历此列中的所有当前单元格
     dobCol.eachCell({ includeEmpty: true }, (cell, rowNumber)=> {
     let ad_address = worksheet.getCell(`${cell._address}`).value
     // 这里应该放关键字
     });
     // 下载excel
       let file = './file/' + Date.now()+ '.xlsx';
       workbook.xlsx.writeBuffer(file).then( value => {
         const blob = new Blob([value], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
         const url = window.URL.createObjectURL(blob);
         const link = document.createElement('a');
         link.style.display = 'none';
         link.href = url;
         link.setAttribute('download', `${this.FileName}`);
         document.body.appendChild(link);
         link.click();
         //释放URL对象所占资源
         window.URL.revokeObjectURL(url);
         //用完即删
         document.body.removeChild(link);
       });
     },
  1. 新建一个工作簿
    var worksheet = workbook.addWorksheet();
  2. 将需要转化的列标出来,并且,可以设置宽度和颜色
    worksheet.columns = [
    { header: ‘商品id’, key: ‘goods_id’, width: 20 },
    { header: ‘商品图’, key: ‘goods_img’, width: 50 },
    { header: ‘商品名称’, key: ‘goods_name’, width: 50 },
    { header: ‘视频文案内容’, key: ‘contents’, width: 50 },
    { header: ‘违禁词’, key: ‘ad_words’, width: 50, style: { font: { color: { argb: ‘ff0000’ } } } },
    ];
    3. 将数据塞到工作簿
    worksheet.addRows(this.listData);
    4. 下载excel

本文标签: 敏感