- 协议与 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 已注册
135 lines
3.5 KiB
Dart
135 lines
3.5 KiB
Dart
/// 与前端 `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};
|
||
}
|