Files
desktop-plugin/lib/server/protocol.dart
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

135 lines
3.5 KiB
Dart
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.
/// 与前端 `biz-pc-cloud-zax/src/api/plugin/cardPrinter.ts` 约定的协议 DTO。
///
/// 字段序列化一律 camelCase,响应统一信封 `{code, msg, data}`(code=0 成功),
/// 与 C# 版 card-printer-agent 的 ApiModels.cs 逐字段对齐。
library;
class ManifestPlugin {
ManifestPlugin({this.id = 'card-printer', this.name = '卡片打印机', this.version = '1.0.0'});
final String id;
final String name;
final String version;
Map<String, dynamic> toJson() => {'id': id, 'name': name, 'version': version};
}
class RibbonInfo {
RibbonInfo({this.type = '', this.remain = -1, this.remainCount = -1});
/// 色带类型名(如 YMCKO),未知空串
String type;
/// 色带余量百分比 0~100,未知 -1(按常见 100 张装色带折算)
int remain;
/// 色带剩余张数(设备原始值),未知 -1
int remainCount;
Map<String, dynamic> toJson() => {'type': type, 'remain': remain, 'remainCount': remainCount};
}
/// GET /api/card-printer/status 响应
class PrinterStatus {
PrinterStatus({
this.online = false,
this.model = '',
this.firmware = '',
this.connection = 'USB',
RibbonInfo? ribbon,
this.cardLow = false,
this.cardLeft = -1,
this.status = 0,
this.statusText = '',
}) : ribbon = ribbon ?? RibbonInfo();
bool online;
String model;
String firmware;
/// USB / IP
String connection;
RibbonInfo ribbon;
/// 卡量是否不足
bool cardLow;
/// 剩余卡量(张),未知 -1
int cardLeft;
/// HiTi 设备状态码,0 = 就绪
int status;
String statusText;
/// 打印机已断开/未连接的通用离线态
factory PrinterStatus.offline(String statusText) => PrinterStatus(
online: false,
status: 0x00000080,
statusText: statusText,
);
Map<String, dynamic> toJson() => {
'online': online,
'model': model,
'firmware': firmware,
'connection': connection,
'ribbon': ribbon.toJson(),
'cardLow': cardLow,
'cardLeft': cardLeft,
'status': status,
'statusText': statusText,
};
}
/// 单面打印图:color 必传,k 为可选树脂黑文字层
class CardSideImage {
CardSideImage({required this.color, this.k});
/// 1014×642 彩色层 PNG data URL
final String color;
/// 8bit 灰度树脂 K 文字层 PNG data URL,白底黑字
final String? k;
factory CardSideImage.fromJson(Map<String, dynamic> json) => CardSideImage(
color: json['color'] as String? ?? '',
k: json['k'] as String?,
);
}
/// POST /api/card-printer/print 请求
class PrintRequest {
PrintRequest({this.copies = 1, this.front, this.back});
final int copies;
final CardSideImage? front;
final CardSideImage? back;
factory PrintRequest.fromJson(Map<String, dynamic> json) {
CardSideImage? side(Object? raw) =>
raw is Map<String, dynamic> ? CardSideImage.fromJson(raw) : null;
return PrintRequest(
copies: (json['copies'] as num?)?.toInt() ?? 1,
front: side(json['front']),
back: side(json['back']),
);
}
}
/// GET /api/card-printer/task/{taskId} 响应
class PrintTaskDto {
PrintTaskDto({required this.taskId, this.state = 'printing', this.status = 0, this.statusText = ''});
final String taskId;
/// printing / done / error
final String state;
final int status;
/// error 态时携带错误文案
final String statusText;
Map<String, dynamic> toJson() =>
{'taskId': taskId, 'state': state, 'status': status, 'statusText': statusText};
}