licp
2024-12-25 958ee855acb3431d2da10aa67e2e9453a268fcd4
src/components/tool/file-preview.vue
@@ -1,17 +1,17 @@
<template>
  <div>
    <div v-if="isImage">
      <img :src="fileUrl" alt="Image Preview" />
      <img :src="imgUrl" alt="Image Preview" />
    </div>
    <div v-if="isPdf">
      <object :data="fileUrl" type="application/pdf" width="100%" height="600px">
      <object :data="fileUrl" type="application/pdf" width="100%" height="750px">
        <p>您的浏览器不支持 PDF 预览。<a :href="fileUrl">下载 PDF 文件</a></p>
      </object>
    </div>
    <div v-if="isDoc">
      <p v-if="!isDocShow">文档无法直接预览,请下载查看。</p>
      <a :href="fileUrl" v-if="!isDocShow">下载文件</a>
      <vue-office-docx
      <vue-office-docx v-else
          :src="fileUrl"
          style="height: 100vh;"
          @rendered="renderedHandler"
@@ -21,7 +21,7 @@
    <div v-if="isXls">
      <p v-if="!isDocShow">文档无法直接预览,请下载查看。</p>
      <a :href="fileUrl" v-if="!isDocShow">下载文件</a>
      <vue-office-excel
      <vue-office-excel v-else
        :src="fileUrl"
        :options="options"
        style="height: 100vh;"
@@ -34,9 +34,25 @@
      <a :href="fileUrl">下载文件</a>
    </div>
    <div v-if="isCsv">
      <p>CSV 文件无法直接预览,请下载查看。</p>
      <a :href="fileUrl">下载文件</a>
      <div id="teacherPaperAnswer"></div>
      <p v-if="csvList.length==0">CSV 文件无法直接预览,请下载查看。</p>
      <a :href="fileUrl" v-if="csvList.length==0">下载文件</a>
      <el-tabs type="border-card" v-if="csvList.length>0" tab-position="bottom">
        <el-tab-pane :label="item.sheetName" v-for="(item,index) in csvList" :key="index">
          <el-table :data="item.tableData" height="75vh">
            <el-table-column :label="m.label" :prop="m.prop" v-for="(m,i) in item.column" :key="i" min-width="120px" show-overflow-tooltip>
              <template slot-scope="scope" slot="header">
                <div>
                  <el-tooltip  :content="m.label" placement="top">
                    <div class="oneLine">
                      <span>{{m.label}}</span>
                    </div>
                  </el-tooltip>
                </div>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </div>
    <div v-if="!isSupported">
      <p>不支持的文件格式</p>
@@ -51,8 +67,6 @@
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
import Papa from 'papaparse';
import jschardet from 'jschardet'
export default {
  components: {
    VueOfficeDocx,
@@ -80,11 +94,18 @@
        beforeTransformData: (workbookData) => {return workbookData}, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
        transformData: (workbookData) => {return workbookData}, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
      },
      csvList:[],//csv文件数据
      imgUrl:''
    }
  },
  computed: {
    isImage() {
      return /\.(jpg|jpeg|png|gif)$/i.test(this.fileUrl);
      let state = /\.(jpg|jpeg|png|gif)$/i.test(this.fileUrl)
      this.imgUrl = this.fileUrl
      if(state){
        this.imgUrl = this.fileUrl.replaceAll('word', 'img')
      }
      return state;
    },
    isPdf() {
      return /\.pdf$/i.test(this.fileUrl);
@@ -93,7 +114,15 @@
      return /\.(doc|docx)$/i.test(this.fileUrl);
    },
    isXls(){
      return /\.(xls|xlsx)$/i.test(this.fileUrl);
      let state = /\.(xls|xlsx)$/i.test(this.fileUrl)
      if(state){
        if(/\.(xlsx)$/i.test(this.fileUrl)){
          this.options.xls = false
        }else{
          this.options.xls = true
        }
      }
      return state;
    },
    isZipOrRar() {
      return /\.(zip|rar)$/i.test(this.fileUrl);
@@ -114,6 +143,7 @@
    renderedHandler() {
        console.log("渲染完成")
        this.isDocShow = true
        this.resetStyle()
    },
    errorHandler() {
        console.log("渲染失败")
@@ -123,34 +153,73 @@
      this.$axios.post(this.$api.insOrderPlan.preview, {
        id: this.currentFile.id,
      }).then( res => {
        console.log(res.data)
        let arr = res.data
        arr = arr.map(m=>{
          let obj = {
            sheetName:m.sheetName,
            tableData:[],
            column:[]
          }
          obj.tableData = this.formatCSVToTable(m.content.replaceAll('null',' '))
          // .replaceAll('MIN','=MIN').replaceAll('MAX','=MAX').replaceAll('AVERAGE','=AVERAGE')
          for (let item in obj.tableData[0]) {
            obj.column.push({
              label: item,
              prop: item,
            })
          }
          return obj
        })
        this.csvList = arr
      }).catch( err => {
        console.log(err)
      })
    },
    async main(){
      //渲染表格
      this.paintingTable(criteriaAnswer,"teacherPaperAnswer"); //用id定位渲染目标
    },
    paintingTable(File, location) {
        $("#" + location + "").empty();
        let table = '<table class="table table-bordered" style="zoom:0.8";>';
        for (let j = 0; j < File.length; j++) {
            if (j == 0) {
                table += '<thead><tr style="white-space: nowrap;"><th scope="col">#</th>';
                for (let k in File[j]) {
                    table += '<th scope="col">' + k + '</th>';
    formatCSVToTable(str){
      const result = [];
      const jsonObj = str.split("\n");
      let arrHeader = [];
      for (const i in jsonObj) {
        if (typeof jsonObj[i] === 'string' && jsonObj[i].length > 0) {
          const row = `${jsonObj[i]}`;
          if (row.trim().length > 0) {
            const kv = jsonObj[i].split(',');
            if (i == 0) {
              // 获取column表头
              arrHeader = kv;
            } else {
              const obj = {};
              for (let index = 0; index < arrHeader.length; index++) {
                // 组装表格数据
                const name = String(arrHeader[index]);
                if (!arrHeader[index]) continue
                if (!obj[name]) {
                  try {
                    if (kv[index]) {
                      obj[name] = String(kv[index]);
                    } else {
                      obj[name] = '';
                    }
                  } catch (err) {
                    obj[name] = '';
                  }
                }
                table += '</tr></thead><tbody style="white-space: pre;">';
              }
              result.push(obj);
            }
            table += '<tr><th scope="row" style="vertical-align: middle;">' + Number(j + 1) + '</th>';
            for (let k in File[j]) {
                table += '<td style="vertical-align: middle; padding:0 20px; border: inset;background:#FFFFFF;"><div style="text-align:left;">' + File[j][k] + '</div></td>';
            }
            table += '</tr>';
          }
        }
        table += '</tbody>';
        $("#" + location + "").append(table);
      }
      return result
    },
    resetStyle(){
      const elements = document.querySelectorAll('[style*="pt"]');
      for (const element of elements) {
        const style = element.getAttribute('style');
        if (!!style) {
          element.setAttribute('style', style.replace(/pt/g, 'px'));
        }
      }
    },
  }
}
@@ -160,4 +229,10 @@
img {
  max-width: 100%;
}
.oneLine {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
</style>