|
|
@@ -1,227 +1,164 @@
|
|
|
-<h2 id="rSVWk">1. 组件概述</h2>
|
|
|
-ViewFile 是一个功能强大的文件预览组件,支持多种文件格式的在线预览,包括文档、表格、演示文稿、图片和文本文件等。该组件能够根据文件类型自动选择合适的渲染器进行内容展示,为用户提供便捷的文件预览体验。该项目基于 Vue 3.5 开发,请确保您的项目使用 Vue 3.x 版本。
|
|
|
-
|
|
|
-<h2 id="SK0VG">2. 组件结构</h2>
|
|
|
-ViewFile 组件采用模块化设计,主要包含以下部分:
|
|
|
-
|
|
|
-```plain
|
|
|
-view_file/
|
|
|
-├── index.vue # 主组件入口
|
|
|
-├── index.less # 样式文件
|
|
|
-├── util.js # 工具函数
|
|
|
-├── renders.js # 渲染器注册
|
|
|
-└── vendors/ # 各类型文件渲染器
|
|
|
- ├── image/ # 图片渲染
|
|
|
- ├── other/ # 不支持预览的文件处理
|
|
|
- ├── pdf/ # PDF渲染
|
|
|
- ├── pptx/ # PPT渲染
|
|
|
- ├── text/ # 文本渲染
|
|
|
- └── xlsx/ # Excel渲染
|
|
|
- └── colz/ # Colz渲染
|
|
|
-```
|
|
|
-
|
|
|
-<h2 id="shZJb">3. 使用方法</h2>
|
|
|
-<h3 id="i1B2h">3.1 基本用法</h3>
|
|
|
-1. 安装依赖包
|
|
|
+# huijia-viewfile
|
|
|
|
|
|
-| 依赖包名称 | 版本 | 用途 |
|
|
|
-| :---: | :---: | :---: |
|
|
|
-| docx-preview | 0.3.5 | Word 文档预览 |
|
|
|
-| exceljs | 4.4.0 | Excel 文件解析 |
|
|
|
-| pdfjs-dist | 5.1.91 | PDF 文档预览 |
|
|
|
-| html2canvas | 1.4.1 | HTML 转图像 |
|
|
|
-| tinycolor2 | 1.6.0 | 颜色处理 |
|
|
|
-| x-data-spreadsheet | 1.1.9 | Excel 表格渲染 |
|
|
|
-| lodash-es | 4.17.21 | JavaScript 工具库 |
|
|
|
-| element-plus | 2.9.8 | el-image 显示图片 |
|
|
|
+一个基于 Vue 3 的多格式文件预览组件,支持文档、表格、演示文稿、图片与纯文本/代码的在线预览。
|
|
|
|
|
|
+## 安装
|
|
|
|
|
|
```bash
|
|
|
-npm install docx-preview@0.3.5 exceljs@4.4.0 pdfjs-dist html2canvas@1.4.1 tinycolor2@1.6.0 x-data-spreadsheet lodash-es element-plus
|
|
|
+npm i huijia-viewfile
|
|
|
```
|
|
|
|
|
|
+或
|
|
|
+
|
|
|
```bash
|
|
|
-yarn add docx-preview@0.3.5 exceljs@4.4.0 pdfjs-dist html2canvas@1.4.1 tinycolor2@1.6.0 x-data-spreadsheet lodash-es element-plus
|
|
|
+pnpm add huijia-viewfile
|
|
|
```
|
|
|
|
|
|
+或
|
|
|
+
|
|
|
```bash
|
|
|
-pnpm add docx-preview@0.3.5 exceljs@4.4.0 pdfjs-dist html2canvas@1.4.1 tinycolor2@1.6.0 x-data-spreadsheet lodash-es element-plus
|
|
|
+yarn add huijia-viewfile
|
|
|
```
|
|
|
|
|
|
-2. 将viewFile组件源码移入项目components目录下在需要使用的页面中引入
|
|
|
+要求:Vue 3(peerDependency)。
|
|
|
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <view-file
|
|
|
- :file="fileObject"
|
|
|
- />
|
|
|
-</template>
|
|
|
+## 快速开始(全局注册)
|
|
|
|
|
|
-<script setup>
|
|
|
- import { ref } from 'vue'
|
|
|
- import ViewFile from "@/components/view_file/index.vue"
|
|
|
+在入口文件(如 `main.ts`)中安装插件,并引入样式:
|
|
|
|
|
|
- const fileObject = ref({
|
|
|
- filename: "示例文件.docx",
|
|
|
- type: "docx",
|
|
|
- fileBuffer: null // ArrayBuffer类型的文件内容
|
|
|
- })
|
|
|
-</script>
|
|
|
+```ts
|
|
|
+import { createApp } from "vue"
|
|
|
+import App from "./App.vue"
|
|
|
+
|
|
|
+import ViewFilePlugin from "huijia-viewfile"
|
|
|
+import "huijia-viewfile/style.css"
|
|
|
+
|
|
|
+createApp(App).use(ViewFilePlugin).mount("#app")
|
|
|
```
|
|
|
|
|
|
-<h3 id="kWppv">3.2 参数说明</h3>
|
|
|
-Props
|
|
|
+在页面中直接使用:
|
|
|
|
|
|
-| 参数名 | 类型 | 默认值 | 说明 | 是否必填 |
|
|
|
-| :---: | :---: | :---: | :---: | :---: |
|
|
|
-| file | Object | {} | 文件对象,包含文件名、类型和文件内容 | 是 |
|
|
|
+```vue
|
|
|
+<template>
|
|
|
+ <view-file :file="fileObject" />
|
|
|
+</template>
|
|
|
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref } from "vue"
|
|
|
|
|
|
-file 对象属性
|
|
|
+const fileObject = ref({
|
|
|
+ filename: "示例文件.pdf",
|
|
|
+ type: "pdf",
|
|
|
+ fileBuffer: null as ArrayBuffer | null,
|
|
|
+})
|
|
|
+</script>
|
|
|
+```
|
|
|
|
|
|
-| 属性名 | 类型 | 说明 | 是否必填 |
|
|
|
-| :---: | :---: | :---: | :---: |
|
|
|
-| filename | String | 文件名称 | 是 |
|
|
|
-| type | String | 文件类型(扩展名,如docx、xlsx等) | 是 |
|
|
|
-| fileBuffer | ArrayBuffer | 文件内容的二进制数据 | 是 |
|
|
|
+## Props
|
|
|
|
|
|
+### file
|
|
|
|
|
|
-<h2 id="lns5o">4. 支持的文件类型</h2>
|
|
|
-ViewFile 组件支持以下文件类型的在线预览:
|
|
|
+`file` 为一个对象,核心字段如下:
|
|
|
|
|
|
-<h3 id="HGCfn">4.1 文档类</h3>
|
|
|
-+ Word文档 :docx
|
|
|
-+ PDF文档 :pdf
|
|
|
+| 字段 | 类型 | 必填 | 说明 |
|
|
|
+| --- | --- | --- | --- |
|
|
|
+| filename | string | 建议 | 文件名(用于展示与辅助推断类型) |
|
|
|
+| type | string | 是 | 文件扩展名(不带点),如 `pdf` / `docx` / `xlsx` |
|
|
|
+| fileBuffer | ArrayBuffer \| null | 是 | 文件二进制内容(ArrayBuffer) |
|
|
|
+| size | number | 否 | 文件大小(仅用于兜底 UI 展示) |
|
|
|
+| name | string | 否 | 兜底文件名(仅用于兜底 UI 展示) |
|
|
|
|
|
|
-<h3 id="d32Wg">4.2 表格类</h3>
|
|
|
-+ Excel表格 :xlsx
|
|
|
+## 支持的文件类型
|
|
|
|
|
|
-<h3 id="DXweJ">4.3 演示文稿</h3>
|
|
|
-+ PowerPoint :pptx
|
|
|
+- 文档:`docx`、`pdf`
|
|
|
+- 表格:`xlsx`
|
|
|
+- 演示:`pptx`
|
|
|
+- 图片:`gif`、`jpg`、`jpeg`、`bmp`、`tiff`、`tif`、`png`、`svg`
|
|
|
+- 文本/代码:`txt`、`json`、`js`、`css`、`java`、`py`、`html`、`jsx`、`ts`、`tsx`、`xml`、`md`、`log`
|
|
|
|
|
|
-<h3 id="oH43n">4.4 图片类</h3>
|
|
|
-支持多种图片格式:
|
|
|
+不支持的类型会展示“该类型文件不支持在线预览”的兜底视图。
|
|
|
|
|
|
-+ gif
|
|
|
-+ jpg/jpeg
|
|
|
-+ bmp
|
|
|
-+ tiff/tif
|
|
|
-+ png
|
|
|
-+ svg
|
|
|
+## 读取文件并预览
|
|
|
|
|
|
-<h3 id="ggdtM">4.5 文本类</h3>
|
|
|
-支持多种文本和代码文件:
|
|
|
+### 读取本地文件
|
|
|
|
|
|
-+ txt(纯文本)
|
|
|
-+ json(JSON数据)
|
|
|
-+ js(JavaScript)
|
|
|
-+ css(样式表)
|
|
|
-+ java(Java代码)
|
|
|
-+ py(Python代码)
|
|
|
-+ html(HTML文档)
|
|
|
-+ jsx(React JSX)
|
|
|
-+ ts/tsx(TypeScript)
|
|
|
-+ xml(XML文档)
|
|
|
-+ md(Markdown)
|
|
|
-+ log(日志文件)
|
|
|
+组件导出了读取工具函数,推荐直接从包名导入:
|
|
|
|
|
|
-<h2 id="wc5fk">5. 示例代码</h2>
|
|
|
-<h3 id="XRxq1">5.1 从文件对象创建预览</h3>
|
|
|
```vue
|
|
|
<template>
|
|
|
- <div>
|
|
|
- <input type="file" @change="handleFileChange" />
|
|
|
- <view-file
|
|
|
- :file="fileObject"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <input type="file" @change="onChange" />
|
|
|
+ <view-file :file="fileObject" />
|
|
|
</template>
|
|
|
-<script setup>
|
|
|
-import ViewFile from "@/components/view_file/index.vue"
|
|
|
-import { readBuffer } from "@/components/view_file/util"
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref } from "vue"
|
|
|
+import { readBuffer } from "huijia-viewfile"
|
|
|
|
|
|
const fileObject = ref({
|
|
|
filename: "",
|
|
|
type: "",
|
|
|
- fileBuffer: null
|
|
|
+ fileBuffer: null as ArrayBuffer | null,
|
|
|
})
|
|
|
-
|
|
|
-const handleFileChange = async (e) => {
|
|
|
- const file = e.target.files[0]
|
|
|
- if (!file) return
|
|
|
- try {
|
|
|
- const buffer = await readBuffer(file)
|
|
|
- this.fileObject = {
|
|
|
- filename: file.name,
|
|
|
- type: file.name.split('.').pop().toLowerCase(),
|
|
|
+
|
|
|
+function onChange(e: Event) {
|
|
|
+ const input = e.target as HTMLInputElement
|
|
|
+ const f = input.files?.[0]
|
|
|
+ if (!f) return
|
|
|
+
|
|
|
+ readBuffer(f)
|
|
|
+ .then((buffer) => {
|
|
|
+ const ext = (f.name.split(".").pop() || "").toLowerCase()
|
|
|
+ fileObject.value = {
|
|
|
+ filename: f.name,
|
|
|
+ type: ext,
|
|
|
fileBuffer: buffer,
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.error('文件读取失败', error)
|
|
|
- }
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.error("读取文件失败:", err)
|
|
|
+ })
|
|
|
}
|
|
|
</script>
|
|
|
+```
|
|
|
+
|
|
|
+### 从 URL 获取文件并预览
|
|
|
|
|
|
+```ts
|
|
|
+function fetchArrayBuffer(url: string) {
|
|
|
+ return fetch(url)
|
|
|
+ .then((res) => {
|
|
|
+ if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
|
|
+ return res.arrayBuffer()
|
|
|
+ })
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
-<h3 id="GfNtc">5.2 从服务器获取文件并预览</h3>
|
|
|
-假设请求返回数据格式response.data
|
|
|
+拿到 `ArrayBuffer` 后,填充到 `fileObject.fileBuffer` 即可。
|
|
|
|
|
|
-| 属性名 | 类型 | 说明 |
|
|
|
-| :---: | :---: | :---: |
|
|
|
-| filename | String | 文件名称 |
|
|
|
-| file | Blob | 文件内容数据 |
|
|
|
+## 插槽(图片自定义渲染)
|
|
|
|
|
|
+当文件类型为图片时,提供 `image` 具名插槽,可用于自定义展示与预览交互。
|
|
|
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <view-file
|
|
|
- :file="fileObject"
|
|
|
- />
|
|
|
-</template>
|
|
|
-<script setup>
|
|
|
-import { ref, onMounted } from 'vue'
|
|
|
-import { useRoute } from 'vue-router'
|
|
|
-import ViewFile from "@/components/view_file/index.vue"
|
|
|
-import { readBuffer } from "@/components/view_file/util"
|
|
|
-import axios from 'axios'
|
|
|
-
|
|
|
-const route = useRoute()
|
|
|
-const fileObject = ref({
|
|
|
- filename: "",
|
|
|
- type: "",
|
|
|
- fileBuffer: null
|
|
|
-})
|
|
|
+插槽参数:
|
|
|
|
|
|
-const fetchFile = async (fileId) => {
|
|
|
- try {
|
|
|
- const response = await axios.get(`/api/files/${fileId}`)
|
|
|
- const name = response.data.filename
|
|
|
- // 获取文件名和类型
|
|
|
- fileObject.value.filename = name
|
|
|
- fileObject.value.type = name.split('.').pop().toLowerCase()
|
|
|
- const arrayBuffer = await readBuffer(response.data.file)
|
|
|
- fileObject.value.fileBuffer = arrayBuffer
|
|
|
- } catch (error) {
|
|
|
- console.error('文件获取失败', error)
|
|
|
- }
|
|
|
-}
|
|
|
+- `src`:当前图片 src
|
|
|
+- `srcList`:图片列表(当前实现为单图,保留扩展能力)
|
|
|
+- `index`:当前预览索引
|
|
|
+- `file`:原始 `file` 对象
|
|
|
+- `preview`:预览控制对象 `{ visible, open, close, next, prev }`
|
|
|
|
|
|
-onMounted(() => {
|
|
|
- // 从路由参数获取文件ID
|
|
|
- const fileId = route.params.fileId
|
|
|
- if (fileId) {
|
|
|
- fetchFile(fileId)
|
|
|
- }
|
|
|
-})
|
|
|
-</script>
|
|
|
+示例:
|
|
|
|
|
|
+```vue
|
|
|
+<view-file :file="fileObject">
|
|
|
+ <template #image="{ src, preview }">
|
|
|
+ <img :src="src" style="max-width: 100%; max-height: 100%" @click="preview.open(0)" />
|
|
|
+ </template>
|
|
|
+</view-file>
|
|
|
```
|
|
|
|
|
|
-<h2 id="Dc4BG">6. 注意事项</h2>
|
|
|
-1. 确保提供正确的文件类型(扩展名),组件根据扩展名选择渲染器
|
|
|
-2. 文件内容必须是 ArrayBuffer 格式
|
|
|
-3. 大文件可能会影响性能,特别是复杂的Excel或PDF文件
|
|
|
-4. 对于不支持的文件类型,组件会显示提示信息而不是尝试渲染
|
|
|
-5. 组件内部已处理异常,但建议在外部添加错误处理逻辑
|
|
|
+## 常见问题
|
|
|
|
|
|
+1. `fileBuffer` 必须是 `ArrayBuffer`,不要直接传 `Blob` / `File`。
|
|
|
+2. 传入的 `type` 建议使用真实扩展名(不带 `.`),组件会据此选择渲染器。
|
|
|
+3. 预览远端文件时注意 CORS,必要时通过后端代理获取。
|