import 'package:miaoji_zhang/shared/services/screenshot_channel.dart'; class RecognitionDiagnosticDisplay { final String stageLabel; final String resultLabel; final String summaryLabel; final String reasonLabel; final String? recognitionKindLabel; final String? amountSourceLabel; final String? statusStrengthLabel; final bool statusStrengthPositive; const RecognitionDiagnosticDisplay({ required this.stageLabel, required this.resultLabel, required this.summaryLabel, required this.reasonLabel, this.recognitionKindLabel, this.amountSourceLabel, this.statusStrengthLabel, this.statusStrengthPositive = false, }); factory RecognitionDiagnosticDisplay.from(RecognitionDiagnostic diagnostic) { final reason = diagnostic.reason; return RecognitionDiagnosticDisplay( stageLabel: _stageLabel(diagnostic.stage), resultLabel: _resultLabel(diagnostic.result), summaryLabel: _summaryLabel(diagnostic.result, reason), reasonLabel: _reasonLabel(reason), recognitionKindLabel: _recognitionKindLabel(diagnostic.recognitionKind), amountSourceLabel: _amountSourceLabel(diagnostic.amountSource), statusStrengthLabel: _statusStrengthLabel(diagnostic.statusStrength), statusStrengthPositive: diagnostic.statusStrength == 'strong', ); } static String _stageLabel(String value) { return switch (value) { 'capture' => '本地截屏', 'ocr' => '本地 OCR', 'tree' => '控件树识别', _ => '无障碍事件', }; } static String _resultLabel(String value) { return switch (value) { 'matched' || 'auto_ready' => '已识别', 'confirm' => '待确认', 'started' => '处理中', 'failed' => '失败', _ => '未触发入账', }; } static String _summaryLabel(String result, String reason) { if (reason == 'duplicate_result_surface') return '已合并'; if (_captureFailureReasons.contains(reason)) return '截图失败'; if (_ocrNoResultReasons.contains(reason)) return 'OCR 无结果'; if (_ruleRejectedReasons.contains(reason) || result == 'rejected') { return '规则拒绝'; } return switch (result) { 'matched' || 'auto_ready' => '已识别', 'confirm' => '待确认', 'started' => '处理中', 'failed' => '失败', _ => '没事件', }; } static String _reasonLabel(String reason) { return switch (reason) { 'history_page' => '当前是账单或交易历史页', 'blocked_status' => '当前状态为失败、处理中或已取消', 'no_text' => '截图中没有识别到文字', 'no_success_status' => '没有找到明确或弱完成状态,可开启诊断预览查看脱敏结果', 'payment_input_page' => '当前仍是付款输入或确认页面,已拒绝入账', 'direction_unknown' => '识别到完成状态,但无法确认收支方向', 'missing_amount' => '成功状态已识别,但没有找到金额', 'expected_amount_missing' => '结果页没有金额,且付款前金额不唯一或未捕获', 'expected_amount_fallback' => '结果页未读到金额,已使用本次付款流程确认的金额', 'weak_expected_fallback' => '结果页未读到金额,付款前金额来源不可靠,请确认后入账', 'result_amount_conflict' => '结果页金额与本次付款金额不一致,请确认后入账', 'amount_source_untrusted' => '金额无法与当前付款流程可靠关联,请确认后入账', 'red_packet_not_settled' => '红包尚未明确到账或退回,不会自动入账', 'duplicate_result_surface' => '同一结果页已处理,本次刷新已忽略', 'weak_status_confirm' => '只识别到弱完成状态,组合证据不足,需确认后入账', 'combined_high_confidence' => '弱完成状态已通过流程、跳转和金额组合校验', 'ambiguous_or_unarmed' => '金额存在歧义或未捕获到完整支付流程', 'secure_window' => '当前页面被系统禁止截屏', 'window_fallback' => '单窗口截图失败,正在切换整屏截图', 'invalid_window' => '支付页面窗口已切换,单窗口截图已失效', 'internal_error' => '系统单窗口截图失败,请停留在成功页重试', 'display_capture_start_failed' => '整屏截图请求无法启动', 'invalid_display' => '当前屏幕暂时无法截取', 'capture_timeout' => '系统截屏长时间没有返回结果,已自动结束', 'capture_start_failed' => '系统截屏请求无法启动', 'ocr_timeout' => '本地 OCR 超时,已自动结束,可在支付成功页重试', 'ocr_start_failed' => '本地 OCR 请求无法启动', 'ocr_init_failed' => '本地 OCR 组件初始化失败,请重新开启无障碍服务', 'ocr_model_unavailable' => '本地中文识别模型不可用,请重新安装内测包', 'ocr_unavailable' => '本地 OCR 服务暂不可用,请稍后重试', 'ocr_failed' => '本地 OCR 识别失败,请停留在支付成功页重试', 'ocr_parse_failed' => '本地 OCR 结果处理失败', 'operation_interrupted' => '识别进程曾被系统中断,任务已自动结束', 'interval_short' => '系统限制了过于频繁的截屏', 'accessibility_unavailable' => '无障碍截屏能力暂不可用', 'image_encode_failed' => '截图结果编码失败,请重试', 'success' || 'high_confidence' => '成功状态和金额均已确认', _ => reason.isEmpty ? '等待新的支付事件' : reason, }; } static String? _recognitionKindLabel(String? value) { return switch (value) { 'payment' => '扫码支付', 'transfer' => '转账', 'red_packet_send' => '发出红包', 'red_packet_receive' => '红包到账', 'red_packet_refund' => '红包退回', _ => null, }; } static String? _amountSourceLabel(String? value) { return switch (value) { 'expected' => '使用本次付款金额', 'result' => '使用结果页金额', _ => null, }; } static String? _statusStrengthLabel(String value) { return switch (value) { 'strong' => '明确成功状态', 'weak' => '弱完成状态', _ => null, }; } static const _captureFailureReasons = { 'secure_window', 'invalid_window', 'internal_error', 'display_capture_start_failed', 'invalid_display', 'capture_timeout', 'capture_start_failed', 'interval_short', 'accessibility_unavailable', 'image_encode_failed', }; static const _ocrNoResultReasons = { 'no_text', 'ocr_timeout', 'ocr_start_failed', 'ocr_init_failed', 'ocr_model_unavailable', 'ocr_unavailable', 'ocr_failed', 'ocr_parse_failed', }; static const _ruleRejectedReasons = { 'history_page', 'blocked_status', 'no_success_status', 'payment_input_page', 'direction_unknown', 'missing_amount', 'expected_amount_missing', 'red_packet_not_settled', 'weak_status_confirm', 'ambiguous_or_unarmed', 'weak_expected_fallback', 'result_amount_conflict', 'amount_source_untrusted', }; }