# 📝 记分本(Point Book)Flutter 纯本地版 PRD ## 文档信息 - **文档状态**:已完成(重构版) - **适用端**:iOS / Android 客户端(Flutter 纯本地架构) - **变现模式**:免费试用 + iOS 苹果内购(IAP 买断/解锁) - **关联模块**:本地训练统计 / 个人资料管理 / 记分管理 / 苹果内购 --- ## 1. 页面概述 ### 1.1 页面定位与目标 - **定位**:记分本业务线的 **总入口与本地数据总览页**。 - **目标**: 1. **零门槛使用**:无任何登录流程,首次打开即可直接查看本地统计或发起记分。 2. **正向数据反馈**:直观展示本地累计射箭数据、日均消耗、环值命中分布与落点热力图。 3. **内购合规转化**:提供免费体验额度,在用户第 N 次点击【开始记分】时,平滑唤起苹果内购付费解锁弹框。 ### 1.2 权限与架构变更 - **数据架构**:**纯本地架构(Local-First)**,无后端服务器、无网络 API,所有训练数据与配置均存储于手机本地数据库(Isar/Hive)。 - **用户体系**:**完全免登录**,移除所有手机号获取、微信登录及协议勾选框。 - **排行榜**:**彻底移除**周榜、点赞及任何他人对比功能。 --- ## 2. 页面流转与初始化逻辑 ```mermaid graph TD A[用户打开 App / 进入首页] --> B[加载本地数据库 Isar] B --> C[读取/初始化本地 UserProfile] B --> D[读取/初始化本地 AppConfig] B --> E[读取本地历史 PointRecord 列表] C --> F[渲染:顶部个人资料卡片] D --> G[渲染:用户权益/免费剩余次数] E --> H[渲染:本地统计指标、落点热力图、环值分布图] ``` --- ## 3. 核心功能与交互说明 ### 3.1 本地个人资料管理(头像与昵称修改) - **默认生成**:App 首次启动时,本地自动创建默认 Profile: - **默认昵称**:`弓箭手_XXXX`(四位随机数字)。 - **默认头像**:预设本地 Avatar Asset。 - **编辑交互**: - **入口**:点击首页顶部的个人资料卡片或【编辑】图标。 - **修改昵称**:弹出本地输入框,限制 1~12 个字符。 - **修改头像**:支持从手机本地相册选择图片或调起相机拍摄;选中后将图片异步拷贝至 App 本地沙盒目录 `ApplicationDocumentsDirectory/avatar.png`,数据库中仅保存文件路径。 --- ### 3.2 个人训练统计卡片(纯本地计算) - **关键指标**:今日射箭数、今日消耗、运动强度、训练天数、累计射箭数、平均环数。 - **计算规则**: - **无数据时**:指标统一展示为 `-`。 - **今日消耗**:$\text{今日箭数} \times 1.6$。 - **运动强度**:$\frac{\text{今日箭数} \times 5}{60}$(上限封顶为 10)。 - $> 6$:标记为 **重度** - $4 \sim 6$:标记为 **中度** - $< 4$:标记为 **轻度** --- ### 3.3 核心业务入口与苹果内购(IAP)拦截 #### 🔹 入口一:【计分记录】 - **交互**:点击直接进入 `本地计分记录列表页`(支持按弓型/距离/靶纸筛选及本地记录滑动删除)。 #### 🔹 入口二:【开始记分】(含免费试用与内购拦截) - **参数配置**: - `free_trial_limit`: 可配置免费试用次数(默认 `2` 次)。 - `used_trial_count`: 已使用免费试用次数。 - `is_vip_unlocked`: 是否已购买内购解锁(`true` / `false`)。 - **拦截判定流程**: ```mermaid graph TD Start[点击“开始记分”] --> VIPCheck{is_vip_unlocked == true ?} VIPCheck -- 是 --> DraftCheck VIPCheck -- 否 --> TrialCheck{used_trial_count < free_trial_limit ?} TrialCheck -- 是 (试用额度内) --> DraftCheck TrialCheck -- 否 (试用额度已满) --> Paywall[阻断进入,弹出收费解锁弹框] DraftCheck{本地是否存在未完成草稿?} -- 无草稿 --> CreatePage[进入参数选择/新建记分页] DraftCheck -- 有草稿 --> DraftConfirmDialog[弹出草稿二选一确认框] DraftConfirmDialog -- 继续编辑 --> EditPage[进入记分编辑页加载草稿] DraftConfirmDialog -- 重新计分 --> ClearDraft[清空本地草稿] --> CreatePage ``` > **计数更新时机**:当用户在试用期内完成一次完整记分并点击**【保存记分】**成功写入本地数据库后,系统自动执行 `used_trial_count + 1`。 #### 💳 内购解锁弹窗与结果流转 - **弹窗展示**:包含内购商品名称、价格、买断权益说明、`[立即解锁]` 按钮、`[恢复购买]` 按钮及 `[取消/暂不解锁]` 按钮。 - **支付流转规则**: | 用户操作 / 支付状态 | 系统响应 | 页面流转 | | ------------------------ | ------------------------------------------ | --------------------------- | | **点击 [立即解锁]** | 调起 Apple App Store 原生支付组件。 | 界面显示原生 Loading 遮罩。 | | **支付成功 (Purchased)** | 1. 本地数据库更新 `is_vip_unlocked = true` | | 2. 弹出 Toast 提示:“解锁成功!已获得无限记分权益” | 1. 关闭内购弹窗; 3. **返回【记分本首页】**; 4. 再次点击【开始记分】自动解锁放行。 | | **取消支付 (Canceled)** | 1. 弹出 Toast 提示:“支付已取消” | 1. 关闭内购弹窗; 5. **停留在【记分本首页】**。 | | **支付失败 (Error)** | 1. 弹出 Toast 提示:“支付失败:[错误信息]” | 1. 关闭 Loading; 6. **停留在【记分本首页】**。 | | **点击 [恢复购买]** | 调起 `InAppPurchase.instance.restorePurchases()` | 查到历史购买凭证后更新 `is_vip_unlocked = true` 并提示“权益已恢复”,关闭弹窗并**返回【记分本首页】**。 | --- ### 3.4 本地图像分析模块(热力图与环值分布) #### 🎯 落点热力图 - **展示条件**:本地存在历史训练数据时展示。 - **生成方式**:读取本地 `PointRecord` 中的 `hitPoints` 坐标数据,使用 Flutter Canvas 在本地预设靶纸底图上直接绘制热力点覆盖层。 #### 📊 个人环值分布图 - **展示条件**:本地存在历史记录时展示。 - **展示形式**:按 `M / X / 1~10 环` 统计本地所有箭数的占比,以柱状图形式呈现。 --- ## 4. 边界异常处理与业务细节(QA 关注) | 场景 | 预期处理机制 | 备注 / 风险点 | | --------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- | | **首次安装 / 无数据** | 统计数据指标展示 `-`,热力图展示纯靶纸背景图,免费次数显示 `0/2`。 | 避免因为数据为空导致本地 Canvas 渲染报错。 | | **本地草稿覆盖** | 点击“重新计分”会强制删除本地 SQLite/Isar 中的草稿记录,并覆盖写入。 | 需有二次弹窗明确确认,防止误删未保存数据。 | | **重装 App / 换手机** | 纯本地 App 不支持跨设备数据同步;用户可通过内购弹窗的 **[恢复购买]** 恢复付费权益。 | 需在 App 内“关于我们”或设置页明确告知“数据存储于本地,卸载 App 会清空训练记录”。 | | **网络离线内购** | 发起购买需要网络连接,若离线调起内购,提示:“无法连接到 App Store,请检查网络设置”。 | - | --- --- ## 5. 关联页面流转汇总 - 📄 **记分本首页** (`PointBookHomeScreen`):本地数据总览、免费次数提示、个人资料编辑入口、内购弹窗触发。 - 📄 **计分记录列表** (`PointBookListPage`):读取本地 Isar 历史列表、草稿展示与记录删除。 - 📄 **新建参数配置** (`PointBookCreatePage`):选择弓型、距离、靶纸类型及组数。 - 📄 **记分编辑/打靶页** (`PointBookEditPage`):本地实时记录落点与环数,保存时写入本地数据库并扣减试用次数。