Files
desktop-plugin/README.md
T
dzc 0a78ff1b58 feat: Windows PavoApi ffi 直打后端(Phase 3 代码完成,待实机验收)
- lib/print/pavo/:PavoApiW_x64.dll 的 dart:ffi 绑定(结构体布局对齐 C#,W 后缀导出名回退兼容)
- pavo_printer.dart:枚举(UTF-8/UTF-16 自动解码)/状态/色带信息/单卡直打/忙碌轮询(3 分钟超时)/LayerHolder 非托管内存管理
- pavo_backend.dart:全部 ffi 调用与像素转换跑在 Isolate.run,主 isolate HTTP 服务零阻塞
- lib/image/card_image.dart:PNG data URL → 纵横比选卡面 → 手动 alpha 铺白底 → BGR24/Gray8 紧凑像素(image 包 compositeImage 对全透明像素非 src-over 语义,改为逐像素混合对齐 C#)
- windows/ 目录:从 Flutter SDK windows.tmpl 手动实例化(mac 上 flutter create 拒绝生成的绕过),窗口标题"饭卡打印助手"
- windows/vendor/:收录 SDK 的 PavoApiW_x64.dll/PavoCardSDK_x64.dll/HeatTB3.dll/heatthcd.bin,CMake POST_BUILD 自动拷到 exe 旁
- backend.dart 工厂接通 Windows 分支;analyze 零问题、单测 12 个全过
2026-09-21 12:19:07 +08:00

90 lines
5.7 KiB
Markdown
Raw 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.
# desktop-plugin(饭卡打印站客户端 · Flutter 版)
用 Flutter 重写打印站客户端,替代 C# 版 card-printer-agent。HTTP 协议**完全不变**,前端(`biz-pc-cloud-zax/src/api/plugin/cardPrinter.ts`)零改动,两版助手可并存灰度替换。
- 目录名 `desktop-plugin`,Dart 包名 `desktop_plugin`(Dart 标识符不允许连字符)
- macOS bundle id:`com.zax.desktop-plugin`(`macos/Runner/Configs/AppInfo.xcconfig`)
- 总体计划见 `../card-printer-agent/flutter-client-plan.md`
## 协议(与 C# 版逐字段对齐)
监听 `127.0.0.1:38200`,被占用顺延 38201/38202;CORS `*`(含 OPTIONS 预检);响应统一 `{code, msg, data}`,code=0 成功;JSON 字段一律驼峰。
| 端点 | 说明 |
|---|---|
| `GET /manifest` | `{plugins:[…], agent:"desktop-plugin", backend:"pavo\|cups", mock}` |
| `GET /api/card-printer/status` | PrinterStatus(online/model/firmware/connection/ribbon/cardLow/cardLeft/status/statusText) |
| `POST /api/card-printer/print` | `{copies, front:{color,k?}, back:{color,k?}}` → `{taskId}` |
| `GET /api/card-printer/task/{taskId}` | `{taskId, state:printing\|done\|error, status, statusText}` |
任务串行执行(打印机物理一次一张),完成后保留 30 分钟。
## 目录结构
```
lib/
├── main.dart # Flutter 窗口入口(服务状态 + 打印机状态 + 运行日志)
├── agent.dart # 核心组合:参数解析 + 日志缓冲 + 后端/队列/服务装配(纯 Dart,无 Flutter 依赖)
├── server/
│ ├── protocol.dart # 协议 DTO(toJson 手写驼峰,对齐 C# ApiModels.cs)
│ ├── http_server.dart # shelf 服务:端口顺延、CORS、四端点
│ └── print_queue.dart # 串行任务队列 + 30 分钟清理
├── print/
│ ├── backend.dart # PrintBackend 抽象 + OS 工厂
│ ├── mock_backend.dart # --mock 模拟(打印 2.5s 完成)
│ ├── cups_backend.dart # macOS:lpoptions 发现队列 + lp 提交(参数列表传参防注入)
│ └── pavo/ # Windows:HiTi PavoApi ffi 直打
│ ├── pavo_ffi.dart # 结构体/导出绑定(PavoApiW_x64.dll,W 后缀回退兼容)
│ ├── pavo_printer.dart # 枚举/状态/色带/单卡直打/轮询/内存管理(对齐 C# PavoPrinter.cs)
│ └── pavo_backend.dart # 后端实现(全部跑在 Isolate.run,主 isolate 不阻塞)
├── image/
│ └── card_image.dart # PNG data URL → 缩放铺白底 → BGR24/Gray8(对齐 C# CardImage.cs)
├── utils/
│ └── command_runner.dart # 外部命令执行(LC_ALL=C、超时杀进程、参数列表)
bin/agent.dart # headless 入口(开发联调,行为对齐 C# 控制台助手)
tool/make_test_card.dart # 生成 1014×642 测试卡(真实打印验收用)
```
## 常用命令
```bash
flutter pub get
flutter analyze
flutter test
# headless 联调(不需要窗口/真机)
dart run bin/agent.dart --mock # mock 模式,端口 38200-38202 顺延
dart run bin/agent.dart --port 38203 # 指定端口(本机 C# 助手占用时的开发姿势)
dart run bin/agent.dart # 真实模式(macOS 走 CUPS 队列)
# 测试卡 + 真实打印
dart run tool/make_test_card.dart
# 生成 data URL 后 POST /api/card-printer/print,观察 lpoptions 的 printer-state 4→3
# 构建
flutter build macos --release
```
## 本机开发注意(血泪坑,勿再踩)
- **同机 C# 助手占端口**:测试前 `launchctl unload ~/Library/LaunchAgents/com.zax.cardprinteragent.plist`,测完 `launchctl load` 恢复;两个版本的 manifest.agent 字段可区分(card-printer-agent / desktop-plugin)
- **AMFI 卡死进程**:早前测试遗留的 CardPrinterAgent 进程 STAT=UE/UNE,kill -9 无效,占用 38201 直到重启;Flutter 版会自动落到其他候选端口,前端自适应
- **macOS 必须关 App Sandbox**(`macos/Runner/*.entitlements` 已置空):沙箱拦截 127.0.0.1 端口绑定与 lp/lpoptions 子进程访问 CUPS
- **macos 平台目录生成前提**:本机 flutter config 曾禁用 `enable-macos-desktop` 且缺 CocoaPods,均已修复(brew install cocoapods;注意 brew 装 ca-certificates 链接冲突时先 `brew unlink` 再重装)
- **windows/ 目录无法在 Mac 生成**:需在 Windows 实机上 `flutter create --platforms windows .` 补齐(Phase 3)
## 进度(2026-09-21)
- [x] Phase 1:协议服务器 + mock + 任务队列 + 端口顺延(单测 5 个全过,接口自测全过)
- [x] Phase 2:macOS CUPS 后端(真机 status `HiTi CS-200e, 2.4.2 就绪`;真实出卡一张,printer-state 4→3 约 24s)
- [x] Phase 3 代码:Windows PavoApi ffi 后端(mac 上完成编码,analyze 零问题 + 单测 12 个全过;windows/ 目录已从 SDK 模板手动实例化,vendor 收录 SDK DLL/bin 并在 CMake 构建后自动拷贝)——**待 Windows 实机验收**(编译/直打/色带/不装驱动直打验证)
- [ ] Phase 4:托盘/首次引导/URL scheme 唤起(zaxprint scheme 已写入 Info.plist)/开机自启
- [ ] Phase 5:打包签名分发(mac ad-hoc 就地签名;参考 C# 版签名铁律)
### Windows 实机验收清单(Phase 3 收尾)
1. `flutter create --platforms windows .` 对照生成的目录结构核对手动实例化的差异(或直接构建)
2. `flutter build windows --release` 编译过;确认 vendor 四文件拷到 exe 旁
3. `dart run bin/agent.dart`(或直接跑 App)→ status 返回真机型号/固件/色带余量
4. 提交测试卡真实出卡(tool/make_test_card.dart 生成后走 print 接口)
5. 顺带实测:不装 HiTi 官方驱动能否直打(PavoApiW_x64 疑似用户态直连 USB)