chore: prepare docfill project for gitea
This commit is contained in:
281
README.md
281
README.md
@@ -1,79 +1,151 @@
|
||||
# docfill
|
||||
|
||||
`docfill` 是一个最小化本地填报工具:从 Excel 或 SQLite 读取数据,把 `{{字段名}}` 填入 Word/Excel 模板,生成输出文件。
|
||||
`docfill` 是一个本地文档填充命令行工具。它从 Excel 或 SQLite 读取结构化数据,按业务条件筛选出需要使用的数据行,再把数据填入 Word 或 Excel 模板中的 `{{字段名}}` 占位符。
|
||||
|
||||
## Build
|
||||
本工具的定位是“小型、稳定、便于数字员工调用”。它只负责本地数据到本地模板的填充,不内置业务系统登录、审批流、Web 界面、模板设计器或权限系统。
|
||||
|
||||
## 核心理解
|
||||
|
||||
`task.json` 是某一种业务报表的固定任务说明书,命令行 `--var` 是本次运行传入的具体条件。
|
||||
|
||||
```text
|
||||
不同业务 = 不同 task.json
|
||||
本次运行的日期、工单编号、人员、批次 = --var
|
||||
真实数据 = Excel 或 SQLite
|
||||
模板文件 = Word 或 Excel
|
||||
```
|
||||
|
||||
优先级:
|
||||
|
||||
```text
|
||||
数据表里的字段 > 命令行 --var > task.json 里的 vars
|
||||
```
|
||||
|
||||
例如 `task.json` 中写了:
|
||||
|
||||
```json
|
||||
"vars": {
|
||||
"date": "2026-06-18"
|
||||
}
|
||||
```
|
||||
|
||||
运行时执行:
|
||||
|
||||
```bash
|
||||
dist/docfill-darwin-arm64 run -c task.json --var date=2026-06-19 --var ticket_no=GD-001
|
||||
```
|
||||
|
||||
实际使用的是:
|
||||
|
||||
```text
|
||||
date = 2026-06-19
|
||||
ticket_no = GD-001
|
||||
```
|
||||
|
||||
也就是 `--var date=2026-06-19` 会覆盖 `task.json` 里的默认 `date=2026-06-18`。
|
||||
|
||||
## 最小实践
|
||||
|
||||
进入仓库目录:
|
||||
|
||||
```bash
|
||||
cd /Users/zhaoyilun/Documents/xls_doc
|
||||
```
|
||||
|
||||
构建本机二进制:
|
||||
|
||||
```bash
|
||||
go build -o docfill ./cmd/docfill
|
||||
bash scripts/build.sh
|
||||
```
|
||||
|
||||
`scripts/build.sh` writes the local macOS arm64 binary to `dist/docfill-darwin-arm64`.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
./docfill run --config task.json
|
||||
./docfill run -c task.json --var date=2026-06-18 --var batch=早班
|
||||
```
|
||||
|
||||
成功时 stdout 输出生成文件清单:
|
||||
输出示例:
|
||||
|
||||
```text
|
||||
generated 2 file(s)
|
||||
- /path/to/out/report_张三.xlsx
|
||||
- /path/to/out/report_李四.xlsx
|
||||
/Users/zhaoyilun/Documents/xls_doc/dist/docfill-darwin-arm64
|
||||
```
|
||||
|
||||
退出码:
|
||||
|
||||
- `0`: 成功。
|
||||
- `1`: 配置、数据、模板或输出失败。
|
||||
- `2`: 命令行参数错误。
|
||||
|
||||
## Run Case Tests
|
||||
运行“按日期 + 工单编号筛选一条工单并生成 Word”的测试任务:
|
||||
|
||||
```bash
|
||||
go test -run TestCase -v ./internal/docfill
|
||||
dist/docfill-darwin-arm64 run -c manual_tests/04_filter_work_order_to_word/task.json --var date=2026-06-18 --var ticket_no=GD-002 --verbose
|
||||
```
|
||||
|
||||
当前案例覆盖:
|
||||
输出示例:
|
||||
|
||||
- Excel 日报数据填 Excel 模板,批量生成个人日报。
|
||||
- SQLite 日报数据填 Word 模板,批量生成个人日报。
|
||||
- SQLite 汇总数据填 Excel 模板,批量生成部门汇总表。
|
||||
```text
|
||||
log: load config path=manual_tests/04_filter_work_order_to_word/task.json
|
||||
log: read data type=excel path=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/source_work_orders.xlsx
|
||||
log: read data type=excel path=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/source_work_orders.xlsx rows=3
|
||||
log: filter rows=3 matched=1 expect=one
|
||||
log: render row=1 output=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/out/work_order_2026-06-18_GD-002.docx
|
||||
generated 1 file(s)
|
||||
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/out/work_order_2026-06-18_GD-002.docx
|
||||
```
|
||||
|
||||
## Smoke Test
|
||||
查看生成结果:
|
||||
|
||||
```bash
|
||||
open manual_tests/04_filter_work_order_to_word/out
|
||||
```
|
||||
|
||||
更多可运行案例见 [HOWTO.md](HOWTO.md) 和 [manual_tests/README.md](manual_tests/README.md)。
|
||||
|
||||
## 常用命令
|
||||
|
||||
构建:
|
||||
|
||||
```bash
|
||||
bash scripts/build.sh
|
||||
```
|
||||
|
||||
运行一个任务:
|
||||
|
||||
```bash
|
||||
dist/docfill-darwin-arm64 run -c task.json
|
||||
```
|
||||
|
||||
运行任务并传入本次筛选条件:
|
||||
|
||||
```bash
|
||||
dist/docfill-darwin-arm64 run -c 工单日报.json --var date=2026-06-18 --var ticket_no=GD-002
|
||||
```
|
||||
|
||||
输出诊断日志:
|
||||
|
||||
```bash
|
||||
dist/docfill-darwin-arm64 run -c task.json --verbose
|
||||
```
|
||||
|
||||
重新生成本地测试素材:
|
||||
|
||||
```bash
|
||||
/Users/zhaoyilun/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/bin/python3 scripts/make-manual-test-materials.py
|
||||
```
|
||||
|
||||
运行自动化冒烟测试:
|
||||
|
||||
```bash
|
||||
bash scripts/smoke.sh
|
||||
```
|
||||
|
||||
Smoke test 会:
|
||||
运行 Go 测试:
|
||||
|
||||
- 跑全量 Go 测试。
|
||||
- 构建临时 `docfill` 二进制。
|
||||
- 复制 `examples/` 到临时目录。
|
||||
- 生成临时 Excel、Word、SQLite 示例数据。
|
||||
- 执行两个示例任务并检查输出文件。
|
||||
```bash
|
||||
go test -count=1 ./...
|
||||
```
|
||||
|
||||
## Digital Employee Runbook
|
||||
## 筛选配置示例
|
||||
|
||||
给数字员工或调度脚本使用时,看:
|
||||
Excel 工单表:
|
||||
|
||||
- `docs/digital-employee-runbook.md`
|
||||
```text
|
||||
日期 工单编号 客户名称 系统来源 处理结果 下一步
|
||||
2026-06-18 GD-001 A 公司 PMS3.0 已派单 等待现场反馈
|
||||
2026-06-18 GD-002 B 公司 D5000 已完成 归档并同步日报
|
||||
2026-06-19 GD-001 C 公司 风控平台 待复核 补充截图
|
||||
```
|
||||
|
||||
## Runnable Examples
|
||||
|
||||
示例配置在 `examples/`:
|
||||
|
||||
- `examples/excel-to-word/task.json`
|
||||
- `examples/sqlite-to-excel/task.json`
|
||||
|
||||
示例里的二进制 Office/SQLite 文件由 `scripts/smoke-fixtures` 临时生成,不提交到仓库。
|
||||
|
||||
## Excel Data Example
|
||||
`task.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -82,63 +154,88 @@ Smoke test 会:
|
||||
},
|
||||
"data": {
|
||||
"type": "excel",
|
||||
"path": "./data.xlsx",
|
||||
"sheet": "Sheet1",
|
||||
"path": "./source_work_orders.xlsx",
|
||||
"sheet": "工单",
|
||||
"header_row": 1
|
||||
},
|
||||
"filter": {
|
||||
"equals": {
|
||||
"日期": "{{date}}",
|
||||
"工单编号": "{{ticket_no}}"
|
||||
},
|
||||
"expect": "one"
|
||||
},
|
||||
"template": {
|
||||
"path": "./template.docx"
|
||||
"path": "./work_order_template.docx"
|
||||
},
|
||||
"output": {
|
||||
"path": "./out/report_{{date}}_{{name}}_{{_row}}.docx",
|
||||
"overwrite": false
|
||||
"path": "./out/work_order_{{日期}}_{{工单编号}}.docx",
|
||||
"overwrite": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Excel 第一行是字段名,后续每一行生成一个文件。
|
||||
运行:
|
||||
|
||||
## SQLite Data Example
|
||||
|
||||
```json
|
||||
{
|
||||
"vars": {
|
||||
"date": "2026-06-18"
|
||||
},
|
||||
"data": {
|
||||
"type": "sqlite",
|
||||
"path": "./data.db",
|
||||
"query": "select name, date, done from daily_report where date = ?",
|
||||
"params": ["{{date}}"]
|
||||
},
|
||||
"template": {
|
||||
"path": "./template.xlsx"
|
||||
},
|
||||
"output": {
|
||||
"path": "./out/report_{{name}}_{{_row}}.xlsx"
|
||||
}
|
||||
}
|
||||
```bash
|
||||
dist/docfill-darwin-arm64 run -c task.json --var date=2026-06-18 --var ticket_no=GD-002
|
||||
```
|
||||
|
||||
SQL 查询结果的列名就是模板占位符字段名。
|
||||
筛选含义:
|
||||
|
||||
## P0 Rules
|
||||
```text
|
||||
找到 日期 = 2026-06-18,并且 工单编号 = GD-002 的那一行。
|
||||
```
|
||||
|
||||
- 配置里的相对路径按 `task.json` 所在目录解析。
|
||||
- `vars` 可以提供默认变量,命令行 `--var key=value` 会覆盖同名默认变量。
|
||||
- 模板填充时,每行数据字段优先于 `vars`。
|
||||
- `_row` 是内置变量,表示当前数据行序号,从 `1` 开始。
|
||||
- SQLite `params` 对应 SQL 里的 `?` 参数。
|
||||
- Excel `header_row` 从 `1` 开始,默认是 `1`。
|
||||
- 默认不覆盖已有输出文件;只有 `output.overwrite: true` 才允许覆盖。
|
||||
- 输出文件路径中的字段值会清理 `/ \ : * ? " < > |`。
|
||||
- 模板里缺字段或渲染后仍有 `{{字段}}`,会直接失败。
|
||||
- Word 模板支持同一段落内被拆开的文本占位符,例如 `{{na` 和 `me}}` 位于相邻文本节点。
|
||||
`filter.expect` 支持:
|
||||
|
||||
## MVP Limits
|
||||
- `one`: 必须只匹配一行,适合工单、单份日报、单个报表。
|
||||
- `many`: 允许匹配多行,适合按日期生成多个人或多个部门的报表。
|
||||
|
||||
- 只支持 JSON 配置。
|
||||
- 只支持 `.xlsx` 数据源、SQLite 数据源。
|
||||
- 只支持 `.docx` 和 `.xlsx` 模板。
|
||||
- Word 占位符拆分只做最小兼容:支持同一段落内的文本节点拆分,不做复杂表格循环或样式级模板语法。
|
||||
- 不做 Web、权限、审批流、模板设计器或业务系统直连。
|
||||
未配置 `filter` 时,工具沿用旧行为:读取到的每一行都会生成一个输出文件。
|
||||
|
||||
## 核心规则
|
||||
|
||||
- 配置文件使用 JSON。
|
||||
- 数据源支持 `.xlsx` 和 SQLite `.db`。
|
||||
- 模板与输出支持 `.docx` 和 `.xlsx`。
|
||||
- 模板占位符格式为 `{{字段名}}`。
|
||||
- Excel 数据的表头行提供字段名,SQLite 查询结果的列名提供字段名。
|
||||
- 常用场景是通过 `filter.equals` 先筛选数据,再填充模板。
|
||||
- 多个筛选条件之间是“全部满足”关系。
|
||||
- 筛选只支持等值匹配,不支持模糊匹配、范围查询、OR 或复杂表达式。
|
||||
- 复杂情况建议业务人员整理 Excel,例如新增“填报批次”“业务唯一标识”等辅助列。
|
||||
- `vars` 提供默认变量,命令行 `--var key=value` 可以覆盖同名变量。
|
||||
- 数据行字段优先于 `vars` 和 `--var`。
|
||||
- `_row` 是内置变量,表示当前输出对应的结果行序号,从 `1` 开始。
|
||||
- 默认不覆盖已存在文件,只有 `output.overwrite: true` 才允许覆盖。
|
||||
- 成功结果写入 stdout,诊断日志和错误写入 stderr,便于数字员工或调度脚本判断执行结果。
|
||||
|
||||
## 退出码
|
||||
|
||||
- `0`: 执行成功。
|
||||
- `1`: 配置、数据、模板或输出处理失败。
|
||||
- `2`: 命令行参数错误。
|
||||
|
||||
错误输出格式:
|
||||
|
||||
```text
|
||||
docfill: [ERROR_CODE] message
|
||||
hint: repair suggestion
|
||||
context: key=value
|
||||
```
|
||||
|
||||
常见筛选错误:
|
||||
|
||||
- `DATA_FILTER_FIELD`: 筛选字段不在数据表中。
|
||||
- `DATA_FILTER_VALUE`: 筛选条件引用的变量没有提供。
|
||||
- `DATA_FILTER_NO_MATCH`: 没有找到符合条件的数据行。
|
||||
- `DATA_FILTER_MULTI_MATCH`: 期望匹配一行,但实际匹配多行。
|
||||
|
||||
完整错误码、日志说明和集成建议见 [HOWTO.md](HOWTO.md)。
|
||||
|
||||
## 文档索引
|
||||
|
||||
- [HOWTO.md](HOWTO.md): 完整使用说明,包含最小实践、详细配置、输入输出示例、错误处理和数字员工调用建议。
|
||||
- [manual_tests/README.md](manual_tests/README.md): 本地真实测试素材说明。
|
||||
- [docs/digital-employee-runbook.md](docs/digital-employee-runbook.md): 面向数字员工或调度脚本的最小运行约定。
|
||||
|
||||
Reference in New Issue
Block a user