Files
desktop-plugin/README.md
T
dzc 689a07ca44 feat: 饭卡打印助手 Flutter 版(Phase 1/2:协议服务器 + macOS CUPS 真机打印)
- 协议与 C# 版 card-printer-agent 逐字段对齐(38200-38202 顺延、CORS *、串行任务队列、30 分钟保留)
- macOS CUPS 后端:lpoptions 队列发现 + lp 参数列表提交(LC_ALL=C 防本地化粘连坑)
- --mock 模拟模式 + bin/agent.dart headless 入口 + 测试卡生成工具
- 真机验收:HiTi CS-200e status 就绪 + 真实出卡;macOS 通用二进制构建通过
- App Sandbox 已关闭(服务需绑回环端口并调用 lp 子进程);zaxprint URL scheme 已注册
2026-09-21 12:03:27 +08:00

77 lines
4.5 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 提交(参数列表传参防注入)
├── 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)
- [ ] Phase 3:Windows PavoApi ffi 后端(需 Windows 实机 + windows/ 目录)
- [ ] Phase 4:托盘/首次引导/URL scheme 唤起(zaxprint scheme 已写入 Info.plist)/开机自启
- [ ] Phase 5:打包签名分发(mac ad-hoc 就地签名;参考 C# 版签名铁律)