设计令牌
CSS 变量
定义在 core/theme.css,所有组件中可直接使用。
css
/* 主色 */
--tr-primary: #fc4c02; /* Strava 橙 */
/* 背景 */
--tr-bg: #f8fafc; /* 页面背景 */
--tr-bg-card: #ffffff; /* 卡片背景 */
--tr-bg-card-hover: rgba(0, 0, 0, 0.02); /* 卡片悬停 */
/* 文本 */
--tr-text: #1e293b; /* 主文本 */
--tr-text-muted: #64748b; /* 次要文本 */
/* 训练类型 */
--tr-rest: #94a3b8; /* 休息-灰 */
--tr-recovery: #06b6d4; /* 恢复跑-青 */
--tr-easy: #22c55e; /* 有氧跑-绿 */
--tr-tempo: #f59e0b; /* 节奏跑-橙 */
--tr-interval: #ef4444; /* 间歇-红 */
--tr-lsd: #8b5cf6; /* LSD-紫 */
--tr-strength: #6366f1; /* 力量-靛蓝 */
/* 心率区间 */
--hr-zone-1: #3b82f6; /* Z1 蓝 */
--hr-zone-2: #06b6d4; /* Z2 青 */
--hr-zone-3: #22c55e; /* Z3 绿 */
--hr-zone-4: #f97316; /* Z4 橙 */
--hr-zone-5: #f87171; /* Z5 红 */
/* 间距 */
--tr-space-xs: 4px;
--tr-space-sm: 8px;
--tr-space-md: 16px;
--tr-space-lg: 24px;
--tr-space-xl: 32px;
--tr-space-2xl: 48px;
/* 圆角 */
--tr-radius-sm: 4px;
--tr-radius-md: 8px;
--tr-radius-lg: 12px;
--tr-radius-full: 9999px;
/* 字体 */
--tr-font-display: 'Inter', sans-serif; /* 标题/大数字 */
--tr-font-body: 'Inter', sans-serif; /* 正文 */
--tr-font-mono: 'JetBrains Mono', monospace; /* 数据显示 */核心类型定义
ProgressStats (进度统计)
typescript
// core/types.ts
interface ProgressStats {
totalDistance: number;
totalSessions: number;
currentWeek: number;
totalWeeks: number;
weeklyDistance: number;
weeklyTarget: number;
dailyDistances?: number[]; // [Mon=0, Tue=1, ..., Sun=6]
dailyTargets?: number[]; // 每日计划距离,用于柱状图 100% 基准
}ComputedProgressStats (扩展统计,由 compute-stats.ts 返回)
typescript
// utils/compute-stats.ts
interface ComputedProgressStats extends ProgressStats {
weeklySessionCount: number; // 本周训练次数
weeklyCalories: number; // 本周总卡路里
weeklyAvgPace?: string; // 本周加权平均配速
}WorkoutRecord (Strava 实际训练记录)
typescript
// core/types.ts
interface WorkoutRecord {
date: string; // "2026-02-03"
type: 'run' | 'walk' | 'strength' | 'rest';
name: string; // "热身跑"
timeRange?: string; // "19:52-20:09"
location?: string; // "Fuzhou"
duration: string; // "0:17:20"
distance: number; // 2.31 (km)
activeCalories: number;
totalCalories: number;
elevation: number; // 2 (m)
avgPower?: number; // 160 (W)
avgCadence?: number; // 177 (SPM)
avgPace: string; // "7'29\"/km"
avgHeartRate: number; // 135
effort: EffortLevel; // 1-10
effortDescription: 'Easy' | 'Moderate' | 'Hard' | 'All Out';
zoneDistribution?: ZoneDistribution[];
}
interface ZoneDistribution {
zone: 1 | 2 | 3 | 4 | 5;
duration: string; // "35:20"
percentage?: number; // 0-100
}TrainingSession (计划训练)
typescript
// core/types.ts
interface TrainingSession {
type: TrainingType;
name: string; // "节奏跑"
details: string; // 多行文本
distance?: number; // 8 (km)
duration?: number;
targetHR?: { min: number; max: number };
targetPace?: string; // "5:00/km"
weekParity?: 'odd' | 'even'; // 单双周切换
tips?: string; // 睡眠/饮食/补水建议 (多行文本)
}TrainingCycle (训练周期)
typescript
// core/types.ts
interface TrainingCycle {
name: string; // "基础期"
weeks: number; // 12
phase: 'base' | 'build' | 'peak' | 'taper';
description?: string;
}PersonalRecord (个人纪录)
typescript
// core/types.ts
interface PersonalRecord {
distance: string; // "1km"
time: string; // "4:30"
date: string; // "2026-01-21"
dateDisplay: string; // "2026年1月21日"
}暗色模式
通过 VitePress 的 .dark class 自动激活:
css
.dark {
--tr-bg: #0f172a;
--tr-bg-card: #1e293b;
--tr-bg-card-hover: rgba(255, 255, 255, 0.03);
--tr-text: #f8fafc;
--tr-text-muted: #94a3b8;
--tr-border: #334155;
}弹窗通用模式
所有弹窗遵循相同结构:
css
/* Overlay */
.{prefix}-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(8px);
z-index: 1000; /* WorkoutModal: 1010 */
animation: {prefix}-fade-in 200ms ease-out;
}
/* Modal */
.{prefix}-modal {
background: var(--tr-bg-card);
border-radius: var(--tr-radius-lg);
max-width: 440px; /* WorkoutModal: 480px */
max-height: 85vh;
animation: {prefix}-slide-up 250ms cubic-bezier(0.16, 1, 0.3, 1);
}
/* Header */
.{prefix}-header {
padding: 12px var(--tr-space-lg); /* 紧凑头部 */
position: sticky; top: 0;
border-bottom: 1px solid var(--tr-border);
}
/* Close button */
.{prefix}-header__close {
width: 28px; height: 28px;
border-radius: var(--tr-radius-full);
}响应式断点
css
/* 平板 */
@media (max-width: 768px) {
.tr-progress__stats { grid-template-columns: repeat(2, 1fr); }
}
/* 移动端 - 弹窗变 bottom sheet */
@media (max-width: 480px) {
.{prefix}-overlay { align-items: flex-end; padding: 0; }
.{prefix}-modal {
max-height: 90vh;
border-radius: var(--tr-radius-lg) var(--tr-radius-lg) 0 0;
animation: {prefix}-slide-up-mobile 300ms; /* 从底部滑入 */
}
.tr-progress__stats { grid-template-columns: 1fr; }
.tdm-workout__stats { grid-template-columns: repeat(2, 1fr); }
}