xiaocao-fitness/app.js · 约 5354 字符
1// 小草健身打卡 · 交互逻辑
2
3// 首页
4function renderIndex(){
5 const today = WEEK_DATA.find(d=>d.active) || WEEK_DATA[6];
6 document.getElementById('hc-date').textContent = '今天是运动第' + USER.streak + '天 · 周日';
7 animateNum('hc-cal', today.cal);
8 document.getElementById('hs-min').textContent = today.min;
9 document.getElementById('hs-steps').textContent = (today.cal * 12).toLocaleString();
10 document.getElementById('hs-streak').textContent = USER.streak;
11 renderWeekChart();
12 renderPlans();
13 renderCourses();
14}
15function animateNum(id,target){
16 const el=document.getElementById(id); if(!el) return;
17 let cur=0; const step=target/30;
18 const t=setInterval(()=>{cur+=step;if(cur>=target){cur=target;clearInterval(t)}el.textContent=Math.round(cur)},20);
19}
20function renderWeekChart(){
21 const el=document.getElementById('week-chart');
22 if(!el) return;
23 const max=Math.max(...WEEK_DATA.map(d=>d.cal));
24 el.innerHTML=WEEK_DATA.map(d=>`
25 <div class="bar ${d.active?'active':''}" style="height:${max>0?(d.cal/max*80+4):4}px">
26 ${d.cal>0?`<div class="bar-val">${d.cal}</div>`:''}
27 <div class="bar-label">${d.day}</div>
28 </div>`).join('');
29 const wt=document.getElementById('week-total');
30 if(wt) wt.textContent=WEEK_DATA.reduce((s,d)=>s+d.cal,0);
31}
32function renderPlans(){
33 const el=document.getElementById('plan-list');
34 if(!el) return;
35 el.innerHTML=PLANS.map(p=>`
36 <div class="plan-item">
37 <div class="pi-icon" style="background:${p.color}">${p.icon}</div>
38 <div class="pi-info">
39 <div class="pi-name">${p.name}</div>
40 <div class="pi-desc">${p.desc}</div>
41 <div class="pi-progress">进度 ${p.progress}</div>
42 </div>
43 <span class="pi-go">›</span>
44 </div>`).join('');
45}
46function renderCourses(){
47 const el=document.getElementById('course-grid');
48 if(!el) return;
49 el.innerHTML=COURSES.map(c=>`
50 <div class="course-card">
51 <div class="cc-img" style="background:${c.color}">${c.icon}</div>
52 <div class="cc-body">
53 <div class="cc-title">${c.title}</div>
54 <div class="cc-meta">${c.type} · ${c.duration} · ${c.cal}千卡</div>
55 ${c.tag?`<span class="cc-tag" style="background:var(--primary-light);color:var(--primary)">${c.tag}</span>`:''}
56 </div>
57 </div>`).join('');
58}
59function startWorkout(){
60 const courses=['🔥 HIIT燃脂20分钟','🏃 晨跑5公里','💪 力量训练','🧘 瑜伽拉伸'];
61 alert('▶️ 开始运动!\n\n推荐课程:\n'+courses.join('\n')+'\n\n点击确认开始记录运动数据');
62}
63
64// 训练
65function renderTrain(){ renderPlans(); renderCourses(); }
66
67// 统计
68function renderStats(){
69 document.getElementById('s-cal').textContent=USER.totalCal.toLocaleString();
70 document.getElementById('s-min').textContent=USER.totalMin;
71 document.getElementById('s-days').textContent=USER.days;
72 document.getElementById('s-avg').textContent=Math.round(USER.totalCal/USER.days);
73 renderWeekChart();
74}
75
76// 运动圈
77function renderCircle(){
78 const el=document.getElementById('post-list');
79 if(!el) return;
80 el.innerHTML=POSTS.map((p,i)=>`
81 <div class="post-item">
82 <div class="pi-head">
83 <div class="pi-avatar" style="background:var(--primary-light)">${p.avatar}</div>
84 <div><div class="pi-user">${p.user}</div><div class="pi-time">${p.time}</div></div>
85 <div style="margin-left:auto;color:#ccc">⋯</div>
86 </div>
87 <div class="pi-text">${p.text}</div>
88 <div class="pi-img">${p.img}</div>
89 <div class="pi-actions">
90 <span class="${p.liked?'liked':''}" onclick="toggleLike(${i})">${p.liked?'❤️':'🤍'} ${p.likes}</span>
91 <span>💬 ${p.comments}</span>
92 <span>📤 分享</span>
93 </div>
94 </div>`).join('');
95}
96function toggleLike(i){
97 POSTS[i].liked=!POSTS[i].liked;
98 POSTS[i].likes+=POSTS[i].liked?1:-1;
99 renderCircle();
100}
101function publishPost(){
102 alert('📷 发布动态\n\n分享你的运动时刻,让更多人看到你的努力!\n(此为演示页面,实际使用时可上传图片/文字)');
103}
104
105// 我的
106function renderMine(){
107 document.getElementById('p-name').textContent=USER.name;
108 document.getElementById('p-level').textContent=USER.level;
109 document.getElementById('p-streak').textContent=USER.streak;
110 document.getElementById('p-cal').textContent=USER.totalCal.toLocaleString();
111 document.getElementById('p-days').textContent=USER.days;
112 const unlocked=BADGES.filter(b=>b.unlocked).length;
113 document.getElementById('badge-count').textContent=unlocked+'/'+BADGES.length;
114 document.getElementById('badge-grid').innerHTML=BADGES.map(b=>`
115 <div class="badge-item ${b.unlocked?'':'locked'}">
116 <div class="bi-icon" style="background:${b.unlocked?'var(--primary-light)':'var(--light-gray)'}">${b.icon}</div>
117 <div class="bi-name">${b.name}</div>
118 </div>`).join('');
119 document.getElementById('rank-list').innerHTML=RANKING.map(r=>`
120 <div class="rank-item">
121 <div class="ri-no ${r.no<=3?'r'+r.no:'other'}">${r.no}</div>
122 <div class="ri-avatar" style="background:var(--primary-light)">${r.avatar}</div>
123 <div class="ri-name">${r.name}</div>
124 <div class="ri-score">${r.score}</div>
125 </div>`).join('');
126}
127