10 KiB
10 KiB
系统设计文档
1. 系统架构
┌─────────────────────────────────────────────────────────┐
│ 小票打印系统 (本地服务) │
├─────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Web 配置页 │◄──►│ 模板引擎 │◄──►│ 打印机 │ │
│ │ (Vue/React) │ │ (渲染/ESC-POS)│ │ (WiFi ESC)│ │
│ └──────────────┘ └──────────────┘ └───────────┘ │
│ ▲ │
│ │ REST API │
│ ▼ │
│ ┌──────────────┐ │
│ │ 外部调用端 │ ← 脚本、IFTTT、快捷指令等 │
│ │ (curl/HTTP) │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
数据流
- 配置阶段: Web 页创建/编辑模板 → 保存为 YAML 配置
- 调用阶段: POST 数据到
/api/print/:templateId→ 模板引擎渲染 → 生成 ESC/POS 指令 → 发送到打印机
2. 模板系统
2.1 模板结构
# 模板元信息
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 样式属性
# 对齐
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}}:
content: "订单编号: {{orderId}}"
data: "{{items}}" # 列表数据源
支持嵌套访问:
content: "{{customer.name}} - {{customer.phone}}"
2.5 Schema 自动生成
系统从模板的 {{变量}} 自动提取数据结构:
# 模板示例
blocks:
- content: "{{orderType}} - {{orderId}}"
- data: "{{items}}"
自动生成:
{
"type": "object",
"properties": {
"orderType": { "type": "string" },
"orderId": { "type": "string" },
"items": { "type": "array" }
}
}
通过 GET /api/templates/:id/schema 获取 Schema 和示例数据。
3. Web 配置页
3.1 核心功能
-
模板编辑器
- 左侧:YAML 代码编辑(语法高亮 + 错误提示)
- 右侧:实时预览(HTML 模拟小票效果)
-
块类型选择器
- 快捷插入按钮(文本、表格、图片、分隔线等)
- 点击后插入模板代码片段
-
数据模拟器
- 基于 Schema 生成表单
- 输入模拟数据测试渲染
- 保存测试数据集
-
打印机设置
- IP 地址配置
- 打印测试页
- 打印队列状态
3.2 界面布局
┌─────────────────────────────────────────────────────────┐
│ [Logo] 小票打印机 [打印机状态 ●] │
├────────────┬────────────────────────┬───────────────────┤
│ │ │ │
│ 模板列表 │ YAML 编辑器 │ 实时预览 │
│ ─────── │ │ │
│ daily-todo│ │ ┌─────────┐ │
│ food-order│ - type: text │ │ 📋 待办 │ │
│ ticket │ content: "..." │ │ ======= │ │
│ │ │ │ [☐] ... │ │
│ [+ 新建] │ │ └─────────┘ │
│ │ │ │
├────────────┴────────────────────────┴───────────────────┤
│ 块类型: [文本] [表格] [图片] [分隔线] [条码] [空行] │
└─────────────────────────────────────────────────────────┘
4. 设计参考
4.1 餐饮小票(麦当劳风格)
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 精致小票(铁板烧风格)
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)?
- 是否支持自定义字体?
- 是否支持打印历史记录?
- 是否支持多打印机管理?