huluang头像
关注

DJofficer 项目功能说明

有需要可留言,完全开源。共同完善。

1. 项目概述

DJofficer 是一个基于 PHP 的 Word 文档(.docx)动态生成库。核心思想是在 Word 母版(模板)的基础上做修改:用户用 Word 编辑软件把模板样式调整好,再通过代码向模板中的变量位置填充数据、克隆区块、替换图片等,最终生成成品文档。

  • 技术栈:PHP >= 8.1,仅依赖原生 ZipArchive + DOMDocument(Excel 操作为可选依赖 PhpSpreadsheet)
  • 核心优势:生成 Word 只需关注动态数据与逻辑,无需关心样式调整(样式在母版中借助 Word 完成)
  • 与 PHPWord 的区别:PHPWord 逐元素写入;DJofficer 在母版基础上修改,编码效率更高,支持目录、页眉页脚、克隆等复杂能力

项目双版本

版本目录说明
v0src/原始实现,使用 ${变量名/} 文本标记定位变量
v1v1/全新架构,使用 Word 批注(comment.xml) 定位变量,是当前主推版本

2. 核心功能

2.1 文本变量替换

将模板中的变量替换为实际文本,支持:

  • 普通字符串替换(setValue
  • 批量替换多个变量(setValues
  • 混合内容替换(setValue 传数组,支持换行 BREAK、超链接 LINK、图片 IMG 类型)

2.2 图片替换

将变量位置替换为图片(setImage),支持:

  • 自动管理媒体文件(MediaManager 避免与模板图片重名)
  • 自定义尺寸
  • 自动建立图片关系(RelationshipManager

2.3 超链接替换

将变量替换为超链接(setLink),支持:

  • 外部链接(\o 字段)
  • 内部锚点链接(#anchor\l 字段)
  • 保留原 run 作为显示文本

2.4 克隆(区块/段落/节)

方法功能
cloneRange智能克隆:表格行或多段落范围
cloneParagraph克隆变量所在段落 N 次
cloneSection克隆整个节(含页面布局 sectPr)

克隆时自动处理批注 id 重映射、变量名后缀(#0/#1)、comments.xml 同步。

2.5 数据绑定(bind)

bind($name, $data, $callback?) 将数据行绑定到模板范围:

  • 每行数据自动克隆一次范围并填充
  • 支持嵌套克隆(数据值为数组时递归绑定,生成 childVar#0#1 复合变量名)
  • 支持 $keyMap 映射模板变量名到数据键
  • 支持回调函数处理每个值

2.6 表格批量填充

setTable($name, $rows, $hasHeaderRow?, $autoNumber?, $rowLimit?) 一次调用批量填充表格:

  • 批量写入:所有行从模板数据行克隆,通过 DocumentFragment 一次 DOM 插入(500 行仅数毫秒)
  • 标题行保留hasHeaderRow=true 时首行保留为标题,数据从第二行填充
  • 序号自动填充autoNumber=true 时第一列自动填 1,2,3...(符合中文习惯,首行首列为"序号"),数据自带的序号列被忽略,保证序号连贯
  • 行数校验rowLimit 限制最大数据行数,超限抛 InvalidArgumentException
  • 性能优化:单元格文本节点每表只定位一次(全局 <w:t> 索引),每个克隆行仅一次 DOM 查询

2.7 删除

delete($name, $scope?) 按范围删除内容:

  • SCOPE_PARAGRAPH:删除段落
  • SCOPE_ROW:删除表格行
  • SCOPE_TABLE:删除表格
  • SCOPE_SECTION:删除整个节(从上一 sectPr 边界到下一 sectPr 边界)

2.8 插入

  • insertPageBreak:插入分页符
  • insertEmptyParagraph:插入空行

2.9 Word 域(Field)

方法功能
setNowPage当前页码(PAGE 域)
setTotalPage总页数(NUMPAGES 域)
setRef书签引用(REF 域)
setPageRef书签页码(PAGEREF 域)

2.10 图表数据修改

  • setChartData($part, $series, $cats, $data):按部件路径修改图表数据
  • setChartDataByName($name, $series, $cats, $data):按批注名称定位图表并修改

同时更新嵌入 xlsx 源数据chart XML 渲染缓存,支持:

  • 多 sheet 检测、combo chart、scatterChart(xVal/yVal)
  • formatCode 保留、sharedStrings 共享字符串表
  • 系列数量调整(不足克隆、多余删除,自动分配主题强调色避免颜色重复)

2.11 内嵌 Excel 操作

  • excel():返回 ExcelManagerInterface(需部件路径,底层逃生舱)
  • excelByName($name):按批注名称定位内嵌 Excel,返回 BoundExcelManager,支持 setCellValue / getCellValue

2.12 目录更新

updateToc() 将文档中所有 TOC 域标记为脏,Word 打开时自动刷新目录。支持复杂域(fldChar begin/end)和简单域(fldSimple)。

2.13 批量操作(batch)

batch($operations, $continueOnError?) 在一次编辑会话中执行多个操作,共享同一 DOM 上下文:

$editor->batch([
    ['method' => 'setValue', 'name' => 'title', 'value' => '报告'],
    ['method' => 'setImage', 'name' => 'logo', 'imagePath' => 'logo.png'],
    ['method' => 'cloneRange', 'name' => 'row', 'count' => 3],
    ['method' => 'setChartDataByName', 'name' => '图表1', 'seriesNames' => [...], ...],
]);

getBatchErrors() 可获取批量操作累积的错误。

2.14 变量定位(locate)

locate($name) 返回变量名对应的批注内容范围,用于预检变量是否存在及范围位置。

2.15 模板缓存

  • registerTemplate / unregisterTemplate / listTemplates:模板注册管理
  • setTemplateDir / setCacheDir:自定义模板与缓存目录
  • 同名模板二次加载时复用解析后的 XML 与批注索引,加速加载

3. 架构设计

3.1 v1 核心目标:批注定位机制

v1 的核心链路是通过 comment.xml 中的批注文本(w:t)定位 document.xml 中的内容范围,再执行操作方法

用户选择方法 + 提供 comment.xml 中 w:t 文本
        │
        ▼
① w:t 文本 → comment id
   (CommentIndexManager::buildVariableIndex)
        │
        ▼
② id → document.xml 内容范围
   (VariableLocator::findRangeStarts / findRangeEnd)
        │
        ▼
③ 对内容范围执行操作
   (setValue / setImage / cloneRange / bind / setChartDataByName ...)
        │
        ▼
④ 批量执行(多个操作共享同一 DOM 上下文)
        │
        ▼
⑤ 统一保存(save(),清理批注标记)

3.2 分层架构

┌──────────────────────────────────────────────┐
│              门面层(Facade)                  │
│         WordEditor(统一 API 入口)            │
│         ComponentFactory(DI 容器)           │
└──────────────────────────────────────────────┘
                      │
┌──────────────────────────────────────────────┐
│           Operation 组件层(业务逻辑)          │
│  Binder / TextReplacer / ImageReplacer /     │
│  LinkReplacer / TableBuilder / ChartManager  │
│  RangeCloner / ParagraphCloner / SectionCloner│
│  ContentDeleter / FieldReplacer / TocUpdater  │
│  BreakInserter / HeaderFooterManager / ...    │
└──────────────────────────────────────────────┘
        │                │              │
        ▼                ▼              ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│  Tool 工具层  │ │  Xml 组件层   │ │  Zip 组件层   │
│ VariableLocator│ │ XmlDocument  │ │ DocxArchive  │
│ CommentIndex  │ │ FragmentFactory│ │ MediaManager │
│ PartLocator   │ │ NodeImporter │ │ RelationshipMgr│
│ RangeExtractor│ │ TextEncoder  │ │ TempFileMgr  │
│ ContainerDetector│ │ XPathBuilder │ │              │
└──────────────┘ └──────────────┘ └──────────────┘

3.3 核心设计原则

  1. 名称寻址:所有面向用户的 API 以批注文本(变量名)定位,用户无需关心部件路径或 comment id
  2. id 中转:w:t 文本 → comment id → document.xml 内容范围,两步解析由 CommentIndexManager + VariableLocator 完成
  3. 范围操作:每个方法在 commentRangeStart/End 范围内操作,不越界、不误伤其他批注
  4. 批量执行:支持链式调用或 batch API,共享同一 DOM 上下文,最后统一保存
  5. 统一保存:save() 一次性写出,清理批注标记并(可选)移除 comments.xml

3.4 v0 与 v1 对比

维度v0(src/)v1(v1/)
变量定位${变量名/} 文本标记Word 批注(comment.xml w:t)
表格填充clones() + setValue(name#N) 逐单元格setTable() 批量填充
架构单一大类门面 + Operation + Tool/Xml/Zip 分层
性能逐单元格操作,性能低DocumentFragment 批量插入,500 行毫秒级

4. 目录结构

DJofficer-main/
├── src/                      # v0 原始实现
│   ├── Api/                  # 公共 API
│   ├── Common/               # 公共组件
│   ├── Config/               # 配置
│   ├── Edit/Part/            # 编辑部件(Document 等)
│   ├── Read/Part/            # 读取部件
│   └── XmlTemple/            # XML 模板
├── v1/                       # v1 全新架构
│   ├── Component/
│   │   ├── WordEditor.php    # 门面层:统一 API 入口
│   │   ├── ComponentFactory.php  # DI 容器
│   │   ├── Operation/        # 业务操作层(30+ 组件)
│   │   ├── Tool/             # 工具层(定位/范围/索引)
│   │   ├── Xml/              # XML 组件层
│   │   ├── Zip/              # ZIP 组件层
│   │   └── Exception/        # 异常定义
│   ├── Cache/                # 模板缓存层
│   └── tests/Unit/           # PHPUnit 单元测试
├── tests/                    # 集成测试与样例模板
│   ├── samples/              # 测试模板(docx)
│   └── v1_test_*.php         # v1 集成测试脚本
├── scripts/                  # 工具脚本(索引生成、性能扫描)
├── templates/                # 模板目录
├── AGENTS.md                 # 架构规范
├── ARCHITECTURE_CHANGELOG.md # 架构变更记录
├── claude.md                 # 方法索引(自动生成)
├── CODE_WIKI.md              # 代码 Wiki
└── composer.json             # 依赖与自动加载

5. 快速上手

5.1 安装

composer require mkdreams/DJofficer
# 或手动引入
require_once('Autoloader.php');

5.2 模板准备

在 Word 中打开模板,选中变量文本(如 {{title}}),插入 > 批注,批注文本即变量名。表格数据行用批注标记整行。

5.3 基本使用

use DJofficer\v1\Component\WordEditor;

$editor = new WordEditor();
$editor->load('temple.docx');

// 文本替换
$editor->setValue('title', '月度报告');
$editor->setValues(['date' => '2026-08-16', 'author' => '张三']);

// 图片替换
$editor->setImage('logo', '/path/to/logo.png');

// 表格批量填充
$editor->setTable('table1', [
    ['姓名' => '张三', '年龄' => 25, '职业' => '工程师'],
    ['姓名' => '李四', '年龄' => 30, '职业' => '设计师'],
], true); // hasHeaderRow = true

// 克隆
$editor->cloneRange('people', 3);

// 保存
$editor->save('output.docx');
$editor->free();

6. 测试覆盖

测试类型位置覆盖内容
PHPUnit 单元测试v1/tests/Unit/128 项:WordEditor、TextReplacer、XmlDocument、DocxArchive、TableBuilder、ChartManager 等核心组件
集成测试tests/v1_test_*.phpreadme(24)、temple(60)、chart(图表)、clone(19)、image(18)、table(36)、template_cache(16)等
CI 流水线.github/workflows/phpunit.ymlPHP 8.1–8.4 矩阵监控代码质量

7. 相关文档

文档说明
AGENTS.md项目架构规范与核心约束
ARCHITECTURE_CHANGELOG.md架构变更记录
CODE_WIKI.md代码 Wiki(架构、模块、API)
claude.md方法索引(自动生成)
v1/README.mdv1 使用说明
v1/CODE_INDEX.mdv1 代码库索引(自动生成)

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/huluang/article/details/163804088

文章来源crawl

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--