feat: add growth tracking page and related functionality
- Implemented a new Growth page to track practice time and trends. - Added API integration for fetching review data. - Created components for displaying practice statistics and trends. - Updated navigation titles for the main index and growth pages. - Removed unused styles from the index page. - Introduced a Projects management page for adding and editing practice projects. - Developed a Record form for logging practice sessions with validation. - Added utility functions for date manipulation and duration formatting. - Implemented error handling and session management in the practice service. - Created unit tests for the practice service to ensure reliability.
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# iHour 的哪些能力支撑练习记录与回顾,截图证明了哪些实际用法?
|
||||
|
||||
Type: research
|
||||
Labels: wayfinder:research
|
||||
Status: resolved
|
||||
Assignee: yuxuanhui
|
||||
Research agent: /root/ihour_research
|
||||
Research agent status: complete
|
||||
Resolved: 2026-09-28
|
||||
Parent: [芭蕾岛第一期:练习记录与成长回顾](../map.md)
|
||||
Blocked by: none
|
||||
|
||||
## Question
|
||||
|
||||
通过 iHour 官方资料和用户截图,核实项目组织、日常记录、计时、提醒、统计、成就、分享和数据延续能力。区分官方证实、截图直接观察、推断和未知,提供后续第一期取舍所需依据;不代替用户决定功能范围。
|
||||
|
||||
## Answer
|
||||
|
||||
研究子代理 `/root/ihour_research` 已完成只读检索;主代理抽查官方产品页、Google Play 与中国区 App Store,并查看用户提供的原始统计截图。未安装或实际操作 iHour,以下不是运行验证。
|
||||
|
||||
### 官方可核实的能力
|
||||
|
||||
| 能力 | 已核实事实 | 来源 |
|
||||
| --- | --- | --- |
|
||||
| 项目与记录 | 按不同项目记录每日投入,展示项目累计时间 | [官方产品页](https://app.ipad.ly/ihour?lang=zh_hans) |
|
||||
| 计时、提醒与规划 | 日常提醒、正倒计时,以及长期时间规划 | [Google Play 开发者介绍](https://play.google.com/store/apps/details?hl=zh&id=com.clover.ihour) |
|
||||
| 图表与进度 | 时间投入统计、各项目累计进度 | [官方产品页](https://app.ipad.ly/ihour?lang=zh_hans) |
|
||||
| 激励与个性化 | 成就、隐藏成就、社交分享、背景与项目图标 | [官方产品页](https://app.ipad.ly/ihour?lang=zh_hans) |
|
||||
| 专注与同步 | iOS 介绍列出专注主题、环境音、禁用手机模式、云端同步及怪兽收集;版本说明列出每日专注目标与快捷启动 | [中国区 App Store](https://apps.apple.com/cn/app/ihour-%E6%97%B6%E9%97%B4%E6%8A%95%E8%B5%84%E8%AE%A1%E5%88%92-%E4%B8%93%E6%B3%A8%E8%AE%A1%E6%97%B6%E5%A4%A7%E5%B8%88/id687625208) |
|
||||
|
||||
可归纳出的产品循环为:组织项目 → 记录投入或计时 → 回顾时间分布与累计 → 获得激励。该循环是研究归纳;“线下上课”和“自主练习”不是官方已证实的独立记录类型。
|
||||
|
||||
### 截图直接观察
|
||||
|
||||
用户提供三个页面:时间投资计划、我的项目、我的统计。证据来自本次对话附件,文件名分别为 `codex-clipboard-4f251b27-ac28-41ea-af31-3a571f87a65d.jpg`、`codex-clipboard-57729cc0-5e2f-44ac-bfbe-a64c46ea2986.jpg`、`codex-clipboard-bcfe8704-b26f-4de9-9b74-942814031d3f.jpg`;没有把临时图片路径视为长期有效的资产链接。
|
||||
|
||||
- “芭蕾”之下列出八个项目;每个有图标、名称和添加入口。截图没有展示添加后的表单,不能据此还原具体输入步骤。
|
||||
- 统计页显示 163 条记录、167 小时、平均每周 4 小时、最近 7 天 4.5 小时;另有“在 iHour 记录时间的 103 天”。“103 天”的算法未核实,不能解读为连续打卡。
|
||||
- 同一统计页的专注时长为 0,怪兽数量为 0、成就数量为 31。只能说明该页面的记录总时长与专注时长不同,不能断言用户从未使用计时或不喜欢游戏化。
|
||||
- 页面包含日期热图、单日项目分布、最近 7 天/每周/每月/每年柱状统计,以及全部/年/月/周的累计分布。
|
||||
|
||||
统计页的精确展示如下:
|
||||
|
||||
| 项目 | 小时 |
|
||||
| --- | ---: |
|
||||
| 足髋训练 | 3 |
|
||||
| 软开素质 | 19 |
|
||||
| 基础提升 | 45.5 |
|
||||
| 小球核心 | 19 |
|
||||
| 天鹅臂颈 | 31 |
|
||||
| 呼吸训练 | 2 |
|
||||
| 核心臀腿 | 11 |
|
||||
| 零基础 | 36.5 |
|
||||
| 合计 | 167 |
|
||||
|
||||
八项相加恰为 167,支持此样本中“芭蕾”是汇总层的判断;不证明 iHour 所有父子项目都采用相同规则。项目页把基础提升和零基础显示为 46、37 小时,统计页显示为 45.5、36.5 小时,提示页面精度不同,不能用取整后的展示值重新计算总量。
|
||||
|
||||
### 对芭蕾场景的启发,尚待用户决策
|
||||
|
||||
- 课后快速记录应作为优先候选:这个样本积累了大量记录,却没有显示相应的专注时长。需要真实使用习惯进一步确认,不能据此直接取消计时。
|
||||
- 现有名称同时包含学习阶段、身体部位和器械等信息,也可能直接来自课程名称。应允许讨论保留熟悉的名称,不宜立即强制统一为专业动作分类。
|
||||
- 回顾可以先回答“这周练了什么、投入多少、过去积累了多少”;是否加入教师提示、主观收获、目标和里程碑属于后续决策。时长不能直接换算为技术等级。
|
||||
|
||||
### 资料边界
|
||||
|
||||
- 官方公开资料没有核实过去日期补记、编辑和删除的操作规则、父子项目汇总细节、各统计指标算法、文件导出与导入能力。未证实不表示应用没有这些功能。
|
||||
- 官方网站同时提供 iOS 和 Android 入口。两端商店均有付费项目,但免费/会员权限边界及跨端一致性未核实;不据此制定本项目付费策略。
|
||||
- 调研没有使用旧用户评论来定义当前功能,也没有把 iOS 专属能力推定到 Android 或微信小程序。
|
||||
- 三张截图只有汇总与局部日期信息,无法重建 163 条原始记录;不能承诺仅凭截图完整迁移历史明细。
|
||||
|
||||
## Comments
|
||||
|
||||
- 2026-09-28:按用户“先调研”要求完成研究,由主代理保存结论;本票解决事实问题,不确认第一期功能清单。
|
||||
@@ -0,0 +1,36 @@
|
||||
# 第一期如何让上课和自主练习被轻松记下来?
|
||||
|
||||
Type: grilling
|
||||
Labels: wayfinder:grilling
|
||||
Status: resolved
|
||||
Assignee: yuxuanhui
|
||||
Parent: [芭蕾岛第一期:练习记录与成长回顾](../map.md)
|
||||
Blocked by: 01
|
||||
|
||||
## Question
|
||||
|
||||
在用户已有线下课或跟练内容的前提下,首期主要采用练后填写时长、练前启动计时,还是两者都提供?通过一节 90 分钟线下课和一次 15 分钟自主练习,明确录入的最少必填内容、常用项目复用方式、是否需要课后感受或教师提示,以及补记、修改、删除的边界。
|
||||
|
||||
先确认真实记录习惯,再决定功能优先级;不能仅凭截图中的“+”或专注计时为零断言用户一定怎样操作。
|
||||
|
||||
## Answer
|
||||
|
||||
经逐项讨论及用户最终回复“可以”,第一期记录流程确定如下:
|
||||
|
||||
1. 练完后填写时长;以整堂课为一条记录,不要求拆分课内内容。额外自主练习另记。
|
||||
2. 最小表单为项目、日期、时长,以及选填文字笔记。笔记可用于教师提示或个人收获,不填也能保存。
|
||||
3. 预置少量常用项目,允许用户改名、删除和新增。已有记录的项目采用归档,从常用列表移除,历史记录和累计统计保留。
|
||||
4. 允许补记过去日期、修改已保存记录和删除误记。统计随有效记录变化更新;项目归档与单条记录更正、删除是不同操作。
|
||||
|
||||
由上述规则推导的验收例子:一节 90 分钟课程及额外 15 分钟自主练习分别登记,合计 105 分钟;将课程更正为 60 分钟后合计 75 分钟;删除误记的 15 分钟后合计 60 分钟。归档课程项目不再减少这 60 分钟。以上是后续实现的验收依据,尚未执行产品测试。
|
||||
|
||||
具体预置清单、项目分组、改名后的历史呈现及汇总层级由[练习项目如何组织,才能保留熟悉的课名又不重复计算时间?](03-practice-organization.md)继续确认;图表口径、数据延续和页面反馈由各自后续事项处理。本票不代表全部第一期需求已定稿。
|
||||
|
||||
## Comments
|
||||
|
||||
- 用户确认:“练完后填写时长”。第一期的主记录方式确定为练后登记;不将练前启动计时作为主流程。该回答没有决定具体表单字段、补记与修改规则,也不等于永久排除计时能力。
|
||||
- 用户确认:“整堂记录”。一堂课记一条练习记录并填写整堂总时长,不要求按把杆、中间、核心等内容拆分。承接上一轮选项,额外自主练习另记。
|
||||
- 用户确认:“预置几个常用项目,允许改名、删除和新增”。首次使用提供少量可直接选择的项目,用户可按自己的课程与练习习惯管理;具体预置清单尚未确定。该回答未决定删除项目是否影响既有记录,也未决定改名对历史名称的呈现方式。
|
||||
- 用户确认:“保留历史(推荐)”。已有练习记录的项目从常用列表移除时采用“归档”,历史记录及其累计统计继续保留。本决定针对项目管理,不代表禁止用户更正或删除单条误记;单条记录的维护边界尚待确认。
|
||||
- 用户确认:“增加选填笔记”。每条练习记录可附一段文字,用于教师提示或个人练习收获;不填写笔记也能保存。没有据此增加图片、视频或其他附件需求。
|
||||
- 用户对“项目、日期、时长与选填笔记”的表单,以及“允许补记、修改、删除误记,统计同步更新”的规则回复“可以”。本票据此解决,完整结论见 Answer。
|
||||
@@ -0,0 +1,36 @@
|
||||
# 练习项目如何组织,才能保留熟悉的课名又不重复计算时间?
|
||||
|
||||
Type: grilling
|
||||
Labels: wayfinder:grilling
|
||||
Status: resolved
|
||||
Assignee: yuxuanhui
|
||||
Parent: [芭蕾岛第一期:练习记录与成长回顾](../map.md)
|
||||
Blocked by: 01, 02
|
||||
|
||||
## Question
|
||||
|
||||
沿用[第一期如何让上课和自主练习被轻松记下来?](02-recording-flow.md)已经确认的记录粒度及项目管理规则,不重新讨论。剩余需要决定:项目采用平铺列表还是需要分组/父子层级,具体预置哪些名称,项目改名后历史记录如何呈现?
|
||||
|
||||
截图中的“零基础、基础提升、足髋训练、小球核心”等名称可以作为候选,不视为统一训练标准。若使用分组,需明确分组是否仅用于组织和汇总、是否允许直接登记,避免重复累计。时长输入与图表显示精度转入成长回顾事项统一明确;这里不决定技术结构。
|
||||
|
||||
## Answer
|
||||
|
||||
用户已确认第一期采用以下项目组织规则:
|
||||
|
||||
1. 平铺展示具体练习项目,不设分组或父子项目层级。
|
||||
2. 首批预置八个项目:零基础、基础提升、软开素质、足髋训练、核心臀腿、小球核心、天鹅臂颈、呼吸训练。这些是可编辑的起始名称,不是统一训练分类标准。
|
||||
3. 项目改名后,历史记录和统计统一显示新名称,仍属于原来的同一项目;日期、时长和笔记保持不变。
|
||||
|
||||
沿用[已确认的记录流程](02-recording-flow.md),一条练习记录选择一个项目。由此推导,总量按有效记录各累计一次,项目汇总不是另一份额外投入;改名不生成新项目或新的记录,不增加或减少累计时长。项目新增及归档规则由记录流程事项保存,本票不重复定义。
|
||||
|
||||
例如,将“基础提升”改名为“芭蕾基训”后,旧记录与项目统计均显示“芭蕾基训”,原来登记的 90 分钟仍是同一条 90 分钟记录。这是后续实现验收场景,尚未执行产品测试。
|
||||
|
||||
时长输入、显示精度及各图表的具体口径统一交由[成长回顾首先应回答哪些问题,并提供怎样的鼓励?](04-growth-review.md)处理,尚未视为已决定。
|
||||
|
||||
## Comments
|
||||
|
||||
- 记录流程已确认后领取本票;先讨论平铺与分组,再确定预置清单及其余组织规则。
|
||||
- 用户确认:“平铺列表”。第一期直接展示并选择具体练习项目,不设置分组或父子项目层级。
|
||||
- 用户对所提八项回复“可以”,首批预置项目确定为:零基础、基础提升、软开素质、足髋训练、核心臀腿、小球核心、天鹅臂颈、呼吸训练。这些仅作为可编辑的起始项目名称,不是统一训练标准。
|
||||
- 用户确认:“统一显示新名称(推荐)”。历史记录与统计统一显示改名后的名称,原有日期、时长和笔记不变。项目组织问题据此解决。
|
||||
- 时长输入与显示精度和统计呈现关联更紧,已明确转入成长回顾事项继续讨论,没有在本票中默认为已确认。
|
||||
@@ -0,0 +1,34 @@
|
||||
# 成长回顾首先应回答哪些问题,并提供怎样的鼓励?
|
||||
|
||||
Type: grilling
|
||||
Labels: wayfinder:grilling
|
||||
Status: resolved
|
||||
Assignee: yuxuanhui
|
||||
Parent: [芭蕾岛第一期:练习记录与成长回顾](../map.md)
|
||||
Blocked by: 02, 03
|
||||
|
||||
## Question
|
||||
|
||||
用户最需要回顾的是练了多少、多久练一次、各项目时间分布,还是每次练习的收获?据此决定总时长、记录次数、练习天数、周月趋势、日历和项目分布的首期优先级,以及是否需要目标、里程碑或分享。
|
||||
|
||||
明确练习天数与连续天数、记录条数与课次的区别,以及补记对图表和里程碑的影响。投入时间不等于技术水平提升;需要讨论如何呈现休息日,而不是默认以每日连续打卡作为唯一激励。
|
||||
|
||||
承接项目组织事项中的时长精度问题,明确用户如何输入时长、统计如何展示小时和分钟,以及总量与项目展示值之间的关系,避免先取整再汇总造成误差。
|
||||
|
||||
## Answer
|
||||
|
||||
用户确认首期包含累计时长与练习天数、练习日历、周月时长趋势,以及各项目时长和占比。日历可点开日期回看记录;同一天多条记录,练习天数计一天。
|
||||
|
||||
用户明确决定练习目标、成就徽章和分享卡片均放到后续版本。第一期的成长回顾由练习数据及已有笔记支撑,不额外建立技能等级、打卡奖励或分享流程。
|
||||
|
||||
采用以下常规默认方案,后续在原型和规格中集中验证:时长按分钟输入,使用完整时长汇总后再格式化;周按周一至周日、月按自然月;补记按实际练习日期归属;项目归档不影响其历史统计。以上为代理提供的默认细节,并非用户逐项确认。
|
||||
|
||||
验收推导:同日登记 90 分钟课程与 15 分钟自主练习,累计 105 分钟、练习天数为一天;将其中一条改到另一个日期后,累计时长不变,练习天数及相应日期的图表随有效记录变化。尚未执行产品测试。
|
||||
|
||||
## Comments
|
||||
|
||||
- 记录流程与项目组织均已解决,现领取本票。
|
||||
- 用户对所提统计范围回复“可以”:第一期包含累计时长与练习天数、可点开日期回看记录的练习日历、周月时长趋势、各项目时长及占比。同一天多条练习记录,练习天数计一天。
|
||||
- 常规细节拟采用以下默认方案,后续统一在原型或规格中呈现,不逐项追加问答:时长以分钟为输入精度,汇总使用完整时长后再格式化展示;日期默认今天且可补记;周按周一至周日、月按自然月;补记按实际练习日期归属;归档项目的历史继续计入统计。这些是代理提出的默认方案,不标记为用户逐项确认。
|
||||
- 用户明确确认:“练习目标、成就徽章和分享卡片,都放到后续版本”。本票据此解决。
|
||||
- 用户询问剩余决策:除本票的激励与分享外,现有地图还需确认数据保存及旧记录衔接,并通过核心流程原型确认页面。后续问题聚焦影响范围或数据含义的取舍,常规可逆细节提供默认方案。
|
||||
@@ -0,0 +1,26 @@
|
||||
# 练习记录需要怎样保存,已有 iHour 积累如何衔接?
|
||||
|
||||
Type: grilling
|
||||
Labels: wayfinder:grilling
|
||||
Status: resolved
|
||||
Assignee: yuxuanhui
|
||||
Parent: [芭蕾岛第一期:练习记录与成长回顾](../map.md)
|
||||
Blocked by: 01
|
||||
|
||||
## Question
|
||||
|
||||
用户首次使用、换设备或重装后应如何保留自己的记录,首次录入前是否接受登录?对于已有的 iHour 积累,第一期从新记录开始、允许逐条补录,还是需要期初汇总?
|
||||
|
||||
如果带入历史总时长,需要决定其是否进入趋势、练习天数和次数统计,不能从总时长虚构历史明细。自动导入必须先取得真实可导出样例再评估,公开资料未证实其可用;不因参考 iHour 就默认承诺同步或迁移能力。
|
||||
|
||||
## Answer
|
||||
|
||||
用户确认数据保存按建议执行:关联微信身份,云端保存练习记录,同一微信身份换设备后可以恢复自己的记录。该项是产品要求,尚未接入或验证实际登录、云端保存与恢复;实现继续沿用当前小程序和后端项目,不因“云端保存”一词改变技术供应商。
|
||||
|
||||
用户明确“先不考虑旧数据衔接”。第一期从本产品新建立的记录开始,不做 iHour 导入、迁移或期初累计录入,也不带入截图中的历史总量。这不取消记录流程已确认的日常漏记补录能力。
|
||||
|
||||
首次使用的登录提示与保存反馈作为原型中的体验细节验证;不增加独立的手机号注册流程。原型只用内存模拟数据,不实际调用身份服务或上传用户内容。
|
||||
|
||||
## Comments
|
||||
|
||||
- 用户在同一条回复中明确确认数据保存、旧数据范围和激励范围;据此记录已经作出的产品取舍,不重复请求确认。
|
||||
@@ -0,0 +1,47 @@
|
||||
# 哪套最小页面与流程能完成记录和回顾?
|
||||
|
||||
Type: prototype
|
||||
Labels: wayfinder:prototype
|
||||
Status: resolved
|
||||
Assignee: yuxuanhui
|
||||
Parent: [芭蕾岛第一期:练习记录与成长回顾](../map.md)
|
||||
Blocked by: 02, 03, 04, 05
|
||||
|
||||
## Question
|
||||
|
||||
在记录方式、项目组织、回顾指标和数据延续边界得到确认后,以低保真流程或可交互草图讨论“首次建立常用项目 → 记录一次练习 → 回看本周与累计”的最小路径。哪些页面、入口、空状态和反馈必须存在,什么结果能证明第一期已经满足需要?
|
||||
|
||||
原型是讨论材料,需要用户实际反馈后才能解决本票;不交付生产界面,也不把当前候选的“记录、日历、成长”当作已确认导航。
|
||||
|
||||
## Answer
|
||||
|
||||
用户体验原型后明确回复:“顺手,可以按此设计”。据此确认该原型作为第一期交互设计依据:
|
||||
|
||||
- 主导航采用“记录、日历、成长”三个入口。
|
||||
- 记录页直接选择平铺项目,进入包含项目、日期、整堂时长与选填笔记的表单;保存后回到来源页面并显示结果。
|
||||
- 日历页选择日期后查看当天记录,可新增该日期的记录或编辑已有记录;修改后日历与统计同步更新。
|
||||
- 成长页展示已确认的累计投入、练习天数、周月趋势及项目分布。
|
||||
- 项目管理从记录页进入,支持新增、改名及移除;有历史记录的项目按已确认规则归档,历史继续保留。
|
||||
- 沿用草图中展示的空状态、表单提示、保存/取消和误记删除路径,作为正式实现时的设计基线。演示场景切换和“当前演示数据”面板仅供讨论,不属于正式产品功能。
|
||||
|
||||
本票确认的是用户认可的交互方案。正式组件适配、真实微信登录、云端保存与恢复、网络失败和重试仍需在后续实现中完成并验证;不将内存原型当成已上线或已接通后端的产品。现有原型保留为设计参考,不直接替换业务代码。
|
||||
|
||||
## Comments
|
||||
|
||||
- 前置产品决策已明确,开始制作“记录、日历、成长”的可交互流程草图。采用 prototype 的状态/操作流程分支,检验新增、更正、项目改名/归档后各页面数据是否易于理解;不在此轮比较正式视觉风格。
|
||||
- 将原来的模糊项“中断、漏记、重复录入反馈”纳入本票的具体检查:保存与取消入口、补记日期、空状态、无效时长提示、误记删除、提交后返回位置。首次使用与保存反馈也在此讨论。
|
||||
- 使用内存中的演示数据;不调用微信登录或云服务,不修改业务源码,不提交或切换分支。用户反馈前保持 claimed。
|
||||
- 用户已反馈“顺手,可以按此设计”,本票据此收束,不再重复询问已确认的入口和操作路径。
|
||||
|
||||
## Assets
|
||||
|
||||
- [练习记录与回顾的交互草图](/Users/yuxuanhui/.codex/visualizations/2026/09/28/01a0e6a5-d2a3-7f51-bff3-545ef8c42df0/ballet-practice-flow.html):会话内展示,纯本地交互;提供“首次使用”和“已有练习记录”两个演示场景。示例数据不来自用户历史记录,刷新后重置。
|
||||
|
||||
## Verification
|
||||
|
||||
- 已在浏览器实际操作:新增 90 分钟记录并保存笔记;更正为 60 分钟后成长页显示 1 小时、1 天;项目改名并归档后统计仍保留 1 小时且使用新名称。
|
||||
- 已操作日历回看与日期更正;删除该条模拟误记后,累计回到 0 分钟、0 天。
|
||||
- 已切换示例场景和周/月统计;示例三条记录合计 195 分钟、三个练习日。
|
||||
- 已检查约 320px 内容宽度下的成长页和日历;检查后的浏览器预览尺寸已恢复。原型脚本通过语法检查。
|
||||
- 尚未验证真实微信身份、云端保存、换设备恢复及生产端能力。首次登录提示、网络失败与重试也未在草图中模拟。
|
||||
- 用户验收反馈已收到:认可三个入口以及原型中的操作路径。交互检查和用户反馈均已有记录;真实产品接入仍未验证。
|
||||
@@ -0,0 +1,13 @@
|
||||
# 哪些公开芭蕾知识来源适合建立动作目录?
|
||||
|
||||
Type: research
|
||||
Labels: wayfinder:research
|
||||
Status: claimed
|
||||
Assignee: yuxuanhui
|
||||
Research agent: /root/ballet_knowledge
|
||||
Parent: [芭蕾岛产品规划:练习记录、语音录入与动作成长](../map.md)
|
||||
Blocked by: none
|
||||
|
||||
## Question
|
||||
|
||||
查找舞团、舞校、考试机构等公开的芭蕾动作术语来源,核实哪些适合作为动作名称、别名、分类和简短释义的参考。给出少量种子动作,区分术语目录与分级教学/掌握标准,说明法语及中文名称差异、访问与复用边界;不复制完整教材、不创建正式知识库,不替用户定义动作解锁规则。
|
||||
@@ -0,0 +1,13 @@
|
||||
# 语音解析、LLM 与工具调用如何可靠地产生练习记录?
|
||||
|
||||
Type: research
|
||||
Labels: wayfinder:research
|
||||
Status: claimed
|
||||
Assignee: yuxuanhui
|
||||
Research agent: /root/voice_feasibility
|
||||
Parent: [芭蕾岛产品规划:练习记录、语音录入与动作成长](../map.md)
|
||||
Blocked by: none
|
||||
|
||||
## Question
|
||||
|
||||
结合 Taro 微信小程序与现有 Go 后端,核实录音、语音识别、中文与芭蕾术语处理、结构化抽取及工具调用所需的可用能力。比较短录音后处理与实时交互对首期的影响,提出可验证的记录草稿流程;列明相对日期、多项练习、信息缺失、语音更正、重复提交和模型失败的处理原则。只做文档研究,不调用付费模型、不选择最终供应商、不修改业务代码。
|
||||
@@ -0,0 +1,12 @@
|
||||
# 语音录入与动作成就分别在哪一期交付?
|
||||
|
||||
Type: grilling
|
||||
Labels: wayfinder:grilling
|
||||
Status: claimed
|
||||
Assignee: yuxuanhui
|
||||
Parent: [芭蕾岛产品规划:练习记录、语音录入与动作成长](../map.md)
|
||||
Blocked by: none
|
||||
|
||||
## Question
|
||||
|
||||
整体产品包含练习记录、语音录入和动作成就;首期是否包含语音录入及动作成就,哪些作为后续扩展?
|
||||
@@ -0,0 +1,49 @@
|
||||
# 第一期本地实现与验证
|
||||
|
||||
Type: task
|
||||
Status: resolved
|
||||
Scope: [已确认规格](../spec.md)
|
||||
|
||||
## Work
|
||||
|
||||
完成微信身份与业务会话、PostgreSQL 迁移、项目管理、练习记录、日历和成长页;保持 07–09 规划票不变。不部署、发布、提交或推送。
|
||||
|
||||
## Validation
|
||||
|
||||
按规格默认测试安排,通过 HTTP 请求/响应验证真实 PostgreSQL 持久化、身份隔离、幂等、归档与统计;仅替换外部微信核验。另执行后端 vet/race/build、小程序 typecheck/build。微信开发者工具、真实身份和跨设备验收分别记录,不由构建结果替代。
|
||||
|
||||
## Comments
|
||||
|
||||
- 2026-09-28:已读取交接、规格及仓库约定。工作区原有 `AGENTS.md` 修改和 `.scratch/`、`docs/` 材料保留。
|
||||
- 2026-09-29:用户完成微信开发者工具登录并授权开启本机服务端口。CLI 通过 34789 确认 `login: true` 并打开项目,通过 34790 接入官方自动化 SDK;验收边界与结果补充如下。
|
||||
- 2026-09-29:用户配置后端微信凭据后,核对 AppID 与项目一致;已启动本机 Compose PostgreSQL 和 Go 开发服务。`healthz`、`readyz` 均为 200;从模拟器取得真实 `wx.login` code,由本机 HTTP 客户端提交后端,微信身份交换成功返回业务会话,携带会话读取到 8 个初始项目。没有输出或另存凭据。模拟器直接请求本机接口仍被域名校验拦截,已请求用户确认仅对被 Git 忽略的本机私有配置关闭该校验;确认前不修改安全设置。
|
||||
- 2026-09-29:用户手动勾选本机“不校验合法域名”。确认私有配置 `urlCheck: false` 后,完成真实后端的模拟器保存、更正、重读和统计联调;临时记录已清理,后端与数据库保持运行。
|
||||
|
||||
## Answer
|
||||
|
||||
2026-09-28 完成第一期本地实现,2026-09-29 补充真实微信身份及本机模拟器联调;本票不代表生产发布或完整真机验收完成。
|
||||
|
||||
- 后端:版本化事务迁移;微信 code2Session 核验适配器;30 天随机业务会话;八个项目原子预置;项目新增/改名/删除或归档;练习增删改查、提交幂等及删除回执;按实际练习日期计算累计、去重练习日、周/月趋势和项目分布。写入按用户串行化并校验归属。
|
||||
- 小程序:记录、日历、成长三个入口,独立记录表单和项目管理页;保存后回来源页并刷新;失败与空结果分开;会话失效恢复;待确认提交保留输入和原标识。近期列表按登记/更正时间排序,补记可立即看到。未加入演示数据、计时器、激励、分享或 07–09 的其他规划。
|
||||
- 执行默认值:项目名 40 个 Unicode 字符、笔记 2000 字符;分钟为正整数并受 PostgreSQL integer 范围约束。暂存表单只跨当前进程内页面导航,不提供离线队列或重启后的草稿持久化。
|
||||
|
||||
### 实际验证
|
||||
|
||||
- `go vet ./...`、连接隔离 PostgreSQL 18 的 `REQUIRE_TEST_DATABASE=1 go test -race ./...`、`go build -o bin/api ./cmd/server` 全部通过。Go 共 12 个顶层测试(其中 9 个业务/数据库集成测试、3 个健康检查测试);业务测试替换微信外部网络响应,其他会话、授权和数据库操作真实执行。
|
||||
- HTTP 验证包括首次/再次登录、过期会话、另一账户猜测标识、改名/归档、归档记录编辑限制、补记与更正/删除后的统计、周日/周一及月底边界、上海业务日期、正整数/空值/长度约束、分页、重复提交/主动重复登记、并发重试/项目移除、删除回执、服务失败。重新创建 handler 后仍能恢复同一账户的数据库记录。
|
||||
- `./scripts/test-integration.sh` 已实际启动独立临时 PostgreSQL 并执行 race 测试成功,退出后自动清理其容器。开发过程中另建的隔离测试容器也在收尾清理;这些隔离集成测试没有使用业务数据库或 Compose 数据卷。
|
||||
- `pnpm typecheck`、`pnpm test:client`(3 项通过)、`pnpm build` 全部通过。客户端测试在 Taro 网络/存储边界验证续期、待确认提交、失败状态及成功写入通知,不等于小程序端到端运行验证。
|
||||
- `docker compose --env-file .env.example config --quiet` 和本地镜像 `ballet-island-v1-local-check` 构建通过。构建时有上游 Node `punycode` 弃用提示,不影响编译成功。
|
||||
- 两次只读核验:后端核验未发现确定缺陷;前端核验发现“未确认保存可取消而丢失提交标识”,已由主代理修正并补充客户端回归检查。主代理另修正近期记录排序,并以失败到通过的 HTTP 回归验证。
|
||||
- 2026-09-29 微信模拟器:开发者工具 2.02.2608070、基础库 3.17.4、iPhone 12/13 (Pro) 390px 视口。记录、日历、成长三个页面均能打开,在真实后端不可达时明确显示网络失败及重试入口,没有捕获到未处理异常。
|
||||
- 临时模拟微信/HTTP 响应后,9 项 UI 检查通过:八项目与近期记录、项目卡片进入表单并预选、空时长阻止提交、填写与保存后返回首页、日历标记及当天记录、补记首项选择与取消返回、周趋势和分布、月趋势切换与点按、项目管理添加。模拟结果不代表真实微信核验或数据库持久化;未写入真实后端或本地业务会话存储,检查后恢复原始 wx 方法并清除模拟数据。
|
||||
- 截图发现 Taroify 默认按钮尺寸与项目 375px 设计宽度不匹配;仅通过公开主题变量修正按钮尺寸、边距和字号。再次执行 `pnpm typecheck`、`pnpm build`、`git diff --check` 通过,并重新通过上述 9 项 UI 检查。模拟器测得小按钮 33px、主按钮 45px,四个快捷时长按钮同排;已目视检查五页截图。
|
||||
- 本机真实联调 7 项通过,全程未模拟微信身份或 HTTP 响应:登录后读取项目;模拟器保存 1 分钟临时记录并由已认证接口读回;日历显示记录及练习日标记;成长页与接口均增加 1 分钟、1 条记录;重新进入首页仍读到记录;表单更正为 2 分钟且记录数不增加;通过已认证 DELETE 接口清理本次临时记录后,累计时长和记录数恢复联调前值。没有捕获到未处理异常。此轮没有验证原生删除确认弹窗;清理仅按本次唯一临时标记定位,不修改用户其他记录。
|
||||
|
||||
### 未验证与下一步
|
||||
|
||||
- 本机 `backend/.env` 已配置 `WECHAT_APP_ID` / `WECHAT_APP_SECRET`,真实微信身份交换与已认证项目读取已验证。凭据只供服务端使用,没有输出或加入小程序包。
|
||||
- 微信开发者工具登录、项目打开和五页模拟器渲染已验证;原生键盘、其他窄屏尺寸、弱网/断网保存及系统返回提示仍未完成平台验收。本次模拟器验证使用自动化输入事件,并仅对部分页面执行滚动检查。
|
||||
- 本机 127.0.0.1:8080 的后端与 PostgreSQL 已启动且就绪。用户关闭本机开发者工具域名校验后,小程序到后端、数据库的真实保存、更正与读取链路已通过。
|
||||
- 正式 request 合法域名/HTTPS、另一设备读取、客户端进程重启恢复和真实多账户隔离仍待验收;重新进入首页不等于完整进程重启。HTTP 中的受控微信响应不能替代这些证据。
|
||||
- 本轮没有部署、发布、提交或推送;07–09 规划票保持原状。启动步骤和接口约定见根目录 `README.md`。
|
||||
@@ -0,0 +1,45 @@
|
||||
# 芭蕾岛第一期:练习记录与成长回顾
|
||||
|
||||
Labels: wayfinder:map
|
||||
Status: open
|
||||
Created: 2026-09-28
|
||||
|
||||
## Destination
|
||||
|
||||
明确面向已有线下课或跟练内容的芭蕾爱好者,第一期应保留哪些 iHour 能力、如何适配练习场景,以及核心流程、统计口径和验收边界。地图完成后,后续工作可据此形成实现规格并开发。
|
||||
|
||||
## Notes
|
||||
|
||||
- 用户已确认第一期主要解决“已有线下课或跟练内容,只需记录练习、回顾成长”。这一定位来自建图对话,不代表具体功能已获确认。
|
||||
- 本地图只做调研与决策。遵循 wayfinder;人与产品有关的决策结合 grilling、domain-modeling,流程形态通过 prototype 与用户讨论。
|
||||
- 每次只问一个关键问题;事实由代理查询,取舍由用户确认。候选建议不得写成已决定事项;建图阶段不关闭人工决策票,后续讨论按用户实际确认逐项解决。
|
||||
- 事实依据分为官方产品资料、用户提供的三张截图、推断。单个用户的分类和使用数据不能代表全部芭蕾爱好者。
|
||||
- 用户明确要求先调研 iHour,因此先行只读检索,再收录研究票。research 子技能未安装,采用网页检索与官方来源抽查;研究代理只读,主代理保存本地结论,不创建研究提交或切换分支。
|
||||
- 本仓库按 `docs/agents/issue-tracker.md` 在本地 Markdown 跟踪;依赖使用 `Blocked by`,领取使用 `Status: claimed`。事项详情只保存在各自票中,本文件仅作索引。
|
||||
- 本任务中的术语与规则以各决策票为准,未决建议继续标注为草案。已确认术语先留在本任务,不修改共享 CONTEXT.md 或 ADR。
|
||||
- 本轮已收束基础记录与回顾的产品及交互设计。同目录中未参与本轮讨论的其他规划事项保持原状,不据此扩充已确认的第一期范围;整张地图暂不标记为全部完成。
|
||||
- 已依据已解决事项整理[第一期实现规格](spec.md),状态为 `ready-for-agent`;实现范围、数据规则与验收依据以该规格为入口。
|
||||
|
||||
## Decisions so far
|
||||
|
||||
<!-- 仅索引已解决事项;未决事项通过 issues/ 中的状态与依赖查找。 -->
|
||||
|
||||
- [iHour 的哪些能力支撑练习记录与回顾,截图证明了哪些实际用法?](issues/01-ihour-evidence.md):已核实项目记时、统计和激励能力;截图表明用户按芭蕾项目积累记录,记录时长与专注时长需要区分,具体操作与导入规则仍未证实。
|
||||
- [第一期如何让上课和自主练习被轻松记下来?](issues/02-recording-flow.md):练后整堂登记,笔记选填;项目可管理且归档保留历史,练习记录允许补记与更正,统计随之更新。
|
||||
- [练习项目如何组织,才能保留熟悉的课名又不重复计算时间?](issues/03-practice-organization.md):平铺八个可编辑预置项目,改名后历史与统计统一使用新名称,同一条练习记录只累计一次。
|
||||
- [成长回顾首先应回答哪些问题,并提供怎样的鼓励?](issues/04-growth-review.md):累计、日历、周月趋势和项目分布进入首期;目标、徽章和分享后置。
|
||||
- [练习记录需要怎样保存,已有 iHour 积累如何衔接?](issues/05-record-continuity.md):微信身份关联云端记录,首期不做旧数据衔接,保留日常补记能力。
|
||||
- [哪套最小页面与流程能完成记录和回顾?](issues/06-core-flow-prototype.md):用户认可“记录、日历、成长”三个入口与草图操作路径,作为第一期交互设计依据。
|
||||
- [第一期本地实现与验证](issues/10-v1-implementation.md):后续执行阶段已按规格完成本地代码、真实 PostgreSQL HTTP 集成验证和两端构建;真实微信与设备验收仍待环境配置,未部署、发布或提交。07–09 规划票保持原状。
|
||||
|
||||
## Not yet specified
|
||||
|
||||
- 产品范围稳定后,识别需要核实的小程序能力限制及实现前置条件。
|
||||
|
||||
## Out of scope
|
||||
|
||||
- 本轮不实现业务代码、不部署、不发布;这些属于地图完成后的执行阶段。
|
||||
- 第一期开设或推荐训练内容、自动编排训练计划,不属于用户已确认的“记录已有练习”定位。
|
||||
- 全量复刻 iHour、多平台原生客户端、商业化体系不属于本地图的目的。
|
||||
- 第一期的练习目标、成就徽章和分享卡片后置,依据见[成长回顾决策](issues/04-growth-review.md)。
|
||||
- 第一期不做旧数据衔接,依据见[记录保存与历史衔接决策](issues/05-record-continuity.md)。
|
||||
@@ -0,0 +1,213 @@
|
||||
# 芭蕾岛第一期:练习记录与成长回顾
|
||||
|
||||
Status: ready-for-agent
|
||||
Created: 2026-09-28
|
||||
Parent: [第一期决策地图](map.md)
|
||||
|
||||
## Problem Statement
|
||||
|
||||
芭蕾爱好者已经在线下上课或跟随现有内容练习,需要一个适合课后快速登记、长期回顾投入的工具。用户提供的 iHour 截图展示了按熟悉的课程或练习名称记录时长、回看累计与项目分布的实际使用方式,但通用时间管理中的项目层级、计时和激励体系并非第一期都需要。
|
||||
|
||||
用户希望练完后一笔记下整堂课,不必拆分把杆、中间或每个动作;偶尔另外练习,也能单独记录。课名和练习习惯会变化,因此项目需要可管理,改名或停用不能损失历史。回顾应能回答“练了多久、在哪些天练习、时间花在哪里、当时有什么收获”,而不是把时长当作技术水平。
|
||||
|
||||
## Solution
|
||||
|
||||
提供微信小程序中的“记录、日历、成长”三个入口,沿用用户已认可的交互草图。
|
||||
|
||||
| 入口 | 第一期开通的能力 |
|
||||
| --- | --- |
|
||||
| 记录 | 从平铺项目进入课后登记;填写实际练习日期、整堂时长和选填笔记;查看近期记录;进入项目管理 |
|
||||
| 日历 | 识别有练习的日期;点选日期查看当天记录;为所选日期补记,或更正已有记录 |
|
||||
| 成长 | 累计时长、练习天数、周/月时长趋势、各项目时长与占比 |
|
||||
|
||||
首次使用预置八个可编辑项目:零基础、基础提升、软开素质、足髋训练、核心臀腿、小球核心、天鹅臂颈、呼吸训练。这些是来自用户使用习惯的便捷名称,不是芭蕾训练的标准分类。
|
||||
|
||||
数据关联微信身份并存于现有后端使用的数据库,同一微信身份换设备后可恢复记录。新账户从空记录开始;不导入 iHour 历史,不带入截图中的累计数字。练习目标、成就徽章和分享卡片留待后续版本。
|
||||
|
||||
## User Stories
|
||||
|
||||
1. 作为芭蕾爱好者,我希望打开小程序即可理解“记录、日历、成长”三个入口,以便快速找到登记和回顾的位置。
|
||||
2. 作为首次使用者,我希望获得八个熟悉的预置项目,以便无需先建立分类体系就能记录练习。
|
||||
3. 作为首次使用者,我希望历史与统计真实地从零开始,以便区分自己的投入和产品演示数据。
|
||||
4. 作为上课的学员,我希望练完后手动填写整堂课的时长,以便不在上课时操作计时器。
|
||||
5. 作为上课的学员,我希望一条记录只选择一个项目,以便无需拆分课堂环节,也不会重复计算同一段时间。
|
||||
6. 作为自主练习者,我希望能另外登记一次练习,以便保留课程之外的投入。
|
||||
7. 作为记录者,我希望常用项目平铺展示,以便直接选中课名或练习名称。
|
||||
8. 作为记录者,我希望日期默认今天,以便完成常见的课后登记。
|
||||
9. 作为漏记过练习的人,我希望能选择实际练习日期补记,以便日历和趋势反映练习发生的时间。
|
||||
10. 作为记录者,我希望按分钟填写时长,以便保留不足一小时的练习。
|
||||
11. 作为记录者,我希望选填老师反馈或个人收获,以便回顾那一次练习的具体内容。
|
||||
12. 作为记录者,我希望不写笔记也能保存,以便只想记时长时快速完成。
|
||||
13. 作为记录者,我希望无效日期、时长或缺失项目得到明确提示,以便在保存前改正输入。
|
||||
14. 作为记录者,我希望可以取消登记,以便未完成的输入不会变成正式记录。
|
||||
15. 作为记录者,我希望保存成功后回到发起登记的页面并看到结果,以便确认本次操作已经完成。
|
||||
16. 作为记录者,我希望保存失败时保留输入并允许重试,以便无需重新填写整堂课的信息。
|
||||
17. 作为记录者,我希望重复点击或重试同一次保存不会生成重复记录,以便统计不会被网络问题放大。
|
||||
18. 作为回顾练习的人,我希望在记录页看到近期记录,以便检查刚刚登记的信息。
|
||||
19. 作为误填信息的人,我希望更正记录的项目、日期、时长和笔记,以便保留准确的练习历史。
|
||||
20. 作为误记练习的人,我希望删除单条错误记录,以便将其从日历和统计中移除。
|
||||
21. 作为回顾练习的人,我希望日历标记有记录的日期,以便看清练习在时间上的分布。
|
||||
22. 作为回顾练习的人,我希望点选日期后看到当天的全部记录及笔记,以便回想那天练了什么。
|
||||
23. 作为补记练习的人,我希望从日历发起登记时沿用所选日期,以便不必重复选择日期。
|
||||
24. 作为更正记录的人,我希望修改后相关日期、累计与趋势一起更新,以便不同页面展示一致的事实。
|
||||
25. 作为有个人练习习惯的人,我希望新增项目,以便使用自己的课程或练习名称。
|
||||
26. 作为调整课名的人,我希望给项目改名,以便名称符合现在的用法。
|
||||
27. 作为回顾历史的人,我希望改名后的项目在旧记录和统计里也统一使用新名称,以便仍能识别为同一个项目。
|
||||
28. 作为整理项目的人,我希望删除没有使用过的项目,以便缩短日常选择列表。
|
||||
29. 作为停止某类练习的人,我希望将有记录的项目移出常用列表并保留历史,以便不用担心整理项目导致数据丢失。
|
||||
30. 作为回顾历史的人,我希望归档项目的记录、笔记和时长仍可查看和更正,以便过去的练习不会消失。
|
||||
31. 作为关注投入的人,我希望看到准确的累计时长,以便了解自己在芭蕾练习上投入了多少时间。
|
||||
32. 作为关注练习习惯的人,我希望同一天无论登记几次都只算一个练习日,以便练习天数不被记录条数放大。
|
||||
33. 作为回顾近期练习的人,我希望切换周和月查看时长趋势,以便了解一段时间内的练习安排。
|
||||
34. 作为回顾练习结构的人,我希望看到各项目时长及占比,以便了解投入分布。
|
||||
35. 作为需要休息的练习者,我希望没有练习的日期如实留空,以便回顾不依赖连续打卡或惩罚休息日。
|
||||
36. 作为使用多个设备的人,我希望同一微信身份能读取已保存的项目和记录,以便更换设备后继续使用。
|
||||
37. 作为记录个人笔记的人,我希望自己的数据只能由自己的身份读取和修改,以便笔记和练习历史保持私密。
|
||||
38. 作为遇到网络或登录问题的人,我希望界面说明当前未能加载或保存,而不把失败显示为零记录或保存成功,以便判断是否需要重试。
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
### 决策来源与实现默认值
|
||||
|
||||
- 用户已确认:练后填写、整堂记录、选填笔记、八个可编辑平铺项目、删除项目保留历史、改名统一显示新名称、三页流程、云端身份关联保存、不衔接旧数据、激励与分享后置。
|
||||
- 已认可的原型决定页面入口、操作顺序、保存后返回位置、空状态与更正路径。正式界面适配小程序;演示场景切换、固定演示日期和演示数据面板不进入产品。
|
||||
- 为使规格可执行,采用已讨论过的常规默认值:正整数分钟、日期默认今天、允许过去日期而不允许未来日期、周一至周日为一周、自然月为一个月。这些是实现默认值,不表述为用户逐项确认的产品取舍。
|
||||
- 日历日期统一按一个业务时区解释,首期默认 Asia/Shanghai;练习日期存为日期值,与创建时间分开。不依据设备时区或创建时间重新划分已保存记录的日期,首期不增加时区设置页面。
|
||||
- 下文身份校验、失败反馈、幂等写入和数据约束属于完成云端保存及准确统计所需的实现要求,不扩展为新的独立产品功能。
|
||||
|
||||
### 架构与模块职责
|
||||
|
||||
- 延续 Taro React 小程序和 Go/PostgreSQL 后端。云端保存指现有后端持久化,不因此改用另一套云服务或建立第二套业务数据源。
|
||||
- 身份与会话模块负责核验微信身份、映射内部用户标识、建立与校验业务会话。外部身份核验集中在一个适配边界;不得将客户端自报的用户标识直接作为授权依据。
|
||||
- 练习业务模块统一负责项目管理、记录增删改查和回顾统计。对外提供业务操作,内部封装归属校验、分钟与日期规则、归档规则及数据库操作;不按每个页面重复实现统计逻辑。
|
||||
- 小程序负责页面状态、表单反馈与展示,通过统一请求边界使用业务接口。服务端对所有写入再次校验,不依赖客户端校验保证正确性。
|
||||
- 复用现有服务启动、数据库连接和 HTTP 请求处理结构。现有存活及就绪检查继续保持职责独立;新增业务接口必须校验身份。
|
||||
- 首期统计直接从有效记录计算,避免维护另一套容易失真的累计余额。需要优化时以相同可观察结果为约束,不提前建立复杂缓存或异步统计系统。
|
||||
|
||||
### 数据模型与不变量
|
||||
|
||||
| 对象 | 必要信息 | 约束 |
|
||||
| --- | --- | --- |
|
||||
| 用户 | 内部身份、经服务端验证的微信身份关联 | 同一身份恢复同一份数据;身份密钥与平台凭据仅存于服务端 |
|
||||
| 练习项目 | 稳定标识、所属用户、当前名称、是否归档 | 用户之间隔离;改名保留标识;有历史记录时不可级联删除 |
|
||||
| 练习记录 | 稳定标识、所属用户、项目标识、实际练习日期、整数分钟、可空文本笔记 | 每条只属于一个本人的项目;日期不晚于业务当天;分钟大于零;笔记可留空 |
|
||||
| 写入识别信息 | 用户范围内的请求标识及处理结果 | 同一次新增的重试可识别;不能吞掉用户有意新建的第二条相同内容记录 |
|
||||
|
||||
- 服务端首次建立用户时一次性创建八个预置项目。初始化应原子且可重入;再次登录不得重复创建,也不得恢复用户已删除或归档的预置项目。
|
||||
- 项目改名后,历史记录通过同一项目标识读取当前名称。记录日期、分钟与笔记不变,不另存一份用于展示的旧项目名称。
|
||||
- 没有记录的项目可以删除;存在记录的项目执行归档。判定与移除应具有一致性,避免与同时新增记录竞争时删掉历史。
|
||||
- 归档项目不出现在新增记录的项目选择中,仍参与历史查询和全部统计。编辑其原有记录时可保留该项目或改选一个活跃项目;不能把另一条记录新改入已归档项目。
|
||||
- 删除练习记录后,该记录不再参与日历、练习天数和时长统计。项目归档与记录删除是不同操作:前者保留历史,后者去掉误记。
|
||||
- 新增、改名时拒绝全空白项目名;笔记按普通文本保存和展示。客户端与服务端保持一致的输入长度限制和错误提示,不把原型中的临时输入上限当作产品决策。
|
||||
- 所有关联校验都包含用户归属;不能通过猜测另一个项目或记录标识跨账户读取或修改数据。
|
||||
|
||||
### 接口契约
|
||||
|
||||
以下约定业务输入输出,不预先固定路由命名或内部函数形状。所有业务操作从有效会话识别用户,错误返回应能区分需要重新登录、输入无效、对象不可用和暂时性服务失败。
|
||||
|
||||
| 操作 | 输入与条件 | 可观察结果 |
|
||||
| --- | --- | --- |
|
||||
| 建立/恢复会话 | 微信端取得的有效身份交换凭据 | 返回业务会话;恢复同一用户,必要时完成一次性预置初始化 |
|
||||
| 查询项目 | 有效会话 | 返回当前活跃项目;查询历史时仍能解析归档项目的名称和状态 |
|
||||
| 新增/改名项目 | 名称;改名另带项目标识 | 返回稳定标识与最新名称;改名在后续历史和统计查询中统一生效 |
|
||||
| 移除项目 | 本人项目标识 | 未使用项目删除,已使用项目归档;结果明确告知采取的操作 |
|
||||
| 查询练习记录 | 日期或日期范围;近期列表使用有界查询 | 返回本人记录、当前项目名称、日期、分钟及笔记;归档项目记录仍可返回 |
|
||||
| 新增记录 | 活跃项目、练习日期、分钟、可空笔记、此次提交标识 | 完整持久化后返回记录;相同提交标识的重试不重复新增 |
|
||||
| 更正记录 | 本人记录标识和完整有效表单 | 原记录被更新;不新增记录;遵守归档项目的编辑规则 |
|
||||
| 删除记录 | 本人记录标识 | 记录不再可见且不参与汇总;重试不会作用于其他记录 |
|
||||
| 查询回顾 | 累计范围、选定周或月等所需范围 | 返回总分钟、去重练习天数、按日期的分钟及项目分布;结果使用一致的范围口径 |
|
||||
|
||||
- 对同一次新增,客户端在等待或重试期间复用提交标识,首次成功后结束该次提交;再次主动登记生成新的标识。重复提交不同内容时应给出可识别错误,不静默覆盖第一次结果。
|
||||
- 加载失败与有效空结果是不同状态。失败不得被映射为零分钟、零天或空历史;保存提示以服务端确认持久化为准。
|
||||
- 写入成功后更新或重新获取受影响的记录、日历和成长数据。迟到的旧请求响应不得覆盖新结果;返回来源页面时应能看到本次修改。
|
||||
- 会话失效时允许重新建立会话并继续操作;在结果未确认前保留用户填写内容。客户端仅作临时表单保留,不承担跨设备数据持久化或离线冲突合并。
|
||||
|
||||
### 页面与交互
|
||||
|
||||
- 记录页以活跃项目平铺列表作为主要录入入口,展示近期记录并提供项目管理入口;新用户看到真实空状态和预置项目。
|
||||
- 记录表单包含项目、实际练习日期、分钟、选填笔记。整堂课只产生一条记录,额外练习另建记录。保存期间阻止重复操作;失败保留表单;取消不写入。
|
||||
- 从记录页新增时日期默认今天;从日历新增时沿用选中日期;编辑时读取原记录。保存完成回到原页面,并展示成功反馈及更新后的数据。
|
||||
- 记录删除沿用原型中的误记删除路径并清楚提示影响,避免将“移除项目”和“删除记录”混淆。无效提交不能关闭表单或显示成功。
|
||||
- 项目管理支持新增、改名和移除。有历史时明确告知将从常用项目中移除、历史仍保留;首期不增加项目分组、层级或独立归档恢复中心。
|
||||
- 日历支持月份切换、练习日期标记和当天明细。没有记录的日期展示可补记的空状态;有多条时完整列出,不把当天汇总伪装成一堂课。
|
||||
- 成长页展示累计、练习天数、周/月趋势及项目时长分布。采用原型中的趋势切换路径;首期不再增加年趋势或任意范围分析面板。
|
||||
- 所有项目均移出活跃列表时,仍可查看历史和成长,并提供新增项目入口。零记录时占比展示为空状态,不出现无效百分比或虚构数据。
|
||||
|
||||
### 统计口径
|
||||
|
||||
- 总时长等于所选范围内有效记录的整数分钟之和;先汇总,再格式化为小时和分钟。展示取整不得反向参与统计。
|
||||
- 练习天数等于所选范围内至少有一条有效记录的不同练习日期数,不等于记录条数、注册天数或连续打卡天数。
|
||||
- 每条记录计入一个项目一次;所有项目分钟之和等于同范围总分钟。有历史的归档项目照常计入,名称使用最新名称。
|
||||
- 项目占比以该项目分钟除以同范围总分钟计算;零总量时不做除法。显示百分比可按统一精度取整,因此显示值总和可能有舍入差异,不能靠改动分钟数强凑。
|
||||
- 周趋势按所选周的日期汇总,月趋势按所选自然月的日期汇总;无记录日为零。日历与图表按实际练习日期归属,不按提交日期归属。
|
||||
- 补记、更改日期、更改项目、修改分钟或删除记录后,所有受影响日期、范围和项目的统计应重新反映有效记录。改名和归档本身不改变累计时长或练习天数。
|
||||
|
||||
## Testing Decisions
|
||||
|
||||
### 主要自动化边界
|
||||
|
||||
优先使用现有 HTTP handler 的公开请求/响应边界,覆盖身份后的项目、记录、回顾完整业务路径。现有健康检查测试已经使用 Go 标准测试工具和 HTTP 测试请求验证状态码、响应及上下文行为,可沿用该风格。
|
||||
|
||||
业务集成测试连接独立 PostgreSQL 测试数据库或隔离命名空间,运行相同的数据结构初始化,验证真实持久化、关联和查询。只在外部微信身份核验边界替换不可控的平台网络响应,业务会话、归属校验和数据库行为继续实际执行。不为每个内部函数、SQL 语句或页面组件另设一套测试边界。
|
||||
|
||||
仓库当前只有健康检查测试,没有项目、练习记录或前端端到端测试。上述业务测试环境需要随功能建立;默认不另引入小程序端到端自动化框架。该安排是依据现有测试入口提出的执行默认方案,尚未经用户单独确认;不影响已经确认的产品范围。
|
||||
|
||||
### 验收场景
|
||||
|
||||
| 场景 | 对外结果 |
|
||||
| --- | --- |
|
||||
| 同一身份首次进入与再次登录 | 首次得到八个活跃项目和零记录;再次进入不重复预置、不恢复已移除项目;有效历史保持不变 |
|
||||
| 不同用户访问同一对象标识 | 第二个用户不能读取、更改或删除第一个用户的项目及记录;接口不泄露其笔记 |
|
||||
| 同日登记 90 分钟课程及 15 分钟额外练习 | 两条记录、105 分钟、1 个练习日;项目分布分钟合计为 105 |
|
||||
| 将 90 分钟改为 60,再删除 15 分钟误记 | 先得到 75 分钟,再得到 60 分钟;日历、近期记录与成长一致 |
|
||||
| 将同日两条中的一条移到另一日期 | 总分钟不变,练习日从 1 变为 2;原日期和新日期的日历与趋势同时变化 |
|
||||
| 改名并归档有记录的项目 | 历史和统计统一显示新名称,时长及练习天数不变;新增选择器中不再出现该项目 |
|
||||
| 编辑归档项目原有记录 | 可更正日期、时长、笔记并保留原项目,或改选活跃项目;不能新增记录到归档项目 |
|
||||
| 删除未使用项目并重新登录 | 项目仍保持移除状态,不被再次初始化;仍可添加新的项目 |
|
||||
| 删除某天最后一条记录 | 该日期不再计入练习天数;删除全部记录后累计为 0、练习天数为 0,分布展示空状态 |
|
||||
| 分钟精度与边界日期 | 45 分钟和 30 分钟合计显示 1 小时 15 分钟;月底、周日/周一的记录按约定边界归属,补记不落在提交日 |
|
||||
| 可空笔记和无效表单 | 空笔记成功保存;零、负数、非整数分钟、未来日期、空项目名以及不可用项目写入被拒绝,不产生部分数据 |
|
||||
| 重复提交与主动重复登记 | 同一提交标识重试只得到一条记录;用户两次主动登记相同内容可得到两条记录 |
|
||||
| 提交已成功但响应丢失 | 使用原提交标识重试后得到已保存记录,不重复累计;输入不会因未经确认的结果而丢失 |
|
||||
| 服务异常或会话失效 | 明确区分失败与空历史;重试或重新登录后可继续;不显示虚假保存成功 |
|
||||
|
||||
好的测试从请求开始,断言返回结果及后续读取能看到的事实;时长、练习天数和归档语义均通过业务接口验证。不以内部调用次数、SQL 字符串、组件结构或样式快照替代业务结果。日期测试使用受控的业务当天,避免执行日期不同造成不稳定。
|
||||
|
||||
### 小程序与真实平台验收
|
||||
|
||||
- 用微信开发者工具走完三页导航、首次空状态、整堂记录、补记、更正、误记删除、项目改名与归档,核对表单键盘、滚动和窄屏布局。
|
||||
- 用真实微信身份完成首次使用、会话恢复和另一设备读取同一份记录;重启客户端后仍能读取,另一身份看不到这些记录。
|
||||
- 检查弱网/断网保存失败、重复点击、会话失效、重新进入页面后的反馈。确认保存成功来源于真实后端响应。
|
||||
- 小程序源码变更后,在其项目目录执行 `pnpm typecheck`、`pnpm build`;后端源码变更后,在其项目目录执行 `go vet ./...`、`go test -race ./...`、`go build -o bin/api ./cmd/server`。若调整部署配置,另验证 Compose 和镜像构建。
|
||||
- 静态检查、构建、HTTP 集成测试和真实微信设备验收分别记录结果;任何一项通过均不替代其他项。本文是规格,本轮未执行这些生产实现检查。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 实时计时器、后台计时、番茄钟,以及把一堂课拆为多个动作或训练环节。
|
||||
- 自建课程、教学视频、动作知识库、训练计划、自动推荐、技能等级评估或医疗/康复建议。
|
||||
- 语音录入、LLM 解析练习、动作识别。其他尚未确认的规划事项不自动扩充本规格。
|
||||
- 练习目标、成就徽章、分享卡片、连续打卡奖励和社交排行。
|
||||
- iHour 自动同步、数据导入、历史迁移、期初累计;普通的按实际日期补记仍在范围内。
|
||||
- 项目父子层级、同时给多项目累计同一条记录、完整归档管理或回收站体系。
|
||||
- 笔记附件、图片或视频上传,以及笔记内容的自动分析。
|
||||
- 独立手机号注册、多平台原生客户端、订阅或付费体系。
|
||||
- 离线保存队列、多设备同时编辑冲突合并、实时推送同步。已确认的云端记录跨设备读取与恢复仍在范围内。
|
||||
- 本次规格交付不包含业务代码实现、生产部署或发布。
|
||||
|
||||
## Further Notes
|
||||
|
||||
### 依据与交付边界
|
||||
|
||||
- 需求依据为当前对话及已解决的[记录流程](issues/02-recording-flow.md)、[项目组织](issues/03-practice-organization.md)、[成长回顾](issues/04-growth-review.md)、[数据保存](issues/05-record-continuity.md)、[核心交互](issues/06-core-flow-prototype.md)决策。
|
||||
- [iHour 调研](issues/01-ihour-evidence.md)用于理解参考产品;用户截图中的数字与布局是使用证据,不是导入要求,也不构成训练分类或能力评估标准。
|
||||
- [用户认可的交互草图](/Users/yuxuanhui/.codex/visualizations/2026/09/28/01a0e6a5-d2a3-7f51-bff3-545ef8c42df0/ballet-practice-flow.html)是本机设计参考,不直接复制为生产实现。原型使用内存和虚构样例,未接入微信或后端;正式实现不得依赖该本机路径运行。
|
||||
- 原型已实际验证新增、编辑、删除、改名、归档、日历回看和周/月切换,并检查过窄屏显示;这些证据只说明流程草图可操作,不证明生产持久化、登录或跨设备恢复可用。
|
||||
- 同目录的其他规划票保持原状,未纳入这轮已确认范围。本规格不宣称整张规划地图全部完成。
|
||||
|
||||
### 实现前置条件
|
||||
|
||||
- 当前仓库是小程序欢迎页与 Go 服务健康检查骨架,尚无业务数据结构、身份认证、项目/记录接口或成长页面。应把本规格作为完整业务闭环的新实现,不能假设相应接口已经存在。
|
||||
- 当前项目声明 Taro 4.2.1、React 18.3.1、Taroify 1.0.6,后端使用 Go、pgx 和 PostgreSQL;实现时依照各项目约定核对实际依赖和所需官方文档。此处版本描述来自配置读取,不表示本轮运行过这些工具。
|
||||
- 实现阶段需要为新业务结构建立可重复执行的数据迁移,并为测试提供隔离数据库。不得使用用户实际练习数据作破坏性验收样本。
|
||||
- 微信身份交换、会话生命周期、平台所需网络配置和可用的 HTTPS 后端地址需按真实应用配置接通并核实。平台凭据不能放入小程序包,部署及凭据配置不能由“规格已完成”推定为已授权发布。
|
||||
- `ready-for-agent` 表示范围和验收依据足以交给开发代理,不表示业务代码已完成、构建已通过或产品已经上线。
|
||||
Reference in New Issue
Block a user