Files
arcx-app/docs/prd.md
2026-08-08 10:57:54 +08:00

8.3 KiB
Raw Permalink Blame History

📝 记分本(Point BookFlutter 纯本地版 PRD

文档信息

  • 文档状态:已完成(重构版)
  • 适用端iOS / Android 客户端(Flutter 纯本地架构)
  • 变现模式:免费试用 + iOS 苹果内购(IAP 买断/解锁)
  • 关联模块:本地训练统计 / 个人资料管理 / 记分管理 / 苹果内购

1. 页面概述

1.1 页面定位与目标

  • 定位:记分本业务线的 总入口与本地数据总览页
  • 目标
  1. 零门槛使用:无任何登录流程,首次打开即可直接查看本地统计或发起记分。
  2. 正向数据反馈:直观展示本地累计射箭数据、日均消耗、环值命中分布与落点热力图。
  3. 内购合规转化:提供免费体验额度,在用户第 N 次点击【开始记分】时,平滑唤起苹果内购付费解锁弹框。

1.2 权限与架构变更

  • 数据架构纯本地架构(Local-First,无后端服务器、无网络 API,所有训练数据与配置均存储于手机本地数据库(Isar/Hive)。
  • 用户体系完全免登录,移除所有手机号获取、微信登录及协议勾选框。
  • 排行榜彻底移除周榜、点赞及任何他人对比功能。

2. 页面流转与初始化逻辑

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)。
  • 拦截判定流程
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
  1. 弹出 Toast 提示:“解锁成功!已获得无限记分权益” | 1. 关闭内购弹窗;

  2. 返回【记分本首页】

  3. 再次点击【开始记分】自动解锁放行。 | | 取消支付 (Canceled) | 1. 弹出 Toast 提示:“支付已取消” | 1. 关闭内购弹窗;

  4. 停留在【记分本首页】。 | | 支付失败 (Error) | 1. 弹出 Toast 提示:“支付失败:[错误信息]” | 1. 关闭 Loading

  5. 停留在【记分本首页】。 | | 点击 [恢复购买] | 调起 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):本地实时记录落点与环数,保存时写入本地数据库并扣减试用次数。