Kaynağa Gözat

docs: 补充USB小票照片复刻设计

lq 1 ay önce
ebeveyn
işleme
4598c949b9

+ 92 - 0
docs/superpowers/specs/2026-07-31-usb-ticket-photo-layout-design.md

@@ -0,0 +1,92 @@
+# USB 小票照片复刻设计
+
+> 日期:2026-07-31  
+> 范围:仅调整 USB/CSN 打印路径,串口打印路径保持不变
+
+## 目标
+
+将 USB 热敏打印小票复刻为参考照片中的信息层级和视觉结构。保留现有业务字段来源、数字票生成流程和二维码内容,不修改车辆入场、结算或扫码出场逻辑。
+
+## 票面结构
+
+USB 小票自上而下按以下顺序打印:
+
+```text
+            Parking Ticket       Font A、双宽、加粗、居中
+               {lotName}         Font B、居中
+------------------------------------------  Font B、42 字符
+
+       PARK AT YOUR OWN RISK     Font B、居中
+{lotName} A-General Car          Font B、左对齐
+In-Time::{entryTime}             Font A、左对齐
+InGate::{channelCode}            Font A、左对齐,可选
+Slip No::{ticketID}              Font A、左对齐
+Veh No::{plateNo}                Font A、双宽、加粗、可选
+
+             [二维码]            居中,宽度参数 8
+
+       SCAN AND PAY WITH NEW     Font B、居中
+        THE CANADIA BANK APP     Font B、居中
+
+
+              [全切纸]
+```
+
+## 字段映射
+
+| 票面字段 | 数据来源 | 规则 |
+|---|---|---|
+| 停车场名称 | `parking_lot.lot_name` | 标题下方显示一次,并在车型行再次显示 |
+| 车型 | 固定文本 | `A-General Car` |
+| 入场时间 | 打印时的本地时间 | 格式 `02-01-2006 15:04:05` |
+| 入口 | API 请求的 `channel_code` | 空值时省略整行 |
+| 票号 | `digital_ticket.id` | `Slip No::{id}` |
+| 车牌 | API 请求的 `plate_number` | 空值时省略整行 |
+| 二维码 | `digital_ticket.ticket_no` | 保留现有 32 位十六进制票号内容 |
+
+## 排版指令
+
+- 初始化后使用原始 ESC/POS 指令打印文字,继续绕开参数传递不稳定的 `Pos_Text`。
+- 标题使用 Font A、双宽、加粗、居中;双宽使用标准 ESC/POS `GS ! 0x10`,打印后使用 `GS ! 0x00` 恢复正常尺寸并关闭粗体。
+- 副标题、风险提示、停车场车型行和支付提示使用 Font B。
+- 时间、入口和票号使用 Font A 正常尺寸。
+- 车牌使用 Font A、`GS ! 0x10` 双宽和加粗;打印后立即恢复正常尺寸和粗细。
+- 顶部分隔线使用 42 个短横线,以 Font B 打印,匹配 80mm 票纸有效宽度。
+- 移除当前 USB 票面中信息块之间的额外分隔线。
+- 二维码继续调用 CSN SDK 的 `Pos_Qrcode`,宽度参数由 4 调整为 8。
+- 二维码前后使用紧凑走纸;支付提示后保留切刀需要的尾部空间,再执行全切。
+
+## 代码结构
+
+将 USB 票面的排版定义从设备调用中抽离为可测试的操作序列:
+
+- 纯布局函数负责生成文字、对齐、字号、二维码、走纸和切纸操作的有序列表。
+- CSN 执行器负责把操作映射到 `Csn_WriteData`、`csn_QRCode`、走纸和切纸函数。
+- `PrintTicket` 仍负责读取打印机配置、打开端口、执行票面和更新设备状态。
+- 串口分支不调用新的 USB 布局函数,行为保持不变。
+
+## 错误处理
+
+- 本次不改变现有端口打开和 DLL 加载策略。
+- USB 原始字节写入返回 0 或短写时,执行器返回错误,不把打印机状态更新为 `online`。
+- 二维码和切纸 SDK 函数当前没有可靠返回值,保持现有调用方式。
+
+## 测试
+
+新增 USB 布局单元测试,至少验证:
+
+- 字段严格按照片顺序出现。
+- 标题和车牌前后包含正确的字号、粗体和复位指令。
+- 入口和车牌为空时对应行被省略。
+- 只生成一条 42 字符分隔线。
+- 二维码操作位于车牌之后、支付提示之前,宽度为 8。
+- 支付提示分为 `SCAN AND PAY WITH NEW` 和 `THE CANADIA BANK APP` 两行。
+- 串口路径不受 USB 布局改动影响。
+
+## 不在本次范围内
+
+- 串口票面同步改版。
+- 打印机配置管理页面。
+- DLL 路径配置化。
+- 中文字符集转换。
+- 入场记录与打印失败的事务补偿。