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