当前原型的价值是结构简单、可以在一台门店电脑上完整验证。它适合开发、受控试用和单机功能确认,但不适合直接复制到几十台设备。
一、当前技术栈
| 组件 | 当前实现 | 主要职责 |
|---|---|---|
| 微信小程序 | JavaScript + WXML + WXSS | 用户首页、上传、打印配置、订单和状态 |
| API | Node.js + Fastify | 登录、文件、报价、订单、任务和代理接口 |
| 数据库 | SQLite | 保存用户、门店、打印机、订单和任务 |
| 文件 | API 本地上传目录 | 保存受控测试文件 |
| 门店代理 | Node.js + PowerShell | 心跳、领取任务、下载校验和调用打印工具 |
| PDF 打印 | SumatraPDF 3.6.1 | 静默把 PDF 提交给指定 Windows 队列 |
| 驱动 | Epson 官方 Windows 驱动 | 把队列作业交给 L3250 |
| 自启动 | Windows 登录后计划任务 | 监督 API 和代理进程 |
二、代码结构
主要目录可以概括为:
zhenhaoyin-platform/
├─ apps/
│ ├─ miniprogram/ 微信小程序
│ ├─ api/ Fastify API、SQLite 与上传目录
│ └─ agent/ Windows 门店打印代理
├─ docs/ 架构、API、打印、生产和验收文档
├─ scripts/windows/ Windows 启动、预览与测试脚本
└─ output/pdf/ 系统工程 PDF 手册
API 的核心代码位于 apps/api/src/,代理核心代码位于 apps/agent/src/。小程序通过统一请求工具调用 API。
三、一次任务如何执行
1. API 启动
API 打开 SQLite 数据库,初始化默认门店和打印机,创建上传目录并监听小程序和代理请求。
2. 小程序加载首页
首页请求门店、打印机和常用服务。当前原型为了快速验证,部分流程默认取第一家门店和第一台打印机。
3. 用户上传文件
文件传到 API 本地目录,API 完成格式、大小、PDF 页数或图片尺寸检查,再生成文件记录。
4. 创建订单
API 根据文件和打印参数生成订单。当前使用模拟支付,支付完成后生成一条打印任务。
5. 代理领取
门店代理使用配置中的打印机标识和 Windows 队列名,轮询 API 领取任务。进程级 busy 防止一次处理多个作业。
6. 文件下载和校验
代理下载文件,对比长度和 SHA-256。失败时不接触打印机,并向 API 报告可诊断错误。
7. 提交打印
PDF、JPG 和 PNG 当前都直接交给 SumatraPDF 静默打印。打印工具明确指定 EPSON L3250 Series,避免落到 Windows 默认打印机。
8. 结果回传
代理先上报 printing,然后调用 SumatraPDF,最后上报完成、失败或需要人工确认;当前没有独立的 submitted 状态接口,Spooler 作业号随终态结果回传。中心 API 更新任务和订单,小程序查询后显示最终结果。
四、当前已有的可靠性设计
用户请求幂等
创建订单使用 (user_id, client_request_id) 唯一约束。用户重复点击、网络重发或页面恢复时返回同一订单。
一单一任务
每个订单只允许一条打印任务,阻止重复支付回调或接口重试生成多次打印。
尝试号和租约
代理领取任务时使用尝试号和处理租约。当前实现只在特定 processing 更新中校验请求尝试号,尚未做到所有状态更新都携带并验证独立 lease_token;完整栅栏协议属于生产化改造项。
人工确认状态
如果打印工具可能已经提交任务,但代理无法确定结果,使用 attention_required,不自动重打。
原子回执
代理当前会为完成或需要人工确认的终态保存 JSON 回执,再向 API 重复上报。提交前 prepared 回执、独立 submitted 回执和本地回执数据库尚未实现,是防止崩溃窗口重复打印的重点改造项。状态上报的网络失败不应触发重新打印。
五、当前单机假设在哪里
后续扩展前必须处理以下位置:
apps/api/src/app.js中首页和报价流程存在默认第一家门店、第一台打印机的选择。apps/api/src/database.js初始化硬编码默认打印机。apps/api/src/config.js使用本地 SQLite 路径、本地上传目录和模拟支付配置。apps/agent/src/config.js只有一个printerName。apps/agent/src/index.js使用进程级全局busy,且多个平台打印机标识可能共享同一上报状态。
这些并不代表原型错误,而是验证阶段为了减少变量做出的范围控制。规模化时不能仅复制进程和修改队列名,而要重构设备路由、并发隔离和中心存储。
六、受控启动方式
当前 Windows 计划任务在用户登录后监督 API 和代理。这种方式便于开发人员看到进程并快速排错,但有三个限制:
- 无人值守重启后可能停在登录界面。
- 用户注销会影响进程。
- 权限、日志轮转和升级不如标准服务清晰。
生产门店应把代理打包为 Windows Service,使用专用最小权限账户,配置自动启动、崩溃恢复、日志轮转、磁盘保护、时间同步检查和签名升级。
七、何时保留当前方案
以下场景可以继续使用单机原型:
- 开发调试
- 单台打印机功能验证
- 门店受控演示
- 不收真实费用的小范围试用
- 新打印机型号的兼容性实验
一旦涉及公开收费、两台以上打印机、多个门店或无人值守,就应切换到下一章的中心化架构。