Vue在线预览excel、word、ppt等格式数据。

目录

前言

1.安装库

         2.预览文件子组件代码

3、新建store/system.ts

4、父页面进行使用

总结


前言

 纯前端处理文件预览,包含excel、word、ppt、txt等格式,不需要后端服务器进行部署,并且内网也可以使用。


1.安装

npm install @vue-office/docx @vue-office/excel @vue-office/pdf
# 或
yarn add @vue-office/docx @vue-office/excel @vue-office/pdf

2.预览文件子组件代码

<template>
  <div class="fileView">
    <n-modal v-model:show="fileViewVisible">
      <n-card
        style="
          width: 65%;
          position: fixed;
          top: 50px;
          left: 50%;
          transform: translateX(-50%);
        "
        :title="sysStore.fileViewInfo.name"
        :bordered="true"
        size="medium"
        role="dialog"
        aria-modal="true"
      >
        <template #header-extra>
          <n-button circle @click="fileViewVisible = false">
            <template #icon>
              <n-icon>
                <Close />
              </n-icon>
            </template>
          </n-button>
        </template>
        <div>
          <iframe
            v-if="sysStore.fileViewInfo.fileType === 'txt'"
            style="width: 100%; height: calc(100vh - 190px)"
            :src="sysStore.fileViewInfo.viewUrl"
            frameborder="0"
          ></iframe>
          <vue-office-pdf
            v-if="sysStore.fileViewInfo.fileType === 'pdf'"
            style="width: 100%; height: calc(100vh - 180px)"
            :src="sysStore.fileViewInfo.viewUrl"
            frameborder="0"
          ></vue-office-pdf>
          <vue-office-docx
            v-if="sysStore.fileViewInfo.fileType === 'doc'"
            style="width: 100%; height: calc(100vh - 180px)"
            :src="sysStore.fileViewInfo.viewUrl"
            frameborder="0"
          ></vue-office-docx>
          <vue-office-excel
            v-if="sysStore.fileViewInfo.fileType === 'xlsx'"
            style="width: 100%; height: calc(100vh - 180px)"
            :src="sysStore.fileViewInfo.viewUrl"
            frameborder="0"
          ></vue-office-excel>
        </div>
      </n-card>
    </n-modal>
  </div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import useSystemStore from "@/store/system";
import { Close } from "@vicons/ionicons5";
// 引入VueOffice组件
import VueOfficeDocx from "@vue-office/docx";
import VueOfficeExcel from "@vue-office/excel";
import VueOfficePdf from "@vue-office/pdf";
// 引入相关样式
import "@vue-office/docx/lib/index.css";
import "@vue-office/excel/lib/index.css";


const sysStore = useSystemStore();

const fileViewVisible = ref(false);

const show = () => {
  fileViewVisible.value = true;
};

// 监听外部变化
watch(() => props.visible, (newVal) => {
  fileViewVisible.value = newValue
}, {
 immediate: true
})
// 暴漏show给父组件使用
defineExpose({
  show,
});
</script>
<style lang="less" scoped></style>

3、新建store/system.ts

代码如下:

import { defineStore } from "pinia";

interface State {
  fileViewInfo: any; // 文件预览信息
}

const useSystemStore = defineStore("system", {
  state: (): State => ({
    fileViewInfo: {},
  }),
  actions: {
    setFileViewInfo(val: any) {
      this.fileViewInfo = val;
    },
  },
});

export default useSystemStore;

4、父页面进行使用

 此处的需求是:点击列表的某一行数据,执行fileView方法,拿此方法的id去调用后端服务请求,获取需要的数据,包含:

 url:完整的url文件流地址
name: 文件名
 size: 文件字节大小
 mime_type: 文件对应的类型 譬如txt对应 text/plain

ps: 你可根据实际需求进行修改。 

<template>
  <n-space class="file-view" style="gap: 8px 8px" :inline="true">
    <div
      class="file-item"
      v-for="(file, index) in fileComp"
      :key="index"
      @click="fileView(file)"
    >
      <div class="file-icon">
        <img width="28" :src="file.iconIamge" alt="" />
      </div>
    </div>
  </n-space>
  <FilePreviewDialog v-model:visible="obj.showDialog" ref="filePreviewDialogRef" />
</template>
<script setup>
import { computed, ref } from "vue";
import useSystemStore from "@/store/system";
import FilePreviewDialog from "@/components/FilePreviewDialog.vue";

const filePreviewDialogRef = ref();
const props = defineProps({
  files: {
    type: [Object,Array],
    required: true,
  },
  role: {
    type: String,
  },
});

// 引入vuex
const sysStore = useSystemStore();

// 文件信息
const obj = reactive({
  showDialog: false, // 是否展示附件
  fileUrl: [] // 附件地址
})

const getIcon = (type) => {
  type = type.toLowerCase();
// fileType 类型:"doc" | "pdf" | "xlsx" | "txt" 
  let fileType = "";
  const docMap = [
    "doc",
    "docx",
    "application/msword",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  ];
  const pdfMap = ["application/pdf", "pdf"];
  const xlsxMap = [
    "application/vnd.ms-excel",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "xls",
    "xlsx",
  ];
  const textMap = ["txt", "text/plain", "text"];
  if (docMap.includes(type)) {
    fileType = "doc"
  } else if (pdfMap.includes(type)) {
    fileType = "pdf";
  } else if (xlsxMap.includes(type)) {
    fileType = "xlsx";
  } else if (textMap.includes(type)) {
    fileType = "txt";
  } else {
    fileType = "";
  }
  return {
    fileType
  };
};

// 获取文件数据
const fileView = async(item) => {
const {id} = item
const res = await getPolicy(id)
const {url,name,size,mime_type} = res.data
// 这里拿到的数据:url:完整的url文件流地址
 // name: 文件名
 //size: 文件字节大小
 // mime_type: 文件对应的类型 譬如txt对应 text/plain
// 获取文件后缀类型
const {fileType} = getIcon(mime_type)
const fileInfo = {
  name,
  fileType,
  type: mime_type,
  size,
  viewUrl: url
}
 // 更新文件信息
 sysStore.setFileViewInfo(fileInfo);

 // 先关闭
 obj.showDialog = false

// 确保dom更新后再次打卡
await nextTick()
obj.showDialog = true
};




</script>



<style lang="less" scoped>
.file-view {
  .file-item {
    display: flex;
    align-items: center;
    border: 1px solid var(--baseColor);
    padding: 8px;
    cursor: pointer;
    min-width: 240px;
    max-width: 300px;
    border-radius: 5px;
    .file-icon {
      margin-right: 5px;
    }
    .file-info {
      max-width: calc(100% - 28px);
      .file-size {
        font-size: var(--fontSizeSmall);
      }
    }
  }
}
</style>

总结

记录一下 希望能帮助到你

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值