<!--
@name: fullScreenFileLook
@description: 全屏文件预览组件
@author: zc
@time: 2024/4/16
@描述: 支持docx/excel/pdf文件预览
@引入:

    <fullScreenFileLook ref="fullScreenFileLook"></fullScreenFileLook>

    import fullScreenFileLook from "@/components/fullScreenFileLook/fullScreenFileLook.vue";

    components: {
      fullScreenFileLook,
    },
    //name:名称 url:地址  type:类型标记/docx/excel/pdf
    fullScreenFileLookClick(item){
      this.$refs['fullScreenFileLook'].initialize(item.name,item.url,item.type);
    },

-->
<template>
  <transition name="fade" mode="in-out">
    <div class="fullScreenFileLook" v-if="showType">
      <div class="fullScreenFileLook-top-button-box">
        <!--下载按钮-->
        <p class="position-download-p el-icon-download" @click="downloadOffice" v-if="!officeNullType&&officeType!='text'"></p>
        <p class="title-p">{{lookName}}</p>
        <!--关闭按钮-->
        <p class="position-off-p el-icon-circle-close" @click="outButton"></p>
      </div>
      <div class="max-img-box" ref="viewBox">
        <transition name="fade" mode="in-out">
          <vue-office-docx
            v-if="officeType === 'docx'&&!officeNullType"
            :src="lookUrl"
            :class="pdfType == 1?'':'vertical'"
            @rendered="renderedHandler"
            @error="errorHandler"
          />
          <vue-office-excel
            v-if="officeType === 'excel'&&!officeNullType"
            :src="lookUrl"
            @rendered="renderedHandler"
            @error="errorHandler"
          />
          <vue-office-pdf
            v-if="officeType === 'pdf'&&!officeNullType"
            :src="lookUrl"
            :class="pdfType == 1?'':'vertical'"
            @rendered="renderedHandler"
            @error="errorHandler"/>
          <p v-if="officeNullType" class="office-null-text">加载失败...</p>
          <video v-if="officeType === 'video'" class="video-box" :src="lookUrl" controls></video>
          <div  v-if="officeType === 'text'" class="rich-text-box" v-html="lookUrl"></div>
        </transition>
      </div>
    </div>
  </transition>
</template>
<script>
  //引入VueOfficeDocx组件
  import VueOfficeDocx from '@vue-office/docx'
  import '@vue-office/docx/lib/index.css'
  //引入VueOfficeExcel组件
  import VueOfficeExcel from '@vue-office/excel'
  import '@vue-office/excel/lib/index.css'
  //引入VueOfficePdf组件
  import VueOfficePdf from '@vue-office/pdf'
  import JSZip from 'jszip'
  export default {
    name: 'fullScreenFileLook',
    components: {
      VueOfficeDocx,
      VueOfficeExcel,
      VueOfficePdf,
    },
    data () {
      return {
        showType:false,
        officeNullType:false,
        //文档类型
        officeType:null,
        //文档名称
        lookName:"",
        //文档地址
        lookUrl:"",
        currentPage: 1,
        totalPages: 1,
        currentScale: 1.0, // 初始缩放比例
        pdfType:1,
      }
    },
    created () {

    },
    mounted () {

    },
    methods: {
      //初始化
      initialize(name,url,type){
        if(name&&url&&type){
          this.$set(this,'officeType',type);
          this.$set(this,'lookName',name);
          this.$set(this,'lookUrl',url);
          this.$set(this,'officeNullType',false);
          this.$set(this,'pdfType',1);
          this.$set(this,'showType',true);
          if(type === 'docx'){
            this._detectDocxOrientation(url);
          }
        }else{
          this.msgError('文件参数异常')
        }
      },
      // 解析 docx XML 自动判断纸张方向，设置 pdfType（1纵向 2横向）
      async _detectDocxOrientation(url) {
        try {
          const res = await fetch(url);
          const buf = await res.arrayBuffer();
          const zip = await JSZip.loadAsync(buf);
          const xmlStr = await zip.file('word/document.xml').async('string');
          const orientMatch = xmlStr.match(/w:pgSz[^/]*?w:orient="([^"]+)"/);
          if (orientMatch) {
            this.$set(this, 'pdfType', orientMatch[1] === 'landscape' ? 2 : 1);
            return;
          }
          // 无 orient 属性时比较 w:w 与 w:h
          const sizeMatch = xmlStr.match(/w:pgSz[^/]*?w:w="(\d+)"[^/]*?w:h="(\d+)"/);
          if (sizeMatch) {
            this.$set(this, 'pdfType', parseInt(sizeMatch[1]) > parseInt(sizeMatch[2]) ? 2 : 1);
          }
        } catch (e) {
          // 解析失败保持默认纵向
        }
      },
      //文件加载成功
      renderedHandler() {
        this.$set(this,'officeNullType',false);
      },
      //文件加载失败
      errorHandler() {
        this.$set(this,'officeNullType',true);
      },
      //退出按钮
      outButton(){
        this.$set(this,'showType',false);
        this.$set(this,'officeNullType',true);
        this.$set(this,'officeType',null);
        this.$set(this,'lookName','');
        this.$set(this,'lookUrl','');
      },
      //下载
      async downloadOffice() {
        // let currentDate = this.getCurrentTime()
        // 获取图片对象和画布对象
        const imgUrl = this.lookUrl
        const response = await fetch(imgUrl)
        const blob = await response.blob()
        // 创建下载链接
        const url = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = url
        link.download = this.lookName
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        // 释放 Blob URL
        window.URL.revokeObjectURL(url)
      },
    },
  }
</script>
<style scoped lang="scss">
  .vertical{
    ::v-deep .docx{
      padding:0!important;
    }
  }
  .fade-enter-active, .fade-leave-active {
    transition: opacity .3s;
  }
  .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
    opacity: 0;
  }
  .fullScreenFileLook{
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    position:fixed;
    top:0;
    left:0;
    z-index:99999;
    width:100%;
    height:100%;
    background-color: rgba(0,0,0,0.9);
    display: flex;
    flex-direction: column;
    .fullScreenFileLook-top-button-box{
      display: flex;
      height:50px;
      .title-p{
        flex:1;
        color:#fff;
        font-size:20px;
        text-align: center;
        line-height:50px;
      }
      .position-off-p{
        color:#fff;
        width:30px;
        height:30px;
        line-height:30px;
        text-align: center;
        font-size:30px;
        cursor: pointer;
        z-index: 999;
        margin:10px 40px 0 0;
      }
      .position-off-p:hover{
        color:#0183FA;
      }
      .position-download-p{
        color:#fff;
        width:30px;
        height:30px;
        line-height:30px;
        text-align: center;
        font-size:30px;
        cursor: pointer;
        z-index: 999;
        margin:10px 0 0 40px;
      }
      .position-download-p:hover{
        color:#0183FA;
      }
    }
    .max-img-box{
      flex:1;
      display: flex;
      flex-direction: column;
      overflow: scroll;
      position: relative;
      .office-null-text{
        line-height:700px;
        text-align: center;
        color:#dedede;
        font-size:16px;
      }
      .video-box{
        flex:1;
        max-height: 1030px;
      }
      .rich-text-box {
        padding:20px 100px;
        flex:1;
        background-color: #fff;
        line-height: 1.6; /* 基础行高 */
        word-break: break-word; /* 防止长单词或长链接撑破布局 */
      }

      /* 穿透样式，控制富文本内部的标签 */
      .rich-text-box ::v-deep img {
        max-width: 100% !important; /* 防止图片超出容器 */
        height: auto !important;
        display: block;
        margin: 10px auto;
      }

      .rich-text-box ::v-deep table {
        width: 100%;
        border-collapse: collapse;
      }

      .rich-text-box ::v-deep p {
        margin-bottom: 10px;
      }
    }
    //滚动条样式
    .max-img-box::-webkit-scrollbar{
      width: 6px;     /*高宽分别对应横竖滚动条的尺寸*/
      height: 6px;
    }
    .max-img-box::-webkit-scrollbar-thumb{
      border-radius: 5px;
      background: #D3D7D4;
    }
    .max-img-box::-webkit-scrollbar-track{
      -webkit-box-shadow: inset 0 0 5px #FFFFFF;
      border-radius: 0;
      background: #FFFFFF;
    }
    //滚动条样式
    ::v-deep .ofd-footer{
      padding:10px 0;
    }
    ::v-deep .ofd-body::-webkit-scrollbar{
      width: 6px;     /*高宽分别对应横竖滚动条的尺寸*/
      height: 6px;
    }
    ::v-deep .ofd-body::-webkit-scrollbar-thumb{
      border-radius: 5px;
      background: #D3D7D4;
    }
    ::v-deep .ofd-body::-webkit-scrollbar-track{
      -webkit-box-shadow: inset 0 0 5px #FFFFFF;
      border-radius: 0;
      background: #FFFFFF;
    }
  }
</style>
