news 2026/6/3 11:58:28

表单与文件联动:公文/合同在线预览 + 签章 + 套红实现方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
表单与文件联动:公文/合同在线预览 + 签章 + 套红实现方案

表单与文件联动:公文/合同在线预览 + 签章 + 套红实现方案

🌐演示地址:http://ruoyioffice.com | 📦源码1:ruoyi-office-vben | 📦源码2:ruoyi-office | 📦源码3:ruoyi-office | 💬微信:17156169080(备注「RuoYi Office」)

审批表单里挂了 5 个附件,领导点开全是下载——这是 OA/合同系统里最常见的体验断层。公文正文要套红预览、合同 PDF 要在线核对、用印材料要留痕,预览能力不是锦上添花,而是业务闭环的硬门槛。RuoYi Office 在attachment-list.vue里用「双模预览」统一解决:图片/PDF/Office/视频按扩展名分流;KKFileView 未配置时 docx/xlsx 走 vue-office 零部署;配置了VITE_GLOB_KKFILEVIEW_URL后旧版 Office 格式全兜底。本文把这条链路从组件到公文 GB/T 9704 套红、用印签章完整拆开。

▲ 双模预览决策流程:扩展名分流 → 原生/vue-office/KKFileView 三路径 → 业务层套红/签章/合同复用同一 AttachmentList 组件

引言:表单与文件联动到底难在哪?

AttachmentList(附件列表组件)是 RuoYi Office 里连接「业务表单」与「文件存储」的通用桥梁——请假单、合同、用印申请、公文发文都复用它。难点不在上传,而在预览

痛点一:格式碎片化。一张审批单可能同时有扫描件 PDF、Word 正文、Excel 明细、现场照片——每种格式的浏览器能力不同,不能「一个 iframe 打天下」。

痛点二:部署与能力的 trade-off。KKFileView 能预览 doc/ppt/xls 等旧格式,但要额外部署 LibreOffice 转码服务;中小团队往往希望「先跑起来」,再按需增强。

痛点三:私有文件鉴权。附件 URL 可能是 MinIO 预签名地址,也可能是带 Bearer Token 的后端/admin-api/infra/file/路径——预览前必须刷新签名、携带租户头,否则 iframe 里全是 401。

痛点四:公文套红是「渲染」不是「预览文件」。发文模块的正文预览来自套红模板 + 表单字段实时合成,符合GB/T 9704《党政机关公文格式》排版规范——这和「打开一个 docx 附件」是两条不同的技术路径。

痛点五:签章是流程节点,不是 UI 装饰。用印审批通过后才有「确认用印」操作;印章图片来自台账,和公文套红模板里的seal_image_url是同一套文件基础设施。

现状后果
所有附件只能下载审批人懒得看,合规风险上升
只接 KKFileView小团队部署门槛高,POC 周期长
预览不带鉴权私有桶链接过期、跨域失败
公文套红与附件预览混为一谈产品方案不清晰,开发返工

结论前置:RuoYi Office 用getPreviewType(ext)做扩展名分流,默认 vue-office 覆盖 docx/xlsx,可选 KKFileView 增强;公文套红走独立DocPreview组件;业务表单统一挂载AttachmentList


一、业务全景:三类「文件场景」

1.1 三类场景对照

场景典型模块预览对象实现方式
附件预览合同、用印、请假、报销用户上传的 docx/pdf/图片attachment-list.vue双模预览
套红预览公文发文模板 + 表单字段合成的正式版式DocPreview+ GB/T 9704 排版
签章留痕用印管理、公文签发印章图片 + 审批状态台账seal_image_url+ BPM 节点

1.2 组件路径与复用关系

核心源码路径:

ruoyi-office-vben/apps/web-antd/src/components/attachment-list/ ├── attachment-list.vue # 预览分流 + 表格 + 弹窗 ├── attachment-upload-modal.vue ├── data.ts # 列定义与操作按钮 └── index.ts

环境变量(KKFileView 可选):

VITE_GLOB_KKFILEVIEW_URL=https://preview.example.com

未配置时kkFileViewUrl为空字符串,Office 旧格式无法在线预览时会提示下载——不影响 docx/xlsx 的 vue-office 路径


二、双模预览架构设计

2.1 设计目标

决策点方案理由
默认 Office 预览vue-office(docx/xlsx)纯前端、零额外服务、POC 10 分钟可演示
全格式增强KKFileView iframedoc/ppt/xls 等旧格式、复杂排版
PDF浏览器 iframe原生能力足够
图片Ant Design Image轻量
不支持格式自动下载避免空白弹窗
私有文件fetch + Token + 预签名刷新KKFileView 需完整 HTTP URL

2.2 预览类型枚举

组件内部定义PreviewType,由扩展名映射:

typePreviewType=|'audio'|'docx'|'excel'|'iframe'|'image'|'kkfileview'|'none'|'text'|'video';

分流规则(结论)

  1. 图片扩展名 →image
  2. pdf →iframe
  3. 视频/音频 →video/audio
  4. 文本类(txt/json/md/sql…)→text
  5. docx →docx(vue-office,优先于 KKFileView)
  6. xlsx →excel(vue-office)
  7. 若配置了kkFileViewUrl,其余 Office 扩展名 →kkfileview
  8. 都不匹配 →none(提示并下载)

2.3 双模决策流程(文字版)

用户点击预览 ↓ 解析 fileExtension / fileName ↓ getPreviewType(ext) ├─ 图片/PDF/音视频/文本 → 浏览器原生能力 ├─ docx/xlsx → fetch Blob → VueOfficeDocx / VueOfficeExcel ├─ kkFileViewUrl 已配置且为 Office 类 → iframe → KKFileView └─ none → message.info + handleDownload()

三、AttachmentList 核心实现

3.1 扩展名集合与分流函数

组件顶部声明扩展名白名单,避免魔法字符串散落:

constDOCX_EXTS=newSet(['docx']);constEXCEL_EXTS=newSet(['xlsx']);constOFFICE_EXTS=newSet(['csv','doc','docx','ppt','pptx','xls','xlsx',]);functiongetPreviewType(ext?:string):PreviewType{conste=(ext||'').toLowerCase();if(IMAGE_EXTS.has(e))return'image';if(PDF_EXTS.has(e))return'iframe';if(VIDEO_EXTS.has(e))return'video';if(AUDIO_EXTS.has(e))return'audio';if(TEXT_EXTS.has(e))return'text';if(DOCX_EXTS.has(e))return'docx';if(EXCEL_EXTS.has(e))return'excel';if(kkFileViewUrl){if(OFFICE_EXTS.has(e))return'kkfileview';return'kkfileview';}return'none';}

设计要点:docx/xlsx 在 KKFileView 判断之前 return,保证「零部署模式」下新 Office 格式依然可预览。

3.2 私有 URL 与预签名刷新

getAccessibleUrl处理三类地址:

  • 同源或/admin-api/infra/file/→ 直接带 Token fetch
  • 有效 MinIO 预签名 → 原样使用
  • 过期或外部 URL → 调getFilePresignedGetUrl刷新
asyncfunctiongetAccessibleUrl(fileUrl:string):Promise<string>{if(!fileUrl||fileUrl.startsWith('blob:'))returnfileUrl;constparsed=newURL(fileUrl);if(isBackendFileUrl(parsed)){returnparsed.pathname+parsed.search;}if(parsed.searchParams.has('X-Amz-Signature')&&isValidPresignedUrl(parsed)){returnparsed.href;}try{returnawaitgetFilePresignedGetUrl(fileUrl);}catch{returnparsed.href;}}

admin-api 文件请求自动附加 OAuth2 与多租户头:

functionbuildPreviewFetchOptions(fileUrl:string):RequestInit|undefined{if(!isAdminApiFileUrl(fileUrl))returnundefined;constaccessStore=useAccessStore();constheaders:Record<string,string>={};if(accessStore.accessToken){headers.Authorization=`Bearer${accessStore.accessToken}`;}if(tenantEnable&&accessStore.tenantId!==null){headers['tenant-id']=String(accessStore.tenantId);}return{headers};}

3.3 vue-office 预览链路

docx/xlsx 不直接把 URL 塞给组件,而是fetch 成 Blob再渲染——这样可以走鉴权头,也避免跨域:

case'docx':case'excel':{constresp=awaitfetchOfficePreviewFile(accessUrl,row.fileUrl);previewBlob.value=awaitresp.blob();break;}

模板中分别挂载:

<VueOfficeDocx v-else :src="previewBlob" @error="handleOfficePreviewError" /> <VueOfficeExcel v-else :src="previewBlob" @error="handleOfficePreviewError" />

渲染失败时previewRenderFailed置 true,提示下载——不 silently 失败

3.4 KKFileView 集成

KKFileView 要求从其容器内能 HTTP 访问源文件,因此需要完整 URL + Base64 编码:

functionbuildKKFileViewUrl(fileUrl:string):string{constfullUrl=getFullFileUrl(fileUrl);return`${kkFileViewUrl}/onlinePreview?url=${encodeURIComponent(btoa(unescape(encodeURIComponent(fullUrl))),)}`;}

配置读取来自useAppConfig

const{kkFileViewUrl}=useAppConfig(import.meta.env,import.meta.env.PROD);// 对应环境变量 VITE_GLOB_KKFILEVIEW_URL

部署注意:KKFileView 容器必须能访问 MinIO/后端文件 URL;内网部署时常把文件域名与 KKFileView 放同一 VPC。


四、vue-office 零部署方案详解

4.1 适用场景

条件推荐
POC / 内网无外网vue-office 即可
仅 docx/xlsx 附件vue-office 足够
大量 doc/ppt/xls 老文件建议加 KKFileView
复杂 Excel 公式/宏预览有限,建议下载或 KKFileView

4.2 与 OnlyOffice / WOPI 对比

方案部署成本编辑能力预览 fidelity
vue-office★ 零服务只读docx/xlsx 中等
KKFileView★★ 单 Docker只读全格式较好
OnlyOffice★★★ 集群可协同编辑

RuoYi Office 当前定位是审批只读预览——编辑在业务表单或外部 Word 完成,系统侧重「看」而不是「改」。

4.3 依赖版本

前端使用@vue-office/docx@vue-office/excelV3 分支,与 Vue 3.5 兼容。打包体积会增加,但可按路由/组件异步加载控制。


五、KKFileView 增强模式

5.1 何时启用

.env或部署环境配置:

VITE_GLOB_KKFILEVIEW_URL=http://127.0.0.1:8012

启用后,getPreviewType对 doc/ppt/xls/csv 等走kkfileview分支,iframe 全屏 80vh 展示。

5.2 常见问题

现象原因处理
KKFileView 空白文件 URL 容器不可达检查网络/域名/预签名
中文文件名乱码Base64 编码组件已用encodeURIComponent + btoa
401私有桶未刷新签名getAccessibleUrl再拼预览 URL
docx 走 KKFileView 而非 vue-office不应发生docx 在分流里优先 return docx

六、公文套红:GB/T 9704 实时预览

6.1 套红与附件预览的区别

套红预览不是打开上传的 docx,而是:

  1. 用户在发文表单选择套红模板(机关名称、发文字号前缀、印章图、分隔线)
  2. 填写标题、主送、正文、附件列表
  3. 右侧DocPreviewGB/T 9704排版实时渲染红头、版心、落款

国标要点(简化):

要素规范要求系统实现
版头机关名称、标志、发文字号模板orgNamedocPrefix
主体标题、主送、正文表单字段绑定
版记抄送、印发机关可选扩展字段
印章发文机关印章模板seal_image_url

6.2 套红模板数据模型

独立表oa_office_doc_template(示意):

字段说明
org_name机关名称(红头大字)
doc_prefix发文字号前缀,如「XX发」
seal_image_url印章图片,走统一 FileApi
divider_style分隔线样式

发文单template_id外键关联——同一模板被多次复用,改模板即可统一升级红头样式。

6.3 左右分栏交互

详情页布局:

  • 左侧:form-create / 自定义表单(套红模板选择弹窗、密级、紧急程度、主送部门、正文富文本、AttachmentList)
  • 右侧:DocPreview 实时同步

选中模板后「HelpInput + 弹窗选择」支持搜索、双击快选——模板名与字号前缀自动回填,预览立即刷新。

6.4 正式 PDF 生成

审批签发通过后,后端根据同一套模板数据生成正式 PDF 归档——预览 DOM 与 PDF 生成共享字段模型,避免「预览一套、归档另一套」。


七、签章与用印:流程驱动的「盖印」

7.1 用印 vs 公文套红印章

维度公文套红用印申请
目的版式展示实物/外借印章
印章来源套红模板图片印章台账
触发选模板即见BPM 审批通过后「确认用印」
冲突检测外借时间段冲突算法

用印模块 2 张表 + 5 种状态机:审批通过前不能操作印章;外借需检测时间重叠——签章是业务状态,不是预览组件职责

7.2 与 AttachmentList 的协作

用印申请单上的「用印文件」仍用 AttachmentList——审批人预览材料走本文双模链路;行政确认用印时核对的是同一份在线预览

合同模块同理:合同正文附件、补充协议 PDF 在审批节点打开预览,减少下载往返。


八、后端文件服务要点

8.1 统一 FileApi

上传写入 MinIO(或本地),返回fileUrl;下载/预览统一走:

  • GET /admin-api/infra/file/{configId}/get/{path}(鉴权)
  • getFilePresignedGetUrl刷新外部对象存储

8.2 多租户与 visit-tenant

预览 fetch 时传递tenant-id/visit-tenant-id,与网关 Security 过滤器一致——预览请求和 API 请求同一套租户上下文


九、设计决策对比表

设计要点传统 OARuoYi Office 方案价值
Office 预览仅下载或单一 KKFileViewvue-office + 可选 KKFileView零部署与全格式可兼得
扩展名策略硬编码 if-elseSet 集合 + PreviewType易扩展新格式
私有文件直链常 403预签名刷新 + Bearer预览成功率提升
公文上传 Word 当正文GB/T 9704 套红实时预览合规 + 体验
组件复用每模块一套上传AttachmentList 统一降维护成本
失败策略白屏明确提示 + 降级下载可预期

十、技术亮点总结

设计要点实现方式价值
双模预览getPreviewType 分流部署灵活
零部署 Office@vue-office/docx excelPOC 快
全格式兜底VITE_GLOB_KKFILEVIEW_URL老格式覆盖
鉴权预览fetch + OAuth2 + 租户头私有桶可用
套红合规DocPreview + 模板表GB/T 9704
签章闭环用印台账 + BPM一印一审
表单联动v-model 附件列表全模块复用

十一、快速体验

  • 在线演示:http://ruoyioffice.com/web/(admin / admin123)
  • 推荐路径
    1. OA → 发文管理:选套红模板,看右侧 GB/T 9704 预览
    2. OA → 用印申请:上传 pdf/docx,点附件预览测双模链路
    3. CRM → 合同管理:合同附件预览
    4. 本地不配 KKFileView,验证 docx/xlsx 仍可预览
    5. 配置VITE_GLOB_KKFILEVIEW_URL后测 doc/ppt 老格式

本地启动

cd W:\ruoyi-office\ruoyi-office-vben pnpm dev:antd

源码:

仓库地址
前端ruoyi-office-vben
后端ruoyi-office

结语

表单与文件的联动,本质是让审批人「看得见」。RuoYi Office 用 AttachmentList 的双模预览把 vue-office 的零部署与 KKFileView 的全格式增强组合在一起;公文套红则用 GB/T 9704 实时渲染解决「正式版式」;用印签章用 BPM 状态机守住合规底线。三者共用同一套文件基础设施,却各走最适合的 presentation 路径——这是「一套组件、多种场景」的典型落地方式。

你们现在预览是只用 KKFileView,还是前端 vue-office?公文套红有没有踩过「预览和 PDF 不一致」的坑?欢迎评论区交流。


常见问题(FAQ)

KKFileView 不配也能预览 Office 吗?

能。docx/xlsx 走@vue-office/docx/@vue-office/excel前端渲染,无需额外服务。doc/ppt/xls 等旧格式需要配置VITE_GLOB_KKFILEVIEW_URL或下载查看。

vue-office 和 KKFileView 会同时启用吗?

会协同而非互斥。docx/xlsx 固定走 vue-office;配置 KKFileView 后,其他 Office 扩展名走 iframe 预览。

公文套红预览和附件预览是同一个组件吗?

不是。套红是DocPreview按 GB/T 9704 合成版式;附件是attachment-list.vue打开已上传文件。发文表单可同时包含「正文套红预览 + 附件列表」。

预览私有 MinIO 文件 403 怎么办?

检查预签名是否过期、KKFileView 容器能否访问文件 URL;组件会先调getFilePresignedGetUrl刷新,admin-api 路径会自动带 Bearer Token。

支持在线编辑吗?

当前 AttachmentList 定位为只读预览。编辑在业务表单或外部 Word 完成;如需 OnlyOffice 协同编辑需另行集成。


💡想要体验 RuoYi Office 的强大功能?

🌐在线演示:http://ruoyioffice.com/web/(账号 admin / admin123)

📦源码仓库:GitCode | GitHub

💬技术咨询:添加微信17156169080,备注「RuoYi Office」

如果觉得不错,请给个 Star 支持一下!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/3 11:55:39

CodeT5社区资源汇总:学习资料、工具和最佳实践

CodeT5社区资源汇总&#xff1a;学习资料、工具和最佳实践 【免费下载链接】codet5-base 项目地址: https://ai.gitcode.com/hf_mirrors/Beijing-Ascend/codet5-base CodeT5是一款由Salesforce开发的统一预训练编码器-解码器Transformer模型&#xff0c;专为代码理解和…

作者头像 李华
网站建设 2026/6/3 11:53:55

MediaCrawler企业级实战指南:构建自动化多平台数据采集管道

MediaCrawler企业级实战指南&#xff1a;构建自动化多平台数据采集管道 【免费下载链接】MediaCrawler-new 项目地址: https://gitcode.com/GitHub_Trending/me/MediaCrawler-new 在当今数据驱动的商业环境中&#xff0c;社交媒体数据已成为企业决策、市场分析和用户洞…

作者头像 李华
网站建设 2026/6/3 11:51:33

HEC-HMS水文模型

HEC-HMS是一款水文模型。HMS能够模拟各种类型的降雨事件对流域水文&#xff0c;河道水动力以及水利设施的影响&#xff0c;在世界范围内得到了广泛的应用。它有着完善的前后处理软件&#xff0c;能有效减轻建模的负担&#xff1b;能够与HEC开发的DSS数据管理软件以及RAS二维水动…

作者头像 李华
网站建设 2026/6/3 11:49:31

Umi-OCR终极指南:如何免费实现高效离线批量文字识别

Umi-OCR终极指南&#xff1a;如何免费实现高效离线批量文字识别 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片&#xff0c;PDF文档识别&#xff0c;排除水印/页眉页脚&#xff0c;扫描/生成二维码。内置多国语言库…

作者头像 李华
网站建设 2026/6/3 11:48:17

一文读懂Node Foreman环境变量加载机制:envs.js实现原理

一文读懂Node Foreman环境变量加载机制&#xff1a;envs.js实现原理 【免费下载链接】node-foreman A Node.js Version of Foreman 项目地址: https://gitcode.com/gh_mirrors/no/node-foreman Node Foreman作为Node.js版本的Foreman工具&#xff0c;其核心功能之一就是…

作者头像 李华