From de61b2ced1cea023d19e42541bdcdaf4bfcf9451 Mon Sep 17 00:00:00 2001 From: eternallycyf <969475322@qq.com> Date: Sat, 14 Dec 2024 10:08:04 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(ims-view-pc):=20add=20FileView?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/FileViewer/FileView.tsx | 217 ++++++++++++++++++ .../src/components/FileViewer/FileViewer.tsx | 99 ++++++++ .../src/components/FileViewer/MarkDown.tsx | 34 +++ .../components/FileViewer/demo/constant.ts | 88 +++++++ .../src/components/FileViewer/demo/index.tsx | 58 +++++ .../src/components/FileViewer/demo/utils.ts | 69 ++++++ .../src/components/FileViewer/index.less | 67 ++++++ .../src/components/FileViewer/index.md | 2 +- .../src/components/FileViewer/index.tsx | 2 + .../src/components/FileViewer/interface.ts | 0 packages/ims-view-pc/src/index.ts | 2 + 11 files changed, 637 insertions(+), 1 deletion(-) create mode 100644 packages/ims-view-pc/src/components/FileViewer/FileView.tsx create mode 100644 packages/ims-view-pc/src/components/FileViewer/FileViewer.tsx create mode 100644 packages/ims-view-pc/src/components/FileViewer/MarkDown.tsx create mode 100644 packages/ims-view-pc/src/components/FileViewer/demo/constant.ts create mode 100644 packages/ims-view-pc/src/components/FileViewer/demo/index.tsx create mode 100644 packages/ims-view-pc/src/components/FileViewer/demo/utils.ts create mode 100644 packages/ims-view-pc/src/components/FileViewer/index.less create mode 100644 packages/ims-view-pc/src/components/FileViewer/index.tsx create mode 100644 packages/ims-view-pc/src/components/FileViewer/interface.ts diff --git a/packages/ims-view-pc/src/components/FileViewer/FileView.tsx b/packages/ims-view-pc/src/components/FileViewer/FileView.tsx new file mode 100644 index 0000000..10e598e --- /dev/null +++ b/packages/ims-view-pc/src/components/FileViewer/FileView.tsx @@ -0,0 +1,217 @@ +import { Image, Skeleton } from 'antd'; +import cx from 'classnames'; +import { renderAsync } from 'docx-preview'; +import type { CSSProperties } from 'react'; +import { PureComponent } from 'react'; +import { OutTable } from 'react-excel-renderer'; +import './index.less'; +import MarkDown from './MarkDown'; + +interface IProps { + styles?: CSSProperties; + src?: string; + base64?: string; + [onherProps: string]: any; +} + +const txtFileTypes = [ + 'txt', + 'json', + 'js', + 'css', + 'java', + 'py', + 'html', + 'jsx', + 'ts', + 'tsx', + 'xml', + 'md', + 'log', +]; + +class FileView extends PureComponent { + constructor(props: IProps | Readonly) { + super(props); + this.state = { + pdfSrc: '', + loading: false, + text: '', + }; + } + componentDidMount() { + const { src, base64 } = this.props; + if (src) { + this.showPDFBySrc(src); + } else if (base64) { + this.showPDFByBase64(base64); + } + } + componentwillUnmount() { + URL.revokeObjectURL(this.state.pdfSrc); + } + //通过src展示 + showPDFBySrc = async (src: string) => { + const { fileType } = this.props; + if (fileType == 'pdf') { + try { + this.setState({ + loading: true, + }); + this.setState({ + pdfSrc: src, + loading: false, + }); + } catch (err) {} + } + + if (fileType == 'word') { + // const url = `xxxxx/${src}`; + // const blob = await axios.get(url, { + // responseType: 'blob' + // }) + // renderAsync( + // blob, + // document.getElementById("file-preview-modal") as HTMLDivElement, + // null as unknown as HTMLDivElement, + // { + // className: "docx", // 默认和文档样式类的类名/前缀 + // inWrapper: true, // 启用围绕文档内容渲染包装器 + // ignoreWidth: false, // 禁止页面渲染宽度 + // ignoreHeight: false, // 禁止页面渲染高度 + // ignoreFonts: false, // 禁止字体渲染 + // breakPages: true, // 在分页符上启用分页 + // ignoreLastRenderedPageBreak: true, //禁用lastRenderedPageBreak元素的分页 + // experimental: false, //启用实验性功能(制表符停止计算) + // trimXmlDeclaration: true, //如果为真,xml声明将在解析之前从xml文档中删除 + // debug: false, // 启用额外的日志记录 + // }, + // ); + } + }; + + //base64转blob + dataURItoBlob = (dataURI: string) => { + const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // mime类型 + const byteString = atob(dataURI.split(',')[1]); //base64 解码 + const arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组 + const intArray = new Uint8Array(arrayBuffer); //创建视图 + for (let i = 0; i < byteString.length; i++) { + intArray[i] = byteString.charCodeAt(i); + } + return new Blob([intArray], { type: mimeString }); + }; + + // 转baffer + readBuffer = async (file: any): Promise => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = (loadEvent: any) => resolve(loadEvent.target.result); + reader.onerror = (e) => reject(e); + reader.readAsArrayBuffer(file); + }); + }; + + // 转文本string + readText = async (buffer: Buffer): Promise => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = (loadEvent: any) => resolve(loadEvent.target.result); + reader.onerror = (e) => reject(e); + reader.readAsText(new Blob([buffer]), 'utf-8'); + }); + }; + + //通过base64展示 + showPDFByBase64 = async (content: string) => { + const { fileType } = this.props; + const blob = this.dataURItoBlob(content); + const fileUrl = URL.createObjectURL(blob); + this.setState({ + pdfSrc: fileUrl, + loading: false, + }); + + if (txtFileTypes.includes(fileType)) { + const Buffer = await this.readBuffer(blob); + const text = await this.readText(Buffer); + this.setState({ + text, + }); + } + + // 当使用旧版浏览器时 需要兼容 globalThis + if (fileType === 'docx') { + setTimeout(() => { + renderAsync( + blob, + document.getElementById('file-preview-modal') as HTMLDivElement, + null as unknown as HTMLDivElement, + { + className: 'docx', // 默认和文档样式类的类名/前缀 + inWrapper: true, // 启用围绕文档内容渲染包装器 + ignoreWidth: false, // 禁止页面渲染宽度 + ignoreHeight: false, // 禁止页面渲染高度 + ignoreFonts: false, // 禁止字体渲染 + breakPages: true, // 在分页符上启用分页 + ignoreLastRenderedPageBreak: true, //禁用lastRenderedPageBreak元素的分页 + experimental: false, //启用实验性功能(制表符停止计算) + trimXmlDeclaration: true, //如果为真,xml声明将在解析之前从xml文档中删除 + debug: false, // 启用额外的日志记录 + }, + ); + }, 0); + } + }; + + render() { + const { styles, className, fileType, txtFileTypes, excelData } = this.props; + const { loading, pdfSrc, text } = this.state; + const src = `${pdfSrc}`; + + if (loading) { + return ; + } + + if (fileType == 'docx') { + return
; + } + + if (fileType == 'xlsx') { + return ( + + ); + } + + if (fileType == 'png' || fileType == 'jpg') { + return ( +
+ +
+ ); + } + + if (txtFileTypes?.includes(fileType)) { + const newText = ` +~~~${fileType} +${text} +~~~ +`; + return ; + } + + if (fileType == 'pdf') { + return ( +