Add AI batch reconciliation for accessibility bills
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:miaoji_zhang/shared/services/screenshot_channel.dart';
|
||||
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
||||
@@ -147,6 +148,9 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
|
||||
!await _confirmLocalOcrConsent()) {
|
||||
return;
|
||||
}
|
||||
if (enabled && key == 'ai_screenshot' && !await _confirmAiBatchConsent()) {
|
||||
return;
|
||||
}
|
||||
if (!enabled) {
|
||||
_pendingAuthorizationKey = null;
|
||||
final changed = await ScreenshotChannel.setRecognitionToggle(key, false);
|
||||
@@ -275,6 +279,71 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<bool> _confirmAiBatchConsent() async {
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
if (preferences.getBool('ai_batch_consent_v2') == true) return true;
|
||||
if (!mounted) return false;
|
||||
final accepted = await showModalBottomSheet<bool>(
|
||||
context: context,
|
||||
useSafeArea: true,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (sheetContext) => Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
|
||||
decoration: BoxDecoration(
|
||||
color: sheetContext.jz.card,
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const JzSheetHeader(
|
||||
title: '启用 AI 批次对账',
|
||||
subtitle: '请确认支付页截图的批量处理方式',
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const _ConsentPoint(
|
||||
icon: Icons.schedule_rounded,
|
||||
text: '支付结果会按 30 秒空闲窗口归为一批,最长等待 2 分钟或累计 10 条。',
|
||||
),
|
||||
const _ConsentPoint(
|
||||
icon: Icons.auto_fix_high_rounded,
|
||||
text: '本批截图和本地候选会发送给 AI,仅允许在当前批次内保留、修正、补全或剔除。',
|
||||
),
|
||||
const _ConsentPoint(
|
||||
icon: Icons.enhanced_encryption_outlined,
|
||||
text: '待提交图片仅在本机临时加密保存,批次完成或回退后立即删除,不进入最近对账记录。',
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: JzActionButton(
|
||||
label: '暂不开启',
|
||||
secondary: true,
|
||||
onPressed: () => Navigator.pop(sheetContext, false),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: JzActionButton(
|
||||
label: '同意并开启',
|
||||
onPressed: () => Navigator.pop(sheetContext, true),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
if (accepted == true) {
|
||||
await preferences.setBool('ai_batch_consent_v2', true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _showMessage(String message) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
@@ -413,24 +482,46 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
|
||||
_RecognitionCard(
|
||||
icon: Icons.document_scanner_outlined,
|
||||
title: 'AI 截图补全',
|
||||
description: '本地 OCR 已确认支付成功但字段仍不足时才在线分析。截图完成、失败或超时后立即释放。',
|
||||
description: '支付结果按 30 秒空闲窗口批量提交,AI 只在本批次内纠错、补全或剔除。处理结束立即删除图片。',
|
||||
authorized: aiAvailable,
|
||||
connected: aiAvailable && status.accessibilityConnected,
|
||||
statusLabel: !aiAvailable ? 'AI 不可用' : null,
|
||||
onOpenSettings: status.accessibilityAuthorized
|
||||
? null
|
||||
: ScreenshotChannel.openAccessibilitySettings,
|
||||
child: JzSwitchTile(
|
||||
value: status.aiScreenshot,
|
||||
title: '补全开关',
|
||||
subtitle: !aiAvailable
|
||||
? '需要登录且账号具备 AI 权限'
|
||||
: !status.accessibilityAuthorized
|
||||
? '需要先授权无障碍截屏能力'
|
||||
: '默认关闭,仅在支付应用前台运行',
|
||||
onChanged: !aiAvailable
|
||||
? null
|
||||
: (value) => _toggle('ai_screenshot', value),
|
||||
child: Column(
|
||||
children: [
|
||||
JzSwitchTile(
|
||||
value: status.aiScreenshot,
|
||||
title: '批次对账开关',
|
||||
subtitle: !aiAvailable
|
||||
? '需要登录且账号具备 AI 权限'
|
||||
: !status.accessibilityAuthorized
|
||||
? '需要先授权无障碍截屏能力'
|
||||
: '默认关闭,仅在支付应用前台运行',
|
||||
onChanged: !aiAvailable
|
||||
? null
|
||||
: (value) => _toggle('ai_screenshot', value),
|
||||
),
|
||||
Divider(height: 1, color: context.jz.line),
|
||||
InkWell(
|
||||
onTap: () => context.push('/recognition-batches'),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 4,
|
||||
vertical: 13,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.fact_check_outlined, size: 20),
|
||||
SizedBox(width: 10),
|
||||
Expanded(child: Text('最近 AI 对账')),
|
||||
Icon(Icons.chevron_right_rounded),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (status.latestDiagnostic != null) ...[
|
||||
@@ -487,7 +578,7 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
|
||||
const SizedBox(width: 9),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'银行密码页等安全窗口由系统禁止截屏,记之不会绕过限制。本地 OCR 图片仅在内存中处理;只有你开启 AI 截图补全时才会上传当前支付页。',
|
||||
'银行密码页等安全窗口由系统禁止截屏,记之不会绕过限制。本地 OCR 图片仅在内存中处理;开启 AI 批次对账后,支付结果页会临时加密并按批上传,处理结束立即删除。',
|
||||
style: TextStyle(
|
||||
color: palette.text2,
|
||||
fontSize: 11.5,
|
||||
|
||||
Reference in New Issue
Block a user