Files
jizhi/frontend/lib/features/settings/legal_document_page.dart
T

193 lines
11 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 'package:flutter/material.dart';
import 'package:miaoji_zhang/shared/theme/app_theme.dart';
enum LegalDocumentKind {
privacy('privacy', '隐私政策'),
terms('terms', '用户协议'),
permissions('permissions', '权限用途说明'),
sdk('sdk', '第三方 SDK 清单');
final String key;
final String title;
const LegalDocumentKind(this.key, this.title);
static LegalDocumentKind fromKey(String? key) =>
values.firstWhere((item) => item.key == key, orElse: () => privacy);
}
class LegalDocumentPage extends StatelessWidget {
final LegalDocumentKind kind;
const LegalDocumentPage({super.key, required this.kind});
static const _effectiveDate = '2026 年 7 月 25 日';
@override
Widget build(BuildContext context) {
final sections = _sections(kind);
return Scaffold(
appBar: AppBar(title: Text(kind.title)),
body: SelectionArea(
child: ListView(
padding: const EdgeInsets.fromLTRB(18, 8, 18, 32),
children: [
Text(
'更新及生效日期:$_effectiveDate',
style: TextStyle(fontSize: 12, color: context.jz.text3),
),
SizedBox(height: 14),
...sections.map(
(section) => Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
section.title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w800,
color: context.jz.text,
),
),
SizedBox(height: 8),
Text(
section.body,
style: TextStyle(
fontSize: 13.5,
height: 1.75,
color: context.jz.text2,
),
),
],
),
),
),
],
),
),
);
}
static List<_LegalSection> _sections(LegalDocumentKind kind) =>
switch (kind) {
LegalDocumentKind.privacy => _privacy,
LegalDocumentKind.terms => _terms,
LegalDocumentKind.permissions => _permissions,
LegalDocumentKind.sdk => _sdk,
};
static const _privacy = <_LegalSection>[
_LegalSection(
'一、我们如何处理信息',
'记之由个人开发者丁伊文运营。我们重视你的个人信息与财务隐私。为提供账号、记账、统计、预算、AI 对话及数据导出功能,我们会处理你主动提交的账号名称、昵称、账本、分类、账单、预算、聊天文本,以及你主动选择的图片或截屏。密码仅以不可逆哈希形式保存在服务器,不保存明文密码。',
),
_LegalSection(
'二、语音、图片与 AI 数据',
'使用语音记账时,麦克风音频由设备系统语音识别能力处理,记之接收识别后的文字;使用拍照或相册识别时,只有你主动选择的图片会用于本次识别。开启无障碍事件识别后,记之会在微信、支付宝疑似支付流程结束时按需截取当前页面,并由设备内置 OCR 在内存中识别。只有你另行开启 AI 批次对账时,支付结果页截图与本地候选才会按 30 秒空闲窗口成批发送至我们配置的火山方舟大模型服务,单批最长等待 2 分钟或累计 10 条。AI 仅可对当前批次执行保留、修正、补全或剔除,不能改动批次外账单。待提交图片只在设备上临时加密保存,批次完成或失败回退后立即删除。我们不会将完整账单历史无差别发送给模型,也不会把这些数据用于广告画像。',
),
_LegalSection(
'三、设备、网络与日志',
'为保障登录和接口安全,服务器可能记录访问时间、网络地址、请求结果、应用版本及去标识化故障信息。故障日志不得记录密码、JWT、API Key、完整图片 Base64 或完整隐私内容。',
),
_LegalSection(
'四、存储期限与安全',
'账号数据在你使用服务期间保存。你删除的账单进入 30 天回收站;AI 批次图片在批次完成或失败回退后立即删除,最近 7 天仅保留不含图片的批次操作摘要用于核对与恢复。手动截屏识别文件在完成、取消或失败后清理,遗留文件会在超过 24 小时后清理。账号注销进入 15 天后悔期,到期后永久删除账号关联数据。导出文件由你主动分享,应用会在分享完成或失败后清理临时副本。',
),
_LegalSection(
'五、你的权利',
'你可以在应用内查询、更正和删除账单,导出数据,修改昵称或密码,撤回非必要权限,并申请注销账号。关闭麦克风、通知、相册选择、无障碍或截屏授权不会影响基础手工记账,但对应功能将无法使用。',
),
_LegalSection(
'六、未成年人、变更与联系',
'未满 14 周岁的未成年人应在监护人同意和指导下使用。政策发生重要变化时,我们会通过应用内显著方式提示并重新征得必要同意。如对本政策、个人信息处理或账号注销有疑问,可发送邮件至 nanxun@nxsir.cn,或拨打 13607268374 联系运营者丁伊文。',
),
];
static const _terms = <_LegalSection>[
_LegalSection(
'一、协议范围',
'本协议是你与记之运营者丁伊文之间关于使用记之记账、统计、预算、AI 助手及相关服务的约定。注册或继续使用前,请完整阅读本协议与隐私政策。',
),
_LegalSection(
'二、账号使用',
'你应提供真实、合法且不侵害他人权益的账号信息,妥善保管登录凭据,并对账号内操作负责。发现账号异常时应及时修改密码。修改密码会使其他设备的既有登录状态失效。',
),
_LegalSection(
'三、AI 功能说明',
'AI 识别和建议可能存在误差。涉及金额、收支类型、分类、时间和预算时,请在确认页面核对。AI 不构成投资、税务、法律或其他专业建议,最终记账和资金决策由你自行确认。',
),
_LegalSection(
'四、使用规范',
'不得利用服务上传违法内容、攻击系统、窃取他人数据、绕过安全截屏限制或干扰服务运行。因系统维护、网络、上游模型或设备权限导致的暂时不可用,我们会尽力恢复并提供明确错误提示。',
),
_LegalSection(
'五、数据与注销',
'你保留对自己输入数据的权利,并可通过应用导出。申请注销后账号进入 15 天后悔期,期间重新登录可取消;等待期结束后数据将按规则永久删除且无法恢复。',
),
];
static const _permissions = <_LegalSection>[
_LegalSection('麦克风', '仅在你主动长按语音输入或发起语音记账时使用,用于系统语音识别。拒绝后仍可使用键盘记账和文字聊天。'),
_LegalSection(
'相册与照片选择',
'仅在你主动选择账单截图或图片识别时读取所选文件。Android 新版本优先使用系统照片选择器,不会扫描整套相册。',
),
_LegalSection(
'通知与振动',
'用于展示 AI 图片识别进度、智能识别候选、自动入账结果以及撤销入口。拒绝后本地识别仍可运行,但后台结果和确认提示可能不可见。',
),
_LegalSection(
'无障碍服务',
'可选权限。用于快捷磁贴静默截屏,以及在你主动开启“无障碍事件识别”后,仅处理微信、支付宝的支付流程事件、当前页面可见文字和按需本地截图 OCR。不会监听或拦截音量键,不会保存完整控件树;未开启 AI 批次对账时,本地 OCR 截图只在内存中处理。开启 AI 批次对账后,支付结果页会临时加密保存并按批上传,批次结束立即删除。关闭后基础手工记账仍可使用。',
),
_LegalSection(
'屏幕录制 / 截屏授权',
'当无障碍截图不可用且你主动点击截屏记账时,系统会显示一次性授权。应用只截取一帧用于本次识别,完成后立即释放投屏会话;受保护页面不会尝试绕过系统限制。',
),
_LegalSection('网络', '用于登录、同步账本、调用 AI 识别和获取配置。所有生产数据应通过受信任的 HTTPS 服务传输。'),
];
static const _sdk = <_LegalSection>[
_LegalSection(
'FlutterGoogle',
'用于构建应用界面和跨平台运行。基础运行可能处理设备系统版本、界面状态及崩溃上下文;本项目未集成 Flutter 广告或行为分析 SDK。',
),
_LegalSection(
'Dio(开源网络库)',
'用于与记之后端进行 HTTPS 通信,传输登录凭据、账本数据、聊天文本和你主动提交的识别内容。',
),
_LegalSection(
'flutter_secure_storage',
'用于在设备安全存储中保存登录 Token。Android 使用系统加密存储能力,iOS 使用 Keychain。',
),
_LegalSection(
'sqlite3 / SQLCipher',
'用于在本机加密保存游客或账号的账本、分类、账单、预算及待同步操作。数据库密钥保存在系统安全存储中,本地数据库不会由该组件自行上传。',
),
_LegalSection(
'archive',
'用于在设备内存中生成 CSV 与 JSON 数据导出 ZIP,不连接网络、不收集数据;分享完成或失败后应用会清理临时 ZIP 文件。',
),
_LegalSection('image_picker', '用于调用系统相册或照片选择器,只返回你主动选中的图片。'),
_LegalSection('share_plus', '用于调用系统分享面板导出 ZIP。接收方由你选择;分享流程结束后应用清理临时导出文件。'),
_LegalSection(
'ML Kit 中文文字识别(Google',
'用于在 Android 设备本地识别微信、支付宝支付结果页中的成功状态和金额。模型随应用安装,处理过程不需要登录或联网,不会由该 SDK 自行上传截图;图片仅在内存中使用并在完成后释放。',
),
_LegalSection(
'火山方舟大模型服务(字节跳动)',
'用于 AI 对话、账单文本解析、图片识别、无障碍支付结果批次对账及预算草稿调整。会处理完成对应请求所需的文本、图片和最小化财务上下文,不接收密码、JWT 或 API Key。批次对账仅处理当前批次,图片在处理结束后由应用删除。',
),
_LegalSection(
'Android / iOS 系统能力',
'系统语音识别、照片选择器、通知、无障碍截图、MediaProjection 和系统分享属于操作系统能力,并非记之植入的广告或统计 SDK。',
),
];
}
class _LegalSection {
final String title;
final String body;
const _LegalSection(this.title, this.body);
}