FilePreviewTs 上传图片组件封装

86 阅读1分钟

FilePreviewTs

<template>
  <!-- doc -->
  <el-dialog v-model="dialogDocxValue" :title="dialogTitle" width="80%" @close="dialogDocxClose">
    <div ref="docxRef" class="word-div"></div>
  </el-dialog>

  <!-- xlsx -->
  <el-dialog v-model="dialogXlsxValue" :title="dialogTitle" width="80%" @close="dialogXlsxClose">
    <div ref="xlsxRef" class="xlsx-div">
      <el-tabs v-model="activeName" type="border-card">
        <el-tab-pane v-for="(item, index) in excelSheet" :key="index" :label="item.name" :name="item.name">
          <div class="table" v-html="item.html"></div>
        </el-tab-pane>
      </el-tabs>
    </div>
  </el-dialog>

  <!-- 图片 -->
  <el-dialog v-model="dialogImgValue" :title="dialogTitle" width="80%" @close="dialogImgClose">
    <div class="img-div">
      <el-image :src="fileData.src" :alt="fileData.fileOldName" />
    </div>
  </el-dialog>

  <!-- pdf -->
  <el-dialog v-model="dialogPdfValue" :title="dialogTitle" width="80%" @close="dialogPdfClose">
    <div class="pdf-div">
      <iframe id="pdfRef" :src="iframeUrl" frameborder="0" style="width: 100%; height: 99%"></iframe>
    </div>
  </el-dialog>
</template>
<script setup lang="ts">
import axios from 'axios';
import { defineProps, ref, reactive, computed, nextTick } from 'vue';
import { renderAsync } from 'docx-preview';
import * as XLSX from 'xlsx';
interface Props {
  dialogDocx?: boolean;
  dialogXlsx?: boolean;
  dialogTitle?: string;
}
const props: any = withDefaults(defineProps<Props>(), {
  dialogDocx: false,
  dialogTitle: '',
  dialogXlsx: false,
});
const dialogDocxValue: any = ref(false);
let dialogTitle = computed(() => {
  return props.dialogTitle;
});
const fileHtml = ref('');

const docxRef = ref<any>();
// doc 文档预览
const viewDocx = (data: any) => {
  docxRef.value = '';
  dialogDocxValue.value = true;
  console.log(data);
  if (data.src) {
    // 已上传的文件
    axios({
      url: data.src,
      method: 'get',
      responseType: 'blob',
    }).then((res) => {
      console.log(res);
      if (res.status == 200) {
        const content = res.data;
        const blob = new Blob([content]);
        nextTick(() => {
          dialogDocxValue.value = true;
          renderAsync(blob, docxRef.value);
          dialogTitle = data.fileOldName || data.name;
        });
      }
    });
  } else {
    // 本地文件
    const blob = new Blob([data.raw]);
    nextTick(() => {
      dialogDocxValue.value = true;
      renderAsync(blob, docxRef.value);
      dialogTitle = data.fileOldName || data.name;
    });
  }
};
const dialogXlsxValue: any = ref(false);
const excelSheet: any = ref([]);
const activeName = ref('');
const dialogDocxClose = () => {
  dialogDocxValue.value = false;
  docxRef.value = '';
};
// xlsx 预览
const viewXlsx = (data: any) => {
  dialogXlsxValue.value = true;
  console.log(data);
  if (data.src) {
    axios({
      url: data.src,
      method: 'get',
      responseType: 'blob',
    }).then((res) => {
      console.log(res);
      if (res.status == 200) {
        const content = res.data;
        // const blob = new Blob(content);
        const reader = new FileReader();
        reader.readAsArrayBuffer(content);
        reader.onload = function (loadEvent: any) {
          const arrayBuffer = loadEvent.target['result'];
          const workbook = XLSX.read(new Uint8Array(arrayBuffer), {
            type: 'array',
          });
          const list = [];
          const sheetNames = workbook.SheetNames;
          activeName.value = sheetNames[0];
          for (const p of sheetNames) {
            let html = '';
            try {
              html = XLSX.utils.sheet_to_html(workbook.Sheets[p]);
            } catch (e) {
              html = '';
            }
            const map = {
              name: p,
              html: html,
            };
            list.push(map);
          }
          excelSheet.value = list;
          dialogTitle = data.fileName || data.name;
        };
      }
    });
  } else {
    const blob = new Blob([data.raw]);
    const reader = new FileReader();
    reader.readAsArrayBuffer(blob);
    reader.onload = function (loadEvent: any) {
      const arrayBuffer = loadEvent.target['result'];
      const workbook = XLSX.read(new Uint8Array(arrayBuffer), {
        type: 'array',
      });
      const list = [];
      const sheetNames = workbook.SheetNames;
      activeName.value = sheetNames[0];
      for (const p of sheetNames) {
        let html = '';
        try {
          html = XLSX.utils.sheet_to_html(workbook.Sheets[p]);
        } catch (e) {
          html = '';
        }
        const map = {
          name: p,
          html: html,
        };
        list.push(map);
      }
      excelSheet.value = list;
      dialogTitle = data.fileName || data.name;
    };
  }
};

const dialogXlsxClose = () => {
  dialogXlsxValue.value = false;
  excelSheet.value = '';
  activeName.value = '';
};
const fileData: any = ref({});
const dialogImgValue: any = ref(false);
// 图片预览
const viewImg = (data: any) => {
  if (data.src) {
    // 已上传的图片
    fileData.value = data;
  } else {
    // 本地图片
    const freader = new FileReader();
    freader.readAsDataURL(data.raw);
    freader.onload = (e: any) => {
      fileData.value = {
        src: e.target.result,
        id: new Date(),
        fileName: data.fileOldName || data.name,
      };
    };
  }
  dialogTitle = data.fileOldName || data.name;
  dialogImgValue.value = true;
};
const dialogImgClose = () => {
  dialogImgValue.value = false;
};

const dialogPdfValue: any = ref(false);
const iframeUrl: any = ref('');
const pdfRef = ref<any>();
const viewPdf = (data: any) => {
  if (data.src) {
    axios({
      url: data.src,
      method: 'get',
      responseType: 'blob',
    }).then((res) => {
      if (res.status == 200) {
        // 把文件流转化为url
        iframeUrl.value = URL.createObjectURL(res.data);
        dialogPdfValue.value = true;
      }
    });
  } else {
    iframeUrl.value = URL.createObjectURL(data.raw);
    dialogPdfValue.value = true;
  }
};
const dialogPdfClose = () => {
  dialogPdfValue.value = false;
};
defineExpose({
  viewDocx,
  viewXlsx,
  viewImg,
  viewPdf,
});
</script>
<style scoped lang="scss">
.word-div {
  height: calc(70vh);
  overflow: auto;
}
.xlsx-div {
  height: calc(70vh);
  overflow: auto;
}
.img-div {
  height: calc(70vh);
  overflow: auto;
  img {
    width: 100%;
    height: 100%;
  }
}
.pdf-div {
  height: calc(70vh);
  overflow: auto;
}
</style>
<style lang="scss">
.xlsx-div {
  .table-html-wrap table {
    border-right: 1px solid #fff;
    border-bottom: 1px solid #e8eaec;
    border-collapse: collapse;
    // margin: auto;
  }

  .table-html-wrap table td {
    border-left: 1px solid #e8eaec;
    border-top: 1px solid #e8eaec;
    white-space: wrap;
    text-align: left;
    min-width: 100px;
    padding: 4px;
  }

  table {
    border-top: 1px solid #ebeef5;
    border-left: 1px solid #ebeef5;
    width: 100%;
    // overflow: auto;

    tr {
      height: 44px;
    }

    td {
      min-width: 200px;
      max-width: 400px;
      padding: 4px 8px;
      border-right: 1px solid #ebeef5;
      border-bottom: 1px solid #ebeef5;
    }
  }

  .el-tabs--border-card > .el-tabs__content {
    overflow-x: auto;
  }
}
</style>