| | |
| | | </div> |
| | | <div v-if="isFilePreviewOpen(file)" class="docx-preview"> |
| | | <div v-if="isReviewFile(file) && getFileUrl(file)"> |
| | | <div :ref="el => setDocxContainer(file, el)" v-if="isDocxFile(file)" style="width: 100%; height: 600px; overflow: auto;"></div> |
| | | <vue-office-docx :src="getFileUrl(file)" style="width: 100%; height: 600px;" v-if="isDocxFile(file)"/> |
| | | <vue-office-excel :src="getFileUrl(file)" style="width: 100%; height: 600px;" v-if="isXlsxFile(file)"/> |
| | | <vue-office-pdf :src="getFileUrl(file)" style="width: 100%; height: 600px;" v-if="isPdfFile(file)"/> |
| | | <template v-if="isTxtFile(file)"> |
| | |
| | | </div> |
| | | <div v-if="isFilePreviewOpen(file)" class="docx-preview"> |
| | | <div v-if="isReviewFile(file) && getFileUrl(file)"> |
| | | <div :ref="el => setDocxContainer(file, el)" v-if="isDocxFile(file)" style="width: 100%; height: 600px; overflow: auto;"></div> |
| | | <vue-office-docx :src="getFileUrl(file)" style="width: 100%; height: 600px;" v-if="isDocxFile(file)"/> |
| | | <vue-office-excel :src="getFileUrl(file)" style="width: 100%; height: 600px;" v-if="isXlsxFile(file)"/> |
| | | <vue-office-pdf :src="getFileUrl(file)" style="width: 100%; height: 600px;" v-if="isPdfFile(file)"/> |
| | | <template v-if="isTxtFile(file)"> |
| | |
| | | </PageWrapper> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { defineComponent, reactive, ref, onMounted, nextTick } from 'vue'; |
| | | import { defineComponent, reactive, ref, onMounted } from 'vue'; |
| | | import { PageWrapper } from '/@/components/Page'; |
| | | import { message } from 'ant-design-vue'; |
| | | import { useRoute, useRouter } from 'vue-router'; |
| | | import { defHttp } from '/@/utils/http/axios'; |
| | | import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; |
| | | import { renderAsync } from 'docx-preview'; |
| | | 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'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'DescDetailKehu', |
| | | components: { PageWrapper, VueOfficeExcel, VueOfficePdf }, |
| | | components: { PageWrapper, VueOfficeDocx, VueOfficeExcel, VueOfficePdf }, |
| | | setup() { |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | |
| | | const filePreviewState = reactive<Record<string, boolean>>({}); |
| | | const txtContentMap = reactive<Record<string, string>>({}); |
| | | const txtLoadingMap = reactive<Record<string, boolean>>({}); |
| | | const docxContainerMap = reactive<Record<string, HTMLElement | null>>({}); |
| | | const docxRenderedMap = reactive<Record<string, boolean>>({}); |
| | | |
| | | // 加载客户数据 |
| | | const loadCustomerData = async () => { |
| | |
| | | return !!txtLoadingMap[key]; |
| | | }; |
| | | |
| | | // 渲染 DOCX 文件 |
| | | const renderDocx = async (file: any, container: HTMLElement) => { |
| | | const fileId = getFileKey(file); |
| | | if (!fileId || !container || docxRenderedMap[fileId]) return; |
| | | |
| | | // 标记为正在渲染,避免重复渲染 |
| | | docxRenderedMap[fileId] = true; |
| | | |
| | | try { |
| | | const url = getFileUrl(file); |
| | | if (!url) { |
| | | docxRenderedMap[fileId] = false; // 重置状态 |
| | | throw new Error('DOCX 文件地址不存在'); |
| | | } |
| | | |
| | | const response = await fetch(url); |
| | | if (!response.ok) { |
| | | docxRenderedMap[fileId] = false; // 重置状态 |
| | | throw new Error(`请求失败:${response.status}`); |
| | | } |
| | | |
| | | const arrayBuffer = await response.arrayBuffer(); |
| | | // 确保容器存在且可见 |
| | | if (container && container.parentElement) { |
| | | // 清空容器内容,避免重复渲染 |
| | | container.innerHTML = ''; |
| | | await renderAsync(arrayBuffer, container); |
| | | } |
| | | } catch (error) { |
| | | console.error('DOCX 文件渲染失败', error); |
| | | docxRenderedMap[fileId] = false; // 重置状态以便重试 |
| | | message.error('DOCX 文件预览失败'); |
| | | } |
| | | }; |
| | | |
| | | // 设置 DOCX 容器引用 |
| | | const setDocxContainer = (file: any, el: any) => { |
| | | const fileId = getFileKey(file); |
| | | if (!fileId) return; |
| | | |
| | | if (el) { |
| | | docxContainerMap[fileId] = el; |
| | | // 如果预览已打开且未渲染,则在 nextTick 后渲染 |
| | | if (filePreviewState[fileId] && !docxRenderedMap[fileId]) { |
| | | nextTick(() => { |
| | | if (docxContainerMap[fileId] && filePreviewState[fileId]) { |
| | | renderDocx(file, el); |
| | | } |
| | | }); |
| | | } |
| | | } else { |
| | | docxContainerMap[fileId] = null; |
| | | } |
| | | }; |
| | | |
| | | // 切换文件预览状态 |
| | | const toggleFilePreview = (file: any) => { |
| | | const fileId = getFileKey(file); |
| | |
| | | // 打开 TXT 时加载内容 |
| | | if (nextState && isTxtFile(file) && !txtContentMap[fileId]) { |
| | | fetchTxtContent(file); |
| | | } |
| | | |
| | | // 打开 DOCX 时渲染 |
| | | if (nextState && isDocxFile(file)) { |
| | | nextTick(() => { |
| | | const container = docxContainerMap[fileId]; |
| | | if (container && !docxRenderedMap[fileId]) { |
| | | renderDocx(file, container); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | |
| | | isFilePreviewOpen, |
| | | formatPrice, |
| | | formatRanking, |
| | | setDocxContainer, |
| | | }; |
| | | }, |
| | | }); |