# 文件预览功能 **本文引用的文件** - [FilePreviewPanel.vue](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue) - [fileVisual.js](file://fms-vue/src/components/fms-file/fileVisual.js) - [FmsFile.vue](file://fms-vue/src/components/fms-file/FmsFile.vue) - [FileListPanel.vue](file://fms-vue/src/components/fms-file/FileListPanel.vue) - [FileCard.vue](file://fms-vue/src/components/fms-file/FileCard.vue) - [fileService.js](file://fms-vue/src/services/fileService.js) - [useFileCategory.js](file://fms-vue/src/components/fms-file/composables/useFileCategory.js) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录:扩展与定制指南](#附录扩展与定制指南) ## 简介 本文件聚焦 FMS 前端“文件预览”能力,围绕 FilePreviewPanel 组件及其协作模块,说明多格式文件的在线预览实现现状、数据流、渲染策略与可扩展点。当前仓库实现了图片类文件的内联预览;其他类型(PDF、Office、文本等)以元信息占位展示,并支持下载。文档同时给出后续扩展建议(如 PDF/Office 的 iframe 或第三方库集成)、性能优化策略(大文件分块、内存管理、缓存)与安全注意事项(XSS 防护、大小限制)。 ## 项目结构 文件预览相关代码集中在 fms-vue 的 fms-file 组件目录下,采用“列表-卡片-预览”三栏布局,通过 Splitter 分割区域,事件与状态在父组件 FmsFile 中协调。 ```mermaid graph TB A["FmsFile.vue
三栏布局与状态协调"] --> B["FileListPanel.vue
文件列表/上传/分页"] A --> C["FilePreviewPanel.vue
预览面板"] B --> D["FileCard.vue
单文件卡片"] B --> E["fileService.js
上传/下载/预览URL"] C --> E C --> F["fileVisual.js
扩展名配色/图片判断/大小格式化"] B --> F D --> F A --> G["useFileCategory.js
分类树数据"] ``` 图表来源 - [FmsFile.vue:136-193](file://fms-vue/src/components/fms-file/FmsFile.vue#L136-L193) - [FileListPanel.vue:393-635](file://fms-vue/src/components/fms-file/FileListPanel.vue#L393-L635) - [FilePreviewPanel.vue:41-95](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L41-L95) - [FileCard.vue:60-107](file://fms-vue/src/components/fms-file/FileCard.vue#L60-L107) - [fileService.js:135-143](file://fms-vue/src/services/fileService.js#L135-L143) - [fileVisual.js:40-62](file://fms-vue/src/components/fms-file/fileVisual.js#L40-L62) - [useFileCategory.js:16-54](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L16-L54) 章节来源 - [FmsFile.vue:1-134](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L134) - [FileListPanel.vue:1-133](file://fms-vue/src/components/fms-file/FileListPanel.vue#L1-L133) - [FilePreviewPanel.vue:1-95](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L1-L95) - [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149) - [fileVisual.js:1-63](file://fms-vue/src/components/fms-file/fileVisual.js#L1-L63) - [useFileCategory.js:1-77](file://fms-vue/src/components/fms-file/composables/useFileCategory.js#L1-L77) ## 核心组件 - FilePreviewPanel.vue:预览面板,负责根据文件类型选择渲染方式(当前仅图片直接显示),并提供上下翻页导航与文件名、大小、扩展名等信息展示。 - fileVisual.js:集中提供扩展名解析、语义配色、图片类型判断、文件大小格式化等工具函数,被多个文件组件复用。 - FmsFile.vue:三栏布局容器,协调分类、列表与预览的状态流转,处理选中文件与前后切换。 - FileListPanel.vue:文件列表与上传逻辑,维护待上传队列、分页、拖拽/粘贴上传、批量操作等。 - FileCard.vue:单文件卡片,展示缩略图/类型标识、操作按钮(预览/下载/删除)。 - fileService.js:文件服务,封装上传(本地/OSS)、凭证缓存、删除、获取预览/下载地址等。 章节来源 - [FilePreviewPanel.vue:1-95](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L1-L95) - [fileVisual.js:1-63](file://fms-vue/src/components/fms-file/fileVisual.js#L1-L63) - [FmsFile.vue:1-134](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L134) - [FileListPanel.vue:1-133](file://fms-vue/src/components/fms-file/FileListPanel.vue#L1-L133) - [FileCard.vue:1-58](file://fms-vue/src/components/fms-file/FileCard.vue#L1-L58) - [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149) ## 架构总览 预览流程从用户点击文件开始,经列表组件触发预览事件,由父组件更新选中文件并传递给预览面板,预览面板计算预览 URL 并渲染内容。 ```mermaid sequenceDiagram participant U as "用户" participant L as "FileListPanel.vue" participant P as "FmsFile.vue" participant V as "FilePreviewPanel.vue" participant S as "fileService.js" U->>L : 点击文件卡片/行 L-->>P : emit("preview", file) P->>P : 更新 selectedFile P-->>V : 传递 file + fileList V->>V : computed(previewUrl = getPreviewUrl(file)) V->>S : getPreviewUrl(fileRow) S-->>V : 返回 mx_mapfilename V-->>U : 渲染图片/通用占位 ``` 图表来源 - [FileListPanel.vue:366-369](file://fms-vue/src/components/fms-file/FileListPanel.vue#L366-L369) - [FmsFile.vue:82-109](file://fms-vue/src/components/fms-file/FmsFile.vue#L82-L109) - [FilePreviewPanel.vue:27-30](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L27-L30) - [fileService.js:135-138](file://fms-vue/src/services/fileService.js#L135-L138) ## 详细组件分析 ### FilePreviewPanel.vue 分析 - 功能要点 - 计算当前索引与总数,支持上一个/下一个导航。 - 基于扩展名判断是否为图片类型,若是则使用 img 标签直接加载预览 URL。 - 非图片类型显示通用占位:扩展名色块、文件名、大小、扩展名等元信息。 - 空态提示“选择文件查看预览”。 - 关键逻辑路径 - 预览 URL:通过 fileService.getPreviewUrl 获取文件存储地址。 - 图片判断:使用 fileVisual.isImageType 对扩展名进行白名单匹配。 - 颜色与大小:extColor/formatSize 统一视觉与单位。 - 可拓展点 - 增加 PDF/Office/文本等类型的分支渲染逻辑(见“附录:扩展与定制指南”)。 ```mermaid flowchart TD Start(["进入预览"]) --> CheckFile{"是否选择了文件?"} CheckFile -- 否 --> Empty["显示空态提示"] CheckFile -- 是 --> IsImg{"是否图片类型?"} IsImg -- 是 --> ShowImg["img 标签加载预览URL"] IsImg -- 否 --> Generic["显示通用占位(扩展名/大小/名称)"] ShowImg --> End(["完成"]) Generic --> End Empty --> End ``` 图表来源 - [FilePreviewPanel.vue:27-38](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L27-L38) - [FilePreviewPanel.vue:72-93](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L72-L93) - [fileVisual.js:50-54](file://fms-vue/src/components/fms-file/fileVisual.js#L50-L54) 章节来源 - [FilePreviewPanel.vue:1-247](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L1-L247) ### fileVisual.js 分析 - 职责 - 扩展名到颜色的映射表,便于快速识别文件类别。 - 提取扩展名、判断图片类型、格式化文件大小。 - 复杂度 - 查找时间 O(1),空间为常量级映射表。 - 使用范围 - 被 FileCard、FileListPanel、FilePreviewPanel 共同引用,保证视觉一致性。 章节来源 - [fileVisual.js:1-63](file://fms-vue/src/components/fms-file/fileVisual.js#L1-L63) ### FmsFile.vue 分析 - 职责 - 解析模块信息,加载分类树,管理选中文件与预览导航。 - 通过 Splitter 组织三栏布局,将 FileListPanel 与 FilePreviewPanel 组合。 - 关键点 - onPreviewFile/onPreviewPrev/onPreviewNext 控制预览上下文切换。 - 暴露 moduleId 与 refreshCategories 供外部调用。 章节来源 - [FmsFile.vue:1-134](file://fms-vue/src/components/fms-file/FmsFile.vue#L1-L134) - [FmsFile.vue:136-193](file://fms-vue/src/components/fms-file/FmsFile.vue#L136-L193) ### FileListPanel.vue 分析 - 职责 - 文件分页加载、拖拽/粘贴上传、批量选择与删除、下载。 - 维护 pendingFiles 与 blobUrl 用于上传前图片预览。 - 关键点 - 上传成功后清理 Blob URL,避免内存泄漏。 - 删除时区分待上传与已上传记录的处理差异。 - 下载通过创建 a 标签触发浏览器下载行为。 章节来源 - [FileListPanel.vue:1-133](file://fms-vue/src/components/fms-file/FileListPanel.vue#L1-L133) - [FileListPanel.vue:155-258](file://fms-vue/src/components/fms-file/FileListPanel.vue#L155-L258) - [FileListPanel.vue:280-364](file://fms-vue/src/components/fms-file/FileListPanel.vue#L280-L364) - [FileListPanel.vue:366-388](file://fms-vue/src/components/fms-file/FileListPanel.vue#L366-L388) ### FileCard.vue 分析 - 职责 - 单文件卡片展示:缩略图/类型标识、文件名、大小、操作按钮。 - 图片类型优先使用 blobUrl 或后端地址作为缩略图。 - 关键点 - 未上传文件禁用预览/下载等操作。 - 更多菜单提供“预览”入口。 章节来源 - [FileCard.vue:1-58](file://fms-vue/src/components/fms-file/FileCard.vue#L1-L58) - [FileCard.vue:60-107](file://fms-vue/src/components/fms-file/FileCard.vue#L60-L107) ### fileService.js 分析 - 职责 - 初始化存储模式(本地/OSS),批量上传(含直传 OSS 与回调保存记录),删除文件,获取预览/下载地址。 - OSS 凭证缓存与过期判断,减少重复请求。 - 关键点 - getPreviewUrl 直接返回文件存储地址(mx_mapfilename)。 - 上传流程根据存储类型分流,OSS 模式下使用 XHR 直传并生成对象名。 章节来源 - [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149) ## 依赖关系分析 - 组件耦合 - FmsFile 聚合 FileListPanel 与 FilePreviewPanel,通过 props/events 通信,松耦合。 - FilePreviewPanel 依赖 fileService 获取预览 URL,依赖 fileVisual 做类型判断与样式。 - FileListPanel 与 FileCard 共享 fileVisual,保持视觉一致。 - 外部依赖 - HTTP 请求封装在 http.js(通过 fileService 间接使用)。 - UI 组件来自内部 ui 包(Button、Modal、Spin 等)。 ```mermaid graph LR F["FmsFile.vue"] --> FL["FileListPanel.vue"] F --> FP["FilePreviewPanel.vue"] FL --> FC["FileCard.vue"] FP --> FS["fileService.js"] FP --> FV["fileVisual.js"] FL --> FV FC --> FV ``` 图表来源 - [FmsFile.vue:136-193](file://fms-vue/src/components/fms-file/FmsFile.vue#L136-L193) - [FileListPanel.vue:393-635](file://fms-vue/src/components/fms-file/FileListPanel.vue#L393-L635) - [FilePreviewPanel.vue:41-95](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L41-L95) - [FileCard.vue:60-107](file://fms-vue/src/components/fms-file/FileCard.vue#L60-L107) - [fileService.js:135-143](file://fms-vue/src/services/fileService.js#L135-L143) - [fileVisual.js:40-62](file://fms-vue/src/components/fms-file/fileVisual.js#L40-L62) 章节来源 - [FmsFile.vue:136-193](file://fms-vue/src/components/fms-file/FmsFile.vue#L136-L193) - [FileListPanel.vue:393-635](file://fms-vue/src/components/fms-file/FileListPanel.vue#L393-L635) - [FilePreviewPanel.vue:41-95](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L41-L95) - [FileCard.vue:60-107](file://fms-vue/src/components/fms-file/FileCard.vue#L60-L107) - [fileService.js:135-143](file://fms-vue/src/services/fileService.js#L135-L143) - [fileVisual.js:40-62](file://fms-vue/src/components/fms-file/fileVisual.js#L40-L62) ## 性能考虑 - 当前实现 - 图片预览直接使用 img 标签加载远程资源,简单高效。 - 上传阶段对图片使用 URL.createObjectURL 生成临时 Blob URL,用于上传前缩略图预览;上传完成后释放,避免内存泄漏。 - 建议优化 - 大文件分块加载:对 PDF/Office/文本等大文件,可采用服务端分片或前端懒加载(如 PDF 分页渲染、文本按需读取片段)。 - 内存管理:及时 revokeObjectURL,避免大量 Blob 累积;对长列表使用虚拟滚动(若未来引入重型表格)。 - 缓存机制:对频繁访问的文件预览 URL 可做短期内存缓存(注意失效策略);对静态资源可使用浏览器缓存头。 - 网络优化:启用 gzip/压缩,CDN 加速静态资源;对图片进行自适应尺寸与 WebP 转换。 [本节为通用指导,不直接分析具体文件] ## 故障排查指南 - 预览空白 - 检查文件是否包含有效的 mx_mapfilename;确认后端返回的 URL 可访问且跨域策略允许。 - 图片类型判断依赖扩展名,确保文件名后缀正确。 - 上传失败 - 检查 initFileConfig 是否正确返回 storageType;OSS 模式下凭证是否有效且未过期。 - 关注 http 拦截器抛出的错误提示,必要时调整重试或超时配置。 - 内存泄漏 - 确认上传完成后调用 revokeBlobUrls;页面卸载时清理监听与定时器。 - 删除异常 - 区分待上传与已上传记录的删除逻辑;确保 subid 正确传递。 章节来源 - [fileService.js:87-108](file://fms-vue/src/services/fileService.js#L87-L108) - [FileListPanel.vue:226-231](file://fms-vue/src/components/fms-file/FileListPanel.vue#L226-L231) - [FileListPanel.vue:280-364](file://fms-vue/src/components/fms-file/FileListPanel.vue#L280-L364) ## 结论 当前 FMS 文件预览以图片内联为主,其他类型以元信息占位并支持下载。整体架构清晰、组件职责明确,具备良好的扩展基础。后续可通过引入 PDF/Office 渲染方案(iframe 或第三方库)与文本预览能力,完善多格式在线预览体验;同时结合分块加载、缓存与内存管理策略,提升大文件场景下的性能与稳定性。 [本节为总结性内容,不直接分析具体文件] ## 附录:扩展与定制指南 ### 新增文件类型的预览支持 - 步骤 - 在 FilePreviewPanel 中增加类型分支:根据扩展名或 MIME 类型选择渲染器。 - 对于 PDF:建议使用 iframe 嵌入后端提供的预览页或使用 PDF.js 在 Canvas 上分页渲染。 - 对于 Office(Word/Excel/PowerPoint):可借助后端转换为 HTML/PDF 后以 iframe 展示,或集成第三方库(如 mammoth.js 转 HTML、SheetJS 渲染表格、pptxjs 等)。 - 对于文本文件:使用
 或 CodeMirror 编辑器进行高亮展示,支持分页与搜索。
- 参考位置
  - 类型判断与分支逻辑:FilePreviewPanel.vue 中的 isImage 与渲染模板部分。
  - 工具函数:fileVisual.js 的 extFromName/isImageType/formatSize。

章节来源
- [FilePreviewPanel.vue:27-38](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L27-L38)
- [FilePreviewPanel.vue:72-93](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L72-L93)
- [fileVisual.js:40-62](file://fms-vue/src/components/fms-file/fileVisual.js#L40-L62)

### 自定义预览样式
- 通过 CSS 变量与组件样式类名进行主题化定制,例如 fp-panel、fp-toolbar、fp-content__chip 等。
- 可在 FilePreviewPanel 中扩展样式,或在应用层覆盖全局样式。

章节来源
- [FilePreviewPanel.vue:98-247](file://fms-vue/src/components/fms-file/FilePreviewPanel.vue#L98-L247)

### 安全考虑
- XSS 防护
  - 预览 URL 应来自可信后端接口,避免直接拼接用户输入。
  - 对 iframe 嵌入的内容需设置合适的 sandbox 属性,限制脚本执行权限。
- 文件大小限制
  - 在前端校验文件大小,拒绝过大文件上传;在后端也需设置最大文件大小限制。
  - 对文本预览可进行长度限制与分段加载,避免一次性加载超大文本导致卡顿。
- 跨域与资源加载
  - 确保预览资源域名在白名单内,必要时配置 CORS。
  - 对敏感资源添加鉴权参数(如 token),并在服务端验证。

[本节为通用安全建议,不直接分析具体文件]