fix: 更新体重管理相关页面,新增归档单位报告详情页

This commit is contained in:
liuyunqin
2026-07-08 11:32:16 +08:00
parent 10a4a4bf7b
commit 559eee84d1
14 changed files with 1183 additions and 171 deletions
+310 -85
View File
@@ -323,7 +323,60 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.video-card__author-overlay { 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-card__info { padding: 8px 10px 10px; }
.video-card__title { font-size: 13px; font-weight: 600; color: #1a1a1a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.video-card__org { font-size: 10px; color: #bbb; margin-top: 3px; }
.video-card__org { font-size: 10px; color: #bbb; margin-top: 3px; }
/* ===== 本月吃动:日历导航 ===== */
.cal-nav { display: flex; align-items: center; justify-content: space-between; padding: 6px 0 4px; }
.cal-nav__arrow { width: 26px; height: 26px; border-radius: 50%; background: #f7f8fa; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; }
.cal-nav__arrow svg { width: 14px; height: 14px; stroke: #333; }
.cal-nav__month { font-size: 14px; font-weight: 700; color: #1a1a1a; }
/* ===== 本月吃动:日历 ===== */
.cal-grid { padding: 0 0 8px; }
.cal-grid__wd { display: grid; grid-template-columns: repeat(7, 1fr); margin-bottom: 3px; }
.cal-grid__wd span { font-size: 10px; color: #999; text-align: center; }
.cal-grid__days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal-day { display: flex; flex-direction: column; align-items: center; padding: 1px 0 2px; border-radius: 6px; cursor: pointer; min-height: 34px; }
.cal-day:hover { background: #f0f8f8; }
.cal-day.today { background: #e8f8f7; }
.cal-day.sel { background: #e8f8f7; border: 1.5px solid #36cfc9; }
.cal-day__num { font-size: 12px; font-weight: 700; color: #333; line-height: 1.2; }
.cal-day.today .cal-day__num, .cal-day.sel .cal-day__num { color: #36cfc9; }
.cal-day--empty { min-height: 34px; }
.cal-ring-wrap { display: flex; align-items: center; justify-content: center; margin-top: 2px; width: 24px; height: 24px; position: relative; }
.cal-ring--o { position: absolute; width: 21px; height: 21px; }
.cal-ring--o svg { width: 100%; height: 100%; }
.cal-ring--i { position: absolute; width: 14px; height: 14px; }
.cal-ring--i svg { width: 100%; height: 100%; }
.cal-day-diff { font-size: 7px; color: #bbb; margin-top: 0; text-align: center; line-height: 1.2; }
.cal-day-diff span:first-child { color: #36cfc9; }
/* ===== 本月吃动:柱状图 ===== */
.bar-section { padding: 8px 0 4px; }
.bar-section__title { font-size: 13px; font-weight: 700; color: #1a1a1a; margin-bottom: 6px; padding-left: 2px; }
.bar-area { position: relative; width: 100%; height: 200px; }
.bar-area svg { width: 100%; height: 100%; display: block; }
.bar-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
.bar-hit { position: absolute; pointer-events: auto; cursor: pointer; border-radius: 3px 3px 0 0; }
.bar-hit:hover { opacity: 0.85; }
.bar-legend { display: flex; justify-content: center; gap: 14px; margin-top: 6px; }
.bar-legend__item { display: flex; align-items: center; gap: 4px; font-size: 11px; color: #666; }
.bar-legend__sw { width: 10px; height: 7px; border-radius: 2px; flex-shrink: 0; }
.bar-legend__sw--in { background: #5470c6; }
.bar-legend__sw--ex { background: #fac858; }
/* 本月吃动 Tooltip */
.balance-tip { display: none; position: absolute; background: rgba(30,30,30,0.9); color: #fff; border-radius: 10px; padding: 10px 12px; font-size: 11px; line-height: 1.7; pointer-events: none; z-index: 10; min-width: 130px; box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
.balance-tip::after { content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border: 5px solid transparent; border-top-color: rgba(30,30,30,0.9); }
.balance-tip__date { font-weight: 700; font-size: 12px; margin-bottom: 4px; }
.balance-tip__row { display: flex; justify-content: space-between; }
.balance-tip__lbl { color: #ccc; }
.balance-tip__val { font-weight: 600; }
.balance-tip__val--b { color: #7eb8f7; }
.balance-tip__val--y { color: #f7d794; }
.balance-tip__div { border-top: 1px solid rgba(255,255,255,0.15); margin: 4px 0; }
</style>
</head>
<body>
@@ -349,7 +402,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div class="type-menu" id="typeMenu">
<div class="type-menu__item active" data-type="hasact" onclick="setPageType('hasact')">已参加活动</div>
<div class="type-menu__item" data-type="personal" onclick="setPageType('personal')">已设置个人目标</div>
<div class="type-menu__item" data-type="none" onclick="setPageType('none')">未参加未设置</div>
<div class="type-menu__item" data-type="none" onclick="setPageType('none')">未参加未设置未组织</div>
</div>
</div>
</div>
@@ -643,46 +696,56 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<!-- 本月吃动 -->
<div class="balance-body" id="balance-monthly" style="display:none;">
<div class="calorie-diff">
<div class="calorie-diff__label">本月吃动热量差</div>
<div class="calorie-diff__val">-12360 千卡</div>
<!-- 日历导航 -->
<div class="cal-nav">
<button class="cal-nav__arrow" onclick="changeMonth(-1)">
<svg 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>
</button>
<span class="cal-nav__month" id="nav-month">2026年8月</span>
<button class="cal-nav__arrow" onclick="changeMonth(1)">
<svg 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>
</button>
</div>
<div class="calorie-hint">本月累计亏空约 1.6 公斤脂肪</div>
<div class="ring-section">
<div class="ring-card">
<div class="ring-wrap">
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="none" stroke="#f0f0f0" stroke-width="8"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#5470c6" stroke-width="8" stroke-dasharray="180 251" stroke-linecap="round"/>
</svg>
<div class="ring-center">
<div class="ring-center__val">35620</div>
<div class="ring-center__unit">已摄入 千卡</div>
</div>
</div>
<div class="ring-legend">
<div class="ring-legend__item"><span><span class="ring-legend__dot" style="background:#5470c6"></span>碳水</span><span class="ring-legend__val">20300千卡 57%</span></div>
<div class="ring-legend__item"><span><span class="ring-legend__dot" style="background:#fac858"></span>脂肪</span><span class="ring-legend__val">9260千卡 26%</span></div>
<div class="ring-legend__item"><span><span class="ring-legend__dot" style="background:#ee6666"></span>蛋白质</span><span class="ring-legend__val">6060千卡 17%</span></div>
</div>
<!-- 日历 -->
<div class="cal-grid">
<div class="cal-grid__wd">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
<div class="ring-card">
<div class="ring-wrap">
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="none" stroke="#f0f0f0" stroke-width="8"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#fac858" stroke-width="8" stroke-dasharray="160 251" stroke-linecap="round"/>
</svg>
<div class="ring-center">
<div class="ring-center__val">18560</div>
<div class="ring-center__unit">已消耗 千卡</div>
</div>
</div>
<div class="ring-legend">
<div class="ring-legend__item"><span><span class="ring-legend__dot" style="background:#fac858"></span>基础代谢</span><span class="ring-legend__val">12060千卡 65%</span></div>
<div class="ring-legend__item"><span><span class="ring-legend__dot" style="background:#7367f0"></span>运动消耗</span><span class="ring-legend__val">3720千卡 20%</span></div>
<div class="ring-legend__item"><span><span class="ring-legend__dot" style="background:#b39ddb"></span>步行</span><span class="ring-legend__val">2780千卡 15%</span></div>
</div>
<div class="cal-grid__days" id="cal-days"></div>
</div>
<!-- 柱状图 -->
<div class="bar-section">
<div class="bar-section__title">本月吃动趋势</div>
<div class="bar-area" id="bar-area">
<div class="balance-tip" id="balanceTip"><div class="balance-tip__date"></div><div class="balance-tip__body"></div></div>
<svg viewBox="0 0 360 208" preserveAspectRatio="none" id="bar-svg">
<defs>
<linearGradient id="ig" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#5470c6"/><stop offset="100%" stop-color="#3a56a4"/></linearGradient>
<linearGradient id="eg" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#fac858"/><stop offset="100%" stop-color="#e6a817"/></linearGradient>
</defs>
<!-- Y轴标签 -->
<text x="2" y="16" font-size="9" fill="#999">2500</text>
<text x="2" y="48" font-size="9" fill="#999">2000</text>
<text x="2" y="79" font-size="9" fill="#999">1500</text>
<text x="2" y="111" font-size="9" fill="#999">1000</text>
<text x="2" y="142" font-size="9" fill="#999">500</text>
<!-- Y轴刻度线 -->
<line x1="34" y1="12" x2="38" y2="12" stroke="#e0e0e0" stroke-width="1"/>
<line x1="34" y1="44" x2="38" y2="44" stroke="#e0e0e0" stroke-width="1"/>
<line x1="34" y1="75" x2="38" y2="75" stroke="#e0e0e0" stroke-width="1"/>
<line x1="34" y1="107" x2="38" y2="107" stroke="#e0e0e0" stroke-width="1"/>
<line x1="34" y1="138" x2="38" y2="138" stroke="#e0e0e0" stroke-width="1"/>
<!-- X轴线 (y=170) -->
<line x1="38" y1="170" x2="350" y2="170" stroke="#f0f0f0" stroke-width="1"/>
<g id="bars"></g>
</svg>
<div class="bar-overlay" id="bar-overlay"></div>
</div>
<div class="bar-legend">
<div class="bar-legend__item"><div class="bar-legend__sw bar-legend__sw--in"></div><span>摄入</span></div>
<div class="bar-legend__item"><div class="bar-legend__sw bar-legend__sw--ex"></div><span>消耗</span></div>
</div>
</div>
</div>
@@ -796,16 +859,16 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<circle cx="250" cy="130" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
<circle cx="300" cy="154" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
</svg>
</div>
<!-- HTML 数据点覆盖层(用于点击) -->
<div class="chart-dots-overlay">
<div class="chart-dot" data-date="02-12" data-weight="73.50" data-x="17.6" data-y="7.6" onclick="showTip(this)" style="left:17.6%;top:7.6%"></div>
<div class="chart-dot" data-date="02-15" data-weight="70.00" data-x="29.4" data-y="29.1" onclick="showTip(this)" style="left:29.4%;top:29.1%"></div>
<div class="chart-dot" data-date="02-22" data-weight="68.00" data-x="43.5" data-y="50.6" onclick="showTip(this)" style="left:43.5%;top:50.6%"></div>
<div class="chart-dot" data-date="03-01" data-weight="66.00" data-x="58.8" data-y="65.8" onclick="showTip(this)" style="left:58.8%;top:65.8%"></div>
<div class="chart-dot" data-date="03-13" data-weight="64.00" data-x="73.5" data-y="81.0" onclick="showTip(this)" style="left:73.5%;top:81.0%"></div>
<div class="chart-dot" data-date="03-18" data-weight="62.60" data-x="88.2" data-y="96.2" onclick="showTip(this)" style="left:88.2%;top:96.2%"></div>
<!-- HTML 数据点覆盖层(用于点击) -->
<div class="chart-dots-overlay">
<div class="chart-dot" data-date="02-12" data-weight="73.50" data-x="17.6" data-y="7.6" onclick="showTip(this)" style="left:17.6%;top:7.6%"></div>
<div class="chart-dot" data-date="02-15" data-weight="70.00" data-x="29.4" data-y="29.1" onclick="showTip(this)" style="left:29.4%;top:29.1%"></div>
<div class="chart-dot" data-date="02-22" data-weight="68.00" data-x="43.5" data-y="50.6" onclick="showTip(this)" style="left:43.5%;top:50.6%"></div>
<div class="chart-dot" data-date="03-01" data-weight="66.00" data-x="58.8" data-y="65.8" onclick="showTip(this)" style="left:58.8%;top:65.8%"></div>
<div class="chart-dot" data-date="03-13" data-weight="64.00" data-x="73.5" data-y="81.0" onclick="showTip(this)" style="left:73.5%;top:81.0%"></div>
<div class="chart-dot" data-date="03-18" data-weight="62.60" data-x="88.2" data-y="96.2" onclick="showTip(this)" style="left:88.2%;top:96.2%"></div>
</div>
</div>
<!-- 图例 -->
@@ -835,12 +898,10 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div class="stat-item">
<div class="stat-item__label">最大体脂</div>
<div class="stat-item__val">28.5<span class="stat-item__unit">%</span></div>
<div class="stat-item__sub">02-12</div>
</div>
<div class="stat-item">
<div class="stat-item__label">最小体脂</div>
<div class="stat-item__val">20.0<span class="stat-item__unit">%</span></div>
<div class="stat-item__sub">03-18</div>
</div>
<div class="stat-item stat-item--change">
<div class="stat-item__label">体脂变化</div>
@@ -912,16 +973,16 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<circle cx="250" cy="130" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
<circle cx="300" cy="144" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
</svg>
</div>
<!-- HTML 数据点覆盖层 -->
<div class="chart-dots-overlay">
<div class="chart-dot" data-date="02-12" data-weight="28.50" data-x="17.6" data-y="13.3" onclick="showFatTip(this)" style="left:17.6%;top:13.3%"></div>
<div class="chart-dot" data-date="02-15" data-weight="25.00" data-x="29.4" data-y="35.6" onclick="showFatTip(this)" style="left:29.4%;top:35.6%"></div>
<div class="chart-dot" data-date="02-22" data-weight="22.70" data-x="43.5" data-y="54.4" onclick="showFatTip(this)" style="left:43.5%;top:54.4%"></div>
<div class="chart-dot" data-date="03-01" data-weight="21.50" data-x="58.8" data-y="63.1" onclick="showFatTip(this)" style="left:58.8%;top:63.1%"></div>
<div class="chart-dot" data-date="03-13" data-weight="20.70" data-x="73.5" data-y="72.2" onclick="showFatTip(this)" style="left:73.5%;top:72.2%"></div>
<div class="chart-dot" data-date="03-18" data-weight="20.00" data-x="88.2" data-y="80.0" onclick="showFatTip(this)" style="left:88.2%;top:80.0%"></div>
<!-- HTML 数据点覆盖层 -->
<div class="chart-dots-overlay">
<div class="chart-dot" data-date="02-12" data-weight="28.50" data-x="17.6" data-y="13.3" onclick="showFatTip(this)" style="left:17.6%;top:13.3%"></div>
<div class="chart-dot" data-date="02-15" data-weight="25.00" data-x="29.4" data-y="35.6" onclick="showFatTip(this)" style="left:29.4%;top:35.6%"></div>
<div class="chart-dot" data-date="02-22" data-weight="22.70" data-x="43.5" data-y="54.4" onclick="showFatTip(this)" style="left:43.5%;top:54.4%"></div>
<div class="chart-dot" data-date="03-01" data-weight="21.50" data-x="58.8" data-y="63.1" onclick="showFatTip(this)" style="left:58.8%;top:63.1%"></div>
<div class="chart-dot" data-date="03-13" data-weight="20.70" data-x="73.5" data-y="72.2" onclick="showFatTip(this)" style="left:73.5%;top:72.2%"></div>
<div class="chart-dot" data-date="03-18" data-weight="20.00" data-x="88.2" data-y="80.0" onclick="showFatTip(this)" style="left:88.2%;top:80.0%"></div>
</div>
</div>
<!-- 图例 -->
@@ -951,12 +1012,10 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div class="stat-item">
<div class="stat-item__label">最大腰围</div>
<div class="stat-item__val">92.0<span class="stat-item__unit">cm</span></div>
<div class="stat-item__sub">02-12</div>
</div>
<div class="stat-item">
<div class="stat-item__label">最小腰围</div>
<div class="stat-item__val">76.5<span class="stat-item__unit">cm</span></div>
<div class="stat-item__sub">03-18</div>
</div>
<div class="stat-item stat-item--change">
<div class="stat-item__label">腰围变化</div>
@@ -1032,16 +1091,16 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<circle cx="250" cy="128" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
<circle cx="300" cy="143" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
</svg>
</div>
<!-- HTML 数据点覆盖层 -->
<div class="chart-dots-overlay">
<div class="chart-dot" data-date="02-12" data-weight="92.00" data-x="17.6" data-y="16.7" onclick="showWaistTip(this)" style="left:17.6%;top:16.7%"></div>
<div class="chart-dot" data-date="02-15" data-weight="87.00" data-x="29.4" data-y="37.8" onclick="showWaistTip(this)" style="left:29.4%;top:37.8%"></div>
<div class="chart-dot" data-date="02-22" data-weight="83.00" data-x="43.5" data-y="51.1" onclick="showWaistTip(this)" style="left:43.5%;top:51.1%"></div>
<div class="chart-dot" data-date="03-01" data-weight="80.50" data-x="58.8" data-y="61.1" onclick="showWaistTip(this)" style="left:58.8%;top:61.1%"></div>
<div class="chart-dot" data-date="03-13" data-weight="78.00" data-x="73.5" data-y="71.1" onclick="showWaistTip(this)" style="left:73.5%;top:71.1%"></div>
<div class="chart-dot" data-date="03-18" data-weight="76.50" data-x="88.2" data-y="79.4" onclick="showWaistTip(this)" style="left:88.2%;top:79.4%"></div>
<!-- HTML 数据点覆盖层 -->
<div class="chart-dots-overlay">
<div class="chart-dot" data-date="02-12" data-weight="92.00" data-x="17.6" data-y="16.7" onclick="showWaistTip(this)" style="left:17.6%;top:16.7%"></div>
<div class="chart-dot" data-date="02-15" data-weight="87.00" data-x="29.4" data-y="37.8" onclick="showWaistTip(this)" style="left:29.4%;top:37.8%"></div>
<div class="chart-dot" data-date="02-22" data-weight="83.00" data-x="43.5" data-y="51.1" onclick="showWaistTip(this)" style="left:43.5%;top:51.1%"></div>
<div class="chart-dot" data-date="03-01" data-weight="80.50" data-x="58.8" data-y="61.1" onclick="showWaistTip(this)" style="left:58.8%;top:61.1%"></div>
<div class="chart-dot" data-date="03-13" data-weight="78.00" data-x="73.5" data-y="71.1" onclick="showWaistTip(this)" style="left:73.5%;top:71.1%"></div>
<div class="chart-dot" data-date="03-18" data-weight="76.50" data-x="88.2" data-y="79.4" onclick="showWaistTip(this)" style="left:88.2%;top:79.4%"></div>
</div>
</div>
<!-- 图例 -->
@@ -1068,7 +1127,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div class="dash-grid__left">
<!-- 正常排行榜(已参加活动) -->
<!-- [交互] 点击跳转至: weight-ranking.html -->
<div class="rank-card" id="rankCardNormal" onclick="location.href='weight-ranking.html'">
<div class="rank-card" id="rankCardNormal" onclick="location.href='weight-ranking.html?type=' + currentPageType">
<div class="rank-card__title">2026年二季度体重管理活动</div>
<div class="rank-card__my">
<span class="rank-card__my-label">减重排名</span>
@@ -1124,11 +1183,11 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
</div>
<!-- 排行榜缺省占位(已设置个人目标 / 未参加未设置) -->
<div class="rank-card rank-card--empty" id="rankCardEmpty" style="display:none;">
<div class="rank-card rank-card--empty" id="rankCardEmpty" style="display:none; cursor:pointer;" onclick="location.href='weight-ranking.html?type=none'">
<div class="rank-card--empty__icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20V10"/><path d="M18 20V4"/><path d="M6 20v-4"/></svg>
</div>
<div class="rank-card--empty__text">暂未参加活动<br>暂无排行榜数据</div>
<div class="rank-card--empty__text">排行榜示意图</div>
</div>
</div>
@@ -1249,6 +1308,7 @@ function applyPageType(type) {
var progressCard = document.querySelector('.progress-card');
var rankCardNormal = document.getElementById('rankCardNormal');
var rankCardEmpty = document.getElementById('rankCardEmpty');
var rankMy = rankCardNormal ? rankCardNormal.querySelector('.rank-card__my') : null;
// 菜单项高亮
document.querySelectorAll('.type-menu__item').forEach(function(item) {
@@ -1261,12 +1321,14 @@ function applyPageType(type) {
if (progressCard) progressCard.style.display = '';
if (rankCardNormal) rankCardNormal.style.display = '';
if (rankCardEmpty) rankCardEmpty.style.display = 'none';
if (rankMy) rankMy.style.display = '';
} else if (type === 'personal') {
// 已设置个人目标:隐藏排名副标题,排行榜改为缺省样式
// 已设置个人目标:照搬活动排行榜,但隐藏自己的排名
if (rankSubBar) rankSubBar.style.display = 'none';
if (progressCard) progressCard.style.display = '';
if (rankCardNormal) rankCardNormal.style.display = 'none';
if (rankCardEmpty) rankCardEmpty.style.display = '';
if (rankCardNormal) rankCardNormal.style.display = '';
if (rankCardEmpty) rankCardEmpty.style.display = 'none';
if (rankMy) rankMy.style.display = 'none';
} else if (type === 'none') {
// 未参加未设置:隐藏排名副标题,隐藏减重进度卡片,排行榜改为缺省样式
if (rankSubBar) rankSubBar.style.display = 'none';
@@ -1277,11 +1339,13 @@ function applyPageType(type) {
}
applyPageType(currentPageType);
var balanceMonthlyInited = false;
function switchBalanceTab(el, tab) {
el.parentElement.querySelectorAll('.balance-tab').forEach(t => t.classList.remove('active'));
el.classList.add('active');
document.getElementById('balance-daily').style.display = tab === 'daily' ? '' : 'none';
document.getElementById('balance-monthly').style.display = tab === 'monthly' ? '' : 'none';
if (tab === 'monthly' && !balanceMonthlyInited) { balanceMonthlyInited = true; renderCal(); renderBars(); }
}
function switchRecordTab(el, tab) {
el.parentElement.querySelectorAll('.record-tab').forEach(t => t.classList.remove('active'));
@@ -1292,8 +1356,8 @@ function switchRecordTab(el, tab) {
}
// 折线图数据点 tooltip — 体重
function showTip(el) {
var area = document.getElementById('chart-area');
var tip = document.getElementById('chart-tooltip');
if (!tip) return;
var date = el.getAttribute('data-date');
var weight = el.getAttribute('data-weight');
tip.querySelector('.chart-tooltip__date').textContent = date;
@@ -1302,13 +1366,13 @@ function showTip(el) {
var x = parseFloat(el.getAttribute('data-x'));
var y = parseFloat(el.getAttribute('data-y'));
tip.style.left = x + '%';
tip.style.top = '0px';
tip.style.transform = 'translateX(-50%) translateY(-100%)';
tip.style.top = y + '%';
tip.style.transform = 'translate(-50%, -120%)';
}
// 折线图数据点 tooltip — 体脂
function showFatTip(el) {
var area = document.getElementById('chart-area-fat');
var tip = document.getElementById('chart-tooltip-fat');
if (!tip) return;
var date = el.getAttribute('data-date');
var weight = el.getAttribute('data-weight');
tip.querySelector('.chart-tooltip__date').textContent = date;
@@ -1317,13 +1381,13 @@ function showFatTip(el) {
var x = parseFloat(el.getAttribute('data-x'));
var y = parseFloat(el.getAttribute('data-y'));
tip.style.left = x + '%';
tip.style.top = '0px';
tip.style.transform = 'translateX(-50%) translateY(-100%)';
tip.style.top = y + '%';
tip.style.transform = 'translate(-50%, -120%)';
}
// 折线图数据点 tooltip — 腰围
function showWaistTip(el) {
var area = document.getElementById('chart-area-waist');
var tip = document.getElementById('chart-tooltip-waist');
if (!tip) return;
var date = el.getAttribute('data-date');
var weight = el.getAttribute('data-weight');
tip.querySelector('.chart-tooltip__date').textContent = date;
@@ -1332,8 +1396,8 @@ function showWaistTip(el) {
var x = parseFloat(el.getAttribute('data-x'));
var y = parseFloat(el.getAttribute('data-y'));
tip.style.left = x + '%';
tip.style.top = '0px';
tip.style.transform = 'translateX(-50%) translateY(-100%)';
tip.style.top = y + '%';
tip.style.transform = 'translate(-50%, -120%)';
}
// 点击图表空白区域关闭 tooltip
document.addEventListener('click', function(e) {
@@ -1347,7 +1411,168 @@ document.addEventListener('click', function(e) {
tip.style.display = 'none';
}
});
// 同时关闭本月吃动 tooltip
var balanceTip = document.getElementById('balanceTip');
if (balanceTip && !e.target.closest('.bar-hit') && !e.target.closest('.balance-tip')) {
balanceTip.style.display = 'none';
}
});
/* ===== 本月吃动 Tab 逻辑 ===== */
var currentYear = 2026, currentMonth = 8, selectedDay = null;
var dayData = {};
var balanceMock = [
{d:1,i:1920,e:1680,c:1100,f:490,p:330,bf:520,l:820,dn:580,ba:1100,s:320,w:260},
{d:2,i:2100,e:1750,c:1200,f:540,p:360,bf:580,l:900,dn:620,ba:1120,s:350,w:280},
{d:3,i:1850,e:1920,c:1050,f:470,p:330,bf:480,l:780,dn:590,ba:1130,s:480,w:310},
{d:4,i:2050,e:1700,c:1160,f:520,p:370,bf:550,l:870,dn:630,ba:1110,s:310,w:280},
{d:5,i:1780,e:1850,c:1010,f:450,p:320,bf:460,l:750,dn:570,ba:1140,s:420,w:290},
{d:6,i:2200,e:1600,c:1260,f:560,p:380,bf:620,l:940,dn:640,ba:1100,s:260,w:240},
{d:7,i:1950,e:1780,c:1110,f:495,p:345,bf:510,l:830,dn:610,ba:1120,s:360,w:300},
{d:8,i:1880,e:1960,c:1070,f:475,p:335,bf:490,l:800,dn:590,ba:1150,s:500,w:310},
{d:9,i:1960,e:1720,c:1120,f:500,p:340,bf:530,l:840,dn:590,ba:1110,s:330,w:280},
{d:10,i:2080,e:1800,c:1180,f:530,p:370,bf:560,l:890,dn:630,ba:1130,s:370,w:300},
{d:11,i:1820,e:1900,c:1030,f:460,p:330,bf:470,l:770,dn:580,ba:1140,s:450,w:310},
{d:12,i:1940,e:1760,c:1100,f:490,p:350,bf:520,l:830,dn:590,ba:1120,s:340,w:300},
{d:13,i:1900,e:1820,c:1080,f:480,p:340,bf:500,l:810,dn:590,ba:1130,s:380,w:310},
];
balanceMock.forEach(function(m){
dayData['2026-08-'+(m.d<10?'0'+m.d:m.d)] = m;
});
/* 日历渲染 */
function renderCal(){
var c = document.getElementById('cal-days');
if (!c) return;
c.innerHTML = '';
document.getElementById('nav-month').textContent = currentYear+'年'+currentMonth+'月';
var fd = new Date(currentYear, currentMonth-1, 1).getDay();
var dim = new Date(currentYear, currentMonth, 0).getDate();
var off = fd===0?6:fd-1;
var today = new Date();
var tk = today.getFullYear()+'-'+String(today.getMonth()+1).padStart(2,'0')+'-'+String(today.getDate()).padStart(2,'0');
for(var i=0;i<off;i++){var em=document.createElement('div');em.className='cal-day--empty';c.appendChild(em);}
for(var d=1;d<=dim;d++){
var dk = currentYear+'-'+String(currentMonth).padStart(2,'0')+'-'+String(d).padStart(2,'0');
var data = dayData[dk];
var el = document.createElement('div');
el.className='cal-day';
if(dk===tk) el.classList.add('today');
if(selectedDay===d) el.classList.add('sel');
el.setAttribute('data-d',d);el.setAttribute('data-k',dk);
el.onclick=function(){selDay(+this.getAttribute('data-d'),this.getAttribute('data-k'));};
var n=document.createElement('span');n.className='cal-day__num';n.textContent=d;el.appendChild(n);
if(data){
var ip=Math.min(data.i/2500,1),ep=Math.min(data.e/2500,1);
var rw=document.createElement('div');rw.className='cal-ring-wrap';
var oo=document.createElement('div');oo.className='cal-ring--o';
var cc=2*Math.PI*8;
oo.innerHTML='<svg viewBox="0 0 20 20"><circle cx="10" cy="10" r="8" fill="none" stroke="#e0e0e0" stroke-width="2"/><circle cx="10" cy="10" r="8" fill="none" stroke="#5470c6" stroke-width="2" stroke-dasharray="'+(cc*ip).toFixed(1)+' '+ (cc*(1-ip)).toFixed(1)+'" stroke-linecap="round"/></svg>';
rw.appendChild(oo);
var inn=document.createElement('div');inn.className='cal-ring--i';
var cc2=2*Math.PI*8;
inn.innerHTML='<svg viewBox="0 0 20 20"><circle cx="10" cy="10" r="8" fill="none" stroke="#e0e0e0" stroke-width="2"/><circle cx="10" cy="10" r="8" fill="none" stroke="#fac858" stroke-width="2" stroke-dasharray="'+(cc2*ep).toFixed(1)+' '+(cc2*(1-ep)).toFixed(1)+'" stroke-linecap="round"/></svg>';
rw.appendChild(inn);el.appendChild(rw);
var df=document.createElement('div');df.className='cal-day-diff';
df.innerHTML='<span style="color:#ff6b81;font-weight:700;">-1520</span><span style="color:#bbb;">/-300</span>';el.appendChild(df);
}
c.appendChild(el);
}
}
function selDay(d,k){
selectedDay=d;
document.querySelectorAll('#balance-monthly .cal-day').forEach(function(el){el.classList.remove('sel');if(+el.getAttribute('data-d')===d)el.classList.add('sel');});
renderBars();
var intBar=document.querySelector('#balance-monthly .bar-hit[data-k="'+k+'"]');
if(intBar) showBalanceTipIn(intBar);
}
function selectDayFromBar(dk,type){
var d=+dk.split("-")[2];
selectedDay=d;
document.querySelectorAll("#balance-monthly .cal-day").forEach(function(el){el.classList.remove("sel");if(+el.getAttribute("data-d")===d)el.classList.add("sel");});
renderBars();
var h=document.querySelector('#balance-monthly .bar-hit[data-k="'+dk+'"]');
if(h){ if(type==="in")showBalanceTipIn(h); else showBalanceTipEx(h); }
}
function changeMonth(delta){
currentMonth+=delta;
if(currentMonth>12){currentMonth=1;currentYear++;}
if(currentMonth<1){currentMonth=12;currentYear--;}
selectedDay=null;renderCal();renderBars();
}
/* 柱状图渲染 */
function renderBars(){
var g=document.getElementById('bars'),ov=document.getElementById('bar-overlay');
if(!g||!ov) return;
g.innerHTML='';ov.innerHTML='';
var dim=new Date(currentYear,currentMonth,0).getDate();
var md=dim;
var chartLeft=38, chartRight=350, chartTop=12, chartBot=170;
var chartW=chartRight-chartLeft, chartH=chartBot-chartTop;
var pairW=chartW/md, gap=3, barW=(pairW-gap)/2;
var maxY=2500;
for(var d=1;d<=md;d++){
var k=currentYear+'-'+String(currentMonth).padStart(2,'0')+'-'+String(d).padStart(2,'0');
var data=dayData[k];
var xs=chartLeft+(d-1)*pairW, hl=selectedDay===d;
if(data){
var iH=(data.i/maxY)*chartH, iY=chartTop+chartH-iH;
var iX=xs+1, iC=hl?'#5470c6':'url(#ig)';
if(hl) g.innerHTML+='<rect x="'+(iX-1)+'" y="'+iY+'" width="'+(barW+2)+'" height="'+iH+'" rx="2" fill="'+iC+'" opacity="0.25"/>';
g.innerHTML+='<rect x="'+iX+'" y="'+iY+'" width="'+barW+'" height="'+iH+'" rx="2" fill="'+iC+'"/>';
var eH=(data.e/maxY)*chartH, eY=chartTop+chartH-eH;
var eX=xs+barW+gap;
g.innerHTML+='<rect x="'+eX+'" y="'+eY+'" width="'+barW+'" height="'+eH+'" rx="2" fill="url(#eg)"/>';
var lpV=iX/360*100, tpV=iY/208*100, wpV=barW/360*100, hpI=iH/208*100, hpE=eH/208*100;
var ih=document.createElement('div');ih.className='bar-hit';
ih.style.cssText='left:'+lpV.toFixed(2)+'%;top:'+tpV.toFixed(2)+'%;width:'+wpV.toFixed(2)+'%;height:'+hpI.toFixed(2)+'%;background:'+(hl?'#5470c6':'rgba(84,112,198,0.5)');
ih.setAttribute('data-k',k);ih.onclick=function(ev){ev.stopPropagation();var dk=this.getAttribute("data-k");selectDayFromBar(dk,"in");};ov.appendChild(ih);
var eh=document.createElement('div');eh.className='bar-hit';
var elpV=eX/360*100, etpV=eY/208*100; eh.style.cssText='left:'+elpV.toFixed(2)+'%;top:'+etpV.toFixed(2)+'%;width:'+wpV.toFixed(2)+'%;height:'+hpE.toFixed(2)+'%;background:rgba(250,200,88,0.5)';
eh.setAttribute('data-k',k);eh.onclick=function(ev){ev.stopPropagation();var dk=this.getAttribute("data-k");selectDayFromBar(dk,"ex");};ov.appendChild(eh);
}
var step=md>20?5:md>10?3:1;
if(d===1||d%step===0||d===md){
var lx=xs+pairW/2;
g.innerHTML+='<text x="'+lx+'" y="200" font-size="8" fill="#bbb" text-anchor="middle">'+currentMonth+'/'+d+'</text>';
}
}
}
function showBalanceTip(el,dl,html){
var t=document.getElementById('balanceTip');if(!t) return;
t.querySelector('.balance-tip__date').textContent=dl;
t.querySelector('.balance-tip__body').innerHTML=html;t.style.display='block';
t.style.left='50%';t.style.top='2px';t.style.transform='translateX(-50%) translateY(-100%)';
setTimeout(function(){document.addEventListener('click',closeBalanceTip,{once:true});},10);
}
function closeBalanceTip(e){if(!e.target.closest('.bar-hit')&&!e.target.closest('.balance-tip'))document.getElementById('balanceTip').style.display='none';}
function showBalanceTipIn(el){
var k=el.getAttribute('data-k'),data=dayData[k];if(!data)return;
var p=k.split('-');
showBalanceTip(el,p[0]+'年'+(+p[1])+'月'+(+p[2])+'日',
'<div class="balance-tip__div"></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">碳水</span><span class="balance-tip__val balance-tip__val--b">'+data.c+' 千卡</span></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">脂肪</span><span class="balance-tip__val balance-tip__val--b">'+data.f+' 千卡</span></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">蛋白质</span><span class="balance-tip__val balance-tip__val--b">'+data.p+' 千卡</span></div>'+
'<div class="balance-tip__div"></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">早餐</span><span class="balance-tip__val">'+data.bf+' 千卡</span></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">午餐</span><span class="balance-tip__val">'+data.l+' 千卡</span></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">晚餐</span><span class="balance-tip__val">'+data.dn+' 千卡</span></div>');
}
function showBalanceTipEx(el){
var k=el.getAttribute('data-k'),data=dayData[k];if(!data)return;
var p=k.split('-');
showBalanceTip(el,p[0]+'年'+(+p[1])+'月'+(+p[2])+'日',
'<div class="balance-tip__div"></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">基础代谢</span><span class="balance-tip__val balance-tip__val--y">'+data.ba+' 千卡</span></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">运动消耗</span><span class="balance-tip__val balance-tip__val--y">'+data.s+' 千卡</span></div>'+
'<div class="balance-tip__row"><span class="balance-tip__lbl">步行消耗</span><span class="balance-tip__val balance-tip__val--y">'+data.w+' 千卡</span></div>');
}
</script>
</body>
</html>
@@ -83,6 +83,10 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.rank-item__extra { width: 42px; text-align: right; flex-shrink: 0; font-size: 12px; color: #999; }
.bottom-safe { height: 20px; flex-shrink: 0; }
/* ===== 未组织活动提示条 ===== */
.no-org-notice { display: none; background: #fff7e6; border-bottom: 1px solid #ffe58f; padding: 10px 16px; text-align: center; font-size: 13px; color: #d48806; font-weight: 600; }
.no-org-notice.show { display: block; }
</style>
</head>
<body>
@@ -107,6 +111,9 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div class="nav-placeholder"></div>
</div>
<!-- 未组织活动提示 -->
<div class="no-org-notice" id="noOrgNotice">单位暂未组织活动</div>
<div class="scroll-content">
<!-- 活动标题 -->
<div class="activity-header">
@@ -270,6 +277,12 @@ function switchRankTab(tab) {
// 更新列表头
document.getElementById('rankListHeaderScore').textContent = rankHeaderLabels[tab];
if (isNoOrg) {
// 未组织活动:列表为空
document.getElementById('rankList').innerHTML = '';
return;
}
// 更新个人排名卡片
var my = myInfoMap[tab];
document.getElementById('myRankNum').textContent = my.rank;
@@ -315,6 +328,29 @@ function renderRankList(data) {
document.getElementById('rankList').innerHTML = html;
}
/* 根据 type 参数处理页面状态 */
var isNoOrg = false;
(function(){
var params = new URLSearchParams(location.search);
var type = params.get('type') || 'hasact';
if (type === 'none') {
// 未组织活动:提示 + 隐藏活动标题和我的排名 + 列表为空
isNoOrg = true;
var notice = document.getElementById('noOrgNotice');
var header = document.querySelector('.activity-header');
var myCard = document.getElementById('myRankCard');
if (notice) notice.classList.add('show');
if (header) header.style.display = 'none';
if (myCard) myCard.style.display = 'none';
} else if (type === 'personal') {
// 已设置个人目标:仅隐藏我的排名卡片
var myCard = document.getElementById('myRankCard');
if (myCard) myCard.style.display = 'none';
}
// type === 'hasact':全部正常显示
})();
/* 初始化:默认显示减重量 tab */
switchRankTab('weight');
</script>