390 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 系统设计文档
## 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
- [ ] 是否支持自定义字体?
- [ ] 是否支持打印历史记录?
- [ ] 是否支持多打印机管理?