feat: 新增饮食打卡v2页面和体重管理主页v2页面

This commit is contained in:
liuyunqin
2026-07-23 17:50:56 +08:00
parent bab86f72f3
commit 6a87800b95
2 changed files with 1514 additions and 0 deletions
@@ -0,0 +1,860 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>饮食记录 - 员工端 | 健康CQ原型 v2</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #f5f7fa; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; display: flex; flex-direction: column; }
.status-bar { height: 44px; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; background: #fff; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #333; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; }
.nav-back { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: #1a1a1a; }
.nav-title { flex: 1; text-align: center; font-size: 17px; font-weight: 600; color: #1a1a1a; }
.nav-placeholder { width: 28px; height: 28px; }
.scroll-content { flex: 1; overflow-y: auto; background: #f5f7fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* ===== 周日历 ===== */
.calendar-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 14px 12px 10px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); position: relative; }
.calendar-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.calendar-card__arrow { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: #999; border-radius: 50%; transition: background .2s; user-select: none; }
.calendar-card__arrow:hover { background: #f0f0f0; color: #333; }
.calendar-card__range { font-size: 13px; font-weight: 600; color: #333; display: inline-flex; align-items: center; gap: 4px; cursor: pointer; user-select: none; }
.calendar-card__range svg { flex-shrink: 0; }
.calendar-card__date-arrow { transition: transform .2s; }
.calendar-card__date-arrow.open { transform: rotate(180deg); }
/* ===== 月历弹窗 ===== */
.month-picker { position: absolute; top: 46px; left: 12px; right: 12px; z-index: 20; background: #fff; border-radius: 14px; padding: 12px 14px; box-shadow: 0 8px 30px rgba(0,0,0,0.15); display: none; }
.month-picker.show { display: block; }
.month-picker__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.month-picker__title { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.month-picker__nav { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: #999; border-radius: 50%; font-size: 13px; }
.month-picker__nav:hover { background: #f0f0f0; }
.month-picker__weekdays { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; font-size: 11px; color: #bbb; margin-bottom: 6px; }
.month-picker__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; }
.month-picker__day { padding: 6px 0; font-size: 13px; color: #333; border-radius: 8px; cursor: pointer; font-weight: 500; position: relative; }
.month-picker__day:hover { background: #f5f5f5; }
.month-picker__day--other { color: #ddd; }
.month-picker__day--today { background: #e8fbfa; color: #36cfc9; font-weight: 700; }
.month-picker__day--selected { background: #36cfc9; color: #fff; font-weight: 700; }
.month-picker__day--has-data::after { content: ''; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 50%; background: #36cfc9; }
.month-picker__day--selected.month-picker__day--has-data::after { background: #fff; }
.cal-week { display: flex; gap: 4px; }
.cal-day { flex: 1; text-align: center; padding: 8px 0 6px; border-radius: 12px; cursor: pointer; background: #f7f8fa; transition: background .2s; }
.cal-day.active { background: #e8fbfa; }
.cal-day.today .cal-day__num { color: #1a1a1a; font-weight: 800; }
.cal-day.active .cal-day__num { color: #36cfc9; font-weight: 800; }
.cal-day.active .cal-day__wd { color: #36cfc9; font-weight: 600; }
.cal-day__wd { font-size: 10px; color: #999; margin-bottom: 2px; }
.cal-day__num { font-size: 15px; font-weight: 700; color: #333; }
.cal-day__dot { width: 5px; height: 5px; border-radius: 50%; background: #36cfc9; margin: 3px auto 0; }
.cal-day__dot--none { background: #e0e0e0; }
/* ===== 热量缺口标尺卡片 ===== */
.gap-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); }
.gap-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2px; }
.gap-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.gap-card__target { font-size: 12px; font-weight: 600; color: #36cfc9; }
/* ===== 标尺 SVG ===== */
.gauge-wrap { width: 100%; margin-top: -30px; position: relative; }
.gauge-wrap svg { width: 100%; height: auto; display: block; }
.recipe-btn { position: absolute; top: 44px; right: 8px; padding: 5px 12px; border-radius: 14px; border: none; background: linear-gradient(160deg, #36cfc9, #2db8b0); color: #fff; font-size: 11px; font-weight: 600; cursor: pointer; z-index: 5; box-shadow: 0 2px 6px rgba(54,207,201,0.3); }
/* ===== 营养素三列 ===== */
.macros-row { display: flex; gap: 10px; padding: 0 4px 8px; }
.macros-row.hidden { display: none; }
.macro-col { flex: 1; padding: 8px 10px; background: #f7f8fa; border-radius: 10px; text-align: center; }
.macro-col__name { font-size: 11px; color: #999; margin-bottom: 4px; }
.macro-col__val { font-size: 16px; font-weight: 800; color: #333; }
.macro-col__unit { font-size: 10px; font-weight: 400; color: #999; }
.macro-col__bar { height: 4px; border-radius: 2px; background: #e8e8e8; overflow: hidden; margin-top: 6px; }
.macro-col__fill { height: 100%; border-radius: 2px; }
.macro-col__fill--carb { background: #5470c6; }
.macro-col__fill--protein { background: #ee6666; }
.macro-col__fill--fat { background: #fac858; }
/* ===== 餐食卡片通用 ===== */
.meal-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 14px 16px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); }
.meal-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; cursor: pointer; }
.meal-card__left { display: flex; align-items: center; gap: 8px; }
.meal-card__icon { width: 28px; height: 28px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 14px; }
.meal-card__icon--breakfast { background: #fff3e0; color: #fa8c16; }
.meal-card__icon--lunch { background: #fff1f0; color: #ee6666; }
.meal-card__icon--dinner { background: #f0f0ff; color: #5470c6; }
.meal-card__icon--snack { background: #fffbe6; color: #fac858; }
.meal-card__icon--exercise { background: #f0fff0; color: #52c41a; }
.meal-card__name { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.meal-card__kcal { font-size: 13px; font-weight: 600; }
.meal-card__kcal span { font-size: 17px; font-weight: 800; }
.meal-card__kcal--in { color: #fa8c16; }
.meal-card__kcal--in span { color: #fa8c16; }
.meal-card__kcal--out { color: #52c41a; }
.meal-card__kcal--out span { color: #52c41a; }
.meal-card__expand { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: #bbb; transition: transform .25s; }
.meal-card__expand.open { transform: rotate(180deg); }
/* 食物列表 */
.meal-items { display: flex; flex-direction: column; gap: 6px; }
.meal-item { display: flex; align-items: center; padding: 6px 10px; background: #f7f8fa; border-radius: 8px; gap: 8px; }
.meal-item__emoji { font-size: 18px; width: 24px; text-align: center; flex-shrink: 0; }
.meal-item__info { flex: 1; min-width: 0; }
.meal-item__name { font-size: 13px; color: #333; font-weight: 500; }
.meal-item__meta { font-size: 11px; color: #bbb; margin-top: 1px; }
.meal-item__kcal { font-size: 13px; font-weight: 700; color: #fa8c16; white-space: nowrap; flex-shrink: 0; }
.meal-item--exercise .meal-item__kcal { color: #52c41a; }
.meal-empty { text-align: center; padding: 16px 0; color: #ccc; font-size: 13px; }
/* ===== 底部工具栏 ===== */
.toolbar { height: 56px; background: #fff; border-top: 1px solid #f0f0f0; display: flex; align-items: center; padding: 0 8px; flex-shrink: 0; gap: 6px; }
.toolbar__btn { flex: 1; height: 38px; border-radius: 19px; border: none; font-size: 12px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 3px; transition: transform .15s, box-shadow .15s; color: #fff; }
.toolbar__btn:active { transform: scale(0.96); }
.toolbar__btn--breakfast { background: linear-gradient(160deg, #ffc069, #fa8c16); box-shadow: 0 2px 8px rgba(250,140,22,0.25); }
.toolbar__btn--lunch { background: linear-gradient(160deg, #ff7875, #ee6666); box-shadow: 0 2px 8px rgba(238,102,102,0.25); }
.toolbar__btn--dinner { background: linear-gradient(160deg, #7b8ce6, #5470c6); box-shadow: 0 2px 8px rgba(84,112,198,0.25); }
.toolbar__btn--snack { background: linear-gradient(160deg, #ffe07a, #fac858); box-shadow: 0 2px 8px rgba(250,200,88,0.25); }
.toolbar__btn--exercise { background: linear-gradient(160deg, #7ee87e, #52c41a); box-shadow: 0 2px 8px rgba(82,196,26,0.25); }
.toolbar__btn svg { width: 13px; height: 13px; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">09:40</span>
<div class="icons">
<svg width="16" height="16" fill="none"><rect x="1" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="5" y="3" width="3" height="9" rx="1" fill="#333"/><rect x="9" y="1" width="3" height="11" rx="1" fill="#333"/><rect x="13" y="0" width="3" height="12" rx="1" fill="#333" opacity=".3"/></svg>
<svg width="16" height="16" fill="none"><path d="M8 3C5.5 3 3.2 4 1.5 5.5l1.4 1.4C4.3 5.5 6.1 5 8 5s3.7.5 5.1 1.9l1.4-1.4C12.8 4 10.5 3 8 3zm0 4c-1.4 0-2.6.5-3.5 1.3L6 9.8c.6-.5 1.3-.8 2-.8s1.4.3 2 .8l1.5-1.5C10.6 7.5 9.4 7 8 7zm0 4c-.6 0-1 .4-1 1s.4 1 1 1 1-.4 1-1-.4-1-1-1z" fill="#333"/></svg>
<svg width="22" height="12" fill="none"><rect x=".5" y=".5" width="19" height="11" rx="2" stroke="#333"/><rect x="20" y="3.5" width="1.5" height="5" rx=".75" fill="#333"/><rect x="2" y="2" width="14" height="8" rx="1" fill="#333"/></svg>
</div>
</div>
<div class="nav-bar">
<div class="nav-back" onclick="location.href='weight-main-v2.html'">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
</div>
<div class="nav-title">饮食记录</div>
<div class="nav-placeholder"></div>
</div>
<div class="scroll-content">
<!-- ====== 本周7日日历 ====== -->
<div class="calendar-card">
<div class="calendar-card__header">
<div class="calendar-card__arrow" id="calPrev" onclick="prevWeek()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
</div>
<span class="calendar-card__range" onclick="toggleMonthPicker()">
<span id="calRange">2026年7月23日</span>
<svg class="calendar-card__date-arrow" id="dateArrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#999" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</span>
<div class="calendar-card__arrow" id="calNext" onclick="nextWeek()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
</div>
</div>
<!-- 月历弹窗 -->
<div class="month-picker" id="monthPicker">
<div class="month-picker__header">
<div class="month-picker__nav" onclick="event.stopPropagation();prevMonth()"></div>
<span class="month-picker__title" id="monthPickerTitle">2026年7月</span>
<div class="month-picker__nav" onclick="event.stopPropagation();nextMonth()"></div>
</div>
<div class="month-picker__weekdays">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
<div class="month-picker__grid" id="monthGrid"></div>
</div>
<div class="cal-week" id="calWeek"></div>
<div class="gauge-wrap">
<button class="recipe-btn" onclick="location.href='diet-advice-v2.html'">今日饮食建议</button>
<svg viewBox="0 0 340 170" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gapGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#ffc069"/>
<stop offset="35%" stop-color="#fa8c16"/>
<stop offset="100%" stop-color="#52c41a"/>
</linearGradient>
<radialGradient id="glowGrad" cx="50%" cy="70%" r="55%">
<stop offset="0%" stop-color="#e8fbfa" stop-opacity="0.3"/>
<stop offset="100%" stop-color="#fff" stop-opacity="0"/>
</radialGradient>
</defs>
<rect x="0" y="0" width="340" height="170" fill="url(#glowGrad)"/>
<!-- 灰色底轨 -->
<path d="M 90 135 A 80 80 0 0 1 250 135"
fill="none" stroke="#ebeef0" stroke-width="14" stroke-linecap="round"/>
<!-- 进度弧 -->
<path id="gapArc" d="M 90 135 A 80 80 0 0 1 222 75"
fill="none" stroke="url(#gapGrad)" stroke-width="14" stroke-linecap="round"/>
<!-- 刻度圆点 -->
<circle cx="98" cy="103" r="2.5" fill="#cfcfcf"/>
<circle cx="120" cy="75" r="2.5" fill="#cfcfcf"/>
<circle cx="152" cy="60" r="2.5" fill="#cfcfcf"/>
<circle cx="188" cy="60" r="2.5" fill="#cfcfcf"/>
<circle cx="220" cy="75" r="2.5" fill="#cfcfcf"/>
<circle cx="242" cy="103" r="2.5" fill="#cfcfcf"/>
<!-- 端点 -->
<circle cx="90" cy="135" r="5" fill="#bbb" stroke="#fff" stroke-width="2.5"/>
<circle cx="250" cy="135" r="5" fill="#52c41a" stroke="#fff" stroke-width="2.5"/>
<!-- 左侧端点下方:饮食摄入 -->
<text x="90" y="150" font-size="12" fill="#999" text-anchor="middle">饮食摄入</text>
<text x="90" y="165" font-size="18" fill="#fa8c16" text-anchor="middle" font-weight="800"><tspan id="intakeText">1086</tspan><tspan font-size="10" font-weight="400" fill="#bbb">/1950 千卡</tspan></text>
<!-- 右侧端点下方:运动消耗 -->
<text x="250" y="150" font-size="12" fill="#999" text-anchor="middle">运动消耗</text>
<text x="250" y="165" font-size="18" fill="#52c41a" text-anchor="middle" font-weight="800"><tspan id="consumeText">820</tspan><tspan font-size="10" font-weight="400" fill="#bbb">/1000 千卡</tspan></text>
<!-- 中心 -->
<text x="170" y="88" font-size="12" fill="#999" text-anchor="middle">热量缺口</text>
<text id="gapCenterVal" x="170" y="120" font-size="28" fill="#fa8c16" text-anchor="middle" font-weight="800">364</text>
<text x="170" y="137" font-size="11" fill="#bbb" text-anchor="middle">千卡</text>
</svg>
</div>
<!-- 营养素三列 -->
<div class="macros-row" id="macrosRow">
<div class="macro-col">
<div class="macro-col__name">碳水</div>
<div><span class="macro-col__val" id="macroCarb">155</span><span class="macro-col__unit">/260 g</span></div>
<div class="macro-col__bar"><div class="macro-col__fill macro-col__fill--carb" id="macroCarbBar" style="width:58%"></div></div>
</div>
<div class="macro-col">
<div class="macro-col__name">蛋白质</div>
<div><span class="macro-col__val" id="macroProtein">47</span><span class="macro-col__unit">/82 g</span></div>
<div class="macro-col__bar"><div class="macro-col__fill macro-col__fill--protein" id="macroProteinBar" style="width:57%"></div></div>
</div>
<div class="macro-col">
<div class="macro-col__name">脂肪</div>
<div><span class="macro-col__val" id="macroFat">31</span><span class="macro-col__unit">/60 g</span></div>
<div class="macro-col__bar"><div class="macro-col__fill macro-col__fill--fat" id="macroFatBar" style="width:52%"></div></div>
</div>
</div>
</div>
<!-- ====== 早餐卡片 ====== -->
<div class="meal-card" id="cardBreakfast">
<div class="meal-card__header" onclick="toggleMeal('breakfast', this)">
<div class="meal-card__left">
<div class="meal-card__icon meal-card__icon--breakfast"></div>
<span class="meal-card__name">早餐</span>
</div>
<div style="display:flex;align-items:center;gap:8px;">
<span class="meal-card__kcal meal-card__kcal--in"><span id="kcalBreakfast">320</span> kcal</span>
<div class="meal-card__expand">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
</div>
</div>
<div class="meal-items" id="groupBreakfast">
<div class="meal-item">
<div class="meal-item__emoji">🥚</div>
<div class="meal-item__info">
<div class="meal-item__name">水煮鸡蛋</div>
<div class="meal-item__meta">×1 · 约50g</div>
</div>
<div class="meal-item__kcal">80 kcal</div>
</div>
<div class="meal-item">
<div class="meal-item__emoji">🥛</div>
<div class="meal-item__info">
<div class="meal-item__name">纯牛奶</div>
<div class="meal-item__meta">×1 · 250ml</div>
</div>
<div class="meal-item__kcal">120 kcal</div>
</div>
<div class="meal-item">
<div class="meal-item__emoji">🍞</div>
<div class="meal-item__info">
<div class="meal-item__name">全麦面包</div>
<div class="meal-item__meta">×2 · 约80g</div>
</div>
<div class="meal-item__kcal">120 kcal</div>
</div>
</div>
</div>
<!-- ====== 午餐卡片 ====== -->
<div class="meal-card" id="cardLunch">
<div class="meal-card__header" onclick="toggleMeal('lunch', this)">
<div class="meal-card__left">
<div class="meal-card__icon meal-card__icon--lunch"></div>
<span class="meal-card__name">午餐</span>
</div>
<div style="display:flex;align-items:center;gap:8px;">
<span class="meal-card__kcal meal-card__kcal--in"><span id="kcalLunch">480</span> kcal</span>
<div class="meal-card__expand">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
</div>
</div>
<div class="meal-items" id="groupLunch">
<div class="meal-item">
<div class="meal-item__emoji">🍚</div>
<div class="meal-item__info">
<div class="meal-item__name">白米饭</div>
<div class="meal-item__meta">×1 · 约200g</div>
</div>
<div class="meal-item__kcal">232 kcal</div>
</div>
<div class="meal-item">
<div class="meal-item__emoji">🐔</div>
<div class="meal-item__info">
<div class="meal-item__name">宫保鸡丁</div>
<div class="meal-item__meta">×1 · 约150g</div>
</div>
<div class="meal-item__kcal">148 kcal</div>
</div>
<div class="meal-item">
<div class="meal-item__emoji">🥬</div>
<div class="meal-item__info">
<div class="meal-item__name">清炒时蔬</div>
<div class="meal-item__meta">×1 · 约200g</div>
</div>
<div class="meal-item__kcal">100 kcal</div>
</div>
</div>
</div>
<!-- ====== 晚餐卡片 ====== -->
<div class="meal-card" id="cardDinner">
<div class="meal-card__header" onclick="toggleMeal('dinner', this)">
<div class="meal-card__left">
<div class="meal-card__icon meal-card__icon--dinner">🌙</div>
<span class="meal-card__name">晚餐</span>
</div>
<div style="display:flex;align-items:center;gap:8px;">
<span class="meal-card__kcal meal-card__kcal--in"><span id="kcalDinner">220</span> kcal</span>
<div class="meal-card__expand">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
</div>
</div>
<div class="meal-items" id="groupDinner">
<div class="meal-item">
<div class="meal-item__emoji">🥗</div>
<div class="meal-item__info">
<div class="meal-item__name">鸡胸肉沙拉</div>
<div class="meal-item__meta">×1 · 约250g</div>
</div>
<div class="meal-item__kcal">180 kcal</div>
</div>
<div class="meal-item">
<div class="meal-item__emoji">🍠</div>
<div class="meal-item__info">
<div class="meal-item__name">蒸红薯</div>
<div class="meal-item__meta">×1 · 约100g</div>
</div>
<div class="meal-item__kcal">40 kcal</div>
</div>
</div>
</div>
<!-- ====== 加餐卡片 ====== -->
<div class="meal-card" id="cardSnack">
<div class="meal-card__header" onclick="toggleMeal('snack', this)">
<div class="meal-card__left">
<div class="meal-card__icon meal-card__icon--snack">🍎</div>
<span class="meal-card__name">加餐</span>
</div>
<div style="display:flex;align-items:center;gap:8px;">
<span class="meal-card__kcal meal-card__kcal--in"><span id="kcalSnack">66</span> kcal</span>
<div class="meal-card__expand">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
</div>
</div>
<div class="meal-items" id="groupSnack">
<div class="meal-item">
<div class="meal-item__emoji">🍎</div>
<div class="meal-item__info">
<div class="meal-item__name">苹果</div>
<div class="meal-item__meta">×1 · 约200g</div>
</div>
<div class="meal-item__kcal">66 kcal</div>
</div>
</div>
</div>
<!-- ====== 运动卡片 ====== -->
<div class="meal-card" id="cardExercise">
<div class="meal-card__header" onclick="toggleMeal('exercise', this)">
<div class="meal-card__left">
<div class="meal-card__icon meal-card__icon--exercise">🏃</div>
<span class="meal-card__name">运动</span>
</div>
<div style="display:flex;align-items:center;gap:8px;">
<span class="meal-card__kcal meal-card__kcal--out"><span id="kcalExercise">-320</span> kcal</span>
<div class="meal-card__expand">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
</div>
</div>
<div class="meal-items" id="groupExercise">
<div class="meal-item meal-item--exercise">
<div class="meal-item__emoji">🏃</div>
<div class="meal-item__info">
<div class="meal-item__name">户外跑步</div>
<div class="meal-item__meta">5.2km · 32分钟</div>
</div>
<div class="meal-item__kcal">-260 kcal</div>
</div>
<div class="meal-item meal-item--exercise">
<div class="meal-item__emoji">🚶</div>
<div class="meal-item__info">
<div class="meal-item__name">步行</div>
<div class="meal-item__meta">6800步 · 今日累计</div>
</div>
<div class="meal-item__kcal">-60 kcal</div>
</div>
</div>
</div>
<!-- 饮食未记录缺省卡片 -->
<div class="meal-card" id="cardEmptyDiet" style="display:none;">
<div style="text-align:center;padding:24px 0;color:#ccc;">
<div style="font-size:36px;margin-bottom:8px;">🍽️</div>
<div style="font-size:14px;">暂无饮食记录</div>
</div>
</div>
<div style="height: 8px; flex-shrink: 0;"></div>
</div>
<!-- ====== 底部工具栏 ====== -->
<div class="toolbar">
<button class="toolbar__btn toolbar__btn--breakfast" onclick="addMeal('breakfast')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
早餐
</button>
<button class="toolbar__btn toolbar__btn--lunch" onclick="addMeal('lunch')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
午餐
</button>
<button class="toolbar__btn toolbar__btn--dinner" onclick="addMeal('dinner')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
晚餐
</button>
<button class="toolbar__btn toolbar__btn--snack" onclick="addMeal('snack')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
加餐
</button>
<button class="toolbar__btn toolbar__btn--exercise" onclick="addMeal('exercise')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
运动
</button>
</div>
</div>
<script>
/* ===== 日历数据(按日期存储) ===== */
var dayData = {
'2026-07-20': { intake: 1050, consume: 780, gap: -380, macros: {carb:140,carbT:260,protein:52,proteinT:82,fat:28,fatT:60}, meals: {
breakfast: { kcal: 280, items: [{e:'🥚',n:'水煮鸡蛋',m:'×1',k:80},{e:'🥛',n:'纯牛奶',m:'×1 · 250ml',k:120},{e:'🍞',n:'全麦面包',m:'×1',k:80}] },
lunch: { kcal: 450, items: [{e:'🍚',n:'白米饭',m:'×1 · 约200g',k:232},{e:'🐔',n:'红烧鸡块',m:'×1 · 约150g',k:140},{e:'🥬',n:'炒青菜',m:'×1',k:78}] },
dinner: { kcal: 260, items: [{e:'🥗',n:'蔬菜沙拉',m:'×1 · 约200g',k:160},{e:'🍠',n:'蒸红薯',m:'×1',k:100}] },
snack: { kcal: 60, items: [{e:'🍌',n:'香蕉',m:'×1',k:60}] },
exercise: { kcal: -280, items: [{e:'🏃',n:'户外跑步',m:'4.5km · 28分钟',k:-200},{e:'🚶',n:'步行',m:'5500步',k:-80}] }
}},
'2026-07-21': { intake: 1120, consume: 790, gap: -330, macros: {carb:165,carbT:260,protein:44,proteinT:82,fat:34,fatT:60}, meals: {
breakfast: { kcal: 350, items: [{e:'🥛',n:'豆浆',m:'×1 · 300ml',k:90},{e:'🥮',n:'肉包',m:'×2',k:180},{e:'🥚',n:'茶叶蛋',m:'×1',k:80}] },
lunch: { kcal: 480, items: [{e:'🍜',n:'牛肉面',m:'×1 · 约400g',k:380},{e:'🥒',n:'凉拌黄瓜',m:'×1',k:100}] },
dinner: { kcal: 210, items: [{e:'🐟',n:'清蒸鱼',m:'×1 · 约150g',k:130},{e:'🥦',n:'西兰花',m:'×1',k:80}] },
snack: { kcal: 80, items: [{e:'🥜',n:'坚果',m:'×1把 · 约20g',k:80}] },
exercise: { kcal: -250, items: [{e:'🚴',n:'骑行',m:'8km · 35分钟',k:-250}] }
}},
'2026-07-22': { intake: 980, consume: 740, gap: -412, macros: {carb:120,carbT:260,protein:58,proteinT:82,fat:22,fatT:60}, meals: {
breakfast: { kcal: 220, items: [{e:'🥚',n:'水煮蛋',m:'×2',k:160},{e:'☕',n:'黑咖啡',m:'×1',k:5},{e:'🍞',n:'全麦吐司',m:'×1',k:55}] },
lunch: { kcal: 420, items: [{e:'🍚',n:'杂粮饭',m:'×1 · 约180g',k:200},{e:'🐔',n:'鸡胸肉',m:'×1 · 约120g',k:120},{e:'🥬',n:'蒜蓉菠菜',m:'×1',k:100}] },
dinner: { kcal: 280, items: [{e:'🥗',n:'凯撒沙拉',m:'×1 · 约250g',k:220},{e:'🍎',n:'苹果',m:'×1',k:60}] },
snack: { kcal: 60, items: [{e:'🥒',n:'黄瓜',m:'×1根',k:15},{e:'🍅',n:'小番茄',m:'×5颗',k:45}] },
exercise: { kcal: -320, items: [{e:'🏊',n:'游泳',m:'40分钟',k:-260},{e:'🚶',n:'步行',m:'5000步',k:-60}] }
}},
'2026-07-23': { intake: 1086, consume: 820, gap: -364, macros: {carb:155,carbT:260,protein:47,proteinT:82,fat:31,fatT:60}, meals: {
breakfast: { kcal: 320, items: [{e:'🥚',n:'水煮鸡蛋',m:'×1 · 约50g',k:80},{e:'🥛',n:'纯牛奶',m:'×1 · 250ml',k:120},{e:'🍞',n:'全麦面包',m:'×2 · 约80g',k:120}] },
lunch: { kcal: 480, items: [{e:'🍚',n:'白米饭',m:'×1 · 约200g',k:232},{e:'🐔',n:'宫保鸡丁',m:'×1 · 约150g',k:148},{e:'🥬',n:'清炒时蔬',m:'×1 · 约200g',k:100}] },
dinner: { kcal: 220, items: [{e:'🥗',n:'鸡胸肉沙拉',m:'×1 · 约250g',k:180},{e:'🍠',n:'蒸红薯',m:'×1 · 约100g',k:40}] },
snack: { kcal: 66, items: [{e:'🍎',n:'苹果',m:'×1 · 约200g',k:66}] },
exercise: { kcal: -320, items: [{e:'🏃',n:'户外跑步',m:'5.2km · 32分钟',k:-260},{e:'🚶',n:'步行',m:'6800步 · 今日累计',k:-60}] }
}},
'2026-07-24': { intake: 0, consume: 0, gap: 0 },
'2026-07-25': { intake: 0, consume: 0, gap: 0 },
'2026-07-26': { intake: 0, consume: 0, gap: 0 }
};
/* ===== 周导航 ===== */
var WEEK_MS = 7 * 24 * 60 * 60 * 1000;
var today = new Date(2026, 6, 23); // 2026-07-23
var currentWeekStart = getMonday(today);
/* 获取某日期所在周的周一 */
function getMonday(d) {
var m = new Date(d);
var day = m.getDay(); // 0=Sun, 1=Mon, ...
var diff = day === 0 ? -6 : 1 - day;
m.setDate(m.getDate() + diff);
m.setHours(0, 0, 0, 0);
return m;
}
/* 格式化日期:YYYY-MM-DD */
function fmtDate(d) {
var y = d.getFullYear();
var m = ('0' + (d.getMonth() + 1)).slice(-2);
var day = ('0' + d.getDate()).slice(-2);
return y + '-' + m + '-' + day;
}
/* 格式化中文日期 */
function fmtDateCN(d) {
return d.getFullYear() + '年' + (d.getMonth() + 1) + '月' + d.getDate() + '日';
}
/* 判断两个日期是否同一天 */
function isSameDay(a, b) {
return a.getFullYear() === b.getFullYear() &&
a.getMonth() === b.getMonth() &&
a.getDate() === b.getDate();
}
/* 渲染一周日历 */
function renderWeek() {
var container = document.getElementById('calWeek');
container.innerHTML = '';
var weekDayChars = ['日', '一', '二', '三', '四', '五', '六'];
for (var i = 0; i < 7; i++) {
var d = new Date(currentWeekStart);
d.setDate(d.getDate() + i);
var dateStr = fmtDate(d);
var wd = weekDayChars[d.getDay()];
var dayNum = d.getDate();
var isToday = isSameDay(d, today);
var dayEl = document.createElement('div');
dayEl.className = 'cal-day' + (isToday ? ' today' : '');
dayEl.setAttribute('data-date', dateStr);
dayEl.setAttribute('data-wd', wd);
dayEl.onclick = function() { selectDay(this); };
var data = dayData[dateStr];
var hasData = data && data.intake !== 0;
dayEl.innerHTML =
'<div class="cal-day__wd">' + wd + '</div>' +
'<div class="cal-day__num">' + dayNum + '</div>' +
'<div class="cal-day__dot' + (hasData ? '' : ' cal-day__dot--none') + '"></div>';
container.appendChild(dayEl);
}
// 自动选中今天(如果在当前周),否则选中周一
var firstDay = container.querySelector('.cal-day.today');
if (!firstDay) firstDay = container.querySelector('.cal-day');
if (firstDay) selectDay(firstDay);
// 箭头状态:未来周灰显右箭头
var mondayOfThisWeek = getMonday(today);
var nextArrow = document.getElementById('calNext');
if (currentWeekStart.getTime() >= mondayOfThisWeek.getTime()) {
nextArrow.style.opacity = '0.3';
nextArrow.style.pointerEvents = 'none';
} else {
nextArrow.style.opacity = '1';
nextArrow.style.pointerEvents = '';
}
}
function prevWeek() {
currentWeekStart = new Date(currentWeekStart.getTime() - WEEK_MS);
renderWeek();
}
function nextWeek() {
var mondayOfThisWeek = getMonday(today);
if (currentWeekStart.getTime() >= mondayOfThisWeek.getTime()) return;
currentWeekStart = new Date(currentWeekStart.getTime() + WEEK_MS);
renderWeek();
}
/* ===== 月历弹窗 ===== */
var pickerYear = 2026;
var pickerMonth = 6; // 0-based (July)
function toggleMonthPicker() {
var picker = document.getElementById('monthPicker');
var arrow = document.getElementById('dateArrow');
var show = !picker.classList.contains('show');
picker.classList.toggle('show', show);
arrow.classList.toggle('open', show);
if (show) {
// 同步到当前选中日期所在月份
var selDay = document.querySelector('.cal-day.active');
if (selDay) {
var d = selDay.getAttribute('data-date').split('-');
pickerYear = parseInt(d[0]);
pickerMonth = parseInt(d[1]) - 1;
}
renderMonthGrid();
}
}
function prevMonth() {
if (pickerMonth === 0) { pickerMonth = 11; pickerYear--; }
else { pickerMonth--; }
renderMonthGrid();
}
function nextMonth() {
if (pickerMonth === 11) { pickerMonth = 0; pickerYear++; }
else { pickerMonth++; }
renderMonthGrid();
}
function renderMonthGrid() {
document.getElementById('monthPickerTitle').textContent = pickerYear + '年' + (pickerMonth + 1) + '月';
var grid = document.getElementById('monthGrid');
grid.innerHTML = '';
var firstDay = new Date(pickerYear, pickerMonth, 1).getDay(); // 0=Sun
var daysInMonth = new Date(pickerYear, pickerMonth + 1, 0).getDate();
// 填充上月尾巴
var prevDays = new Date(pickerYear, pickerMonth, 0).getDate();
for (var i = firstDay - 1; i >= 0; i--) {
var el = document.createElement('div');
el.className = 'month-picker__day month-picker__day--other';
el.textContent = prevDays - i;
grid.appendChild(el);
}
// 当月日期
var todayStr = fmtDate(today);
var selDay = document.querySelector('.cal-day.active');
var selStr = selDay ? selDay.getAttribute('data-date') : '';
for (var d = 1; d <= daysInMonth; d++) {
var dateStr = pickerYear + '-' + ('0' + (pickerMonth + 1)).slice(-2) + '-' + ('0' + d).slice(-2);
var el = document.createElement('div');
var cls = 'month-picker__day';
if (dateStr === todayStr) cls += ' month-picker__day--today';
if (dateStr === selStr) cls += ' month-picker__day--selected';
if (dayData[dateStr] && dayData[dateStr].intake !== 0) cls += ' month-picker__day--has-data';
el.className = cls;
el.textContent = d;
el.onclick = (function(ds) { return function(e) { e.stopPropagation(); pickDay(ds); }; })(dateStr);
grid.appendChild(el);
}
}
function pickDay(dateStr) {
// 关闭弹窗
document.getElementById('monthPicker').classList.remove('show');
document.getElementById('dateArrow').classList.remove('open');
// 切换到该日期所在的周
var parts = dateStr.split('-');
var d = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));
currentWeekStart = getMonday(d);
renderWeek();
// 选中该日
var target = document.querySelector('.cal-day[data-date="' + dateStr + '"]');
if (target) selectDay(target);
}
// 点击外部关闭月历
document.addEventListener('click', function(e) {
var picker = document.getElementById('monthPicker');
if (!picker.classList.contains('show')) return;
if (!e.target.closest('.calendar-card__range') && !e.target.closest('#monthPicker')) {
picker.classList.remove('show');
document.getElementById('dateArrow').classList.remove('open');
}
});
/* ===== 计算弧线终点 ===== */
// 半圆弧: cx=170, cy=135, r=80。左端点(90,135)角度π,右端点(250,135)角度0。
// sweep=1 在 y-down SVG 中从左向右经顶部走。
// 进度 progress: 0~1,对应角度 θ = π * (1 - progress)
// x = 170 + 80 * cos(π*(1-p)), y = 135 - 80 * sin(π*(1-p))
function arcPoint(progress) {
var angle = Math.PI * (1 - progress);
var x = 170 + 80 * Math.cos(angle);
var y = 135 - 80 * Math.sin(angle);
return { x: Math.round(x * 10) / 10, y: Math.round(y * 10) / 10 };
}
/* ===== 选中日历天 ===== */
function selectDay(el) {
document.querySelectorAll('.cal-day').forEach(function(d) { d.classList.remove('active'); });
el.classList.add('active');
var dateStr = el.getAttribute('data-date');
// 更新顶部日期显示为选中日期
var parts = dateStr.split('-');
document.getElementById('calRange').textContent = parts[0] + '年' + parseInt(parts[1]) + '月' + parseInt(parts[2]) + '日';
var data = dayData[dateStr];
if (!data) {
// 无数据日,清空显示
data = { intake: 0, consume: 0, gap: 0 };
}
var gapAbs = Math.abs(data.gap);
var maxGap = 500;
var progress = data.gap === 0 ? 0 : Math.min(gapAbs / maxGap, 1);
var pt = arcPoint(progress);
var arcD = 'M 90 135 A 80 80 0 0 1 ' + pt.x + ' ' + pt.y;
var gapArc = document.getElementById('gapArc');
gapArc.setAttribute('d', arcD);
document.getElementById('intakeText').textContent = data.intake === 0 ? '--' : data.intake;
document.getElementById('consumeText').textContent = data.consume === 0 ? '--' : data.consume;
var gapCenter = document.getElementById('gapCenterVal');
gapCenter.textContent = data.gap === 0 ? '--' : Math.abs(data.gap);
var colorIntake = data.intake === 0 ? '#bbb' : '#fa8c16';
var colorConsume = data.consume === 0 ? '#bbb' : '#52c41a';
var colorGap = data.gap === 0 ? '#bbb' : '#fa8c16';
document.getElementById('intakeText').setAttribute('fill', colorIntake);
document.getElementById('consumeText').setAttribute('fill', colorConsume);
gapCenter.setAttribute('fill', colorGap);
var rightDot = document.querySelector('.gauge-wrap svg circle[cy="135"][cx="250"]');
rightDot.setAttribute('fill', data.gap === 0 ? '#bbb' : '#52c41a');
// 更新餐食卡片
renderMeals(dateStr);
}
/* ===== 渲染餐食卡片 ===== */
function renderMeals(dateStr) {
var data = dayData[dateStr];
var meals = data && data.meals;
var dietTypes = ['breakfast', 'lunch', 'dinner', 'snack'];
// 检查是否有任何饮食记录
var hasAnyDiet = false;
dietTypes.forEach(function(type) {
var md = meals ? meals[type] : null;
if (md && md.items && md.items.length > 0) hasAnyDiet = true;
});
if (hasAnyDiet) {
// 有饮食记录:逐卡片显示/隐藏
document.getElementById('cardEmptyDiet').style.display = 'none';
dietTypes.forEach(function(type) {
var cap = type.charAt(0).toUpperCase() + type.slice(1);
var card = document.getElementById('card' + cap);
var container = document.getElementById('group' + cap);
var kcalEl = document.getElementById('kcal' + cap);
var md = meals ? meals[type] : null;
if (md && md.items && md.items.length > 0) {
card.style.display = '';
var html = '';
md.items.forEach(function(item) {
html += '<div class="meal-item">' +
'<div class="meal-item__emoji">' + item.e + '</div>' +
'<div class="meal-item__info"><div class="meal-item__name">' + item.n + '</div><div class="meal-item__meta">' + item.m + '</div></div>' +
'<div class="meal-item__kcal">' + item.k + ' kcal</div></div>';
});
container.innerHTML = html;
container.style.display = '';
kcalEl.textContent = md.kcal;
kcalEl.parentElement.style.display = '';
} else {
card.style.display = 'none';
}
});
} else {
// 无任何饮食记录:隐藏4张卡片,显示缺省卡片
dietTypes.forEach(function(type) {
document.getElementById('card' + type.charAt(0).toUpperCase() + type.slice(1)).style.display = 'none';
});
document.getElementById('cardEmptyDiet').style.display = '';
}
// 运动卡片独立处理
var exCard = document.getElementById('cardExercise');
var exContainer = document.getElementById('groupExercise');
var exKcalEl = document.getElementById('kcalExercise');
var exMd = meals ? meals['exercise'] : null;
if (exMd && exMd.items && exMd.items.length > 0) {
exCard.style.display = '';
var html = '';
exMd.items.forEach(function(item) {
html += '<div class="meal-item meal-item--exercise">' +
'<div class="meal-item__emoji">' + item.e + '</div>' +
'<div class="meal-item__info"><div class="meal-item__name">' + item.n + '</div><div class="meal-item__meta">' + item.m + '</div></div>' +
'<div class="meal-item__kcal">' + item.k + ' kcal</div></div>';
});
exContainer.innerHTML = html;
exContainer.style.display = '';
exKcalEl.textContent = exMd.kcal;
exKcalEl.parentElement.style.display = '';
} else {
exCard.style.display = 'none';
}
// 更新营养素三列
var macrosRow = document.getElementById('macrosRow');
var macros = data && data.macros;
if (macros && data.intake !== 0) {
macrosRow.classList.remove('hidden');
document.getElementById('macroCarb').textContent = macros.carb;
document.getElementById('macroCarbBar').style.width = Math.round(macros.carb / macros.carbT * 100) + '%';
document.getElementById('macroProtein').textContent = macros.protein;
document.getElementById('macroProteinBar').style.width = Math.round(macros.protein / macros.proteinT * 100) + '%';
document.getElementById('macroFat').textContent = macros.fat;
document.getElementById('macroFatBar').style.width = Math.round(macros.fat / macros.fatT * 100) + '%';
} else {
macrosRow.classList.add('hidden');
}
}
function toggleMeal(type, headerEl) {
var items = document.getElementById('group' + type.charAt(0).toUpperCase() + type.slice(1));
var expand = headerEl.querySelector('.meal-card__expand');
if (items.style.display === 'none') {
items.style.display = '';
expand.classList.remove('open');
} else {
items.style.display = 'none';
expand.classList.add('open');
}
}
/* ===== 工具栏按钮 ===== */
function addMeal(type) {
var names = { breakfast: '早餐', lunch: '午餐', dinner: '晚餐', snack: '加餐', exercise: '运动' };
alert('跳转到添加' + names[type] + '页面');
}
/* ===== 初始化 ===== */
renderWeek();
</script>
</body>
</html>
@@ -0,0 +1,654 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>体重管理 - 员工端 | 健康CQ原型 v2</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #f5f7fa; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; display: flex; flex-direction: column; }
.status-bar { height: 44px; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; background: #fff; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #333; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; }
.nav-back { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: #1a1a1a; }
.nav-title { flex: 1; text-align: center; font-size: 17px; font-weight: 600; color: #1a1a1a; }
.nav-more { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative; }
.nav-more__dots { display: flex; flex-direction: column; gap: 3px; align-items: center; }
.nav-more__dots span { display: block; width: 4px; height: 4px; border-radius: 50%; background: #333; }
/* 类型切换下拉菜单 */
.type-menu { display: none; position: absolute; top: 34px; right: 0; background: #fff; border-radius: 12px; box-shadow: 0 6px 24px rgba(0,0,0,0.12); z-index: 100; min-width: 180px; overflow: hidden; }
.type-menu.show { display: block; }
.type-menu__item { padding: 13px 16px; font-size: 14px; color: #333; cursor: pointer; display: flex; align-items: center; justify-content: space-between; white-space: nowrap; border-bottom: 1px solid #f5f5f5; }
.type-menu__item:last-child { border-bottom: none; }
.type-menu__item:hover { background: #f7f8fa; }
.type-menu__item.active { color: #36cfc9; font-weight: 700; }
.type-menu__item.active::after { content: '✓'; font-size: 12px; color: #36cfc9; }
.type-mask { display: none; position: fixed; inset: 0; z-index: 50; }
.type-mask.show { display: block; }
.scroll-content { flex: 1; overflow-y: auto; background: #f5f7fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* ===== 体重管理目标卡片 ===== */
.goal-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); }
.goal-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2px; }
.goal-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.goal-card__days { font-size: 13px; font-weight: 600; color: #36cfc9; cursor: pointer; display: flex; align-items: center; gap: 2px; text-decoration: none; }
.goal-card__sub { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0; }
.goal-card__activity { font-size: 13px; color: #666; font-weight: 500; }
.goal-card__rank { font-size: 13px; font-weight: 600; color: #faad14; display: flex; align-items: center; gap: 2px; }
/* ===== 标尺 SVG ===== */
.gauge-wrap { width: 100%; }
.gauge-wrap svg { width: 100%; height: auto; display: block; }
/* ===== 吃记录卡片 ===== */
.eat-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); cursor: pointer; }
.eat-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.eat-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.eat-card__add { width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(160deg, #6ee16e, #3ec46a); display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; box-shadow: 0 2px 8px rgba(62,196,106,0.3); }
.eat-card__add svg { width: 14px; height: 14px; stroke: #fff; }
/* 内容区:左圈 + 右列表 */
.eat-body { display: flex; align-items: center; gap: 16px; }
/* 左侧:圆形进度圈 */
.eat-ring { flex-shrink: 0; position: relative; width: 130px; height: 130px; }
.eat-ring svg { width: 100%; height: 100%; }
.eat-ring__center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.eat-ring__val { font-size: 28px; font-weight: 800; color: #fa8c16; line-height: 1; }
.eat-ring__label { font-size: 12px; color: #999; margin-top: 2px; }
.eat-ring__remain { font-size: 12px; color: #52c41a; margin-top: 1px; font-weight: 600; }
/* 右侧:营养素列表 */
.eat-macros { flex: 1; display: flex; flex-direction: column; gap: 8px; }
.eat-macro { padding: 8px 12px; background: #f7f8fa; border-radius: 10px; }
.eat-macro__row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px; }
.eat-macro__name { font-size: 13px; color: #666; font-weight: 500; }
.eat-macro__val { font-size: 14px; font-weight: 700; color: #333; }
.eat-macro__unit { font-size: 10px; font-weight: 400; color: #999; margin-left: 1px; }
.eat-macro__bar { height: 4px; border-radius: 2px; background: #e8e8e8; overflow: hidden; }
.eat-macro__fill { height: 100%; border-radius: 2px; }
.eat-macro__fill--carb { background: #5470c6; }
.eat-macro__fill--protein { background: #ee6666; }
.eat-macro__fill--fat { background: #fac858; }
/* ===== 体重记录卡片 ===== */
.weight-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); }
.weight-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.weight-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.weight-card__add { width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(160deg, #b08cff, #8b6cff); display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; box-shadow: 0 2px 8px rgba(139,108,255,0.3); }
.weight-card__add svg { width: 14px; height: 14px; stroke: #fff; }
.weight-body { display: flex; align-items: center; gap: 14px; }
.weight-latest { flex-shrink: 0; text-align: center; min-width: 72px; }
.weight-latest__val { font-size: 28px; font-weight: 800; color: #36cfc9; line-height: 1; }
.weight-latest__unit { font-size: 12px; font-weight: 500; color: #36cfc9; margin-left: 2px; }
.weight-latest__label { font-size: 11px; color: #999; margin-top: 4px; }
.weight-latest__date { font-size: 10px; color: #bbb; margin-top: 2px; }
.weight-chart { flex: 1; min-width: 0; }
.weight-chart svg { width: 100%; height: auto; display: block; }
/* ===== 运动记录卡片 ===== */
.move-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); }
.move-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.move-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.move-card__add { width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(160deg, #ffb066, #ff8a3d); display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; box-shadow: 0 2px 8px rgba(255,138,61,0.3); }
.move-card__add svg { width: 14px; height: 14px; stroke: #fff; }
.move-body { display: flex; align-items: center; gap: 16px; }
.move-ring { flex-shrink: 0; position: relative; width: 130px; height: 130px; }
.move-ring svg { width: 100%; height: 100%; }
.move-ring__center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.move-ring__val { font-size: 28px; font-weight: 800; color: #fa8c16; line-height: 1; }
.move-ring__label { font-size: 12px; color: #999; margin-top: 2px; }
.move-ring__remain { font-size: 12px; color: #ff8a3d; margin-top: 1px; font-weight: 600; }
.move-list { flex: 1; display: flex; flex-direction: column; gap: 8px; }
.move-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; background: #f7f8fa; border-radius: 10px; }
.move-item__name { font-size: 13px; color: #666; font-weight: 500; }
.move-item__val { font-size: 14px; font-weight: 700; color: #333; }
.move-item__unit { font-size: 10px; font-weight: 400; color: #999; margin-left: 1px; }
/* ===== 热量缺口卡片 ===== */
.gap-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); cursor: pointer; }
.gap-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; margin-bottom: 10px; display: flex; align-items: center; justify-content: space-between; }
.gap-card__title span:last-child { font-size: 12px; color: #bbb; cursor: pointer; }
/* 周日历 */
.gap-week { display: flex; gap: 4px; margin-bottom: 14px; }
.gap-day { flex: 1; text-align: center; padding: 8px 0 6px; border-radius: 10px; cursor: pointer; background: #f7f8fa; transition: background .2s; }
.gap-day.active { background: #e8fbfa; }
.gap-day__wd { font-size: 10px; color: #999; margin-bottom: 3px; }
.gap-day.active .gap-day__wd { color: #36cfc9; font-weight: 600; }
.gap-day__num { font-size: 15px; font-weight: 700; color: #333; }
.gap-day.active .gap-day__num { color: #36cfc9; }
.gap-day__dot { width: 6px; height: 6px; border-radius: 50%; background: #36cfc9; margin: 3px auto 0; }
.gap-day__dot--none { background: #e0e0e0; }
/* 热量统计行 */
.gap-stats { display: flex; flex-direction: column; gap: 8px; }
.gap-stat { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; background: #f7f8fa; border-radius: 10px; }
.gap-stat__label { font-size: 13px; color: #666; font-weight: 500; }
.gap-stat__val { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.gap-stat__val--good { color: #52c41a; }
.gap-stat__unit { font-size: 11px; font-weight: 400; color: #999; }
/* ===== 推荐视频卡片 ===== */
.video-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px 12px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); }
.video-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; margin-bottom: 12px; padding-left: 4px; }
.video-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.video-item { border-radius: 12px; overflow: hidden; background: #f7f8fa; cursor: pointer; }
.video-item__thumb { position: relative; width: 100%; aspect-ratio: 16/10; overflow: hidden; }
.video-item__thumb svg { width: 100%; height: 100%; display: block; }
.video-item__play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.video-item__play-icon { width: 32px; height: 32px; border-radius: 50%; background: rgba(255,255,255,0.9); display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 6px rgba(0,0,0,0.15); }
.video-item__plays { position: absolute; bottom: 4px; right: 6px; font-size: 10px; color: #fff; font-weight: 600; text-shadow: 0 1px 3px rgba(0,0,0,0.5); }
.video-item__author { position: absolute; bottom: 4px; left: 6px; font-size: 10px; color: #fff; font-weight: 600; text-shadow: 0 1px 3px rgba(0,0,0,0.5); }
.video-item__info { padding: 8px 10px 10px; }
.video-item__title { font-size: 13px; font-weight: 600; color: #1a1a1a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.video-item__org { font-size: 10px; color: #bbb; margin-top: 3px; }
.bottom-safe { height: 20px; flex-shrink: 0; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">09:40</span>
<div class="icons">
<svg width="16" height="16" fill="none"><rect x="1" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="5" y="3" width="3" height="9" rx="1" fill="#333"/><rect x="9" y="1" width="3" height="11" rx="1" fill="#333"/><rect x="13" y="0" width="3" height="12" rx="1" fill="#333" opacity=".3"/></svg>
<svg width="16" height="16" fill="none"><path d="M8 3C5.5 3 3.2 4 1.5 5.5l1.4 1.4C4.3 5.5 6.1 5 8 5s3.7.5 5.1 1.9l1.4-1.4C12.8 4 10.5 3 8 3zm0 4c-1.4 0-2.6.5-3.5 1.3L6 9.8c.6-.5 1.3-.8 2-.8s1.4.3 2 .8l1.5-1.5C10.6 7.5 9.4 7 8 7zm0 4c-.6 0-1 .4-1 1s.4 1 1 1 1-.4 1-1-.4-1-1-1z" fill="#333"/></svg>
<svg width="22" height="12" fill="none"><rect x=".5" y=".5" width="19" height="11" rx="2" stroke="#333"/><rect x="20" y="3.5" width="1.5" height="5" rx=".75" fill="#333"/><rect x="2" y="2" width="14" height="8" rx="1" fill="#333"/></svg>
</div>
</div>
<div class="nav-bar">
<div class="nav-back" onclick="history.back()">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
</div>
<div class="nav-title">体重管理</div>
<div class="nav-more" id="navMore" onclick="toggleTypeMenu(event)">
<div class="nav-more__dots"><span></span><span></span><span></span></div>
<div class="type-menu" id="typeMenu">
<div class="type-menu__item active" data-type="hasact" onclick="setPageType('hasact', event)">已设置-参加活动</div>
<div class="type-menu__item" data-type="personal" onclick="setPageType('personal', event)">已设置-个人目标</div>
<div class="type-menu__item" data-type="none" onclick="setPageType('none', event)">未设置目标</div>
</div>
</div>
</div>
<div class="type-mask" id="typeMask" onclick="closeTypeMenu()"></div>
<div class="scroll-content">
<!-- ====== 体重管理目标卡片 ====== -->
<div class="goal-card">
<div class="goal-card__header">
<span class="goal-card__title">体重管理目标</span>
<a class="goal-card__days" id="daysLink" href="goal-management.html">
当前第52/180天
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
</a>
</div>
<div class="goal-card__sub">
<span class="goal-card__activity" id="activityName">2026年二季度体重管理活动</span>
<span class="goal-card__rank" id="rankBadge">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5C7 4 6 9 6 9z"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5C17 4 18 9 18 9z"/><path d="M4 22h16"/><path d="M10 22V8c0-1.1.9-2 2-2s2 .9 2 2v14"/></svg>
第 8 名
</span>
</div>
<!-- ===== 半圆标尺(初始体重-左 | 当前体重-内 | 目标体重-右) ===== -->
<div class="gauge-wrap">
<svg viewBox="0 0 340 150" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gaugeGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#2dd4bf"/>
<stop offset="100%" stop-color="#5cdbd3"/>
</linearGradient>
<radialGradient id="glowGrad" cx="50%" cy="80%" r="55%">
<stop offset="0%" stop-color="#e8fbfa" stop-opacity="0.3"/>
<stop offset="100%" stop-color="#fff" stop-opacity="0"/>
</radialGradient>
</defs>
<rect x="0" y="0" width="340" height="150" fill="url(#glowGrad)"/>
<!-- ======== 弧 ======== -->
<!-- cx=170, cy=135, r=80, 左端点(90,135) 右端点(250,135) -->
<!-- 灰色底轨 -->
<path d="M 90 135 A 80 80 0 0 1 250 135"
fill="none" stroke="#ebeef0" stroke-width="14" stroke-linecap="round"/>
<!-- 进度弧 62.3%,终点 (200, 61) -->
<path d="M 90 135 A 80 80 0 0 1 200 61"
fill="none" stroke="url(#gaugeGrad)" stroke-width="14" stroke-linecap="round"/>
<!-- ======== 刻度圆点 ======== -->
<circle cx="98" cy="103" r="2.5" fill="#cfcfcf"/>
<circle cx="120" cy="75" r="2.5" fill="#cfcfcf"/>
<circle cx="152" cy="60" r="2.5" fill="#cfcfcf"/>
<circle cx="188" cy="60" r="2.5" fill="#cfcfcf"/>
<circle cx="220" cy="75" r="2.5" fill="#cfcfcf"/>
<circle cx="242" cy="103" r="2.5" fill="#cfcfcf"/>
<!-- 端点 -->
<circle cx="90" cy="135" r="5" fill="#ff6b81" stroke="#fff" stroke-width="2.5"/>
<circle cx="250" cy="135" r="5" fill="#36cfc9" stroke="#fff" stroke-width="2.5"/>
<!-- ======== 当前进度指示器 ======== -->
<circle cx="200" cy="61" r="11" fill="#fff" stroke="#36cfc9" stroke-width="3"/>
<circle cx="200" cy="61" r="5" fill="#36cfc9"/>
<rect x="177" y="31" width="46" height="18" rx="9" fill="#36cfc9"/>
<text x="200" y="44" font-size="10" fill="#fff" text-anchor="middle" font-weight="700">62.6</text>
<!-- ============================================ -->
<!-- 左侧:初始体重(左对齐,距边缘 16) -->
<!-- ============================================ -->
<text x="16" y="90" font-size="12" fill="#999" text-anchor="start">初始体重</text>
<text x="16" y="112" font-size="22" fill="#ff6b81" text-anchor="start" font-weight="800">73.5</text>
<text x="16" y="127" font-size="10" fill="#bbb" text-anchor="start">BMI 28.6</text>
<!-- ============================================ -->
<!-- 右侧:目标体重(右对齐,距边缘 16) -->
<!-- ============================================ -->
<text x="324" y="90" font-size="12" fill="#999" text-anchor="end">目标体重</text>
<text x="324" y="112" font-size="22" fill="#36cfc9" text-anchor="end" font-weight="800">56.0</text>
<text x="324" y="127" font-size="10" fill="#bbb" text-anchor="end">BMI 22.5</text>
<!-- ============================================ -->
<!-- 中心:当前体重(半径居中) -->
<!-- ============================================ -->
<text x="170" y="90" font-size="12" fill="#999" text-anchor="middle">当前体重</text>
<text x="170" y="122" font-size="34" fill="#1a1a1a" text-anchor="middle" font-weight="800">62.6</text>
<text x="170" y="137" font-size="12" fill="#36cfc9" text-anchor="middle" font-weight="600">▼ 10.9</text>
</svg>
</div>
</div>
<!-- ====== 热量缺口卡片 ====== -->
<div class="gap-card" onclick="location.href='eat-checkin-v2.html'">
<div class="gap-card__title"><span>热量缺口</span><span><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#bbb" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></span></div>
<!-- 本周日历 -->
<div class="gap-week" id="gapWeek">
<div class="gap-day" data-day="16" data-wd="一" onclick="event.stopPropagation();selectGapDay(this)">
<div class="gap-day__wd"></div>
<div class="gap-day__num">16</div>
<div class="gap-day__dot"></div>
</div>
<div class="gap-day" data-day="17" data-wd="二" onclick="event.stopPropagation();selectGapDay(this)">
<div class="gap-day__wd"></div>
<div class="gap-day__num">17</div>
<div class="gap-day__dot"></div>
</div>
<div class="gap-day" data-day="18" data-wd="三" onclick="event.stopPropagation();selectGapDay(this)">
<div class="gap-day__wd"></div>
<div class="gap-day__num">18</div>
<div class="gap-day__dot gap-day__dot--none"></div>
</div>
<div class="gap-day" data-day="19" data-wd="四" onclick="event.stopPropagation();selectGapDay(this)">
<div class="gap-day__wd"></div>
<div class="gap-day__num">19</div>
<div class="gap-day__dot"></div>
</div>
<div class="gap-day" data-day="20" data-wd="五" onclick="event.stopPropagation();selectGapDay(this)">
<div class="gap-day__wd"></div>
<div class="gap-day__num">20</div>
<div class="gap-day__dot"></div>
</div>
<div class="gap-day" data-day="21" data-wd="六" onclick="event.stopPropagation();selectGapDay(this)">
<div class="gap-day__wd"></div>
<div class="gap-day__num">21</div>
<div class="gap-day__dot"></div>
</div>
<div class="gap-day active" data-day="22" data-wd="日" onclick="event.stopPropagation();selectGapDay(this)">
<div class="gap-day__wd"></div>
<div class="gap-day__num">22</div>
<div class="gap-day__dot"></div>
</div>
</div>
<!-- 当日热量统计 -->
<div class="gap-stats">
<div class="gap-stat">
<span class="gap-stat__label">当前缺口</span>
<span class="gap-stat__val gap-stat__val--good">-364<span class="gap-stat__unit"> / -500 千卡</span></span>
</div>
<div style="display:flex;gap:8px;">
<div class="gap-stat" style="flex:1;">
<span class="gap-stat__label">总消耗</span>
<span class="gap-stat__val">820<span class="gap-stat__unit"> / 1000 千卡</span></span>
</div>
<div class="gap-stat" style="flex:1;">
<span class="gap-stat__label">总摄入</span>
<span class="gap-stat__val">1086<span class="gap-stat__unit"> / 1950 千卡</span></span>
</div>
</div>
</div>
</div>
<!-- ====== 吃记录卡片 ====== -->
<div class="eat-card" onclick="location.href='eat-checkin-v2.html'">
<div class="eat-card__header">
<span class="eat-card__title">吃记录</span>
<div style="display:flex;align-items:center;gap:8px;">
<button style="padding:5px 12px;border-radius:14px;border:none;background:linear-gradient(160deg,#6ee16e,#3ec46a);color:#fff;font-size:11px;font-weight:600;cursor:pointer;box-shadow:0 2px 6px rgba(62,196,106,0.3);" onclick="event.stopPropagation();location.href='diet-advice-v2.html'">今日饮食建议</button>
<button class="eat-card__add" onclick="event.stopPropagation(); location.href='eat-checkin-v2.html'">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
</div>
<div class="eat-body">
<!-- 左侧:圆形进度圈 -->
<div class="eat-ring">
<svg viewBox="0 0 130 130">
<!-- 底环 -->
<circle cx="65" cy="65" r="56" fill="none" stroke="#f0f0f0" stroke-width="10"/>
<!-- 进度环:1086/1950 ≈ 55.7%,周长 2π×56≈351.9,进度 ≈196 -->
<circle cx="65" cy="65" r="56" fill="none" stroke="#fa8c16" stroke-width="10"
stroke-dasharray="196 352" stroke-linecap="round"
transform="rotate(-90 65 65)"/>
</svg>
<div class="eat-ring__center">
<div class="eat-ring__val">1086</div>
<div class="eat-ring__label">千卡 / 推荐 1950</div>
<div class="eat-ring__remain">还可摄入 864 千卡</div>
</div>
</div>
<!-- 右侧:营养素列表 -->
<div class="eat-macros">
<div class="eat-macro">
<div class="eat-macro__row">
<span class="eat-macro__name">碳水</span>
<span class="eat-macro__val">155<span class="eat-macro__unit">/260 g</span></span>
</div>
<div class="eat-macro__bar"><div class="eat-macro__fill eat-macro__fill--carb" style="width:58%"></div></div>
</div>
<div class="eat-macro">
<div class="eat-macro__row">
<span class="eat-macro__name">蛋白质</span>
<span class="eat-macro__val">47<span class="eat-macro__unit">/82 g</span></span>
</div>
<div class="eat-macro__bar"><div class="eat-macro__fill eat-macro__fill--protein" style="width:57%"></div></div>
</div>
<div class="eat-macro">
<div class="eat-macro__row">
<span class="eat-macro__name">脂肪</span>
<span class="eat-macro__val">31<span class="eat-macro__unit">/60 g</span></span>
</div>
<div class="eat-macro__bar"><div class="eat-macro__fill eat-macro__fill--fat" style="width:52%"></div></div>
</div>
</div>
</div>
</div>
<!-- ====== 运动记录卡片 ====== -->
<div class="move-card">
<div class="move-card__header">
<span class="move-card__title">动记录</span>
<button class="move-card__add" onclick="location.href='exercise-checkin.html'">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
<div class="move-body">
<!-- 左侧:圆形进度圈 -->
<div class="move-ring">
<svg viewBox="0 0 130 130">
<circle cx="65" cy="65" r="56" fill="none" stroke="#f0f0f0" stroke-width="10"/>
<!-- 进度:推荐1000,已消耗58658.6% → 周长351.9 → 进度206 -->
<circle cx="65" cy="65" r="56" fill="none" stroke="#fa8c16" stroke-width="10"
stroke-dasharray="206 352" stroke-linecap="round"
transform="rotate(-90 65 65)"/>
</svg>
<div class="move-ring__center">
<div class="move-ring__val">586</div>
<div class="move-ring__label">千卡 / 推荐 1000</div>
<div class="move-ring__remain">还需消耗 414 千卡</div>
</div>
</div>
<!-- 右侧:消耗列表 -->
<div class="move-list">
<div class="move-item">
<span class="move-item__name">步行消耗</span>
<span class="move-item__val">266<span class="move-item__unit"> kcal</span></span>
</div>
<div class="move-item">
<span class="move-item__name">运动消耗</span>
<span class="move-item__val">320<span class="move-item__unit"> kcal</span></span>
</div>
<div class="move-item">
<span class="move-item__name">基础代谢</span>
<span class="move-item__val">380<span class="move-item__unit"> kcal</span></span>
</div>
</div>
</div>
</div>
<!-- ====== 体重记录卡片 ====== -->
<div class="weight-card">
<div class="weight-card__header">
<span class="weight-card__title">体重记录</span>
<div style="display:flex;align-items:center;gap:8px;">
<button style="padding:5px 12px;border-radius:14px;border:none;background:linear-gradient(160deg,#b08cff,#8b6cff);color:#fff;font-size:12px;font-weight:600;cursor:pointer;box-shadow:0 2px 8px rgba(139,108,255,0.3);display:flex;align-items:center;gap:4px;" onclick="location.href='../bluetooth-scale-miniprogram/main.html'">
<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M14.24 12.01l2.32 2.32c.28-.72.44-1.51.44-2.33 0-.82-.16-1.59-.43-2.31l-2.33 2.32zm5.29-5.3l-1.26 1.26c.63 1.21.98 2.57.98 4.02s-.36 2.82-.98 4.02l1.2 1.2c.97-1.54 1.54-3.36 1.54-5.31-.01-1.89-.55-3.67-1.48-5.19zm-3.82 1L10 2H9v7.59L4.41 5 3 6.41 8.59 12 3 17.59 4.41 19 9 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM11 5.83l1.88 1.88L11 9.59V5.83zm1.88 10.46L11 18.17v-3.76l1.88 1.88z"/></svg>
蓝牙称
</button>
<button class="weight-card__add" onclick="location.href='weight-checkin.html'">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
</div>
<div class="weight-body">
<!-- 左侧:最近一次体重 -->
<div class="weight-latest">
<div><span class="weight-latest__val">62.6</span><span class="weight-latest__unit">kg</span></div>
<div class="weight-latest__date">2026-07-22</div>
</div>
<!-- 右侧:近7日折线趋势 -->
<div class="weight-chart">
<svg viewBox="0 0 240 70" xmlns="http://www.w3.org/2000/svg">
<!-- 参考线 -->
<line x1="0" y1="55" x2="240" y2="55" stroke="#f0f0f0" stroke-width="1"/>
<line x1="0" y1="37" x2="240" y2="37" stroke="#f0f0f0" stroke-width="1"/>
<line x1="0" y1="19" x2="240" y2="19" stroke="#f0f0f0" stroke-width="1"/>
<!-- 折线:63.8→63.5→63.2→63.0→62.8→62.7→62.6 -->
<!-- y映射:63.8→15, 63.5→29, 63.2→42, 63.0→50, 62.8→58, 62.7→63, 62.6→66 -->
<polyline points="10,15 48,29 86,42 124,50 162,58 200,63 238,66"
fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<!-- 填充区域 -->
<polygon points="10,15 48,29 86,42 124,50 162,58 200,63 238,66 238,70 10,70"
fill="#36cfc9" fill-opacity="0.08"/>
<!-- 数据点 -->
<circle cx="10" cy="15" r="3" fill="#fff" stroke="#36cfc9" stroke-width="2"/>
<circle cx="48" cy="29" r="3" fill="#fff" stroke="#36cfc9" stroke-width="2"/>
<circle cx="86" cy="42" r="3" fill="#fff" stroke="#36cfc9" stroke-width="2"/>
<circle cx="124" cy="50" r="3" fill="#fff" stroke="#36cfc9" stroke-width="2"/>
<circle cx="162" cy="58" r="3" fill="#fff" stroke="#36cfc9" stroke-width="2"/>
<circle cx="200" cy="63" r="3" fill="#fff" stroke="#36cfc9" stroke-width="2"/>
<circle cx="238" cy="66" r="4" fill="#36cfc9" stroke="#fff" stroke-width="2"/>
<!-- X轴标签 -->
<text x="20" y="70" font-size="8" fill="#bbb" text-anchor="middle">16</text>
<text x="58" y="70" font-size="8" fill="#bbb" text-anchor="middle">17</text>
<text x="96" y="70" font-size="8" fill="#bbb" text-anchor="middle">18</text>
<text x="134" y="70" font-size="8" fill="#bbb" text-anchor="middle">19</text>
<text x="172" y="70" font-size="8" fill="#bbb" text-anchor="middle">20</text>
<text x="210" y="70" font-size="8" fill="#bbb" text-anchor="middle">21</text>
<text x="238" y="70" font-size="8" fill="#36cfc9" text-anchor="middle" font-weight="600">22</text>
</svg>
</div>
</div>
</div>
<!-- ====== 推荐视频卡片 ====== -->
<div class="video-card">
<div class="video-card__title">推荐视频</div>
<div class="video-grid">
<div class="video-item">
<div class="video-item__thumb">
<svg viewBox="0 0 160 100" preserveAspectRatio="xMidYMid slice"><rect width="160" height="100" fill="#667eea"/><rect x="30" y="20" width="100" height="60" rx="4" fill="rgba(255,255,255,0.15)"/></svg>
<div class="video-item__play"><div class="video-item__play-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="#36cfc9"><polygon points="8,5 19,12 8,19"/></svg></div></div>
<div class="video-item__author">张教练</div>
<div class="video-item__plays">1.2万 次播放</div>
</div>
<div class="video-item__info">
<div class="video-item__title">科学减脂:居家徒手训练指南</div>
<div class="video-item__org">健康管理部</div>
</div>
</div>
<div class="video-item">
<div class="video-item__thumb">
<svg viewBox="0 0 160 100" preserveAspectRatio="xMidYMid slice"><rect width="160" height="100" fill="#f093fb"/><rect x="30" y="20" width="100" height="60" rx="4" fill="rgba(255,255,255,0.15)"/></svg>
<div class="video-item__play"><div class="video-item__play-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="#36cfc9"><polygon points="8,5 19,12 8,19"/></svg></div></div>
<div class="video-item__author">李营养师</div>
<div class="video-item__plays">8560 次播放</div>
</div>
<div class="video-item__info">
<div class="video-item__title">均衡饮食:一日三餐怎么吃</div>
<div class="video-item__org">营养健康中心</div>
</div>
</div>
<div class="video-item">
<div class="video-item__thumb">
<svg viewBox="0 0 160 100" preserveAspectRatio="xMidYMid slice"><rect width="160" height="100" fill="#4facfe"/><rect x="30" y="20" width="100" height="60" rx="4" fill="rgba(255,255,255,0.15)"/></svg>
<div class="video-item__play"><div class="video-item__play-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="#36cfc9"><polygon points="8,5 19,12 8,19"/></svg></div></div>
<div class="video-item__author">王医生</div>
<div class="video-item__plays">6320 次播放</div>
</div>
<div class="video-item__info">
<div class="video-item__title">运动损伤预防与恢复</div>
<div class="video-item__org">职工医院</div>
</div>
</div>
<div class="video-item">
<div class="video-item__thumb">
<svg viewBox="0 0 160 100" preserveAspectRatio="xMidYMid slice"><rect width="160" height="100" fill="#43e97b"/><rect x="30" y="20" width="100" height="60" rx="4" fill="rgba(255,255,255,0.15)"/></svg>
<div class="video-item__play"><div class="video-item__play-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="#36cfc9"><polygon points="8,5 19,12 8,19"/></svg></div></div>
<div class="video-item__author">赵教练</div>
<div class="video-item__plays">4280 次播放</div>
</div>
<div class="video-item__info">
<div class="video-item__title">每天10分钟:办公室微运动</div>
<div class="video-item__org">工会文体部</div>
</div>
</div>
</div>
</div>
<div class="bottom-safe"></div>
</div>
</div>
<script>
/* ===== 右上角类型切换下拉菜单 ===== */
function toggleTypeMenu(e) {
e.stopPropagation();
var menu = document.getElementById('typeMenu');
var mask = document.getElementById('typeMask');
var show = !menu.classList.contains('show');
menu.classList.toggle('show', show);
mask.classList.toggle('show', show);
}
function closeTypeMenu() {
document.getElementById('typeMenu').classList.remove('show');
document.getElementById('typeMask').classList.remove('show');
}
document.addEventListener('click', function(e) {
if (!e.target.closest('#navMore')) closeTypeMenu();
});
function setPageType(type, e) {
if (e) e.stopPropagation();
// 菜单高亮
document.querySelectorAll('.type-menu__item').forEach(function(item) {
item.classList.toggle('active', item.dataset.type === type);
});
closeTypeMenu();
var activityEl = document.getElementById('activityName');
var rankEl = document.getElementById('rankBadge');
var daysEl = document.getElementById('daysLink');
if (type === 'hasact') {
// 已设置-参加活动:全部显示
activityEl.textContent = '2026年二季度体重管理活动';
activityEl.style.display = '';
rankEl.style.display = '';
daysEl.innerHTML = '当前第52/180天 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>';
daysEl.style.color = '#36cfc9';
daysEl.style.cursor = 'pointer';
} else if (type === 'personal') {
// 已设置-个人目标:改活动标题,隐藏排名
activityEl.textContent = '2026年二季度个人体重管理目标';
activityEl.style.display = '';
rankEl.style.display = 'none';
daysEl.innerHTML = '当前第52/180天 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>';
daysEl.style.color = '#36cfc9';
daysEl.style.cursor = 'pointer';
} else if (type === 'none') {
// 未设置目标:隐藏活动标题、排名,天数置灰
activityEl.style.display = 'none';
rankEl.style.display = 'none';
daysEl.innerHTML = '未设置目标 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#bbb" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>';
daysEl.style.color = '#bbb';
daysEl.style.cursor = 'default';
}
}
/* ===== 热量缺口日历切换 ===== */
var gapData = {
'16': { gap: '-412', intake: '980', consume: '740' },
'17': { gap: '-380', intake: '1050', consume: '790' },
'18': { gap: '0', intake: '0', consume: '0' },
'19': { gap: '-450', intake: '920', consume: '850' },
'20': { gap: '-320', intake: '1120', consume: '780' },
'21': { gap: '-390', intake: '1020', consume: '810' },
'22': { gap: '-364', intake: '1086', consume: '820' }
};
function selectGapDay(el) {
document.querySelectorAll('.gap-day').forEach(function(d) { d.classList.remove('active'); });
el.classList.add('active');
var day = el.dataset.day;
var data = gapData[day];
if (!data) return;
var rows = document.querySelectorAll('.gap-stats .gap-stat__val');
if (data.gap === '0') {
rows[0].innerHTML = '<span style="font-size:12px;color:#bbb;">--</span><span class="gap-stat__unit"> / -500 千卡</span>';
rows[0].classList.remove('gap-stat__val--good');
rows[1].innerHTML = '<span style="font-size:12px;color:#bbb;">--</span><span class="gap-stat__unit"> / 1000 千卡</span>';
rows[2].innerHTML = '<span style="font-size:12px;color:#bbb;">--</span><span class="gap-stat__unit"> / 1950 千卡</span>';
} else {
rows[0].innerHTML = data.gap + '<span class="gap-stat__unit"> / -500 千卡</span>';
rows[0].classList.add('gap-stat__val--good');
rows[1].innerHTML = data.consume + '<span class="gap-stat__unit"> / 1000 千卡</span>';
rows[2].innerHTML = data.intake + '<span class="gap-stat__unit"> / 1950 千卡</span>';
}
}
</script>
</body>
</html>