Commit Graph

13 Commits

Author SHA1 Message Date
liucheng 83077648fe perf(voice): app onLaunch 预载语音,进一步消除首段延迟
- app.js onLaunch 调 voice.preload(),app 启动即后台下载全部语音
- 与 timer 页 onLoad 预载形成双保险(已缓存条目 no-op)
- 仅语音引导开启时预载,在 cloud.init 之后调用

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 14:22:29 +08:00
lc 6176f2c341 feat(ui): 记录页月份联动与多项 UI 美化/修复
- records: 底部列表与月份选择器联动,新增 [本月|最近] 分段控件;标题/空态随模式切换
- leaderboard: 领奖台布局(冠军居中+皇冠)、次数标注于底座且三档水平对齐;头像 cloud:// 批量预解析提速(云函数需重新部署)
- index/timer: 主色底图标改白色变体修复隐形;目标数字按微信字体缩放补偿真机遮挡
- settings: 配色方案横滑渐变色卡;头像上传前压缩至 200px
- theme: 新增 teal 主题;暗黑背景统一对齐
- 圆形头像双保险(image 自身 border-radius)修复月/年榜方图

注: cloudfunctions/leaderboard 改动须在开发者工具重新部署才生效。
2026-07-22 09:36:22 +08:00
lc 70b87d424d perf(theme): onLaunch 提前设导航栏色,缩小冷启动橙->主题色跳变
新增 applyChrome() 在 onLaunch 第一行调用,把导航栏变色点从首页 onShow
提前到 onLaunch,缩短冷启动橙色跳变窗口。app.json 静态橙色在 JS 执行前
生效是框架硬限制,无法完全消除。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 09:54:41 +08:00
lc 1eff3d60c4 fix(ui): 多项 UI 修复 — 弹窗遮挡/按钮可见性/暗黑闪烁/云函数版本
- 计划编辑弹窗移出 .container 避免 fixed 降级 + 修复滚动
- dock bottom 40rpx→8rpx 紧贴底部, sheet padding 同步调整
- 计划编辑器取消/恢复默认按钮可见性修复(bg 匹配容器)
- ui-btn--danger 按钮可见性修复
- 清除确认弹窗跟随暗黑模式切换
- icons.js build() 中 Fill 路径覆盖 outlined 路径修复
- plan.js getPlanDay 忽略 customPlans 修复
- darkMode.js 冗余三元简化
- util.js fileToDataURI fallback 可读性提升
- theme.js: BASE_VARS 与 getThemeStyle 统一来源, 去 50ms navbar 延迟
- app.wxss: 移除 page transition 和 background-color 减少闪白
- 云函数 wx-server-sdk 版本统一 ~2.6.3, tts cloud.init 一致化
- 闪白问题: wx.setBackgroundColor 三层防护(onLaunch/applyThemeToPage/switchTab)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 09:40:04 +08:00
lc 850f919269 fix(sync): 数据同步合并化 + 排行榜缓存与游标分页
- storage: 新增 mergeRecords,云端记录与本地按 id 去重合并,restore
  不再覆盖,解决训练中冷启动丢记录与多设备记录丢失
- storage: 新增 recomputeStreak,restore 后基于合并记录重算 streak,
  不再信任云端 streak 值
- storage: 新增 _local_changed_at 标记,settings/profile/customPlans
  在本地有未同步改动时保留本地,避免被云端旧值覆盖
- app: _restoreFromCloud 改合并 + 时间戳保护 + streak 重算;Case 2
  合并后回推让两端收敛
- leaderboard: 模块级 60s 缓存 + 游标分页(_id > lastId)替代 skip,
  全表扫描从每次打开降到 60s 内一次

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 09:06:44 +08:00
lc c43f1d7389 feat: 深色模式基础设施 (system theme + 跟随系统) 2026-07-08 11:33:09 +08:00
lc d817d5d012 fix: 13项数据存储与排行榜修复
致命修复:
- leaderboard: 日榜日期比较改用 dateOnly() 替代严格全等
- plan: 计划天数计算日期比较改用 dateOnly()
- cloud: pullAll 添加 orderBy('updatedAt','desc') 确保取最新文档避免数据丢失

严重修复:
- cloud: 新增 cancelPendingPush() 防止清除数据后被延迟推送复活
- settings: _doClearData 补充 user_profile 清除, 先取消推送再清除
- app: 云端同步改为时间戳比对策略, 支持跨设备拉取
- app: _restoreFromCloud 增加空数据保护和 profile 恢复
- storage: 记录ID改用时间戳+自增计数器确保唯一性

中等修复:
- cloud: init/_fetchOpenid 日志升级, 新增 syncStatus getter
- leaderboard云函数: 添加90天活跃过滤减少全表扫描
- storage: validateStreak 增加lastDate无记录时的通用修复
- leaderboard页面: 云函数失败时Toast提示用户而非静默降级

轻微修复:
- timer: onUnload 添加 voice.destroy() 释放音频上下文
- records: onLongPressDelete 委托给 onDeleteRecord 消除重复代码

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-24 12:22:54 +08:00
liucheng 6d1992869e fix: 修复排行榜数据自增长(冷启动重复创建云端文档)
每次小程序冷启动都会为同一用户创建新的云端文档,
导致 leaderboard 把同一份数据累加 N 次。

改动:
- app.js: onLaunch 改为 async,每次启动先 pullAll 填充 _openid / _docId 缓存
- utils/cloud.js: 引入 _ensureOpenid() 单次解析;_doPush 总是先按 openid
  定位现有文档;update 失败不再回退到 add()(避免创建重复文档)
- utils/storage.js: getTodayRecord 按日期部分比较,修复一天第二次训练
2026-06-21 22:56:51 +08:00
lc 1d55df72b3 feat: v1.5 — plan editor, voice prompts, UI polish
Major features:
- Training plan editor: edit preset days/duration per plan (in-place
  override via custom_plans storage; preset ids preserved so existing
  records stay valid)
- Voice prompts at 4 fixed points during training (halfway / 30s /
  10s / done) via Tencent Cloud TTS (cloudfunctions/tts + utils/voice.js)
- Free-training button: switched from outline (transparent) to ghost
  variant (theme-tinted) for visual weight

Bug fixes:
- 4 functional pages: SVG data URIs failed to render in WeChat because
  '\#' in colors was parsed as a data-URI fragment delimiter. encode the
  whole SVG via encodeURIComponent in utils/icons.js build().
- Old records (saved before id field was added) could not be deleted
  (data-id was empty, triggered defensive guard). Backfill stable
  legacy-<month>-<index>-<duration> ids in getRecords() and persist.
- settings.js plan-row editor button event was bubbling up to the row's
  bindtap (which also fired onSelectPlan). Wrapped in catch:tap.

UI:
- Settings page: 3 hardcoded plans replaced with dynamic buildPlansList
  that overlays custom_plans on top of presets
- Plan editor: bottom-sheet modal in settings page (regular view, not
  ui-modal — WeChat custom component root element drops position:fixed
  in this runtime)
- Free-training button: rounded pill style, full-width, 24rpx gap from
  primary action; bottom sheet uses max-height: 88vh + internal scroll
- Version bumped to v1.5, last updated 2026-06-10

Removed:
- Daily reminder section (dailyReminder / reminderTime) — replaced by
  the 4 voice prompts which cover the same user need without requiring
  long-term scheduling that WeChat mini-programs can't actually do

Misc:
- utils/plan.js refactored to formula-driven: presets declare
  totalDays/startTarget/increment/cycleDays, days[] is generated. Same
  formula applies to custom plans.
- Timer _remind() guards each prompt on minimum duration so short
  free-mode sessions don't fire 'last30' at the start
- Cloud storage cloud_plans field added to data push payload; restored
  on first install via _restoreFromCloud
- .gitignore added for local AI tool caches (.reasonix/, reasonix.toml,
  .codegraph/daemon.pid)
2026-06-10 17:23:13 +08:00
lc fa8d8e7b4b fix: seed existing local data to cloud on first launch
Previously cloud sync only triggered on writes. If the user already
had training records before cloud was enabled, they'd never be pushed
— leaving the database empty until the next training session.

Now onLaunch handles both cases:
  - Local empty → restore from cloud (recovery after deletion)
  - Local has data → check cloud; if cloud empty, push existing data up

Also extract _restoreFromCloud to reduce nesting.
2026-06-04 17:29:13 +08:00
lc a04c017e37 feat: cloud sync with WeChat CloudBase — data survives app deletion
Problem: All data stored in wx.StorageSync is permanently lost when
user deletes the mini-program or clears cache.

Solution: Sync data to WeChat CloudBase (wx.cloud.database).
- Graceful degradation: if cloud env isn't configured, all local
  storage works exactly as before.
- On app launch: if local records are empty, pull from cloud.
- On writes: push to cloud (debounced 2s) after saveRecord,
  deleteRecord, saveSettings, updateStreak, setTheme.
- Clear data in settings also clears cloud.

Files:
- utils/cloud.js: cloud sync wrapper (init, pullAll, pushAll, clearAll)
- app.js: cloud.init() + restore on fresh install
- utils/storage.js: cloud.pushAll() after every mutation
- utils/theme.js: cloud.pushAll() after setTheme
- pages/settings/settings.js: cloud.clearAll() when clearing data
- project.config.json: cloudfunctionRoot added

Setup required (one-time in WeChat DevTools):
  1. Open 'Cloud Development' panel → enable CloudBase
  2. Create environment → copy env ID
  3. In app.js, change wx.cloud.init() → wx.cloud.init({ env: 'YOUR-ENV-ID' })
  4. Create 'plank_data' collection in cloud database
  5. Set collection permission to 'Only creator can read/write'
2026-06-04 17:13:35 +08:00
lc 8c7f633541 refactor: ES6+ modernization + 2 bugfixes
- var→const/let, function→arrow/class across all 13 JS files
- Timer: prototype→class with ES6 getters
- plan days: IIFE→Array.from declarative generation
- storage/plan: unified formatDate via util.js
- Bugfix: getPlanDay now filters by planId (plan switch accuracy)
- Bugfix: getTodayRecord searches all months (cross-month boundary)
- WXML/WXSS unchanged; public API unchanged
2026-06-04 16:29:25 +08:00
lc ff2700c067 backup: snapshot before optimization 2026-06-04 16:25:43 +08:00