Files
desktop-plugin/lib/agent.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

88 lines
2.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.
import 'dart:async';
import 'print/backend.dart';
import 'print/mock_backend.dart';
import 'server/http_server.dart';
import 'server/print_queue.dart';
/// 启动参数:--mock 模拟打印;--port=NNN / --port NNN 指定监听端口(默认 38200-38202 顺延)。
class AgentOptions {
AgentOptions({this.mock = false, this.port});
final bool mock;
final int? port;
factory AgentOptions.parse(List<String> args) {
var mock = false;
int? port;
for (var i = 0; i < args.length; i++) {
final arg = args[i];
if (arg == '--mock') {
mock = true;
} else if (arg.startsWith('--port=')) {
port = int.tryParse(arg.substring('--port='.length));
} else if ((arg == '--port' || arg == '-p') && i + 1 < args.length) {
port = int.tryParse(args[++i]);
}
}
return AgentOptions(mock: mock, port: port);
}
}
/// 运行日志环形缓冲(GUI 展示用),同时打到 stdout。
class AgentLog {
final lines = <String>[];
final _controller = StreamController<String>.broadcast();
Stream<String> get stream => _controller.stream;
void write(String line) {
final stamped = '${DateTime.now().toIso8601String().substring(11, 19)} $line';
lines.add(stamped);
if (lines.length > 500) {
lines.removeRange(0, lines.length - 500);
}
// ignore: avoid_print
print(stamped);
_controller.add(stamped);
}
void dispose() => _controller.close();
}
/// 助手核心:组合打印后端、任务队列与 HTTP 服务(Flutter 窗口与 headless 入口共用)。
class Agent {
Agent(this.options) : log = AgentLog();
final AgentOptions options;
final AgentLog log;
late final PrintQueue queue;
late final PrintBackend backend;
late final AgentHttpServer server;
int? port;
Future<int> start() async {
final backendName = osBackendName();
backend = options.mock ? MockBackend(onLog: log.write) : createOsBackend(onLog: log.write);
queue = PrintQueue(backend, onLog: log.write);
server = AgentHttpServer(
queue: queue,
backend: backend,
mock: options.mock,
manifestBackendName: backendName,
);
final ports = options.port == null ? const [38200, 38201, 38202] : <int>[options.port!];
port = await server.start(candidatePorts: ports);
log.write('饭卡打印助手已启动 http://127.0.0.1:$port'
'(后端=$backendName,mock=${options.mock},agent=desktop-plugin)');
return port!;
}
Future<void> stop() async {
await server.stop();
queue.dispose();
log.dispose();
}
}