Marathon Training Dashboard
基于 React + CSS 的马拉松训练仪表盘,运行在 VitePress 中(通过 @docs-islands/vitepress 岛屿架构)。Strava 风格设计,支持亮/暗色主题。
根目录: daily/long-term-goals/components/
架构概览
Dashboard 采用两层布局:主面板仅展示 ProgressTracker(4 个统计卡片)+ TrainingCalendar(热力图日历),所有详细信息通过点击卡片弹窗展示。
MarathonDashboard
├── ProgressTracker (4 stat cards)
│ ├── 本周里程 ring → click → WeeklyDistributionModal (柱状图)
│ │ └── click bar → WorkoutModal (训练详情)
│ ├── 计划进度 ring → click → CycleOverviewModal (周期时间线)
│ ├── 累计公里 (static)
│ └── 完成训练 → click → PersonalRecords (个人纪录)
└── TrainingCalendar (热力图)
└── click day → TrainingDayModal (日详情)
└── click workout → WorkoutModal快速入口
| 需求 | 文件路径 |
|---|---|
| 修改训练计划数据 | training-config.ts |
| 添加/同步训练记录 | pnpm strava:sync 或编辑 data/workouts.json |
| 修改训练类型颜色/图标 | core/theme.ts + core/theme.css |
| 修改日历弹窗样式 | composites/TrainingDayModal.tsx + .css |
| 修改训练详情弹窗 | composites/WorkoutModal.tsx + .css |
| 修改进度卡片/周里程弹窗 | composites/ProgressTracker.tsx + .css |
| 修改周期概览弹窗 | composites/CycleOverview.tsx + .css |
| 修改个人纪录弹窗 | composites/PersonalRecords.tsx + .css |
| 修改日历样式 | composites/TrainingCalendar.tsx + .css |
| 统计计算逻辑 | utils/compute-stats.ts |
| 添加新组件 | 参考 primitives/ 或 composites/ 目录 |
文件结构
bash
components/
├── core/
│ ├── types.ts # 所有 TypeScript 接口定义
│ ├── theme.ts # 训练类型 → {color, icon, label} 映射
│ └── theme.css # CSS 变量 (颜色/字体/间距/暗色模式)
├── primitives/
│ ├── Badge.tsx # 训练类型标签 <Badge type="tempo" />
│ ├── Card.tsx # 卡片容器 (支持 onClick)
│ ├── HeartRateBar.tsx # 心率5区可视化条
│ ├── ProgressRing.tsx # SVG 环形进度条
│ └── Tabs.tsx # 标签页切换
├── composites/
│ ├── TrainingCalendar.tsx # 热力图日历 + TrainingDayModal 入口
│ ├── TrainingDayModal.tsx # 点击日期后的详情弹窗
│ ├── ProgressTracker.tsx # 进度卡片 + WeeklyDistributionModal (内联)
│ ├── CycleOverview.tsx # CycleOverviewModal 弹窗
│ ├── PersonalRecords.tsx # PersonalRecords 弹窗
│ ├── WorkoutModal.tsx # 训练详情弹窗 (z-index: 1010)
│ ├── HeartRateZones.tsx # 心率区间 (在 TrainingDayModal 中使用)
│ ├── TrainingTable.tsx # 训练计划表格
│ └── WeeklyDistribution.tsx # 独立周分布组件
├── utils/
│ └── compute-stats.ts # 动态统计计算 (周目标/每日目标/配速)
├── training-config.ts # 训练计划配置 + 数据聚合入口
├── MarathonDashboard.tsx # 主组件,组合 ProgressTracker + Calendar
└── index.ts # 导出入口数据流
workouts.json (Strava 同步)
↓
training-config.ts (聚合)
├── workoutRecords ← workouts.json.workouts
├── personalRecords ← workouts.json.personalRecords
├── progressStats ← computeProgressStats(workoutRecords, config)
├── trainingPlan ← 静态配置 (weeklyPlan, cycles, lsdDistanceByWeek)
└── calendarConfig ← { startDate: '2026-01-19' }
↓
MarathonDashboard.tsx
├── ProgressTracker(stats, workoutRecords, cycles, personalRecords)
└── TrainingCalendar(plan, startDate, workoutRecords)核心类型
typescript
type TrainingType =
| 'rest'
| 'recovery'
| 'easy'
| 'tempo'
| 'interval'
| 'lsd'
| 'strength';| 接口 | 用途 | 关键字段 |
|---|---|---|
WorkoutRecord | Strava 实际训练记录 | date, distance, avgPace, avgHeartRate, zoneDistribution |
TrainingSession | 计划训练 | type, details, targetHR, weekParity, tips |
ProgressStats | 进度统计 | weeklyDistance, weeklyTarget, dailyDistances, dailyTargets |
TrainingCycle | 训练周期 | name, weeks, phase (base/build/peak/taper) |
HeartRateZone | 心率区间定义 | zone(1-5), name, min, max, color |
TrainingPlan | 完整训练计划 | weeklyPlan, cycles, heartRateZones, lsdDistanceByWeek |
PersonalRecord | 个人纪录 | distance, time, date, dateDisplay |
弹窗层级 (z-index)
| 弹窗 | z-index | 说明 |
|---|---|---|
| 基础弹窗 (Weekly/Cycle/PR) | 1000 | 一级弹窗,从主面板打开 |
| WorkoutModal | 1010 | 二级弹窗,可从一级弹窗内打开 |
CSS 命名前缀
| 前缀 | 组件 |
|---|---|
tr- | ProgressTracker / 通用 |
wd- | WeeklyDistributionModal |
co- | CycleOverviewModal |
pr- | PersonalRecords |
tdm- | TrainingDayModal |
格式约定
| 数据 | 格式 | 示例 |
|---|---|---|
| 日期 | YYYY-MM-DD | "2026-02-03" |
| 配速 | 分'秒"/km | "5'00\"/km" |
| 时长 | H:MM:SS 或 MM:SS | "0:40:07" |
| 单双周 | weekParity | 'odd' = 1,3,5 周; 'even' = 2,4,6 周 |
| 心率区间 | Z1-Z5 | 基于 Strava 个人设置,最大心率 185 |
Strava 同步
bash
pnpm strava:sync # 同步最近 7 天
pnpm strava:sync --days 14 # 同步最近 14 天
pnpm strava:sync --all # 同步所有数据 (从训练开始日期)
pnpm strava:sync --dry-run # 预览不写入
pnpm strava:auth # 首次 OAuth 授权脚本目录: scripts/strava/ (auth, client, config, sync, transform)
详细参考
| 主题 | 说明 | 参考 |
|---|---|---|
| 设计令牌 | CSS 变量、类型定义、暗色模式 | design-tokens |
| 修改指南 | 常用修改模板、组件 Props、弹窗流程 | modification-guide |