feat: Phase 4 收尾 + Phase 5 打包(首启向导/开机自启/URL scheme 闭环/mac dmg)

Phase 4 剩余三项:
- 首次引导向导(setup/first_run + ui/setup_wizard):服务自检(含 C# 助手共存
  提示)→ 打印机检测与 HiTi 驱动安装指引(官网链接/重新检测,mac 与 win 文案
  分支,允许无打印机完成)→ 开机自启开关 + scheme 注册;侧栏底部常驻设置区
  (自启开关 + 重新运行引导)
- 开机自启(setup/autostart):mac 写 LaunchAgent(RunAtLoad 一次性,不用
  KeepAlive——托盘退出不能被拉回);Windows 走 HKCU Run(reg 命令免 win32 依赖)
- URL scheme 闭环:单实例唤醒端口 38210(setup/single_instance)——zaxprint://
  唤起或重复双击启动第二进程时通知常驻实例弹窗后自退,跨平台一致(弃用
  app_links 的 mac 事件转发不确定性);Windows 启动时幂等注册 HKCU scheme;
  前端 cardPrinter.ts 加 launchAgent()(zaxprint://open),开卡抽屉离线时显示
  "启动打印助手"按钮,点击唤起后 1s×6 轮询自动上线(biz 前端改动待用户提交)

Phase 5:
- tool/package_macos.sh:构建 → ad-hoc 就地签名(--deep,勿加 --options=runtime:
  hardened runtime 库校验会因 ad-hoc 无 Team ID 拒载 framework,实测踩坑)→
  hdiutil dmg;实测产出 22MB dmg + 签名后冒烟通过
- windows/installer.iss:Inno Setup 安装包脚本(快捷方式/桌面图标/开机自启
  Tasks/zaxprint scheme 注册与卸载清理/HiTi SDK DLL 随 Release 目录打包)

依赖 +url_launcher +shared_preferences;13 测试全过、analyze 零问题。
This commit is contained in:
dzc committed 2026-09-21 13:51:42 +08:00
1 parent a7cc69bb92
commit 3ecac9a302
15 files changed
+934 -51

No files matched your search

+101
View File
@@ -0,0 +1,101 @@
import 'dart:io';
import '../utils/command_runner.dart';
/// 开机自启:mac 写 LaunchAgent(RunAtLoad 一次性——托盘退出不能被拉回,故不用 KeepAlive);
/// Windows 写 HKCU Run 注册表键(reg 命令实现,免 win32 依赖)。
/// 自启指向当前可执行文件(Platform.resolvedExecutable),以安装位置为准。
class Autostart {
static const macLabel = 'com.zax.desktop-plugin';
static const winRunName = 'ZaxDesktopPlugin';
static bool get isSupported => Platform.isMacOS || Platform.isWindows;
static String? get _macPlistPath {
final home = Platform.environment['HOME'];
if (home == null) return null;
return '$home/Library/LaunchAgents/$macLabel.plist';
}
/// 自启是否已开启。
static Future<bool> isEnabled() async {
if (Platform.isMacOS) {
final path = _macPlistPath;
return path != null && File(path).existsSync();
}
if (Platform.isWindows) {
final r = await runCommand(
'reg',
['query', r'HKCU\Software\Microsoft\Windows\CurrentVersion\Run', '/v', winRunName],
tolerateExit: true,
);
return r.contains(winRunName);
}
return false;
}
/// 开启自启(mac 顺带把 C# 助手的 LaunchAgent 状态返回,供向导提示端口关系)。
static Future<void> enable() async {
if (Platform.isMacOS) {
final path = _macPlistPath;
if (path == null) throw StateError('无法定位用户目录');
final exe = Platform.resolvedExecutable;
await Directory(File(path).parent.path).create(recursive: true);
await File(path).writeAsString('''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>$macLabel</string>
<key>ProgramArguments</key>
<array>
<string>$exe</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>LaunchOnlyOnce</key>
<true/>
</dict>
</plist>
''');
return;
}
if (Platform.isWindows) {
final exe = Platform.resolvedExecutable;
await runCommand('reg', [
'add', r'HKCU\Software\Microsoft\Windows\CurrentVersion\Run',
'/v', winRunName, '/t', 'REG_SZ', '/d', '"$exe"', '/f',
]);
return;
}
throw UnsupportedError('当前平台不支持开机自启');
}
static Future<void> disable() async {
if (Platform.isMacOS) {
final path = _macPlistPath;
if (path != null && File(path).existsSync()) {
await File(path).delete();
}
return;
}
if (Platform.isWindows) {
await runCommand(
'reg',
['delete', r'HKCU\Software\Microsoft\Windows\CurrentVersion\Run', '/v', winRunName, '/f'],
tolerateExit: true, // 不存在时也算关闭成功
);
return;
}
throw UnsupportedError('当前平台不支持开机自启');
}
/// C# 版助手的 LaunchAgent 是否在(本机灰度共存提示用;mac only)。
static bool get legacyCsharpAgentInstalled {
if (!Platform.isMacOS) return false;
final home = Platform.environment['HOME'];
return home != null &&
File('$home/Library/LaunchAgents/com.zax.cardprinteragent.plist').existsSync();
}
}