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:
yuxuanhui
2026-09-29 13:47:26 +08:00
parent 4b42b55928
commit 6224ef5980
49 changed files with 2824 additions and 71 deletions
@@ -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`。