From 1c4187cb29db3b42f3a0b97dfebbf8659326590c Mon Sep 17 00:00:00 2001 From: Developer Date: Thu, 12 Feb 2026 07:14:10 +0000 Subject: [PATCH] Initial commit: Receipt Printer design docs and examples --- PROJECT.md | 125 +++++++ README.md | 67 ++++ docs/api.md | 425 ++++++++++++++++++++++ docs/design.md | 389 ++++++++++++++++++++ package.json | 30 ++ templates/examples/daily-todo.yaml | 58 +++ templates/examples/fancy-receipt.yaml | 190 ++++++++++ templates/examples/food-order-simple.yaml | 88 +++++ templates/examples/long-text.yaml | 75 ++++ templates/examples/ticket-list.yaml | 107 ++++++ 10 files changed, 1554 insertions(+) create mode 100644 PROJECT.md create mode 100644 README.md create mode 100644 docs/api.md create mode 100644 docs/design.md create mode 100644 package.json create mode 100644 templates/examples/daily-todo.yaml create mode 100644 templates/examples/fancy-receipt.yaml create mode 100644 templates/examples/food-order-simple.yaml create mode 100644 templates/examples/long-text.yaml create mode 100644 templates/examples/ticket-list.yaml diff --git a/PROJECT.md b/PROJECT.md new file mode 100644 index 0000000..08ceb07 --- /dev/null +++ b/PROJECT.md @@ -0,0 +1,125 @@ +# Receipt Printer 项目 + +## 项目概述 +一个基于 WiFi ESC/POS 协议的 80mm 小票打印系统,支持: +- 可视化模板配置(YAML + 实时预览) +- REST API 调用打印 +- 自动从模板提取数据 Schema +- 多种排版元素(文本、表格、图片、条码等) + +## 技术栈 +- **Runtime**: Bun +- **Web 框架**: Hono +- **模板引擎**: Mustache +- **配置格式**: YAML + +## 项目结构 +``` +receipt-printer/ +├── README.md # 项目说明 +├── package.json # 依赖配置 +├── docs/ +│ ├── design.md # 系统设计文档 +│ └── api.md # API 规范 +├── templates/examples/ # 示例模板 +│ ├── daily-todo.yaml # 每日待办 +│ ├── food-order-simple.yaml # 餐饮订单 +│ ├── fancy-receipt.yaml # 精致账单 +│ ├── ticket-list.yaml # Ticket 列表 +│ └── long-text.yaml # 长文阅读 +└── src/ # 源码目录(待开发) +``` + +## 核心设计决策 + +### 1. 模板配置格式 +使用 YAML 而非 JSON: +- 支持注释 +- 多行字符串更友好 +- 编辑器支持语法高亮 + +### 2. Schema 自动生成 +- 从模板中的 `{{变量}}` 自动提取 +- 无需手动维护数据结构 +- API 可 introspect 获取数据要求 + +### 3. 块类型系统 +| 类型 | 用途 | +|------|------| +| text | 普通文本(支持样式) | +| row | 多列行布局 | +| table | 多列表格 | +| list | 循环渲染数组 | +| divider | 分隔线 | +| image | 图片 | +| barcode | 条码/二维码 | +| space | 空行 | + +### 4. 样式支持 +- 对齐:left/center/right +- 字体大小:small/normal/large/xlarge +- 文本样式:bold/italic/underline +- 间距:lineHeight/marginTop/marginBottom + +## API 设计概览 + +``` +POST /api/print/:templateId # 打印 +GET /api/templates # 列出模板 +GET /api/templates/:id # 获取模板 +POST /api/templates # 创建模板 +PUT /api/templates/:id # 更新模板 +DELETE /api/templates/:id # 删除模板 +GET /api/templates/:id/schema # 获取数据 Schema +GET /api/jobs/:id # 查询任务状态 +GET /api/printer/status # 打印机状态 +POST /api/printer/test # 打印测试页 +``` + +## 下一步开发计划 + +1. **核心引擎** + - YAML 模板解析 + - Mustache 数据绑定 + - ESC/POS 指令生成 + +2. **打印驱动** + - WiFi 打印机连接 + - 指令发送队列 + - 状态轮询 + +3. **Web 服务** + - Hono HTTP 服务 + - REST API 实现 + - 静态文件服务 + +4. **配置界面** + - YAML 编辑器(CodeMirror) + - 实时预览(HTML 模拟) + - 数据模拟器 + +5. **示例与文档** + - 更多模板示例 + - API 使用示例 + - 部署指南 + +## 示例模板使用 + +```bash +# 打印每日待办 +curl -X POST http://localhost:3000/api/print/daily-todo \ + -H "Content-Type: application/json" \ + -d '{ + "data": { + "date": "2025-02-12", + "tasks": [ + {"status": "☐", "title": "修复 Bug #123"}, + {"status": "☑", "title": "代码审查"} + ], + "completedCount": 1 + } + }' + +# 获取模板 Schema +curl http://localhost:3000/api/print/daily-todo/schema +``` diff --git a/README.md b/README.md new file mode 100644 index 0000000..62be007 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# Receipt Printer - 80mm 小票打印系统 + +基于 WiFi ESC/POS 的 80mm 小票打印系统,支持可视化模板配置和 REST API 调用。 + +## 核心特性 + +- 🎨 **可视化模板配置** - Web 界面实时编辑和预览 +- 📝 **YAML/JSON 模板** - 声明式排版配置 +- 🔌 **REST API** - 通过 HTTP 调用打印 +- 📐 **自动 Schema 提取** - 从模板变量自动生成数据契约 +- 🖨️ **WiFi ESC/POS** - 支持主流 80mm 热敏打印机 + +## 技术栈 + +- **后端**: Bun + Hono (轻量高性能) +- **模板引擎**: 自研 YAML → ESC/POS 转换器 +- **前端**: 原生 HTML/JS (轻量化) +- **打印机协议**: ESC/POS over TCP + +## 项目结构 + +``` +├── docs/ # 设计文档 +├── templates/ # 模板文件 +├── src/ # 源码 +│ ├── server.ts # HTTP 服务 +│ ├── printer.ts # 打印机驱动 +│ ├── template.ts # 模板引擎 +│ └── static/ # Web 界面 +└── README.md +``` + +## 快速开始 + +```bash +# 安装依赖 +bun install + +# 配置打印机 +bun run config + +# 启动服务 +bun run start + +# 打开配置页面 +open http://localhost:3000 +``` + +## API 示例 + +```bash +# 打印模板 +curl -X POST http://localhost:3000/api/print/daily-todo \ + -H "Content-Type: application/json" \ + -d '{ + "data": { + "date": "2025-02-12", + "tasks": [ + {"status": "☐", "title": "修复 Bug #123"} + ] + } + }' +``` + +## 许可证 + +MIT diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..9de9ca3 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,425 @@ +# API 规范 + +## 基础信息 + +``` +Base URL: http://localhost:3000/api +Content-Type: application/json +``` + +## 端点列表 + +### 1. 打印 + +#### 执行打印 + +``` +POST /print/:templateId +``` + +**请求体:** + +```json +{ + "data": { + "date": "2025-02-12", + "tasks": [ + {"status": "☐", "title": "修复 Bug #123"}, + {"status": "☑", "title": "代码审查"} + ] + }, + "options": { + "copies": 1, + "cutPaper": true + } +} +``` + +**参数说明:** + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `data` | object | 是 | 模板数据,结构由模板 Schema 定义 | +| `options.copies` | number | 否 | 打印份数,默认 1 | +| `options.cutPaper` | boolean | 否 | 是否切纸,默认 true | + +**成功响应 (200):** + +```json +{ + "success": true, + "jobId": "job_abc123", + "status": "queued", + "estimatedTime": "5s" +} +``` + +**错误响应 (400/404/500):** + +```json +{ + "success": false, + "error": { + "code": "VALIDATION_ERROR", + "message": "数据验证失败", + "details": [ + "tasks: 必填字段缺失" + ] + } +} +``` + +**错误码说明:** + +| 错误码 | HTTP 状态 | 说明 | +|--------|-----------|------| +| `TEMPLATE_NOT_FOUND` | 404 | 模板不存在 | +| `VALIDATION_ERROR` | 400 | 数据验证失败 | +| `PRINTER_OFFLINE` | 503 | 打印机离线 | +| `TEMPLATE_RENDER_ERROR` | 500 | 模板渲染失败 | +| `PRINT_FAILED` | 500 | 打印失败 | + +--- + +### 2. 模板管理 + +#### 列出所有模板 + +``` +GET /templates +``` + +**响应:** + +```json +{ + "success": true, + "templates": [ + { + "id": "daily-todo", + "name": "每日待办", + "description": "打印今日待办事项列表", + "updatedAt": "2025-02-12T07:00:00Z" + } + ] +} +``` + +#### 获取单个模板 + +``` +GET /templates/:id +``` + +**响应:** + +```json +{ + "success": true, + "template": { + "id": "daily-todo", + "name": "每日待办", + "config": { /* 完整模板配置 */ } + } +} +``` + +#### 创建模板 + +``` +POST /templates +``` + +**请求体:** + +```json +{ + "id": "food-order", + "name": "餐饮订单", + "description": "打印餐饮订单小票", + "config": { + "name": "餐饮订单", + "width": "80mm", + "blocks": [ /* 块定义 */ ] + } +} +``` + +**响应:** + +```json +{ + "success": true, + "template": { + "id": "food-order", + "name": "餐饮订单", + "createdAt": "2025-02-12T07:00:00Z" + } +} +``` + +#### 更新模板 + +``` +PUT /templates/:id +``` + +**请求体:**(同创建,可部分更新) + +```json +{ + "name": "新的名称", + "config": { /* 新配置 */ } +} +``` + +#### 删除模板 + +``` +DELETE /templates/:id +``` + +**响应:** + +```json +{ + "success": true, + "message": "模板已删除" +} +``` + +--- + +### 3. 模板 Schema + +#### 获取模板数据 Schema + +``` +GET /templates/:id/schema +``` + +用于获取模板所需的数据结构和示例。 + +**响应:** + +```json +{ + "success": true, + "templateId": "food-order", + "schema": { + "type": "object", + "required": ["orderId", "items"], + "properties": { + "orderType": { + "type": "string", + "description": "订单类型" + }, + "orderId": { + "type": "string", + "description": "订单编号" + }, + "items": { + "type": "array", + "description": "商品列表", + "items": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "quantity": { "type": "number" }, + "price": { "type": "number" } + } + } + } + } + }, + "example": { + "orderType": "外带", + "orderId": "35205-1", + "items": [ + { "name": "双层吉士堡", "quantity": 1, "price": 22 } + ] + } +} +``` + +--- + +### 4. 打印任务 + +#### 查询任务状态 + +``` +GET /jobs/:jobId +``` + +**响应:** + +```json +{ + "success": true, + "job": { + "id": "job_abc123", + "templateId": "daily-todo", + "status": "completed", + "createdAt": "2025-02-12T07:00:00Z", + "startedAt": "2025-02-12T07:00:01Z", + "completedAt": "2025-02-12T07:00:05Z" + } +} +``` + +**状态值:** +- `queued` - 排队中 +- `printing` - 打印中 +- `completed` - 完成 +- `failed` - 失败 +- `cancelled` - 已取消 + +#### 列出最近任务 + +``` +GET /jobs?limit=10&status=completed +``` + +**查询参数:** + +| 参数 | 类型 | 说明 | +|------|------|------| +| `limit` | number | 返回数量,默认 10 | +| `status` | string | 按状态筛选 | +| `templateId` | string | 按模板筛选 | + +#### 取消任务 + +``` +DELETE /jobs/:jobId +``` + +仅可取消 `queued` 状态的任务。 + +--- + +### 5. 打印机管理 + +#### 获取打印机状态 + +``` +GET /printer/status +``` + +**响应:** + +```json +{ + "success": true, + "printer": { + "name": "XP-80C", + "ip": "192.168.1.100", + "port": 9100, + "status": "online", + "paperStatus": "ok", + "coverStatus": "closed", + "queueLength": 0 + } +} +``` + +**状态值:** +- `online` - 在线 +- `offline` - 离线 +- `error` - 错误(查看 `errorCode`) + +#### 打印测试页 + +``` +POST /printer/test +``` + +打印一张测试页,用于检查连接和打印质量。 + +**响应:** + +```json +{ + "success": true, + "jobId": "job_test_123" +} +``` + +#### 更新打印机配置 + +``` +POST /printer/config +``` + +**请求体:** + +```json +{ + "ip": "192.168.1.100", + "port": 9100, + "width": 80 +} +``` + +--- + +## 认证(可选) + +如需简单保护,在配置文件中启用 API Key: + +```yaml +security: + enabled: true + apiKey: "your-secret-key" +``` + +启用后,所有请求需携带 Header: + +``` +X-API-Key: your-secret-key +``` + +未提供或错误的 Key 返回: + +```json +{ + "success": false, + "error": { + "code": "UNAUTHORIZED", + "message": "无效的 API Key" + } +} +``` + +--- + +## WebSocket 实时状态(可选) + +如需实时推送打印状态,可连接 WebSocket: + +``` +ws://localhost:3000/ws +``` + +**事件类型:** + +```json +// 任务状态更新 +{ + "type": "jobUpdate", + "data": { + "jobId": "job_abc123", + "status": "printing" + } +} + +// 打印机状态更新 +{ + "type": "printerUpdate", + "data": { + "status": "online", + "paperStatus": "low" + } +} +``` diff --git a/docs/design.md b/docs/design.md new file mode 100644 index 0000000..2d2fa91 --- /dev/null +++ b/docs/design.md @@ -0,0 +1,389 @@ +# 系统设计文档 + +## 1. 系统架构 + +``` +┌─────────────────────────────────────────────────────────┐ +│ 小票打印系统 (本地服务) │ +├─────────────────────────────────────────────────────────┤ +│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ +│ │ Web 配置页 │◄──►│ 模板引擎 │◄──►│ 打印机 │ │ +│ │ (Vue/React) │ │ (渲染/ESC-POS)│ │ (WiFi ESC)│ │ +│ └──────────────┘ └──────────────┘ └───────────┘ │ +│ ▲ │ +│ │ REST API │ +│ ▼ │ +│ ┌──────────────┐ │ +│ │ 外部调用端 │ ← 脚本、IFTTT、快捷指令等 │ +│ │ (curl/HTTP) │ │ +│ └──────────────┘ │ +└─────────────────────────────────────────────────────────┘ +``` + +### 数据流 + +1. **配置阶段**: Web 页创建/编辑模板 → 保存为 YAML 配置 +2. **调用阶段**: POST 数据到 `/api/print/:templateId` → 模板引擎渲染 → 生成 ESC/POS 指令 → 发送到打印机 + +## 2. 模板系统 + +### 2.1 模板结构 + +```yaml +# 模板元信息 +name: "每日待办" +id: "daily-todo" +width: 80mm +description: "打印今日待办事项列表" + +# 页面设置 +page: + marginTop: 2 + marginBottom: 3 + +# 默认样式 +defaults: + fontSize: normal + lineHeight: 1.0 + marginBottom: 0 + +# 内容块 +blocks: + # 文本块 + - type: text + content: "📋 {{date}} 待办" + align: center + fontSize: large + bold: true + marginBottom: 1 + + # 分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # 列表循环 + - type: list + data: "{{tasks}}" + itemTemplate: + - type: text + content: "[{{status}}] {{title}}" + fontSize: normal + marginBottom: 0 + + # 多列行 + - type: row + marginBottom: 1 + columns: + - content: "{{leftText}}" + align: left + width: 50% + bold: true + - content: "{{rightText}}" + align: right + width: 50% + + # 表格 + - type: table + marginBottom: 1 + columns: + - header: "商品" + align: left + width: 50% + - header: "数量" + align: center + width: 25% + - header: "金额" + align: right + width: 25% + data: "{{items}}" + + # 图片 + - type: image + src: "{{logoUrl}}" + align: center + maxWidth: 200 + + # 条码 + - type: barcode + format: "CODE128" # CODE128 | QR | EAN13 + data: "{{orderId}}" + align: center + height: 64 + + # 空行 + - type: space + lines: 2 +``` + +### 2.2 支持的块类型 + +| 类型 | 用途 | 关键属性 | +|------|------|---------| +| `text` | 普通文本 | `content`, `align`, `fontSize`, `bold`, `italic`, `underline`, `lineHeight`, `marginTop`, `marginBottom` | +| `list` | 循环渲染数组 | `data`, `itemTemplate` | +| `table` | 多列表格 | `columns`, `data` | +| `row` | 多列行布局 | `columns` | +| `divider` | 分隔线 | `char` | +| `image` | 图片/Logo | `src`, `align`, `maxWidth` | +| `barcode` | 条码/二维码 | `format`, `data`, `height` | +| `space` | 空行 | `lines` | + +### 2.3 样式属性 + +```yaml +# 对齐 +align: left | center | right + +# 字体大小 +fontSize: small | normal | large | xlarge + +# 文本样式 +bold: true | false +italic: true | false # 打印机支持时 +underline: true | false + +# 间距 +lineHeight: 1.0 # 行高倍数 +marginTop: 0 # 上方间距(行数) +marginBottom: 0 # 下方间距(行数) + +# 列宽(仅 row/table) +width: 50% | 20 # 百分比或字符数 +``` + +### 2.4 数据绑定 + +使用 Mustache 语法 `{{variable}}`: + +```yaml +content: "订单编号: {{orderId}}" +data: "{{items}}" # 列表数据源 +``` + +支持嵌套访问: +```yaml +content: "{{customer.name}} - {{customer.phone}}" +``` + +### 2.5 Schema 自动生成 + +系统从模板的 `{{变量}}` 自动提取数据结构: + +```yaml +# 模板示例 +blocks: + - content: "{{orderType}} - {{orderId}}" + - data: "{{items}}" +``` + +自动生成: +```json +{ + "type": "object", + "properties": { + "orderType": { "type": "string" }, + "orderId": { "type": "string" }, + "items": { "type": "array" } + } +} +``` + +通过 `GET /api/templates/:id/schema` 获取 Schema 和示例数据。 + +## 3. Web 配置页 + +### 3.1 核心功能 + +1. **模板编辑器** + - 左侧:YAML 代码编辑(语法高亮 + 错误提示) + - 右侧:实时预览(HTML 模拟小票效果) + +2. **块类型选择器** + - 快捷插入按钮(文本、表格、图片、分隔线等) + - 点击后插入模板代码片段 + +3. **数据模拟器** + - 基于 Schema 生成表单 + - 输入模拟数据测试渲染 + - 保存测试数据集 + +4. **打印机设置** + - IP 地址配置 + - 打印测试页 + - 打印队列状态 + +### 3.2 界面布局 + +``` +┌─────────────────────────────────────────────────────────┐ +│ [Logo] 小票打印机 [打印机状态 ●] │ +├────────────┬────────────────────────┬───────────────────┤ +│ │ │ │ +│ 模板列表 │ YAML 编辑器 │ 实时预览 │ +│ ─────── │ │ │ +│ daily-todo│ │ ┌─────────┐ │ +│ food-order│ - type: text │ │ 📋 待办 │ │ +│ ticket │ content: "..." │ │ ======= │ │ +│ │ │ │ [☐] ... │ │ +│ [+ 新建] │ │ └─────────┘ │ +│ │ │ │ +├────────────┴────────────────────────┴───────────────────┤ +│ 块类型: [文本] [表格] [图片] [分隔线] [条码] [空行] │ +└─────────────────────────────────────────────────────────┘ +``` + +## 4. 设计参考 + +### 4.1 餐饮小票(麦当劳风格) + +```yaml +blocks: + # 顶部双栏 + - type: row + columns: + - content: "外带" + align: left + - content: "订单编号: {{orderId}}" + align: right + - type: divider + char: "-" + + # 商品列表(带缩进备注) + - type: list + data: "{{items}}" + itemTemplate: + - type: text + content: "{{quantity}} {{name}}" + - type: list + data: "{{notes}}" + itemTemplate: + - type: text + content: " {{.}}" + fontSize: small + - type: divider + char: "-" + + # 取餐号(超大) + - type: text + content: "取餐柜取餐" + align: center + marginBottom: 0 + - type: text + content: "{{pickupNumber}}" + align: center + fontSize: xlarge + bold: true + marginBottom: 1 + + # 条码 + - type: barcode + format: "CODE128" + data: "{{pickupNumber}}" + align: center + + # 时间戳 + - type: row + columns: + - content: "MOBILE" + align: left + fontSize: small + - content: "{{timestamp}}" + align: right + fontSize: small +``` + +### 4.2 精致小票(铁板烧风格) + +```yaml +blocks: + # Logo 图片 + - type: image + src: "{{logoUrl}}" + align: center + maxWidth: 150 + marginBottom: 0 + + # 英文小字 + - type: text + content: "THE SOURCE OF THIS DESIGN MATERIAL IS TEPPANYAKI DESIGN" + align: center + fontSize: small + + # 中文标题 + - type: text + content: "铁板烧设计" + align: center + bold: true + marginBottom: 1 + + # 装饰分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # 表头 + - type: row + columns: + - content: "商品名称" + align: left + bold: true + width: 50% + - content: "数量" + align: center + bold: true + width: 25% + - content: "金额" + align: right + bold: true + width: 25% + + # 表格数据 + - type: table + columns: + - align: left + width: 50% + - align: center + width: 25% + - align: right + width: 25% + data: "{{items}}" + + # 汇总 + - type: divider + char: "=" + - type: row + columns: + - content: "小计" + align: left + - content: "¥{{subtotal}}" + align: right +``` + +## 5. 技术决策 + +### 5.1 为什么选择 YAML? + +- 比 JSON 更易手写(支持注释、多行字符串) +- 比纯代码更声明式(专注"是什么"而非"怎么做") +- 主流编辑器支持语法高亮和验证 + +### 5.2 为什么自动生成 Schema? + +- 降低用户负担(无需学习 JSON Schema) +- 保持数据和模板同步(一处修改,处处生效) +- 自动生成文档和表单 + +### 5.3 为什么用 HTML 预览? + +- 无需连接真实打印机即可调试 +- 跨平台、易实现 +- 样式可精确还原(CSS) + +## 6. 待决策事项 + +- [ ] 是否支持模板继承/复用? +- [ ] 是否支持条件渲染(if/else)? +- [ ] 是否支持自定义字体? +- [ ] 是否支持打印历史记录? +- [ ] 是否支持多打印机管理? diff --git a/package.json b/package.json new file mode 100644 index 0000000..0608e65 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "receipt-printer", + "version": "0.1.0", + "description": "80mm 小票打印系统 - 支持可视化模板配置和 REST API", + "main": "src/server.ts", + "scripts": { + "start": "bun run src/server.ts", + "dev": "bun run --watch src/server.ts", + "build": "bun build src/server.ts --outdir dist", + "test": "bun test" + }, + "dependencies": { + "hono": "^4.0.0", + "js-yaml": "^4.1.0", + "mustache": "^4.2.0" + }, + "devDependencies": { + "@types/js-yaml": "^4.0.9", + "@types/mustache": "^4.2.5", + "bun-types": "latest" + }, + "keywords": [ + "receipt", + "printer", + "esc-pos", + "thermal-printer", + "80mm" + ], + "license": "MIT" +} diff --git a/templates/examples/daily-todo.yaml b/templates/examples/daily-todo.yaml new file mode 100644 index 0000000..d9043e5 --- /dev/null +++ b/templates/examples/daily-todo.yaml @@ -0,0 +1,58 @@ +# 每日待办模板 + +name: "每日待办" +id: "daily-todo" +width: 80mm +description: "打印今日待办事项列表" + +defaults: + fontSize: normal + lineHeight: 1.0 + marginBottom: 0 + +page: + marginTop: 2 + marginBottom: 3 + +blocks: + # 标题 + - type: text + content: "📋 {{date}} 待办" + align: center + fontSize: large + bold: true + marginBottom: 1 + + # 分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # 待办列表 + - type: list + data: "{{tasks}}" + itemTemplate: + - type: text + content: "[{{status}}] {{title}}" + fontSize: normal + marginBottom: 0 + + # 空行 + - type: space + lines: 1 + + # 分隔线 + - type: divider + char: "-" + marginBottom: 1 + + # 统计 + - type: text + content: "共 {{tasks.length}} 项待办" + align: right + fontSize: small + + - type: text + content: "已完成 {{completedCount}} / {{tasks.length}}" + align: right + fontSize: small diff --git a/templates/examples/fancy-receipt.yaml b/templates/examples/fancy-receipt.yaml new file mode 100644 index 0000000..57beb93 --- /dev/null +++ b/templates/examples/fancy-receipt.yaml @@ -0,0 +1,190 @@ +# 精致小票模板(铁板烧风格) + +name: "精致账单" +id: "fancy-receipt" +width: 80mm +description: "带有 Logo 和详细商品信息的精致账单" + +defaults: + fontSize: normal + lineHeight: 1.0 + marginBottom: 0 + +page: + marginTop: 2 + marginBottom: 3 + +blocks: + # Logo 图片 + - type: image + src: "{{logoUrl}}" + align: center + maxWidth: 150 + marginBottom: 0 + + # 英文标语 + - type: text + content: "{{taglineEn}}" + align: center + fontSize: small + marginBottom: 0 + + # 中文店名 + - type: text + content: "{{shopName}}" + align: center + fontSize: large + bold: true + marginBottom: 1 + + # 装饰分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # 菜单标题 + - type: text + content: "{{menuTitle}}" + align: center + fontSize: normal + bold: true + marginBottom: 0 + + # 时间 + - type: text + content: "{{datetime}}" + align: center + fontSize: small + marginBottom: 1 + + # 表头 + - type: row + marginBottom: 0 + columns: + - content: "商品名称" + align: left + bold: true + width: 50% + - content: "数量" + align: center + bold: true + width: 25% + - content: "金额" + align: right + bold: true + width: 25% + + # 分隔线 + - type: divider + char: "=" + marginBottom: 0 + + # 商品表格 + - type: table + data: "{{items}}" + columns: + - align: left + width: 50% + - align: center + width: 25% + - align: right + width: 25% + + # 分隔线 + - type: divider + char: "=" + marginBottom: 0 + + # 汇总行 + - type: row + marginBottom: 0 + columns: + - content: "小计" + align: left + width: 50% + - content: "{{totalQuantity}}" + align: center + width: 25% + - content: "¥{{subtotal}}" + align: right + width: 25% + + - type: row + marginBottom: 0 + columns: + - content: "税收({{taxRate}})" + align: left + width: 50% + - content: "" + align: center + width: 25% + - content: "¥{{tax}}" + align: right + width: 25% + + - type: row + marginBottom: 0 + columns: + - content: "账单总额" + align: left + bold: true + width: 50% + - content: "" + align: center + width: 25% + - content: "¥{{total}}" + align: right + bold: true + width: 25% + + - type: row + marginBottom: 0 + columns: + - content: "折扣" + align: left + width: 50% + - content: "" + align: center + width: 25% + - content: "{{discount}}" + align: right + width: 25% + + # 分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # 签名区 + - type: text + content: "签名" + align: left + marginBottom: 1 + + # 装饰 + - type: text + content: "{{signature}}" + align: center + fontSize: large + italic: true + marginBottom: 1 + + # 底部分隔线 + - type: divider + char: "=" + marginBottom: 0 + + # 版权信息 + - type: row + marginBottom: 0 + columns: + - content: "★" + align: left + width: 10% + - content: "{{copyright}}" + align: center + fontSize: small + width: 80% + - content: "★" + align: right + width: 10% diff --git a/templates/examples/food-order-simple.yaml b/templates/examples/food-order-simple.yaml new file mode 100644 index 0000000..641d8db --- /dev/null +++ b/templates/examples/food-order-simple.yaml @@ -0,0 +1,88 @@ +# 餐饮订单模板(麦当劳风格) + +name: "餐饮订单" +id: "food-order-simple" +width: 80mm +description: "外带餐饮订单小票" + +defaults: + fontSize: normal + lineHeight: 1.0 + marginBottom: 0 + +page: + marginTop: 2 + marginBottom: 3 + +blocks: + # 顶部信息 + - type: row + marginBottom: 0 + columns: + - content: "{{orderType}}" + align: left + fontSize: normal + - content: "订单编号: {{orderId}}" + align: right + fontSize: normal + + # 分隔线 + - type: divider + char: "-" + marginBottom: 1 + + # 商品列表(带备注) + - type: list + data: "{{items}}" + itemTemplate: + - type: text + content: "{{quantity}} {{name}}" + marginBottom: 0 + - type: list + data: "{{notes}}" + itemTemplate: + - type: text + content: " 不要 {{.}}" + fontSize: small + - type: divider + char: "-" + marginBottom: 0 + + # 取餐信息 + - type: text + content: "取餐柜取餐" + align: center + fontSize: normal + marginTop: 1 + marginBottom: 0 + + - type: text + content: "{{pickupNumber}}" + align: center + fontSize: xlarge + bold: true + marginBottom: 1 + + # 条码 + - type: barcode + format: "CODE128" + data: "{{pickupNumber}}" + align: center + height: 64 + marginBottom: 1 + + # 分隔线 + - type: divider + char: "-" + marginBottom: 0 + + # 底部信息 + - type: row + marginBottom: 0 + columns: + - content: "MOBILE" + align: left + fontSize: small + - content: "{{timestamp}}" + align: right + fontSize: small diff --git a/templates/examples/long-text.yaml b/templates/examples/long-text.yaml new file mode 100644 index 0000000..4cd42e8 --- /dev/null +++ b/templates/examples/long-text.yaml @@ -0,0 +1,75 @@ +# 长文阅读模板 + +name: "长文阅读" +id: "long-text" +width: 80mm +description: "打印长篇文章或阅读材料" + +defaults: + fontSize: normal + lineHeight: 1.2 + marginBottom: 0 + +page: + marginTop: 2 + marginBottom: 3 + +blocks: + # 标题 + - type: text + content: "{{title}}" + align: center + fontSize: xlarge + bold: true + marginBottom: 0 + + # 作者 + - type: text + content: "作者: {{author}}" + align: center + fontSize: small + marginBottom: 0 + + # 日期 + - type: text + content: "{{publishDate}}" + align: center + fontSize: small + marginBottom: 1 + + # 分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # 正文段落 + - type: list + data: "{{paragraphs}}" + itemTemplate: + - type: text + content: "{{content}}" + align: left + lineHeight: 1.3 + marginBottom: 1 + + # 空行 + - type: space + lines: 2 + + # 分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # 阅读统计 + - type: text + content: "共 {{wordCount}} 字 | {{paragraphs.length}} 段落" + align: right + fontSize: small + marginBottom: 0 + + - type: text + content: "打印于 {{printDate}}" + align: right + fontSize: small + marginBottom: 0 diff --git a/templates/examples/ticket-list.yaml b/templates/examples/ticket-list.yaml new file mode 100644 index 0000000..889b41c --- /dev/null +++ b/templates/examples/ticket-list.yaml @@ -0,0 +1,107 @@ +# Ticket/Issue 列表模板 + +name: "Ticket 列表" +id: "ticket-list" +width: 80mm +description: "打印 GitHub/Jira 等 Ticket 或 Issue 列表" + +defaults: + fontSize: normal + lineHeight: 1.0 + marginBottom: 0 + +page: + marginTop: 2 + marginBottom: 3 + +blocks: + # 标题 + - type: text + content: "🎫 {{project}} Tickets" + align: center + fontSize: large + bold: true + marginBottom: 0 + + # 副标题 + - type: text + content: "{{filter}} - 共 {{tickets.length}} 条" + align: center + fontSize: small + marginBottom: 1 + + # 分隔线 + - type: divider + char: "=" + marginBottom: 1 + + # Ticket 列表 + - type: list + data: "{{tickets}}" + itemTemplate: + # Ticket 编号和状态 + - type: row + marginBottom: 0 + columns: + - content: "#{{id}}" + align: left + bold: true + width: 30% + - content: "[{{status}}]" + align: center + width: 35% + - content: "{{priority}}" + align: right + width: 35% + + # 标题 + - type: text + content: "{{title}}" + align: left + marginBottom: 0 + + # 标签 + - type: text + content: "标签: {{labels.join ', '}}" + align: left + fontSize: small + marginBottom: 0 + + # 负责人和时间 + - type: row + marginBottom: 0 + columns: + - content: "👤 {{assignee}}" + align: left + fontSize: small + width: 50% + - content: "📅 {{dueDate}}" + align: right + fontSize: small + width: 50% + + # 分隔线 + - type: divider + char: "-" + marginBottom: 1 + + # 底部统计 + - type: divider + char: "=" + marginBottom: 0 + + - type: text + content: "按状态统计:" + align: left + fontSize: small + bold: true + marginBottom: 0 + + - type: list + data: "{{statusStats}}" + itemTemplate: + - type: text + content: " {{status}}: {{count}}" + align: left + fontSize: small + marginBottom: 0