# template-view **Repository Path**: hhs_3/template-view ## Basic Information - **Project Name**: template-view - **Description**: 合同模版管理,采用Spring boot + (简单模板引擎 | FreeMarker | HTML转PDF | Flying Saucer + OpenPDF) + (复杂模板引擎 | poi-tl | Word转换PDF | Collabora CODE ) - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-03-31 - **Last Updated**: 2026-04-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 模板管理平台 (Template Platform) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Java](https://img.shields.io/badge/Java-17+-green.svg)](https://www.oracle.com/java/) [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4.0-brightgreen.svg)](https://spring.io/projects/spring-boot) [![Vue](https://img.shields.io/badge/Vue-3.4-blue.svg)](https://vuejs.org/) 基于 Spring Boot 3 + Vue 3 的模板管理与渲染平台,支持简单模板和复杂模板两种方案,可将模板渲染为 PDF 或 Word 文档。 ## 预览效果 ### 模板列表 ![模板列表](doc/img/模版列表.png) ### 简单模板渲染 ![简单模板渲染](doc/img/简单模版渲染.png) ### 复杂模板渲染 ![复杂模板渲染](doc/img/复杂模版渲染.png) ## 功能特性 - **双模板引擎** - 支持 FreeMarker (简单) 和 poi-tl (复杂) 两种模板方案 - **多格式输出** - 支持 PDF 和 Word 文档输出 - **版本管理** - 完整的版本发布、回滚、切换功能,支持乐观锁并发控制和操作审计日志 - **Collabora CODE 集成** - 使用 Collabora CODE 进行高性能 PDF 转换 - **Word 在线编辑** - 结合 [online-view](https://gitee.com/hhs_3/online-view) 实现 Word 模板在线编辑 - **中文字体支持** - 内置宋体、黑体、仿宋、楷体等中文字体 - **灵活存储** - 支持本地存储 - **API 文档** - 集成 Knife4j,提供完整的 API 文档 ## 技术栈 ### 后端 | 组件 | 技术 | 版本 | |------|-------------------------|--------| | 框架 | Spring Boot | 3.4.0 | | JDK | Java | 17 | | ORM | MyBatis-Plus | 3.5.9 | | 连接池 | Druid | 1.2.23 | | 数据库 | MySQL | 8.x | | 简单模板引擎 | FreeMarker | 2.3.32 | | HTML转PDF | Flying Saucer + OpenPDF | 9.1.22 | | 复杂模板引擎 | poi-tl | 1.12.2 | | PDF转换 | Collabora CODE | - | | 对象存储 | Local | - | | API文档 | Knife4j | 4.5.0 | ### 前端 | 组件 | 技术 | 版本 | |------|------|------| | 框架 | Vue | 3.4 | | UI组件库 | Element Plus | 2.6 | | 构建工具 | Vite | 5.2 | | 语言 | TypeScript | 5.4 | | HTTP客户端 | Axios | 1.6 | ## 方案对比 ### 双引擎对比 | 维度 | 简单模板 | 复杂模板 | |------|----------|----------| | **模板格式** | HTML (.html/.ftl) | Word (.docx) | | **变量语法** | `${variable}` | `{{variable}}` | | **模板引擎** | FreeMarker | poi-tl | | **PDF 生成** | Flying Saucer + OpenPDF | Collabora CODE | | **外部依赖** | 无 | Collabora CODE Docker 容器 | | **部署复杂度** | 极低 | 中等 | | **排版能力** | 表格、文字、基础 CSS | Word 全部功能 | | **并发性能** | 优秀(纯内存) | 优秀(服务池化) | | **适用场景** | 表单、申请表、报告 | 正式合同、法律文件 | | **维护门槛** | 低(改 HTML) | 低(改 Word) | #### 简单模板方案 ``` HTML模板 → FreeMarker变量替换 → XHTML → Flying Saucer → PDF ``` **优点:** 纯 Java 实现,无外部依赖,并发友好 #### 复杂模板方案 ``` Word模板 → poi-tl变量替换 → Word文档 → Collabora CODE → PDF ``` **优点:** 支持 Word 全部功能,精确控制排版格式 ### Word → PDF 方案横向对比 | 方案 | 保真度 | 性能 | 部署复杂度 | 并发能力 | |------|--------|------|------------|----------| | Apache POI + iText | 低(丢失大量格式) | 中 | 低 | 高 | | LibreOffice 命令行 | 中 | 低(每次启动进程) | 中 | 低 | | **Collabora CODE** | **高** | **高(长驻服务)** | **中(Docker 部署)** | **高** | | Aspose.Words | 高 | 高 | 低 | 高(但商业授权昂贵) | #### LibreOffice CLI vs Collabora CODE | 维度 | LibreOffice 命令行 (`soffice --convert-to`) | Collabora CODE | |------|---------------------------------------------|----------------| | 调用方式 | 每次请求 fork 新进程 | 长驻服务,REST API | | LibreOffice 加载方式 | 进程级(每次重新加载) | 库级(LibreOfficeKit,进程内复用) | | 单次转换启动耗时 | 2~5 秒 | 毫秒级(实例已预热) | | 并发处理 | 多进程并行,资源消耗大 | 实例池管理,资源可控 | | 在线编辑 | 不支持 | 支持(WOPI 协议) | ## Word 在线编辑 本项目配合 [online-view](https://gitee.com/hhs_3/online-view) 开源项目,可实现 Word 模板的在线编辑功能。 基于 Collabora CODE 的 WOPI 协议,支持: - Word 文档在线实时编辑 - 自动保存 - 多人协作(Collabora CODE 原生支持) > 早期版本使用 LibreOffice 进行文档转换,后切换为 Collabora CODE,不仅提升了转换质量和性能,还获得了在线编辑能力。 ## 版本管理 系统提供完整的模板版本管理功能,参考语义化版本规范(Semantic Versioning): ### 版本状态机 ``` 创建 │ ▼ ┌────────┐ 发布 ┌───────────┐ │ DRAFT │───────→│ PUBLISHED │◄──── 切换(SetActive) │ 草稿 │ │ 已发布 │ └────────┘ └─────┬─────┘ │ │ │ 删除 │ 归档 / 新版本发布时旧版本自动归档 ▼ ▼ 删除 ┌──────────┐ │ ARCHIVED │ │ 已归档 │──── 回滚 → 创建新 PUBLISHED └──────────┘ ``` ### 关键设计点 - **乐观锁** - `lock_version` 字段防止并发修改冲突 - **非破坏性回滚** - 回滚不是覆盖,而是从归档版本创建一个新的已发布版本,保留完整历史 - **审计日志** - 每个版本操作(CREATE、PUBLISH、ARCHIVE、ROLLBACK、DELETE、SWITCH)都记录操作人、时间和状态变更 - **草稿限制** - 可配置草稿版本数量上限,避免资源浪费 ## 项目结构 ``` template-view/ ├── src/main/java/com/ktwl/template/ │ ├── TemplatePlatformApplication.java # 启动类 │ ├── config/ # 配置类 │ ├── controller/ # 控制器 │ │ ├── TemplateController.java # 模板渲染接口 │ │ ├── TemplateInfoController.java # 模板管理接口 │ │ ├── TemplateCategoryController.java # 分类管理接口 │ │ └── WopiController.java # WOPI协议接口(在线编辑) │ ├── dto/ # 数据传输对象 │ ├── entity/ # 实体类 │ ├── enums/ # 枚举类 │ ├── mapper/ # MyBatis Mapper │ ├── service/ # 服务层 │ │ ├── TemplateVersionService.java # 版本管理服务 │ │ ├── TemplateVersionAuditService.java # 版本审计服务 │ │ ├── TemplateRenderService.java # 模板渲染服务 │ │ ├── ComplexTemplateService.java # 复杂模板服务 │ │ ├── CollaboraPdfConverter.java # Collabora转换器 │ │ ├── CollaboraOnlineEditService.java # 在线编辑服务 │ │ └── file/FileStorageService.java # 文件存储服务 │ └── exception/ # 异常处理 ├── src/main/resources/ │ ├── fonts/ # 字体文件目录 │ ├── application.yml # 主配置文件 │ └── application-local.yml # 本地环境配置 ├── frontend/ # 前端项目 │ └── src/ │ ├── api/ # API 接口层 │ ├── views/ # 页面组件 │ └── utils/ # 工具类 ├── sql/ │ └── schema.sql # 数据库初始化脚本 ├── doc/ │ └── img/ # 文档图片 └── pom.xml ``` ## 快速开始 ### 1. 环境准备 - JDK 17+ - Maven 3.6.3+ - MySQL 8.0+ - Node.js 16+ - Collabora CODE 服务 ### 2. 配置数据库 ```bash # 创建数据库 mysql -u root -p -e "CREATE DATABASE template_platform CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 执行初始化脚本 mysql -u root -p template_platform < sql/schema.sql ``` ### 3. 配置环境变量 ```bash cp .env.example .env ``` 编辑 `.env` 文件: ```bash # 数据库配置 DB_HOST=localhost DB_PORT=3306 DB_NAME=template_platform DB_USERNAME=root DB_PASSWORD=your_password # Collabora CODE 配置(必需,用于 PDF 转换) COLLABORA_SERVER=http://192.168.51.10:9980 ``` ### 4. 添加中文字体 将中文字体文件放入 `src/main/resources/fonts/` 目录: - `simsun.ttc` - 宋体 - `simhei.ttf` - 黑体 - `simfang.ttf` - 仿宋 - `simkai.ttf` - 楷体 ### 5. 启动后端 ```bash mvn spring-boot:run ``` ### 6. 启动前端 ```bash cd frontend npm install npm run dev ``` ### 7. 访问应用 - 前端页面:http://localhost:3000 - 接口文档:http://localhost:8080/doc.html ## API 接口 ### 模板管理 | 接口 | 方法 | 描述 | |------|------|------| | `/api/template/page` | GET | 分页查询模板 | | `/api/template/{id}` | GET | 获取模板详情 | | `/api/template/code/{code}` | GET | 根据编码获取模板 | | `/api/template` | POST | 创建模板 | | `/api/template/{id}/upload` | POST | 上传模板文件 | | `/api/template/{id}/versions` | GET | 获取版本列表 | | `/api/template/{id}/versions/stats` | GET | 获取版本统计 | | `/api/template/versions/{id}/publish` | POST | 发布版本 | | `/api/template/versions/{id}/rollback` | POST | 回滚版本 | | `/api/template/versions/{id}` | DELETE | 删除草稿版本 | | `/api/template/{id}/current-version` | PUT | 切换当前版本 | | `/api/template/{id}/versions/audit-logs` | GET | 查询版本审计日志 | | `/api/template/{id}/status` | PUT | 启用/禁用模板 | ### 模板分类 | 接口 | 方法 | 描述 | |------|------|------| | `/api/template/categories` | GET | 获取所有分类 | | `/api/template/categories/{id}` | GET | 获取分类详情 | | `/api/template/categories` | POST | 创建分类 | ### 模板渲染 ```http POST /api/template/render Content-Type: application/json { "templateCode": "contract_001", "outputFormat": "PDF", "dataModel": { "title": "房屋买卖合同", "partyA": "张三", "partyB": "李四" } } ``` ## 数据库设计 共 7 张表,核心表关系如下: ``` template_category (分类) │ │ 1:N ▼ template_info (模板信息) │ ├── 1:N ──→ template_version (模板版本,含 lock_version 乐观锁) │ │ │ └── 1:N ──→ template_version_audit (版本审计日志) │ ├── 1:N ──→ template_variable (模板变量定义,支持层级嵌套) │ └── N:N ──→ template_font (字体管理) template_render_log (渲染日志,独立记录) ``` | 表名 | 说明 | |------|------| | `template_category` | 模板分类 | | `template_info` | 模板信息 | | `template_version` | 模板版本(含乐观锁) | | `template_version_audit` | 版本操作审计日志 | | `template_variable` | 模板变量定义 | | `template_font` | 字体管理 | | `template_render_log` | 渲染日志 | ## 模板使用指南 ### 简单模板 (HTML/FreeMarker) 简单模板使用 **HTML + FreeMarker** 语法,适用于表单、申请表、简单合同等场景。 #### FreeMarker 语法说明 | 语法 | 说明 | 示例 | |------|------|------| | `${variable}` | 输出变量值 | `${name}` | | `${variable!默认值}` | 变量不存在时输出默认值 | `${name!'未知'}` | | `<#if condition>...` | 条件判断 | `<#if amount > 1000>高额` | | `<#list items as item>...` | 循环遍历 | `<#list users as user>${user.name}` | ### 复杂模板 (Word/poi-tl) 复杂模板使用 **Word 文档 + poi-tl** 语法,适用于正式合同、协议等格式要求高的文档。 #### 模板语法 在 Word 文档中使用 `{{变量名}}` 作为占位符: | 语法 | 说明 | 示例 | |------|------|------| | `{{variable}}` | 文本替换 | `{{contractTitle}}` | | `{{#list}}...{{/list}}` | 列表循环 | 表格行循环 | | `{{@image}}` | 图片插入 | 签名图片 | #### PDF 转换要求 复杂模板输出 PDF 需要部署 **Collabora CODE** 服务: ```bash # Docker 部署 Collabora CODE docker run -t -d -p 9980:9980 \ -e "extra_params=--o:ssl.enable=false" \ collabora/code ``` 配置环境变量: ```bash COLLABORA_SERVER=http://your-server:9980 ``` ### 变量定义 | 类型 | 说明 | 默认值示例 | |------|------|------------| | STRING | 字符串 | `"示例文本"` | | NUMBER | 数字 | `123.45` | | DATE | 日期 | `"2025-03-30"` | | BOOLEAN | 布尔值 | `true` | | OBJECT | JSON对象 | `{"key": "value"}` | | LIST | 数组列表 | `["item1", "item2"]` | ## 环境变量 | 变量名 | 说明 | 默认值 | |--------|------|--------| | `DB_HOST` | 数据库主机 | localhost | | `DB_PORT` | 数据库端口 | 3306 | | `DB_NAME` | 数据库名称 | template_platform | | `DB_USERNAME` | 数据库用户名 | root | | `DB_PASSWORD` | 数据库密码 | (空) | | `COLLABORA_SERVER` | Collabora CODE 服务器地址 | http://192.168.51.10:9980 | | `STORAGE_TYPE` | 存储类型 (local) | local | ## 致谢 - [poi-tl](https://github.com/Sayi/poi-tl) - Word 模板引擎 - [Flying Saucer](https://github.com/flyingsaucerproject/flyingsaucer) - HTML to PDF - [FreeMarker](https://freemarker.apache.org/) - 模板引擎 - [Collabora Online](https://www.collaboraonline.com/) - 文档转换与在线编辑 - [online-view](https://gitee.com/hhs_3/online-view) - 在线编辑集成方案 ## License 本项目采用 [MIT License](LICENSE) 开源协议。