<template>
  <div class="viewItemFile">

    <!-- 预览文件 -->
    <el-dialog width="80%" class="viewItemFileDialog" :title="title" v-model='dialogVisible' :before-close="handleClose"
      :close-on-click-modal="false" :close-on-press-escape="false" draggable>
      <div class="pdf-controls"
        v-if="props.type == 'pdf' || props.type == 'docx' || props.type == 'doc' || props.type == 'xlsx' || props.type == 'bin'">
        <el-button size="small" @click="toggleFullscreen" circle>
          <img v-if="!fullscreen" src="@/assets/images/qvan.png" alt="">
          <img v-else src="@/assets/images/tuiqvan.png" alt="">
        </el-button>
      </div>
      <div class="image"
        v-if="props.type == 'JPG' || props.type == 'jpg' || props.type == 'JPEG' || props.type == 'jpeg' || props.type == 'PNG' || props.type == 'png'">
        <div>
          <img style="display: block; max-width: 100%; margin: 0 auto" :src="imgUrl" alt="" />
        </div>
      </div>
      <div v-loading="loading" element-loading-text="正在加载报告..." element-loading-background="rgba(122, 122, 122, 0.8)"
        class="docWrap" v-if="props.type == 'docx' || props.type == 'doc'">
        <!-- 预览文件的地方（用于渲染） -->
        <div ref="file" :class="{ 'fullscreen-doc': fullscreen }"></div>
      </div>
      <div v-if="props.type == 'xlsx' || props.type == 'xls'" v-loading="loading" element-loading-text="正在加载报告..."
        element-loading-background="rgba(122, 122, 122, 0.8)" class="docWrap">
        <div class="tab">
          <el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
            <el-radio-button v-for="(item, index) in excel.sheetNames" :key="index" :label="item"></el-radio-button>
          </el-radio-group>
        </div>
        <div style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;"
          :class="{ 'fullscreen-xlsx': fullscreen }">
          <div v-html="excel.SheetActiveTable" style="padding: 10px 15px"></div>
        </div>
      </div>
      <div v-if="props.type == 'pdf'">
        <iframe :src="pdfurl" :class="{ 'fullscreen-iframe': fullscreen }" type="application/x-google-chrome-pdf"
          width="100%" :height="fullscreen ? 'calc(100vh - 55px)' : '800px'" />
      </div>
      <div v-if="props.type === 'bin'" v-loading="loading" class="hex-container"
        :class="{ 'fullscreen-bin': fullscreen }">
        <div class="scroller">
          <el-scrollbar :height="fullscreen?'90vh':'54vh'">
            <pre v-for="(item, index) in visibleChunks" :key="hexContent.currentChunk + '-' + index"
              class="hex-content">{{ item.content }}</pre>
          </el-scrollbar>
        </div>
        <div class="pagination-control">
          <el-pagination layout="prev, pager, next" :current-page="hexContent.currentChunk + 1"
            :page-size="hexContent.chunkSize" :total="hexContent.rawData.length" :pager-count="5"
            @current-change="handlePageChange" />
        </div>
      </div>
      <div v-if="props.type === 'pptx'" v-loading="loading" class="ppt-container">
        <div class="ppt-controls">
          <el-button-group>
            <el-button size="small" @click="prevSlide">上一页</el-button>
            <el-button size="small" @click="nextSlide">下一页</el-button>
            <el-button size="small" @click="toggleFullscreen">全屏</el-button>
          </el-button-group>
        </div>
        <div ref="pptViewer" class="ppt-viewer"></div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, nextTick, onMounted, getCurrentInstance, reactive, toRefs, onBeforeUnmount, computed } from 'vue'
import * as docx from 'docx-preview'
import * as XLSX from "xlsx";
import PptxGenJS from 'pptxgenjs';
import axios from 'axios';
// import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
const props = defineProps({
  showTime: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: false
  },

  url: {
    type: String,
    default: ''
  },
  type: {
    type: String,
    default: 'image'
  }
});
const { proxy } = getCurrentInstance();
const typeName = ref(props.type);
const imgUrl = ref('');
const srcList = ref();
const loading = ref(false);
const pdfurl = ref('');
const dialogVisible = ref(props.showTime);
const emits = defineEmits();
const emptyTips = ref('暂无内容');
const fullscreen = ref(false);
const hexContent = ref({
  rawData: new Uint8Array(0), // 初始化为空数组
  chunkSize: 1024,
  totalChunks: 0,
  currentChunk: 0
});
const data = reactive({
  excel: {
    // 数据
    workbook: {},
    // 表名称集合
    sheetNames: [],
    // 激活项
    sheetNameActive: "",
    // 当前激活表格
    SheetActiveTable: ""
  }
})


const { excel } = toRefs(data);
const currentSlide = ref(0);
const totalSlides = ref(0);

const prevSlide = () => {
  if (currentSlide.value > 0) {
    currentSlide.value--;
    scrollToSlide();
  }
};

const nextSlide = () => {
  if (currentSlide.value < totalSlides.value - 1) {
    currentSlide.value++;
    scrollToSlide();
  }
};
const visibleChunks = computed(() => {
  // debugger
  if (!hexContent.value.rawData?.length) {
    console.log('No raw data available');
    return [];
  }
  const start = hexContent.value.currentChunk * hexContent.value.chunkSize;
  const end = start + hexContent.value.chunkSize;
  const chunkData = hexContent.value.rawData.subarray(start, end);
  const content = arrayBufferToHex(chunkData);
  return [{
    index: hexContent.value.currentChunk,
    content: content
  }];
});
const handlePageChange = (currentPage) => {
  hexContent.value.currentChunk = currentPage - 1;
  hexContent.value = { ...hexContent.value }; // 触发响应式更新
};
const scrollToSlide = () => {
  const slides = proxy.$refs.pptViewer.querySelectorAll('.slide-container');
  slides[currentSlide.value].scrollIntoView({
    behavior: 'smooth',
    block: 'center'
  });
};
onMounted(() => {
  init(props.type);
  // if (buffer.length === 0) {
  //   hexContent.value.rawData = new Uint8Array(0);
  // }
})
onBeforeUnmount(() => {
  if (hexContent.value.rawData) {
    hexContent.value.rawData = null; // 释放内存
  }
})
// 前一个页面调用的init  我在前一个页面根据文件名字后缀已经判断是什么类型的文件了
function init(type) {
  typeName.value = type;
  if (type == "JPG" || type == 'JPEG' || type == 'PNG' || type == 'jpg' || type == 'jpeg') {
    axios.request({
      method: "GET", //这个不解释了吧
      url: props.url, //路径
      responseType: "blob", //告诉服务器想到的响应格式
      headers: {
        Accept: "application/octet-stream",
      },
    })
      .then((res) => {
        if (res) {
          let blob = new Blob([res.data], { type: "image/jpg" });
          const imageUrl = URL.createObjectURL(blob);
          imgUrl.value = imageUrl;
          srcList.value = [imageUrl],
            loading.value = true;
        } else {
          // Message.error({ title: "失败", message: "接口请求失败" });
          loading.value = false;
        }
      })
      .catch(function (error) {
        // Message.error({ title: "失败", message: "接口请求失败" });

        loading.value = false;
      });

  } else if (type == "pdf") {
    axios.request({
      method: "GET", //这个不解释了吧
      url: props.url,//路径
      responseType: "blob", //告诉服务器想到的响应格式
      headers: {
        "Content-Type": "application/pdf;charset=UTF-8",
      },
    })
      .then((res) => {
        if (res) {
          let blob = new Blob([res.data], { type: "application/pdf" });
          const url = URL.createObjectURL(blob);
          loading.value = false;
          pdfurl.value = url;
        } else {
          // Message.error({ title: "失败", message: "接口请求失败" });
          loading.value = false;
        }
      })
      .catch(function (error) {
        // Message.error({ title: "失败", message: "接口请求失败" });
        loading.value = false;
      });

  } else if (type == "xlsx" || type == "xls") {
    // //表格
    loading.value = true;
    axios.request({
      method: "GET", //这个不解释了吧
      url: props.url, //路径
      responseType: "arraybuffer", //告诉服务器想到的响应格式
      headers: {
        "Content-Type":
          "application/vnd.ms-excel;",
      }
    }).then((res) => {
      if (res) {
        loading.value = false;
        const workbook = XLSX.read(new Uint8Array(res.data), {
          type: "array",
        });
        const sheetNames = workbook.SheetNames // 工作表名称集合
        excel.value.workbook = workbook
        excel.value.sheetNames = sheetNames
        excel.value.sheetNameActive = sheetNames[0]
        getSheetNameTable(sheetNames[0])
      } else {
        // Message.error({ title: "失败", message: "接口请求失败" });
        loading.value = false;
      }
    })
      .catch(function (error) {
        // Message.error({ title: "失败", message: "接口请求失败" });
        loading.value = false;
      });
  } else if (type == "docx" || type == "doc") {
    loading.value = true;
    axios.request({
      method: "GET", //这个不解释了吧
      url: props.url, //路径
      responseType: "blob", //告诉服务器想到的响应格式
    })
      .then((res) => {

        if (res) {
          docx.renderAsync(res.data, proxy.$refs.file);
          loading.value = false;
        } else {
          loading.value = false;
        }
      })
      .catch(function (error) {
        loading.value = false;
      });
  } else if (type === "bin") {

    loading.value = true;
    axios.request({
      method: "GET",
      url: props.url,
      responseType: "arraybuffer",
    }).then((res) => {
      if (res.data) {
        const buffer = new Uint8Array(res.data);
        hexContent.value.rawData = new Uint8Array(buffer); // 保持响应式引用
        hexContent.value.totalChunks = Math.ceil(buffer.length / 1024);
        hexContent.value.currentChunk = 0;
        loading.value = false;
      }
    }).catch(() => {
      loading.value = false;
    });
  } else if (type === "pptx") {
    // debugger
    loading.value = true;
    axios.request({
      method: "GET",
      url: props.url,
      responseType: "arraybuffer",
    }).then(async (res) => {
      if (res.data) {
        // 初始化PPTX实例
        const pptx = new PptxGenJS();

        // 加载PPTX数据
        await pptx.load(res.data);

        // 获取所有幻灯片
        const slides = pptx.getSlides();

        // 清空容器
        proxy.$refs.pptViewer.innerHTML = '';

        // 渲染每页幻灯片
        slides.forEach((slide, index) => {
          const slideDiv = document.createElement('div');
          slideDiv.className = 'slide-container';
          slideDiv.innerHTML = `
                    <div class="slide-content">
                        ${slide.getPageSVG()} <!-- 获取SVG内容 -->
                        <div class="slide-number">Page ${index + 1}/${slides.length}</div>
                    </div>
                `;
          proxy.$refs.pptViewer.appendChild(slideDiv);
        });

        loading.value = false;
      }
    }).catch(() => {
      loading.value = false;
      ElMessage.error('PPT加载失败');
    });
  }

  dialogVisible.value = true;
}

function getSheetNameTable(sheetName) {
  try {
    // 获取当前工作表的数据
    const worksheet = excel.value.workbook.Sheets[sheetName]
    // 转换为数据  1.json数据有些问题，2.如果是html那么样式需修改
    let htmlData = XLSX.utils.sheet_to_html(worksheet, { header: '', footer: '' })
    htmlData = htmlData === '' ? htmlData : htmlData.replace(/<table/, '<table class="default-table" border="1px solid #ccc" cellpadding="0" cellspacing="0"')
    // 第一行进行改颜色
    htmlData = htmlData === '' ? htmlData : htmlData.replace(/<tr/, '<tr style="background:#b4c9e8"')
    excel.value.SheetActiveTable = htmlData
  } catch (e) {
    // 如果工作表没有数据则到这里来处理
    excel.value.SheetActiveTable = '<h4 style="text-align: center">' + emptyTips.value + '</h4>'
  }
}
// 新增转换方法
function arrayBufferToHex(buffer) {
  // debugger
  return Array.from(buffer)
    .map(byte => byte.toString(16).padStart(2, '0'))
    .join(' ')
    .replace(/([\da-f]{2} ){16}/g, '$&\n'); // 每16字节换行
}
function handleClose() {
  emits('update', false)
}

const toggleFullscreen = () => {
  fullscreen.value = !fullscreen.value;
  nextTick(() => {
    if (fullscreen.value) {
      document.documentElement.style.overflow = 'hidden';
      if (props.type == 'pdf') {
        pdfurl.value = pdfurl.value.split('#')[0] + '#zoom=fit';
      }
    } else {
      document.documentElement.style.overflow = '';
    }
  });
};
</script>

<style lang="scss" scoped>
.viewItemFile {
  .image {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;

    div {
      height: 600px;
      width: 600px;
    }
  }

  .divContent {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  // :deep(.el-dialog) {
  //   margin: 0 !important;
  //   height: 100vh !important;
  // .el-dialog__footer {
  //   margin-bottom: 30px;
  //   padding: 0px;
  // }
  // }
  :deep(.el-dialog__body) {
    height: 96%;
    width: 100%;
    padding: 0;
    overflow: auto;
  }
}

.viewItemFile {
  .file-pre {
    height: calc(100vh - 40px);
    padding: 20px;

    .table-html-wrap v-deep table {
      border-right: 1px solid #e8eaec;
      border-bottom: 1px solid #e8eaec;
      border-collapse: collapse;
      margin: auto;
    }

    .table-html-wrap v-deep 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 {
      // height: calc(100vh - 40px);;
    }

    .el-tabs--border-card>.el-tabs__content {
      overflow: auto;
      height: calc(100vh - 110px);
    }
  }

  :deep(table) {
    width: 100% !important;
    border-collapse: collapse !important;
    border-spacing: 0 !important;
    text-align: center !important;
    border: 0px !important;
    overflow-x: auto !important;
  }

  :deep(table tr td) {
    /* border: 1px solid gray !important; */
    border-right: 1px solid gray !important;
    border-bottom: 1px solid gray !important;
    width: 300px !important;
    height: 33px !important;
  }

  /**整体样式 */
  :deep(.excel-view-container) {
    background-color: #ffffff;
  }

  /**标题样式 */
  :deep(.class4Title) {
    font-size: 22px !important;
    font-weight: bold !important;
    padding: 10px !important;
  }

  /**表格表头样式 */
  :deep(.class4TableTh) {
    /* font-size: 14px !important; */
    font-weight: bold !important;
    padding: 2px !important;
    background-color: #ccc !important;
  }
}

html body {
  width: 100%;
  height: 100vh;
  margin: 0;
}

.docWrap {
  height: calc(100vh - 150px);
  overflow: auto;
}

:deep(.el-loading-spinner .el-loading-text) {
  color: #079263;
}

.hex-container {
  height: 600px;
  overflow: auto;
  padding: 10px;
  background: #f8f8f8;
  border: 1px solid #ddd;

  pre {
    font-family: monospace;
    white-space: pre-wrap;
    word-break: break-all;
    margin: 0;
    color: #333;
  }
}

.ppt-viewer {
  width: 80%;
  margin: 0 auto;
  background: white;

  .slide-container {
    margin-bottom: 20px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

    .slide-content {
      position: relative;
      padding-top: 75%; // 默认4:3比例

      svg {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
      }
    }

    &.widescreen {
      .slide-content {
        padding-top: 56.25%; // 16:9比例
      }
    }
  }
}

//docx预览调整
:deep(.docx-wrapper) {
  padding: 10px !important;
}

:deep(.docx-wrapper>section.docx) {
  width: 100% !important;
}

.fullscreen-doc {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  z-index: 9999;
  background: white;
  overflow: auto;
}

.docWrap {
  height: calc(100vh - 150px);
  overflow: auto;
}

.pdf-controls {
  position: fixed;
  right: 117px;
  top: 12px;
  z-index: 10000;
  background: rgba(255, 255, 255, 0.8);
  padding: 5px;
  border-radius: 20px;
}

.fullscreen-iframe {
  position: fixed !important;
  top: 0 !important;
  /* 调整为0 */
  left: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  /* 调整为100vh */
  z-index: 9999;
  background: white;
  border: none;
}

/* 调整对话框全屏样式 */
.viewItemFileDialog.fullscreen {
  width: 100vw !important;
  max-width: 100vw !important;
  height: 100vh !important;
  margin: 0 !important;
  top: 0 !important;

  .el-dialog__body {
    height: 100vh !important;
    /* 调整为100vh */
    padding: 0 !important;
  }
}

.fullscreen-xlsx {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  z-index: 9999;
  background: white;
  overflow: auto;
}

.fullscreen-bin {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  z-index: 9999;
  background: white;
  overflow: auto;
}

.hex-container {
  .scroller {
    // height: calc(54vh);
    border: 1px solid #ebeef5;
    border-radius: 4px;

    .hex-content {
      // font-family: 'Fira Code', monospace;
      font-size: 14px;
      line-height: 1.5;
      padding: 12px;
      background-color: #fafafa;
      counter-increment: line;
      color: #333;

      &::before {
        // content: counter(line, decimal-leading-zero) ": ";
        color: #666;
        margin-right: 1em;
      }
    }
  }

  .pagination-control {
    margin-top: 12px;
    padding: 8px;
    background: #fff;
    border-top: 1px solid #ebeef5;
  }
}
</style>
