feat: 体重管理v2页面功能增强,新增蓝牙设备、目标历史及体重记录详情页

- 优化目标详情页、目标管理页、体重主页及报告页样式与交互
- 新增蓝牙设备成员/秤/搜索/WiFi配网页面
- 新增目标历史记录页
- 新增体重记录详情页
This commit is contained in:
liuyunqin
2026-07-28 17:55:46 +08:00
parent 7b77e5b1cb
commit a4f61cc65c
10 changed files with 2143 additions and 316 deletions
@@ -0,0 +1,362 @@
<!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; position: relative; }
.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; padding: 16px; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 设备信息卡片 */
.device-info { background: #fff; border-radius: 12px; padding: 16px; display: flex; align-items: center; gap: 12px; margin-bottom: 16px; box-shadow: 0 1px 4px rgba(0,0,0,0.04); }
.device-info__icon { width: 48px; height: 48px; border-radius: 12px; background: #e6f4ff; display: flex; align-items: center; justify-content: center; font-size: 24px; flex-shrink: 0; }
.device-info__detail { flex: 1; }
.device-info__name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.device-info__sn { font-size: 12px; color: #999; margin-top: 2px; line-height: 1.6; }
.device-info__status { font-size: 11px; padding: 3px 10px; border-radius: 10px; font-weight: 600; flex-shrink: 0; }
.device-info__status--online { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
.device-info__status--offline { background: #f5f5f5; color: #999; border: 1px solid #e8e8e8; }
/* 成员列表 */
.section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.section-title { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.sync-btn { font-size: 12px; padding: 5px 12px; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; white-space: nowrap; background: #1677ff; color: #fff; }
.sync-btn:active { opacity: 0.8; }
.sync-btn--disabled { background: #e8e8e8; color: #bbb; cursor: not-allowed; pointer-events: none; }
.member-list { display: flex; flex-direction: column; gap: 10px; }
.member-card { background: #fff; border-radius: 12px; padding: 14px 16px; display: flex; align-items: center; gap: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.04); }
.member-avatar { width: 44px; height: 44px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #fff; font-weight: 700; flex-shrink: 0; }
.member-avatar--male { background: linear-gradient(135deg, #1677ff, #69b1ff); }
.member-avatar--female { background: linear-gradient(135deg, #ff85c0, #ffadd2); }
.member-avatar--child { background: linear-gradient(135deg, #ffc069, #ffd591); }
.member-avatar--elder { background: linear-gradient(135deg, #95de64, #b7eb8f); }
.member-info { flex: 1; min-width: 0; }
.member-top { display: flex; align-items: center; gap: 8px; }
.member-name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.member-tag--self { font-size: 10px; padding: 2px 6px; border-radius: 4px; font-weight: 600; background: #e6f4ff; color: #1677ff; flex-shrink: 0; }
.member-tag--type { font-size: 10px; padding: 2px 6px; border-radius: 4px; font-weight: 500; background: #f5f5f5; color: #888; flex-shrink: 0; }
.member-sync { font-size: 11px; font-weight: 600; margin-left: auto; flex-shrink: 0; }
.member-sync--done { color: #389e0d; }
.member-sync--pending { color: #ff4d4f; }
.member-sync--deleted { color: #ff4d4f; }
.member-detail { font-size: 12px; color: #999; margin-top: 4px; }
.member-actions { display: flex; gap: 12px; margin-top: 8px; }
.action-btn { font-size: 12px; padding: 4px 14px; border-radius: 6px; border: none; font-weight: 500; cursor: pointer; }
.action-btn:active { opacity: 0.7; }
.action-btn--edit { background: #e6f4ff; color: #1677ff; }
.action-btn--delete { background: #fff2f0; color: #ff4d4f; }
.member-card--deleted { opacity: 0.45; pointer-events: none; }
/* 同步提示 */
.sync-hint { margin: 0 0 12px; padding: 10px 14px; border-radius: 10px; font-size: 12px; background: #fff7e6; color: #d46b08; border-left: 3px solid #fa8c16; line-height: 1.6; }
/* 添加按钮 */
.add-member-card { background: #fff; border: 1.5px dashed #d9d9d9; border-radius: 12px; padding: 16px; display: flex; align-items: center; justify-content: center; gap: 6px; color: #999; cursor: pointer; font-size: 14px; }
.add-member-card .plus { font-size: 20px; font-weight: 300; }
.add-member-card--self { background: #e6f4ff; border-color: #1677ff; color: #1677ff; font-weight: 600; }
/* 空状态 */
.member-empty { text-align: center; padding: 50px 20px 30px; }
.member-empty__icon { font-size: 52px; margin-bottom: 12px; opacity: 0.35; }
.member-empty__text { font-size: 14px; color: #999; }
.member-empty__sub { font-size: 12px; color: #bbb; margin-top: 4px; }
/* 底部双按钮 */
.bottom-actions { display: flex; gap: 10px; margin-top: 4px; }
.bottom-actions .add-member-card { flex: 1; }
/* 同步弹窗 */
.sync-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.5); z-index: 1000; display: none; align-items: center; justify-content: center; }
.sync-overlay--show { display: flex; }
.sync-dialog { width: 280px; background: #fff; border-radius: 16px; padding: 32px 24px 24px; text-align: center; box-shadow: 0 12px 40px rgba(0,0,0,0.25); animation: syncDialogIn 0.3s ease; }
@keyframes syncDialogIn { from { opacity: 0; transform: scale(0.85); } to { opacity: 1; transform: scale(1); } }
.sync-spinner { width: 48px; height: 48px; margin: 0 auto 16px; border: 4px solid #f0f0f0; border-top-color: #1677ff; border-radius: 50%; animation: syncSpin 0.8s linear infinite; }
@keyframes syncSpin { to { transform: rotate(360deg); } }
.sync-dialog__title { font-size: 16px; font-weight: 700; color: #1a1a1a; margin-bottom: 8px; }
.sync-dialog__desc { font-size: 13px; color: #999; margin-bottom: 16px; line-height: 1.5; }
.sync-progress { width: 100%; height: 6px; background: #f0f0f0; border-radius: 3px; overflow: hidden; margin-bottom: 8px; }
.sync-progress__bar { height: 100%; background: linear-gradient(90deg, #1677ff, #0aad50); border-radius: 3px; width: 0%; transition: width 0.3s ease; }
.sync-progress__text { font-size: 11px; color: #bbb; }
/* 删除确认弹窗 */
.delete-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.5); z-index: 1000; display: none; align-items: center; justify-content: center; }
.delete-overlay--show { display: flex; }
.delete-dialog { width: 280px; background: #fff; border-radius: 16px; padding: 28px 24px 20px; text-align: center; box-shadow: 0 12px 40px rgba(0,0,0,0.25); animation: deleteDialogIn 0.25s ease; }
@keyframes deleteDialogIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }
.delete-dialog__icon { font-size: 40px; margin-bottom: 12px; }
.delete-dialog__text { font-size: 15px; color: #333; margin-bottom: 20px; line-height: 1.5; }
.delete-dialog__actions { display: flex; gap: 12px; }
.delete-dialog__btn { flex: 1; height: 40px; border: none; border-radius: 10px; font-size: 15px; font-weight: 600; cursor: pointer; }
.delete-dialog__btn:active { opacity: 0.8; }
.delete-dialog__btn--cancel { background: #f5f5f5; color: #666; }
.delete-dialog__btn--confirm { background: #ff4d4f; color: #fff; }
/* Toast */
.toast { position: absolute; top: 60px; left: 50%; transform: translateX(-50%) translateY(-10px); background: rgba(17,24,39,0.88); color: #fff; font-size: 14px; padding: 10px 24px; border-radius: 999px; white-space: nowrap; opacity: 0; transition: all .2s ease; pointer-events: none; z-index: 999; }
.toast--show { opacity: 1; transform: translateX(-50%) translateY(0); }
.bottom-safe { height: 16px; }
</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-placeholder"></div>
</div>
<div class="scroll-content">
<!-- Toast -->
<div class="toast" id="toast"></div>
<!-- 设备信息 -->
<div class="device-info">
<div class="device-info__icon">⚖️</div>
<div class="device-info__detail">
<div class="device-info__name" id="devName">家庭蓝牙体脂秤 S1</div>
<div class="device-info__sn" id="devMeta">型号:BS-A100<br>设备编码:BL2024A00158</div>
</div>
<span class="device-info__status device-info__status--online" id="devStatus">已连接</span>
</div>
<!-- S1 成员列表 -->
<div id="membersS1" style="display:none;">
<div class="section-header">
<span class="section-title" id="sectionTitleS1">已录入成员</span>
<button class="sync-btn" id="syncBtnS1" onclick="syncMembers()">同步成员至设备</button>
</div>
<div class="sync-hint" id="syncHintS1">当前成员信息未同步至设备,请在连接设备的状态下,点击同步按钮完成信息同步</div>
<div class="member-list">
<div class="member-card">
<div class="member-avatar member-avatar--male"></div>
<div class="member-info">
<div class="member-top">
<span class="member-name">张建国</span>
<span class="member-tag--self">本人</span>
<span class="member-sync member-sync--done">已同步</span>
</div>
<div class="member-detail">男 · 45岁 · 175cm</div>
<div class="member-actions">
<button class="action-btn action-btn--delete" onclick="confirmDelete(this)">删除</button>
</div>
</div>
</div>
<div class="member-card">
<div class="member-avatar member-avatar--female"></div>
<div class="member-info">
<div class="member-top">
<span class="member-name">李秀英</span>
<span class="member-tag--type">员工</span>
<span class="member-sync member-sync--done">已同步</span>
</div>
<div class="member-detail">女 · 43岁 · 162cm <span style="font-size:11px;color:#bbb;">(他人添加)</span></div>
<div class="member-actions">
<button class="action-btn action-btn--delete" onclick="confirmDelete(this)">删除</button>
</div>
</div>
</div>
<div class="member-card">
<div class="member-avatar member-avatar--child"></div>
<div class="member-info">
<div class="member-top">
<span class="member-name">张晓明</span>
<span class="member-tag--type">家庭成员</span>
<span class="member-sync member-sync--done">已同步</span>
</div>
<div class="member-detail">男 · 12岁 · 152cm</div>
<div class="member-actions">
<button class="action-btn action-btn--edit" onclick="showToast('编辑功能开发中')">编辑</button>
<button class="action-btn action-btn--delete" onclick="confirmDelete(this)">删除</button>
</div>
</div>
</div>
<div class="member-card">
<div class="member-avatar member-avatar--elder"></div>
<div class="member-info">
<div class="member-top">
<span class="member-name">王淑芬</span>
<span class="member-tag--type">家庭成员</span>
<span class="member-sync member-sync--pending">未同步</span>
</div>
<div class="member-detail">女 · 68岁 · 158cm</div>
<div class="member-actions">
<button class="action-btn action-btn--edit" onclick="showToast('编辑功能开发中')">编辑</button>
<button class="action-btn action-btn--delete" onclick="confirmDelete(this)">删除</button>
</div>
</div>
</div>
<div class="add-member-card" onclick="showToast('添加功能开发中')">
<span class="plus"></span> 添加新用户
</div>
</div>
</div>
<!-- B2 成员列表 -->
<div id="membersB2" style="display:none;">
<div class="section-header">
<span class="section-title" id="sectionTitleB2">已录入成员</span>
<button class="sync-btn sync-btn--disabled" id="syncBtnB2" onclick="syncMembers()">同步成员至设备</button>
</div>
<div class="sync-hint" id="syncHintB2">当前成员信息未同步至设备,请在连接设备的状态下,点击同步按钮完成信息同步</div>
<div class="member-empty" id="memberEmptyB2">
<div class="member-empty__icon">👥</div>
<div class="member-empty__text">暂无用户</div>
<div class="member-empty__sub">请添加用户以使用设备测量</div>
</div>
<div class="member-list" id="memberListB2">
<div class="bottom-actions" id="bottomActionsB2">
<div class="add-member-card add-member-card--self" id="addSelfBtnB2" onclick="addSelfMember()">👤 一键添加本人</div>
<div class="add-member-card" onclick="showToast('添加功能开发中')"><span class="plus"></span> 添加新用户</div>
</div>
</div>
</div>
<div class="bottom-safe"></div>
</div>
<!-- 同步弹窗 -->
<div class="sync-overlay" id="syncOverlay">
<div class="sync-dialog">
<div class="sync-spinner"></div>
<div class="sync-dialog__title">同步成员至设备</div>
<div class="sync-dialog__desc" id="syncProgressText">正在同步信息,请勿离开...</div>
<div class="sync-progress"><div class="sync-progress__bar" id="syncProgressBar"></div></div>
<div class="sync-progress__text" id="syncPercent">0%</div>
</div>
</div>
<!-- 删除确认弹窗 -->
<div class="delete-overlay" id="deleteOverlay">
<div class="delete-dialog">
<div class="delete-dialog__icon">⚠️</div>
<div class="delete-dialog__text" id="deleteDialogText">是否确认删除该成员?</div>
<div class="delete-dialog__actions">
<button class="delete-dialog__btn delete-dialog__btn--cancel" onclick="closeDeleteDialog()">取消</button>
<button class="delete-dialog__btn delete-dialog__btn--confirm" id="deleteConfirmBtn">确定</button>
</div>
</div>
</div>
</div>
<script>
function showToast(msg) {
var t = document.getElementById('toast');
t.textContent = msg;
t.classList.add('toast--show');
clearTimeout(t._timer);
t._timer = setTimeout(function() { t.classList.remove('toast--show'); }, 1800);
}
/* 根据 URL 参数初始化设备信息 */
(function() {
var params = new URLSearchParams(location.search);
var device = params.get('device');
var data = {
s1: { name:'家庭蓝牙体脂秤 S1', model:'BS-A100', code:'BL2024A00158', status:'online', statusText:'已连接', membersDiv:'membersS1', memberCount:4, sectionTitleId:'sectionTitleS1', syncBtnId:'syncBtnS1' },
b2: { name:'办公蓝牙体重秤 B2', model:'BW-B200', code:'BL2024B00321', status:'offline', statusText:'未连接', membersDiv:'membersB2', memberCount:0, sectionTitleId:'sectionTitleB2', syncBtnId:'syncBtnB2' }
}[device] || { name:'家庭蓝牙体脂秤 S1', model:'BS-A100', code:'BL2024A00158', status:'online', statusText:'已连接', membersDiv:'membersS1', memberCount:4, sectionTitleId:'sectionTitleS1', syncBtnId:'syncBtnS1' };
document.getElementById('devName').textContent = data.name;
document.getElementById('devMeta').innerHTML = '型号:' + data.model + '<br>设备编码:' + data.code;
var statusEl = document.getElementById('devStatus');
statusEl.textContent = data.statusText;
statusEl.className = 'device-info__status device-info__status--' + data.status;
document.getElementById(data.membersDiv).style.display = '';
document.getElementById(data.sectionTitleId).textContent = '已录入成员(' + data.memberCount + '/10)';
var syncBtn = document.getElementById(data.syncBtnId);
if (data.status === 'offline') { syncBtn.classList.add('sync-btn--disabled'); syncBtn.disabled = true; }
if (data.memberCount === 0) { syncBtn.style.display = 'none'; var hintEl = document.getElementById('syncHint' + device.toUpperCase()); if (hintEl) hintEl.style.display = 'none'; }
})();
function addSelfMember() {
var params = new URLSearchParams(location.search);
var device = (params.get('device') || 'b2').toUpperCase();
var emptyEl = document.getElementById('memberEmpty' + device);
if (emptyEl) emptyEl.style.display = 'none';
var card = document.createElement('div');
card.className = 'member-card';
card.innerHTML = '<div class="member-avatar member-avatar--male">张</div><div class="member-info"><div class="member-top"><span class="member-name">张建国</span><span class="member-tag--self">本人</span><span class="member-sync member-sync--pending">未同步</span></div><div class="member-detail">男 · 45岁 · 175cm</div><div class="member-actions"><button class="action-btn action-btn--edit" onclick="showToast(\'编辑功能开发中\')">编辑</button><button class="action-btn action-btn--delete" onclick="showToast(\'删除功能开发中\')">删除</button></div></div>';
var list = document.getElementById('memberList' + device);
var bottom = document.getElementById('bottomActions' + device);
if (list && bottom) list.insertBefore(card, bottom);
var selfBtn = document.getElementById('addSelfBtn' + device);
if (selfBtn) selfBtn.style.display = 'none';
var syncBtn = document.getElementById('syncBtn' + device);
var hintEl = document.getElementById('syncHint' + device);
if (syncBtn) syncBtn.style.display = '';
if (hintEl) hintEl.style.display = '';
var sectionTitle = document.getElementById('sectionTitle' + device);
if (sectionTitle) sectionTitle.textContent = '已录入成员(1/10)';
showToast('已添加本人');
}
var _deleteTarget = null;
function confirmDelete(btn) {
_deleteTarget = btn;
var card = btn.closest('.member-card');
var nameEl = card.querySelector('.member-name');
document.getElementById('deleteDialogText').textContent = '是否确认删除' + (nameEl ? nameEl.textContent : '该成员') + '';
document.getElementById('deleteOverlay').classList.add('delete-overlay--show');
document.getElementById('deleteConfirmBtn').onclick = executeDelete;
}
function closeDeleteDialog() {
document.getElementById('deleteOverlay').classList.remove('delete-overlay--show');
_deleteTarget = null;
}
function executeDelete() {
var target = _deleteTarget;
closeDeleteDialog();
if (!target) return;
var card = target.closest('.member-card');
if (card) {
card.classList.add('member-card--deleted');
var syncEl = card.querySelector('.member-sync');
if (syncEl) { syncEl.textContent = '已删除 · 未同步'; syncEl.className = 'member-sync member-sync--deleted'; }
}
showToast('成员已删除');
}
function syncMembers() {
var overlay = document.getElementById('syncOverlay');
var bar = document.getElementById('syncProgressBar');
var text = document.getElementById('syncProgressText');
var pct = document.getElementById('syncPercent');
overlay.classList.add('sync-overlay--show');
bar.style.width = '0%'; pct.textContent = '0%'; text.textContent = '正在同步信息,请勿离开...';
var progress = 0;
var timer = setInterval(function() {
progress += Math.random() * 25 + 10;
if (progress >= 100) { progress = 100; clearInterval(timer); bar.style.width = '100%'; pct.textContent = '100%'; text.textContent = '同步完成';
setTimeout(function() { overlay.classList.remove('sync-overlay--show'); showToast('成员信息同步成功!'); }, 600);
} else { bar.style.width = progress + '%'; pct.textContent = Math.floor(progress) + '%'; }
}, 500);
}
</script>
</body>
</html>
@@ -0,0 +1,196 @@
<!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; position: relative; }
.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; padding: 16px; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 空状态 */
.empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 100px 40px 0; text-align: center; }
.empty-state__icon { font-size: 64px; margin-bottom: 20px; opacity: 0.6; }
.empty-state__text { font-size: 14px; color: #999; margin-bottom: 24px; line-height: 1.6; }
.empty-state__btn { width: 200px; height: 44px; border-radius: 22px; border: none; background: linear-gradient(160deg, #73d13d, #389e0d); color: #fff; font-size: 15px; font-weight: 700; cursor: pointer; box-shadow: 0 2px 8px rgba(82,196,26,0.3); }
.empty-state__btn:active { opacity: 0.85; }
/* 设备列表区域 */
.device-list-area { display: none; }
.device-list-area.show { display: block; }
/* 分区标题 */
.device-section-title {
font-size: 15px; font-weight: 600; color: #1a1a1a;
margin-bottom: 12px; display: flex; align-items: center; justify-content: space-between;
}
.btn { height: 34px; border: none; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 4px; padding: 0 12px; }
.btn--outline { background: #fff; color: #1677ff; border: 1px solid #1677ff; }
.btn--outline:active { background: #e6f4ff; }
.btn--warning { background: #fff; color: #fa8c16; border: 1px solid #fa8c16; }
.btn--warning:active { background: #fffbe6; }
.btn--primary { background: #1677ff; color: #fff; }
.btn--primary:active { background: #0958d9; }
/* 设备列表 */
.device-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }
.device-item {
background: #fff; border-radius: 14px; padding: 16px;
box-shadow: 0 1px 4px rgba(0,0,0,0.04); position: relative;
}
.device-item__unpair {
position: absolute; top: 10px; right: 12px;
font-size: 12px; color: #999; border: none;
background: none; cursor: pointer; padding: 2px 4px;
}
.device-item__unpair:active { color: #ff4d4f; }
.device-item__header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.device-item__icon {
width: 44px; height: 44px; border-radius: 12px;
background: #e6f4ff; display: flex;
align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0;
}
.device-item__icon--offline { background: #f5f5f5; }
.device-item__info { flex: 1; }
.device-item__name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.device-item__model { font-size: 12px; color: #999; margin-top: 2px; line-height: 1.6; }
.device-item__status {
font-size: 11px; padding: 3px 10px; border-radius: 10px; font-weight: 600; white-space: nowrap; flex-shrink: 0;
}
.device-item__status--online { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
.device-item__status--offline { background: #f5f5f5; color: #999; border: 1px solid #e8e8e8; }
.device-item__actions { display: flex; gap: 10px; }
.device-item__actions .btn { flex: 1; }
/* 添加设备按钮 */
.device-add-btn {
width: 100%; height: 44px; border: 1px dashed #d9d9d9; border-radius: 12px;
background: #fafafa; color: #666; font-size: 14px;
font-weight: 500; cursor: pointer;
display: flex; align-items: center; justify-content: center; gap: 6px;
}
.device-add-btn:active { background: #f0f0f0; border-color: #bbb; }
.bottom-safe { height: 16px; }
</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-placeholder"></div>
</div>
<div class="scroll-content">
<!-- 未绑定空状态 -->
<div class="empty-state" id="emptyState">
<div class="empty-state__icon">⚖️</div>
<div class="empty-state__text">暂未绑定蓝牙称设备<br>请点击下方按钮进行绑定</div>
<button class="empty-state__btn" onclick="location.href='bluetooth-search-v2.html'">绑定</button>
</div>
<!-- 已绑定设备列表 -->
<div class="device-list-area" id="deviceListArea">
<div class="device-section-title">
<span>已配对设备</span>
<button class="btn btn--outline" id="btnUnpairAll" style="display:none;height:28px;font-size:11px;color:#ff4d4f;border-color:#ff4d4f;" onclick="unpairAll()">取消全部配对</button>
</div>
<div class="device-list">
<div class="device-item">
<button class="device-item__unpair" onclick="unpairDevice('s1')">取消配对</button>
<div class="device-item__header">
<div class="device-item__icon">⚖️</div>
<div class="device-item__info">
<div class="device-item__name">家庭蓝牙体脂秤 S1</div>
<div class="device-item__model">型号:BS-A100<br>设备编码:BL2024A00158</div>
</div>
<span class="device-item__status device-item__status--online">已连接</span>
</div>
<div class="device-item__actions">
<button class="btn btn--warning" onclick="location.href='bluetooth-wifi-v2.html'">📶 设备WIFI</button>
<button class="btn btn--outline" onclick="location.href='bluetooth-device-members-v2.html?device=s1'">👥 用户(4)</button>
<button class="btn btn--outline" onclick="alert('数据补传已启动')">📤 数据补传</button>
</div>
</div>
<div class="device-item">
<button class="device-item__unpair" onclick="unpairDevice('b2')">取消配对</button>
<div class="device-item__header">
<div class="device-item__icon device-item__icon--offline">⚖️</div>
<div class="device-item__info">
<div class="device-item__name">办公蓝牙体重秤 B2</div>
<div class="device-item__model">型号:BW-B200<br>设备编码:BL2024B00321</div>
</div>
<span class="device-item__status device-item__status--offline">未连接</span>
</div>
<div class="device-item__actions">
<button class="btn btn--primary" onclick="connectDevice()">📡 连接设备</button>
<button class="btn btn--outline" onclick="location.href='bluetooth-device-members-v2.html?device=b2'">👥 用户(0)</button>
</div>
</div>
</div>
<button class="device-add-btn" onclick="location.href='bluetooth-search-v2.html'"> 添加设备</button>
<div class="bottom-safe"></div>
</div>
</div>
</div>
<script>
if (location.hash === '#paired') {
document.getElementById('emptyState').style.display = 'none';
document.getElementById('deviceListArea').classList.add('show');
history.replaceState(null, '', location.pathname);
}
function unpairDevice(id) {
if (confirm('确定取消配对该设备?')) {
var items = document.querySelectorAll('.device-item');
items.forEach(function(item) {
if (item.querySelector('.device-item__unpair').getAttribute('onclick').indexOf(id) !== -1) {
item.remove();
}
});
if (document.querySelectorAll('.device-item').length === 0) {
document.getElementById('deviceListArea').classList.remove('show');
document.getElementById('emptyState').style.display = '';
}
}
}
function unpairAll() {
if (confirm('确定取消全部设备配对?')) {
document.getElementById('deviceListArea').classList.remove('show');
document.getElementById('emptyState').style.display = '';
}
}
function connectDevice() {
location.href = 'bluetooth-wifi-v2.html';
}
</script>
</body>
</html>
@@ -0,0 +1,136 @@
<!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; position: relative; }
.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; }
/* 搜索区域 */
.search-area { display: flex; flex-direction: column; align-items: center; padding: 60px 32px 0; text-align: center; }
.search-icon-wrap { position: relative; width: 90px; height: 90px; margin-bottom: 28px; }
.search-icon-inner { width: 90px; height: 90px; border-radius: 50%; background: #f0fff0; display: flex; align-items: center; justify-content: center; font-size: 42px; }
.search-ring { position: absolute; inset: -8px; border-radius: 50%; border: 2px solid #52c41a; opacity: 0; animation: searchPulse 1.5s ease-out infinite; }
.search-ring:nth-child(2) { animation-delay: 0.5s; }
.search-ring:nth-child(3) { animation-delay: 1s; }
@keyframes searchPulse {
0% { transform: scale(0.85); opacity: 0.6; }
100% { transform: scale(1.3); opacity: 0; }
}
.search-text { font-size: 16px; font-weight: 600; color: #1a1a1a; margin-bottom: 12px; }
.search-hint { font-size: 13px; color: #999; line-height: 1.6; }
.search-distance { margin-top: 40px; font-size: 12px; color: #bbb; }
/* 结果区域 */
.result-area { display: none; padding: 0 14px 20px; }
.result-area.show { display: block; }
.result-title { font-size: 14px; font-weight: 600; color: #1a1a1a; padding: 16px 0 12px; display: flex; align-items: center; gap: 6px; }
.result-list { display: flex; flex-direction: column; gap: 10px; }
.result-item { background: #fff; border-radius: 14px; padding: 16px; display: flex; align-items: center; gap: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.04); cursor: pointer; }
.result-item:active { background: #fafafa; }
.result-item__icon { width: 44px; height: 44px; border-radius: 12px; background: #f0fff0; display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0; }
.result-item__info { flex: 1; }
.result-item__name { font-size: 14px; font-weight: 600; color: #1a1a1a; }
.result-item__signal { font-size: 12px; color: #999; margin-top: 4px; }
.result-item__arrow { font-size: 16px; color: #ccc; }
.result-status { font-size: 11px; padding: 3px 10px; border-radius: 10px; font-weight: 600; flex-shrink: 0; }
.result-status--online { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
.result-status--offline { background: #f5f5f5; color: #999; border: 1px solid #e8e8e8; }
</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-placeholder"></div>
</div>
<div class="scroll-content">
<div class="search-area" id="searchArea">
<div class="search-icon-wrap" id="searchIconWrap">
<div class="search-ring"></div><div class="search-ring"></div><div class="search-ring"></div>
<div class="search-icon-inner">⚖️</div>
</div>
<div class="search-text" id="searchText">搜索设备中…</div>
<div class="search-hint">请确保手机蓝牙已开启<br>设备处于开启状态</div>
<div class="search-distance">📱 手机尽量靠近设备(2米以内)</div>
<div class="result-area" id="resultArea" style="margin-top:24px;">
<button id="btnReSearch" style="width:100%;margin-bottom:12px;background:#fff;border:1px solid #52c41a;color:#52c41a;border-radius:10px;padding:10px;font-size:13px;font-weight:600;cursor:pointer;" onclick="reSearch()">🔄 重新搜索</button>
<div class="result-title">🔍 发现的设备</div>
<div class="result-list">
<div class="result-item" onclick="location.href='bluetooth-scale-v2.html#paired'">
<div class="result-item__icon">⚖️</div>
<div class="result-item__info">
<div class="result-item__name">家庭蓝牙体脂秤 S1</div>
</div>
<span class="result-status result-status--online">已连接</span>
</div>
<div class="result-item" onclick="location.href='bluetooth-wifi-v2.html'">
<div class="result-item__icon">⚖️</div>
<div class="result-item__info">
<div class="result-item__name">办公蓝牙体重秤 B2</div>
</div>
<span class="result-status result-status--offline">未连接</span>
<span class="result-item__arrow"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
/* 搜索模拟:3秒后显示结果 */
setTimeout(function() {
document.getElementById('searchIconWrap').querySelectorAll('.search-ring').forEach(function(r) {
r.style.animation = 'none'; r.style.display = 'none';
});
document.getElementById('searchText').textContent = '搜索完成';
document.getElementById('resultArea').classList.add('show');
}, 3000);
function reSearch() {
document.getElementById('resultArea').classList.remove('show');
document.getElementById('searchIconWrap').querySelectorAll('.search-ring').forEach(function(r) {
r.style.animation = ''; r.style.display = '';
});
document.getElementById('searchText').textContent = '搜索设备中…';
setTimeout(function() {
document.getElementById('searchIconWrap').querySelectorAll('.search-ring').forEach(function(r) {
r.style.animation = 'none'; r.style.display = 'none';
});
document.getElementById('searchText').textContent = '搜索完成';
document.getElementById('resultArea').classList.add('show');
}, 3000);
}
</script>
</body>
</html>
@@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WiFi连接 - 蓝牙称 | 健康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; position: relative; }
.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-skip { font-size: 13px; color: #999; cursor: pointer; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f5f7fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 搜索中 */
.search-area { display: flex; flex-direction: column; align-items: center; padding: 48px 32px 0; text-align: center; }
.search-icon { font-size: 48px; margin-bottom: 16px; }
.search-text { font-size: 15px; font-weight: 600; color: #1a1a1a; margin-bottom: 6px; }
.search-hint { font-size: 13px; color: #999; }
/* WiFi 列表 */
.wifi-area { display: none; padding: 0 14px 20px; }
.wifi-area.show { display: block; }
.wifi-title { font-size: 14px; font-weight: 600; color: #1a1a1a; padding: 16px 0 10px; display: flex; align-items: center; justify-content: space-between; }
.wifi-refresh { font-size: 13px; color: #52c41a; cursor: pointer; text-decoration: none; font-weight: 600; }
.wifi-list { display: flex; flex-direction: column; gap: 8px; }
.wifi-item { background: #fff; border-radius: 12px; padding: 14px 16px; display: flex; align-items: center; gap: 12px; cursor: pointer; box-shadow: 0 1px 4px rgba(0,0,0,0.04); }
.wifi-item:active { background: #fafafa; }
.wifi-icon { font-size: 20px; flex-shrink: 0; }
.wifi-info { flex: 1; }
.wifi-name { font-size: 14px; font-weight: 500; color: #1a1a1a; }
.wifi-secure { font-size: 11px; color: #999; margin-top: 2px; }
.wifi-check { font-size: 14px; color: #52c41a; font-weight: 700; }
.wifi-lock { font-size: 12px; color: #999; }
.wifi-item--connected { border: 1px solid #b7eb8f; background: #fcfff5; }
</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">WiFi 连接</div>
<a class="nav-skip" id="skipBtn" href="bluetooth-scale-v2.html#paired">跳过</a>
</div>
<div class="scroll-content">
<div class="search-area" id="searchArea">
<div class="search-icon">📡</div>
<div class="search-text">正在搜索附近 WiFi…</div>
<div class="search-hint">请稍候</div>
</div>
<div class="wifi-area" id="wifiArea">
<div class="wifi-title">
<span>附近的 WiFi 网络</span>
<a class="wifi-refresh" href="javascript:refreshWifi()">🔄 刷新</a>
</div>
<div class="wifi-list">
<div class="wifi-item wifi-item--connected" onclick="connectWifi('Office-5G')">
<span class="wifi-icon">📶</span>
<div class="wifi-info">
<div class="wifi-name">Office-5G</div>
<div class="wifi-secure">WPA2 安全</div>
</div>
<span class="wifi-check"></span>
</div>
<div class="wifi-item" onclick="connectWifi('Health-Net')">
<span class="wifi-icon">📶</span>
<div class="wifi-info">
<div class="wifi-name">Health-Net</div>
<div class="wifi-secure">WPA2 安全</div>
</div>
<span class="wifi-lock">🔒</span>
</div>
<div class="wifi-item" onclick="connectWifi('Canteen-WiFi')">
<span class="wifi-icon">📶</span>
<div class="wifi-info">
<div class="wifi-name">Canteen-WiFi</div>
<div class="wifi-secure">开放网络</div>
</div>
</div>
<div class="wifi-item" onclick="connectWifi('Guest-2.4G')">
<span class="wifi-icon">📶</span>
<div class="wifi-info">
<div class="wifi-name">Guest-2.4G</div>
<div class="wifi-secure">开放网络</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
/* 1.5秒后显示WiFi列表 */
setTimeout(function() {
document.getElementById('searchArea').style.display = 'none';
document.getElementById('wifiArea').classList.add('show');
}, 1500);
function refreshWifi() {
document.getElementById('wifiArea').classList.remove('show');
document.getElementById('searchArea').style.display = '';
setTimeout(function() {
document.getElementById('searchArea').style.display = 'none';
document.getElementById('wifiArea').classList.add('show');
}, 1500);
}
function connectWifi(name) {
setTimeout(function() {
location.href = 'bluetooth-scale-v2.html#paired';
}, 500);
}
</script>
</body>
</html>
@@ -15,12 +15,13 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.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-title { flex: 1; display: flex; align-items: center; justify-content: center; gap: 4px; font-size: 17px; font-weight: 600; color: #1a1a1a; }
.nav-placeholder { width: 28px; height: 28px; }
.nav-more { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative; flex-shrink: 0; }
.nav-more__dots { display: flex; flex-direction: column; gap: 3px; align-items: center; }
.nav-more__dots span { width: 4px; height: 4px; border-radius: 50%; background: #333; }
.type-menu { display: none; position: absolute; top: 32px; right: 0; background: #fff; border-radius: 12px; box-shadow: 0 6px 24px rgba(0,0,0,0.12); z-index: 20; min-width: 160px; overflow: hidden; }
.type-menu { display: none; position: absolute; top: 28px; right: 0; background: #fff; border-radius: 12px; box-shadow: 0 6px 24px rgba(0,0,0,0.12); z-index: 20; min-width: 160px; 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; border-bottom: 1px solid #f5f5f5; }
.type-menu__item:last-child { border-bottom: none; }
@@ -57,8 +58,9 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.goal-data__row + .goal-data__row { border-top: 1px dashed #e8e8e8; }
.goal-data__label { width: 48px; font-size: 12px; color: #999; flex-shrink: 0; }
.goal-data__init { flex: 1; text-align: center; font-size: 15px; font-weight: 700; color: #1a1a1a; }
.goal-data__current { flex: 1; text-align: center; font-size: 15px; font-weight: 700; color: #36cfc9; }
.goal-data__arrow { width: 28px; text-align: center; font-size: 16px; color: #ccc; flex-shrink: 0; }
.goal-data__target { flex: 1; text-align: center; font-size: 15px; font-weight: 700; color: #36cfc9; }
.goal-data__target { flex: 1; text-align: center; font-size: 15px; font-weight: 700; color: #1a1a1a; }
.goal-data__unit { font-size: 10px; font-weight: 400; color: #999; margin-left: 2px; }
.goal-data__header { display: flex; align-items: center; margin-bottom: 10px; }
.goal-data__header-label { flex: 1; text-align: center; font-size: 11px; font-weight: 700; color: #999; }
@@ -81,6 +83,84 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.state-tab { padding: 4px 10px; border-radius: 10px; font-size: 11px; font-weight: 600; cursor: pointer; background: #f0f0f0; color: #999; border: none; }
.state-tab.active { background: #36cfc9; color: #fff; }
/* ===== 变化趋势卡片 ===== */
.record-card { background: #fff; border-radius: 16px; margin: 10px 12px 0; box-shadow: 0 4px 14px rgba(0,0,0,0.04); padding: 0 0 0 0; }
.record-card__header { display: flex; align-items: center; justify-content: space-between; padding: 14px 14px 0; }
.record-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.record-tabs { display: flex; border-bottom: 1px solid #f0f0f0; margin-top: 10px; }
.record-tab { flex: 1; text-align: center; padding: 10px 0 8px; font-size: 14px; font-weight: 600; color: #bbb; cursor: pointer; position: relative; }
.record-tab.active { color: #36cfc9; }
.record-tab.active::after { content: ''; position: absolute; bottom: -1px; left: 50%; transform: translateX(-50%); width: 40px; height: 3px; background: #36cfc9; border-radius: 2px; }
.record-body { padding: 12px 14px 16px; }
.stat-row { display: flex; gap: 8px; margin-bottom: 14px; }
.stat-item { flex: 1; background: #f7f8fa; border-radius: 12px; padding: 10px 8px; text-align: center; }
.stat-item__label { font-size: 11px; color: #999; margin-bottom: 4px; }
.stat-item__val { font-size: 16px; font-weight: 800; color: #1a1a1a; line-height: 1.1; }
.stat-item__unit { font-size: 10px; font-weight: 500; color: #666; margin-left: 1px; }
.stat-item--change .stat-item__val { color: #36cfc9; }
.chart-area { position: relative; width: 100%; height: 180px; margin-top: 4px; overflow: hidden; }
.chart-area svg { width: 100%; height: 100%; display: block; }
.chart-legend { display: flex; justify-content: center; gap: 8px; margin-top: 10px; flex-wrap: nowrap; }
.chart-legend__item { display: flex; align-items: center; gap: 3px; font-size: 10px; color: #666; white-space: nowrap; }
.chart-legend__line { width: 16px; height: 0; border-top: 1.5px dashed; flex-shrink: 0; }
.chart-legend__line--init { border-color: #ff6b81; }
.chart-legend__line--target { border-color: #36cfc9; }
/* ===== 饮食/运动总结卡片 ===== */
.summary-stats { display: flex; gap: 8px; }
.summary-stat { flex: 1; background: #f7f8fa; border-radius: 10px; padding: 10px 8px; text-align: center; }
.summary-stat__val { font-size: 15px; font-weight: 800; color: #1a1a1a; line-height: 1; }
.summary-stat__val--good { color: #52c41a; }
.summary-stat__unit { font-size: 10px; font-weight: 400; color: #999; }
.summary-stat__label { font-size: 10px; color: #bbb; margin-top: 3px; }
/* ===== 排行榜卡片 ===== */
.rank-card { background: #fff; border-radius: 16px; margin: 10px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); cursor: pointer; }
.rank-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.rank-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.rank-card__arrow { color: #bbb; display: flex; align-items: center; gap: 2px; font-size: 11px; }
.rank-card__my { display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: linear-gradient(135deg, #e8fbfa, #f0fffe); border-radius: 10px; margin-bottom: 10px; border: 1px solid #b6f0eb; }
.rank-card__my-rank { width: 40px; height: 40px; border-radius: 50%; background: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; flex-shrink: 0; font-size: 18px; font-weight: 800; color: #36cfc9; line-height: 1; box-shadow: 0 2px 6px rgba(54,207,201,0.15); }
.rank-card__my-rank span { font-size: 8px; color: #999; font-weight: 500; margin-top: -1px; }
.rank-card__my-info { flex: 1; min-width: 0; }
.rank-card__my-name { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.rank-card__my-dept { font-size: 11px; color: #999; margin-top: 1px; }
.rank-card__my-score { font-size: 14px; font-weight: 700; color: #333; text-align: right; flex-shrink: 0; }
.rank-card__my-score em { font-style: normal; font-size: 10px; color: #999; font-weight: 400; }
.rank-card__top3 { display: flex; flex-direction: column; gap: 4px; }
.rank-card__top-item { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 8px; font-size: 12px; }
.rank-card__top-item:nth-child(1) { background: #fffbe6; }
.rank-card__top-item:nth-child(2) { background: #f7f8fa; }
.rank-card__top-item:nth-child(3) { background: #fdf4ed; }
.rank-card__top-num { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 11px; flex-shrink: 0; }
.rank-card__top-item:nth-child(1) .rank-card__top-num { background: #fadb14; color: #fff; }
.rank-card__top-item:nth-child(2) .rank-card__top-num { background: #d9d9d9; color: #fff; }
.rank-card__top-item:nth-child(3) .rank-card__top-num { background: #ffbb96; color: #fff; }
.rank-card__top-name { flex: 1; color: #333; font-weight: 500; }
.rank-card__top-val { color: #666; font-weight: 600; }
/* ===== 体重报告卡片 ===== */
.report-card { background: #fff; border-radius: 16px; margin: 10px 12px 0; padding: 16px 16px 14px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); cursor: pointer; }
.report-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.report-card__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.report-card__arrow { color: #bbb; display: flex; align-items: center; gap: 2px; font-size: 11px; }
.report-card__meta { display: flex; align-items: center; gap: 12px; font-size: 11px; color: #999; margin-bottom: 12px; }
.report-card__meta em { font-style: normal; font-weight: 600; color: #666; }
.report-card__weight-row { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.report-card__weight-item { flex: 1; text-align: center; }
.report-card__weight-item-val { font-size: 18px; font-weight: 800; color: #1a1a1a; line-height: 1; }
.report-card__weight-item-label { font-size: 10px; color: #999; margin-top: 3px; }
.report-card__weight-arrow { color: #bbb; font-size: 14px; flex-shrink: 0; margin-top: -6px; }
.report-card__stats-row { display: flex; gap: 10px; margin-bottom: 10px; }
.report-card__stat { flex: 1; background: #f7f8fa; border-radius: 10px; padding: 8px 8px; text-align: center; }
.report-card__stat-val { font-size: 15px; font-weight: 800; color: #1a1a1a; line-height: 1; }
.report-card__stat-val--good { color: #52c41a; }
.report-card__stat-label { font-size: 10px; color: #999; margin-top: 3px; }
.report-card__progress { margin-top: 2px; }
.report-card__progress-bar { width: 100%; height: 8px; background: #f0f0f0; border-radius: 4px; overflow: hidden; }
.report-card__progress-fill { height: 100%; background: linear-gradient(90deg, #36cfc9, #2ec4b6); border-radius: 4px; }
.report-card__progress-label { display: flex; justify-content: space-between; font-size: 10px; color: #999; margin-top: 4px; }
.hidden { display: none !important; }
.bottom-safe { height: 16px; flex-shrink: 0; }
</style>
@@ -101,14 +181,17 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<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" id="navTitle">目标详情</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="activity" onclick="switchView('activity', event)">活动目标</div>
<div class="type-menu__item" data-type="personal" onclick="switchView('personal', event)">个人目标</div>
<div class="nav-title">
<span id="navTitle">目标详情</span>
<div class="nav-more" id="navMore" onclick="toggleTypeMenu(event)">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg>
<div class="type-menu" id="typeMenu">
<div class="type-menu__item active" data-type="activity" onclick="switchView('activity', event)">活动目标</div>
<div class="type-menu__item" data-type="personal" onclick="switchView('personal', event)">个人目标</div>
</div>
</div>
</div>
<div class="nav-placeholder"></div>
</div>
<div class="type-mask" id="typeMask" onclick="closeTypeMenu()"></div>
@@ -123,6 +206,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<button class="state-tab" data-state="approved" onclick="switchState('approved')">已通过待签署</button>
<button class="state-tab" data-state="rejected" onclick="switchState('rejected')">已驳回</button>
<button class="state-tab" data-state="signed" onclick="switchState('signed')">已签署</button>
<button class="state-tab" data-state="ended" onclick="switchState('ended')">已结束</button>
</div>
<!-- 审核中状态 -->
@@ -135,19 +219,11 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
</div>
<!-- 活动信息 -->
<div class="card">
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>活动信息</span><a class="card__link" href="activity-detail.html" onclick="event.stopPropagation()">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div class="info-row">
<div class="info-item"><div class="info-item__label">活动名称</div><div class="info-item__value">2026年二季度体重管理活动</div></div>
</div>
<div class="info-row" style="margin-top:8px;">
<div class="info-item"><div class="info-item__label">起止日期</div><div class="info-item__value">2026-04-01 ~ 2026-09-30</div></div>
<div class="info-item"><div class="info-item__label">组织机构</div><div class="info-item__value">公司机关</div></div>
</div>
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>2026年二季度体重管理活动</span><a class="card__link" href="activity-detail.html">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div style="font-size:12px;color:#999;">2026-04-01 ~ 2026-09-30 · 公司机关</div>
</div>
<!-- 目标信息 -->
<div class="card">
<div class="card__title">目标信息</div>
<div class="goal-data">
@@ -193,14 +269,8 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
<div class="card">
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>活动信息</span><a class="card__link" href="activity-detail.html" onclick="event.stopPropagation()">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div class="info-row">
<div class="info-item"><div class="info-item__label">活动名称</div><div class="info-item__value">2026年二季度体重管理活动</div></div>
</div>
<div class="info-row" style="margin-top:8px;">
<div class="info-item"><div class="info-item__label">起止日期</div><div class="info-item__value">2026-04-01 ~ 2026-09-30</div></div>
<div class="info-item"><div class="info-item__label">组织机构</div><div class="info-item__value">公司机关</div></div>
</div>
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>2026年二季度体重管理活动</span><a class="card__link" href="activity-detail.html">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div style="font-size:12px;color:#999;">2026-04-01 ~ 2026-09-30 · 公司机关</div>
</div>
<div class="card">
@@ -247,14 +317,8 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
<div class="card">
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>活动信息</span><a class="card__link" href="activity-detail.html" onclick="event.stopPropagation()">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div class="info-row">
<div class="info-item"><div class="info-item__label">活动名称</div><div class="info-item__value">2026年二季度体重管理活动</div></div>
</div>
<div class="info-row" style="margin-top:8px;">
<div class="info-item"><div class="info-item__label">起止日期</div><div class="info-item__value">2026-04-01 ~ 2026-09-30</div></div>
<div class="info-item"><div class="info-item__label">组织机构</div><div class="info-item__value">公司机关</div></div>
</div>
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>2026年二季度体重管理活动</span><a class="card__link" href="activity-detail.html">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div style="font-size:12px;color:#999;">2026-04-01 ~ 2026-09-30 · 公司机关</div>
</div>
<div class="card">
@@ -294,7 +358,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<span style="display:flex;align-items:center;gap:10px;flex:1;min-width:0;">
<span class="status-banner__icon">🎉</span>
<div>
<div style="font-size:14px;font-weight:700;">目标已签署,活动进行中</div>
<div style="font-size:14px;font-weight:700;white-space:nowrap;">承诺书已签署,活动进行中</div>
<div style="font-size:11px;font-weight:400;opacity:0.7;margin-top:3px;">签署时间:2026-04-05 09:15</div>
</div>
</span>
@@ -302,14 +366,8 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
<div class="card">
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>活动信息</span><a class="card__link" href="activity-detail.html" onclick="event.stopPropagation()">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div class="info-row">
<div class="info-item"><div class="info-item__label">活动名称</div><div class="info-item__value">2026年二季度体重管理活动</div></div>
</div>
<div class="info-row" style="margin-top:8px;">
<div class="info-item"><div class="info-item__label">起止日期</div><div class="info-item__value">2026-04-01 ~ 2026-09-30</div></div>
<div class="info-item"><div class="info-item__label">组织机构</div><div class="info-item__value">公司机关</div></div>
</div>
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>2026年二季度体重管理活动</span><a class="card__link" href="activity-detail.html">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div style="font-size:12px;color:#999;">2026-04-01 ~ 2026-09-30 · 公司机关</div>
</div>
<div class="card">
@@ -319,35 +377,277 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<span class="goal-data__header-spacer"></span>
<span class="goal-data__header-label">初始</span>
<span class="goal-data__header-arrow"></span>
<span class="goal-data__header-label">当前</span>
<span class="goal-data__header-arrow"></span>
<span class="goal-data__header-label">目标</span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">体重</span>
<span class="goal-data__init">73.5<span class="goal-data__unit">kg</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">62.6<span class="goal-data__unit">kg</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">65.0<span class="goal-data__unit">kg</span></span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">体脂率</span>
<span class="goal-data__init">28.6<span class="goal-data__unit">%</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">25.8<span class="goal-data__unit">%</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">22.0<span class="goal-data__unit">%</span></span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">腰围</span>
<span class="goal-data__init">88<span class="goal-data__unit">cm</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">76.5<span class="goal-data__unit">cm</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">78<span class="goal-data__unit">cm</span></span>
</div>
</div>
</div>
</div>
<!-- 已结束状态 -->
<div id="stateEnded" class="hidden">
<div class="status-banner status-banner--signed" style="display:flex;align-items:center;gap:10px;">
<span style="display:flex;align-items:center;gap:10px;flex:1;min-width:0;">
<span class="status-banner__icon">🏁</span>
<div>
<div style="font-size:14px;font-weight:700;white-space:nowrap;">活动已结束,恭喜完成目标!</div>
</div>
</span>
<button class="sign-btn sign-btn--primary" onclick="location.href='my-promise.html'" style="width:auto;height:32px;border-radius:16px;font-size:12px;letter-spacing:1px;padding:0 14px;flex-shrink:0;">承诺书</button>
</div>
<div class="card">
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>2026年二季度体重管理活动</span><a class="card__link" href="activity-detail.html">活动详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a></div>
<div style="font-size:12px;color:#999;">2026-04-01 ~ 2026-09-30 · 公司机关</div>
</div>
<div class="card">
<div class="card__title">目标信息</div>
<div class="goal-data">
<div class="goal-data__header">
<span class="goal-data__header-spacer"></span>
<span class="goal-data__header-label">初始</span>
<span class="goal-data__header-arrow"></span>
<span class="goal-data__header-label">最终</span>
<span class="goal-data__header-arrow"></span>
<span class="goal-data__header-label">目标</span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">体重</span>
<span class="goal-data__init">73.5<span class="goal-data__unit">kg</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">62.6<span class="goal-data__unit">kg</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">65.0<span class="goal-data__unit">kg</span></span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">体脂率</span>
<span class="goal-data__init">28.6<span class="goal-data__unit">%</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">25.8<span class="goal-data__unit">%</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">22.0<span class="goal-data__unit">%</span></span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">腰围</span>
<span class="goal-data__init">88<span class="goal-data__unit">cm</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">76.5<span class="goal-data__unit">cm</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">78<span class="goal-data__unit">cm</span></span>
</div>
</div>
</div>
<div class="record-card">
<div class="record-card__header">
<div class="record-card__title">变化趋势</div>
</div>
<div class="record-tabs">
<div class="record-tab active" onclick="switchRecTab('weight')">体重变化</div>
<div class="record-tab" onclick="switchRecTab('fat')">体脂变化</div>
<div class="record-tab" onclick="switchRecTab('waist')">腰围变化</div>
</div>
<div class="record-body" id="rec-weight">
<div class="stat-row">
<div class="stat-item"><div class="stat-item__label">平均体重</div><div class="stat-item__val">68.2<span class="stat-item__unit">kg</span></div></div>
<div class="stat-item"><div class="stat-item__label">最大体重</div><div class="stat-item__val">73.5<span class="stat-item__unit">kg</span></div></div>
<div class="stat-item"><div class="stat-item__label">最小体重</div><div class="stat-item__val">62.6<span class="stat-item__unit">kg</span></div></div>
<div class="stat-item stat-item--change"><div class="stat-item__label">体重变化</div><div class="stat-item__val">-10.9<span class="stat-item__unit">kg</span></div></div>
</div>
<div class="chart-area">
<svg viewBox="0 0 340 180" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<defs><linearGradient id="fill1" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#36cfc9" stop-opacity="0.15"/><stop offset="100%" stop-color="#36cfc9" stop-opacity="0.08"/></linearGradient></defs>
<text x="2" y="18" font-size="11" fill="#999">75</text><text x="2" y="52" font-size="11" fill="#999">70</text><text x="2" y="86" font-size="11" fill="#999">65</text><text x="2" y="120" font-size="11" fill="#999">60</text><text x="2" y="154" font-size="11" fill="#999">55</text>
<line x1="22" y1="14" x2="26" y2="14" stroke="#e0e0e0"/><line x1="22" y1="48" x2="26" y2="48" stroke="#e0e0e0"/><line x1="22" y1="82" x2="26" y2="82" stroke="#e0e0e0"/><line x1="22" y1="116" x2="26" y2="116" stroke="#e0e0e0"/><line x1="22" y1="150" x2="26" y2="150" stroke="#e0e0e0"/>
<text x="60" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="100" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-15</text><text x="148" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="200" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="250" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="300" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<rect x="40" y="48" width="280" height="34" fill="url(#fill1)"/>
<line x1="40" y1="48" x2="320" y2="48" stroke="#36cfc9" stroke-dasharray="4 3" opacity="0.6"/><line x1="40" y1="82" x2="320" y2="82" stroke="#36cfc9" stroke-dasharray="4 3" opacity="0.6"/>
<line x1="40" y1="14" x2="320" y2="14" stroke="#ff6b81" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="18" font-size="10" fill="#ff6b81" text-anchor="end">73.5</text>
<line x1="40" y1="48" x2="320" y2="48" stroke="#36cfc9" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="52" font-size="10" fill="#36cfc9" text-anchor="end">68.0</text>
<polyline points="60,14 100,48 148,82 200,106 250,130 300,154" fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="60" cy="14" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="100" cy="48" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="148" cy="82" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="200" cy="106" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><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>
<div class="chart-legend">
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--init"></div><span>初始体重 73.50</span></div>
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--target"></div><span>目标体重 68.00</span></div>
</div>
</div>
<div class="record-body" id="rec-fat" style="display:none;">
<div class="stat-row">
<div class="stat-item"><div class="stat-item__label">平均体脂</div><div class="stat-item__val">24.8<span class="stat-item__unit">%</span></div></div>
<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>
<div class="stat-item"><div class="stat-item__label">最小体脂</div><div class="stat-item__val">21.2<span class="stat-item__unit">%</span></div></div>
<div class="stat-item stat-item--change"><div class="stat-item__label">体脂变化</div><div class="stat-item__val">-3.8<span class="stat-item__unit">%</span></div></div>
</div>
<div class="chart-area">
<svg viewBox="0 0 340 180" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<text x="2" y="18" font-size="11" fill="#999">30</text><text x="2" y="52" font-size="11" fill="#999">27</text><text x="2" y="86" font-size="11" fill="#999">24</text><text x="2" y="120" font-size="11" fill="#999">21</text><text x="2" y="154" font-size="11" fill="#999">18</text>
<line x1="22" y1="14" x2="26" y2="14" stroke="#e0e0e0"/><line x1="22" y1="48" x2="26" y2="48" stroke="#e0e0e0"/><line x1="22" y1="82" x2="26" y2="82" stroke="#e0e0e0"/><line x1="22" y1="116" x2="26" y2="116" stroke="#e0e0e0"/><line x1="22" y1="150" x2="26" y2="150" stroke="#e0e0e0"/>
<text x="60" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="148" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="200" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="250" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="300" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<line x1="40" y1="14" x2="320" y2="14" stroke="#ff6b81" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="18" font-size="10" fill="#ff6b81" text-anchor="end">28.6</text>
<line x1="40" y1="82" x2="320" y2="82" stroke="#36cfc9" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="86" font-size="10" fill="#36cfc9" text-anchor="end">22.0</text>
<polyline points="60,20 100,48 148,72 200,95 250,108 300,128" fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="60" cy="20" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="100" cy="48" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="148" cy="72" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="200" cy="95" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="250" cy="108" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="300" cy="128" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
</svg>
</div>
<div class="chart-legend">
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--init"></div><span>初始体脂 28.6%</span></div>
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--target"></div><span>目标体脂 22.0%</span></div>
</div>
</div>
<div class="record-body" id="rec-waist" style="display:none;">
<div class="stat-row">
<div class="stat-item"><div class="stat-item__label">平均腰围</div><div class="stat-item__val">81.2<span class="stat-item__unit">cm</span></div></div>
<div class="stat-item"><div class="stat-item__label">最大腰围</div><div class="stat-item__val">88.0<span class="stat-item__unit">cm</span></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>
<div class="stat-item stat-item--change"><div class="stat-item__label">腰围变化</div><div class="stat-item__val">-11.5<span class="stat-item__unit">cm</span></div></div>
</div>
<div class="chart-area">
<svg viewBox="0 0 340 180" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<text x="2" y="18" font-size="11" fill="#999">90</text><text x="2" y="52" font-size="11" fill="#999">85</text><text x="2" y="86" font-size="11" fill="#999">80</text><text x="2" y="120" font-size="11" fill="#999">75</text><text x="2" y="154" font-size="11" fill="#999">70</text>
<line x1="22" y1="14" x2="26" y2="14" stroke="#e0e0e0"/><line x1="22" y1="48" x2="26" y2="48" stroke="#e0e0e0"/><line x1="22" y1="82" x2="26" y2="82" stroke="#e0e0e0"/><line x1="22" y1="116" x2="26" y2="116" stroke="#e0e0e0"/><line x1="22" y1="150" x2="26" y2="150" stroke="#e0e0e0"/>
<text x="60" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="148" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="200" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="250" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="300" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<line x1="40" y1="14" x2="320" y2="14" stroke="#ff6b81" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="18" font-size="10" fill="#ff6b81" text-anchor="end">88</text>
<line x1="40" y1="82" x2="320" y2="82" stroke="#36cfc9" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="86" font-size="10" fill="#36cfc9" text-anchor="end">78</text>
<polyline points="50,14 100,34 160,58 210,96 260,116 300,136" fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="50" cy="14" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="100" cy="34" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="160" cy="58" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="210" cy="96" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="260" cy="116" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="300" cy="136" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
</svg>
</div>
<div class="chart-legend">
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--init"></div><span>初始腰围 88cm</span></div>
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--target"></div><span>目标腰围 78cm</span></div>
</div>
</div>
</div>
<!-- 排行榜 -->
<div class="rank-card" onclick="location.href='weight-ranking.html'">
<div class="rank-card__header">
<span class="rank-card__title">🏆 排行榜</span>
<span class="rank-card__arrow">查看全部 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></span>
</div>
<div class="rank-card__my">
<div class="rank-card__my-rank">12<span></span></div>
<div class="rank-card__my-info">
<div class="rank-card__my-name"></div>
<div class="rank-card__my-dept">技术研发部</div>
</div>
<div class="rank-card__my-score">86<em></em></div>
</div>
<div class="rank-card__top3">
<div class="rank-card__top-item">
<span class="rank-card__top-num">1</span><span class="rank-card__top-name">张明</span><span class="rank-card__top-val">98 分</span>
</div>
<div class="rank-card__top-item">
<span class="rank-card__top-num">2</span><span class="rank-card__top-name">李婷</span><span class="rank-card__top-val">95 分</span>
</div>
<div class="rank-card__top-item">
<span class="rank-card__top-num">3</span><span class="rank-card__top-name">王磊</span><span class="rank-card__top-val">92 分</span>
</div>
</div>
</div>
<!-- 体重报告 -->
<div class="report-card" onclick="location.href='weight-report.html'">
<div class="report-card__header">
<span class="report-card__title">📊 体重报告</span>
<span class="report-card__arrow">查看详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></span>
</div>
<div class="report-card__meta">
<span>截止至 <em>2026-08-26</em></span><span>|</span><span><em>62天</em></span>
</div>
<div class="report-card__weight-row">
<div class="report-card__weight-item"><div class="report-card__weight-item-val">65.2</div><div class="report-card__weight-item-label">初始体重 kg</div></div>
<span class="report-card__weight-arrow"></span>
<div class="report-card__weight-item"><div class="report-card__weight-item-val">62.6</div><div class="report-card__weight-item-label">当前体重 kg</div></div>
<span class="report-card__weight-arrow"></span>
<div class="report-card__weight-item"><div class="report-card__weight-item-val">60.0</div><div class="report-card__weight-item-label">目标体重 kg</div></div>
</div>
<div class="report-card__stats-row">
<div class="report-card__stat"><div class="report-card__stat-val report-card__stat-val--good">-2.6<span style="font-size:10px;font-weight:400;">kg</span></div><div class="report-card__stat-label">已减体重</div></div>
<div class="report-card__stat"><div class="report-card__stat-val">2.6<span style="font-size:10px;font-weight:400;">kg</span></div><div class="report-card__stat-label">距目标</div></div>
<div class="report-card__stat"><div class="report-card__stat-val">50<span style="font-size:10px;font-weight:400;">%</span></div><div class="report-card__stat-label">目标进度</div></div>
</div>
<div class="report-card__progress">
<div class="report-card__progress-bar"><div class="report-card__progress-fill" style="width:50%;"></div></div>
<div class="report-card__progress-label"><span>0%</span><span>目标 60.0kg</span></div>
</div>
</div>
<div class="card">
<div class="card__title">摄入消耗变化</div>
<div class="summary-stats">
<div class="summary-stat"><div class="summary-stat__val">1480<span class="summary-stat__unit">kcal</span></div><div class="summary-stat__label">日均饮食摄入</div></div>
<div class="summary-stat"><div class="summary-stat__val">820<span class="summary-stat__unit">kcal</span></div><div class="summary-stat__label">日均热量消耗</div></div>
<div class="summary-stat"><div class="summary-stat__val summary-stat__val--good">-660<span class="summary-stat__unit">kcal</span></div><div class="summary-stat__label">日均热量差值</div></div>
</div>
<div class="chart-area" style="height:200px;">
<svg viewBox="0 0 340 200" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<line x1="40" y1="100" x2="320" y2="100" stroke="#ccc" stroke-width="1.5"/>
<text x="36" y="104" font-size="11" fill="#999" text-anchor="end">0</text>
<text x="36" y="64" font-size="10" fill="#999" text-anchor="end">500</text>
<text x="36" y="24" font-size="10" fill="#999" text-anchor="end">1000</text>
<text x="36" y="144" font-size="10" fill="#999" text-anchor="end">500</text>
<text x="36" y="184" font-size="10" fill="#999" text-anchor="end">1000</text>
<line x1="40" y1="20" x2="340" y2="20" stroke="#f5f5f5"/><line x1="40" y1="60" x2="340" y2="60" stroke="#f5f5f5"/><line x1="40" y1="140" x2="340" y2="140" stroke="#f5f5f5"/><line x1="40" y1="180" x2="340" y2="180" stroke="#f5f5f5"/>
<text x="65" y="195" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="105" y="195" font-size="10" fill="#bbb" text-anchor="middle">02-15</text><text x="145" y="195" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="185" y="195" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="225" y="195" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="265" y="195" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<rect x="55" y="28" width="20" height="72" fill="#fa8c16" rx="2"/>
<rect x="55" y="100" width="20" height="40" fill="#52c41a" rx="2"/>
<rect x="95" y="33" width="20" height="67" fill="#fa8c16" rx="2"/>
<rect x="95" y="100" width="20" height="37" fill="#52c41a" rx="2"/>
<rect x="135" y="39" width="20" height="61" fill="#fa8c16" rx="2"/>
<rect x="135" y="100" width="20" height="35" fill="#52c41a" rx="2"/>
<rect x="175" y="32" width="20" height="68" fill="#fa8c16" rx="2"/>
<rect x="175" y="100" width="20" height="38" fill="#52c41a" rx="2"/>
<rect x="215" y="36" width="20" height="64" fill="#fa8c16" rx="2"/>
<rect x="215" y="100" width="20" height="36" fill="#52c41a" rx="2"/>
<rect x="255" y="38" width="20" height="62" fill="#fa8c16" rx="2"/>
<rect x="255" y="100" width="20" height="34" fill="#52c41a" rx="2"/>
</svg>
</div>
<div class="chart-legend">
<div class="chart-legend__item" style="gap:4px;">
<svg width="12" height="12"><rect width="12" height="12" fill="#fa8c16" rx="2"/></svg><span>热量摄入</span>
</div>
<div class="chart-legend__item" style="gap:4px;">
<svg width="12" height="12"><rect width="12" height="12" fill="#52c41a" rx="2"/></svg><span>热量消耗</span>
</div>
</div>
</div>
</div>
</div>
<!-- ===== 个人目标模式 ===== -->
<div id="viewPersonal" class="hidden">
<div class="card">
<div class="card__title">个人目标信息</div>
<div class="card__title" style="display:flex;align-items:center;justify-content:space-between;"><span>个人目标信息</span><span style="font-size:12px;color:#52c41a;font-weight:600;">进行中</span></div>
<div class="info-row">
<div class="info-item"><div class="info-item__label">目标名称</div><div class="info-item__value">2026年二季度个人减脂</div></div>
</div>
@@ -364,31 +664,190 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<span class="goal-data__header-spacer"></span>
<span class="goal-data__header-label">初始</span>
<span class="goal-data__header-arrow"></span>
<span class="goal-data__header-label">当前</span>
<span class="goal-data__header-arrow"></span>
<span class="goal-data__header-label">目标</span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">体重</span>
<span class="goal-data__init">73.5<span class="goal-data__unit">kg</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">62.6<span class="goal-data__unit">kg</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">62.0<span class="goal-data__unit">kg</span></span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">体脂率</span>
<span class="goal-data__init">28.6<span class="goal-data__unit">%</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">25.8<span class="goal-data__unit">%</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">20.0<span class="goal-data__unit">%</span></span>
</div>
<div class="goal-data__row">
<span class="goal-data__label">腰围</span>
<span class="goal-data__init">88<span class="goal-data__unit">cm</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__current">76.5<span class="goal-data__unit">cm</span></span>
<span class="goal-data__arrow"></span>
<span class="goal-data__target">75<span class="goal-data__unit">cm</span></span>
</div>
</div>
</div>
</div>
<div class="sign-bar">
<div class="record-card">
<div class="record-card__header">
<div class="record-card__title">变化趋势</div>
</div>
<div class="record-tabs">
<div class="record-tab active" onclick="switchRecTabP('weight')">体重变化</div>
<div class="record-tab" onclick="switchRecTabP('fat')">体脂变化</div>
<div class="record-tab" onclick="switchRecTabP('waist')">腰围变化</div>
</div>
<div class="record-body" id="prec-weight">
<div class="stat-row">
<div class="stat-item"><div class="stat-item__label">平均体重</div><div class="stat-item__val">68.2<span class="stat-item__unit">kg</span></div></div>
<div class="stat-item"><div class="stat-item__label">最大体重</div><div class="stat-item__val">73.5<span class="stat-item__unit">kg</span></div></div>
<div class="stat-item"><div class="stat-item__label">最小体重</div><div class="stat-item__val">62.6<span class="stat-item__unit">kg</span></div></div>
<div class="stat-item stat-item--change"><div class="stat-item__label">体重变化</div><div class="stat-item__val">-10.9<span class="stat-item__unit">kg</span></div></div>
</div>
<div class="chart-area">
<svg viewBox="0 0 340 180" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<defs><linearGradient id="fill2" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#36cfc9" stop-opacity="0.15"/><stop offset="100%" stop-color="#36cfc9" stop-opacity="0.08"/></linearGradient></defs>
<text x="2" y="18" font-size="11" fill="#999">75</text><text x="2" y="52" font-size="11" fill="#999">70</text><text x="2" y="86" font-size="11" fill="#999">65</text><text x="2" y="120" font-size="11" fill="#999">60</text><text x="2" y="154" font-size="11" fill="#999">55</text>
<line x1="22" y1="14" x2="26" y2="14" stroke="#e0e0e0"/><line x1="22" y1="48" x2="26" y2="48" stroke="#e0e0e0"/><line x1="22" y1="82" x2="26" y2="82" stroke="#e0e0e0"/><line x1="22" y1="116" x2="26" y2="116" stroke="#e0e0e0"/><line x1="22" y1="150" x2="26" y2="150" stroke="#e0e0e0"/>
<text x="60" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="100" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-15</text><text x="148" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="200" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="250" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="300" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<rect x="40" y="48" width="280" height="34" fill="url(#fill2)"/>
<line x1="40" y1="48" x2="320" y2="48" stroke="#36cfc9" stroke-dasharray="4 3" opacity="0.6"/><line x1="40" y1="82" x2="320" y2="82" stroke="#36cfc9" stroke-dasharray="4 3" opacity="0.6"/>
<line x1="40" y1="14" x2="320" y2="14" stroke="#ff6b81" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="18" font-size="10" fill="#ff6b81" text-anchor="end">73.5</text>
<line x1="40" y1="48" x2="320" y2="48" stroke="#36cfc9" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="52" font-size="10" fill="#36cfc9" text-anchor="end">68.0</text>
<polyline points="60,14 100,48 148,82 200,106 250,130 300,154" fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="60" cy="14" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="100" cy="48" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="148" cy="82" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="200" cy="106" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><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>
<div class="chart-legend">
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--init"></div><span>初始体重 73.50</span></div>
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--target"></div><span>目标体重 68.00</span></div>
</div>
</div>
<div class="record-body" id="prec-fat" style="display:none;">
<div class="stat-row">
<div class="stat-item"><div class="stat-item__label">平均体脂</div><div class="stat-item__val">24.8<span class="stat-item__unit">%</span></div></div>
<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>
<div class="stat-item"><div class="stat-item__label">最小体脂</div><div class="stat-item__val">21.2<span class="stat-item__unit">%</span></div></div>
<div class="stat-item stat-item--change"><div class="stat-item__label">体脂变化</div><div class="stat-item__val">-3.8<span class="stat-item__unit">%</span></div></div>
</div>
<div class="chart-area">
<svg viewBox="0 0 340 180" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<text x="2" y="18" font-size="11" fill="#999">30</text><text x="2" y="52" font-size="11" fill="#999">27</text><text x="2" y="86" font-size="11" fill="#999">24</text><text x="2" y="120" font-size="11" fill="#999">21</text><text x="2" y="154" font-size="11" fill="#999">18</text>
<line x1="22" y1="14" x2="26" y2="14" stroke="#e0e0e0"/><line x1="22" y1="48" x2="26" y2="48" stroke="#e0e0e0"/><line x1="22" y1="82" x2="26" y2="82" stroke="#e0e0e0"/><line x1="22" y1="116" x2="26" y2="116" stroke="#e0e0e0"/><line x1="22" y1="150" x2="26" y2="150" stroke="#e0e0e0"/>
<text x="60" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="148" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="200" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="250" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="300" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<line x1="40" y1="14" x2="320" y2="14" stroke="#ff6b81" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="18" font-size="10" fill="#ff6b81" text-anchor="end">28.6</text>
<line x1="40" y1="82" x2="320" y2="82" stroke="#36cfc9" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="86" font-size="10" fill="#36cfc9" text-anchor="end">22.0</text>
<polyline points="60,20 100,48 148,72 200,95 250,108 300,128" fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="60" cy="20" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="100" cy="48" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="148" cy="72" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="200" cy="95" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="250" cy="108" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="300" cy="128" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
</svg>
</div>
<div class="chart-legend">
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--init"></div><span>初始体脂 28.6%</span></div>
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--target"></div><span>目标体脂 22.0%</span></div>
</div>
</div>
<div class="record-body" id="prec-waist" style="display:none;">
<div class="stat-row">
<div class="stat-item"><div class="stat-item__label">平均腰围</div><div class="stat-item__val">81.2<span class="stat-item__unit">cm</span></div></div>
<div class="stat-item"><div class="stat-item__label">最大腰围</div><div class="stat-item__val">88.0<span class="stat-item__unit">cm</span></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>
<div class="stat-item stat-item--change"><div class="stat-item__label">腰围变化</div><div class="stat-item__val">-11.5<span class="stat-item__unit">cm</span></div></div>
</div>
<div class="chart-area">
<svg viewBox="0 0 340 180" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<text x="2" y="18" font-size="11" fill="#999">90</text><text x="2" y="52" font-size="11" fill="#999">85</text><text x="2" y="86" font-size="11" fill="#999">80</text><text x="2" y="120" font-size="11" fill="#999">75</text><text x="2" y="154" font-size="11" fill="#999">70</text>
<line x1="22" y1="14" x2="26" y2="14" stroke="#e0e0e0"/><line x1="22" y1="48" x2="26" y2="48" stroke="#e0e0e0"/><line x1="22" y1="82" x2="26" y2="82" stroke="#e0e0e0"/><line x1="22" y1="116" x2="26" y2="116" stroke="#e0e0e0"/><line x1="22" y1="150" x2="26" y2="150" stroke="#e0e0e0"/>
<text x="60" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="148" y="175" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="200" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="250" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="300" y="175" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<line x1="40" y1="14" x2="320" y2="14" stroke="#ff6b81" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="18" font-size="10" fill="#ff6b81" text-anchor="end">88</text>
<line x1="40" y1="82" x2="320" y2="82" stroke="#36cfc9" stroke-width="1.5" stroke-dasharray="5 4"/><text x="33" y="86" font-size="10" fill="#36cfc9" text-anchor="end">78</text>
<polyline points="50,14 100,34 160,58 210,96 260,116 300,136" fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="50" cy="14" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="100" cy="34" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="160" cy="58" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="210" cy="96" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="260" cy="116" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/><circle cx="300" cy="136" r="4" fill="#fff" stroke="#36cfc9" stroke-width="2.5"/>
</svg>
</div>
<div class="chart-legend">
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--init"></div><span>初始腰围 88cm</span></div>
<div class="chart-legend__item"><div class="chart-legend__line chart-legend__line--target"></div><span>目标腰围 78cm</span></div>
</div>
</div>
</div>
<!-- 体重报告 -->
<div class="report-card" onclick="location.href='weight-report.html'">
<div class="report-card__header">
<span class="report-card__title">📊 体重报告</span>
<span class="report-card__arrow">查看详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></span>
</div>
<div class="report-card__meta">
<span>截止至 <em>2026-08-26</em></span><span>|</span><span><em>62天</em></span>
</div>
<div class="report-card__weight-row">
<div class="report-card__weight-item"><div class="report-card__weight-item-val">73.5</div><div class="report-card__weight-item-label">初始体重 kg</div></div>
<span class="report-card__weight-arrow"></span>
<div class="report-card__weight-item"><div class="report-card__weight-item-val">62.6</div><div class="report-card__weight-item-label">当前体重 kg</div></div>
<span class="report-card__weight-arrow"></span>
<div class="report-card__weight-item"><div class="report-card__weight-item-val">62.0</div><div class="report-card__weight-item-label">目标体重 kg</div></div>
</div>
<div class="report-card__stats-row">
<div class="report-card__stat"><div class="report-card__stat-val report-card__stat-val--good">-10.9<span style="font-size:10px;font-weight:400;">kg</span></div><div class="report-card__stat-label">已减体重</div></div>
<div class="report-card__stat"><div class="report-card__stat-val">0.6<span style="font-size:10px;font-weight:400;">kg</span></div><div class="report-card__stat-label">距目标</div></div>
<div class="report-card__stat"><div class="report-card__stat-val">95<span style="font-size:10px;font-weight:400;">%</span></div><div class="report-card__stat-label">目标进度</div></div>
</div>
<div class="report-card__progress">
<div class="report-card__progress-bar"><div class="report-card__progress-fill" style="width:95%;"></div></div>
<div class="report-card__progress-label"><span>0%</span><span>目标 62.0kg</span></div>
</div>
</div>
<div class="card">
<div class="card__title">摄入消耗变化</div>
<div class="summary-stats">
<div class="summary-stat"><div class="summary-stat__val">1480<span class="summary-stat__unit">kcal</span></div><div class="summary-stat__label">日均饮食摄入</div></div>
<div class="summary-stat"><div class="summary-stat__val">820<span class="summary-stat__unit">kcal</span></div><div class="summary-stat__label">日均热量消耗</div></div>
<div class="summary-stat"><div class="summary-stat__val summary-stat__val--good">-660<span class="summary-stat__unit">kcal</span></div><div class="summary-stat__label">日均热量差值</div></div>
</div>
<div class="chart-area" style="height:200px;">
<svg viewBox="0 0 340 200" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<line x1="40" y1="100" x2="320" y2="100" stroke="#ccc" stroke-width="1.5"/>
<text x="36" y="104" font-size="11" fill="#999" text-anchor="end">0</text>
<text x="36" y="64" font-size="10" fill="#999" text-anchor="end">500</text>
<text x="36" y="24" font-size="10" fill="#999" text-anchor="end">1000</text>
<text x="36" y="144" font-size="10" fill="#999" text-anchor="end">500</text>
<text x="36" y="184" font-size="10" fill="#999" text-anchor="end">1000</text>
<line x1="40" y1="20" x2="340" y2="20" stroke="#f5f5f5"/><line x1="40" y1="60" x2="340" y2="60" stroke="#f5f5f5"/><line x1="40" y1="140" x2="340" y2="140" stroke="#f5f5f5"/><line x1="40" y1="180" x2="340" y2="180" stroke="#f5f5f5"/>
<text x="65" y="195" font-size="10" fill="#bbb" text-anchor="middle">02-12</text><text x="105" y="195" font-size="10" fill="#bbb" text-anchor="middle">02-15</text><text x="145" y="195" font-size="10" fill="#bbb" text-anchor="middle">02-22</text><text x="185" y="195" font-size="10" fill="#bbb" text-anchor="middle">03-01</text><text x="225" y="195" font-size="10" fill="#bbb" text-anchor="middle">03-13</text><text x="265" y="195" font-size="10" fill="#bbb" text-anchor="middle">03-18</text>
<rect x="55" y="28" width="20" height="72" fill="#fa8c16" rx="2"/>
<rect x="55" y="100" width="20" height="40" fill="#52c41a" rx="2"/>
<rect x="95" y="33" width="20" height="67" fill="#fa8c16" rx="2"/>
<rect x="95" y="100" width="20" height="37" fill="#52c41a" rx="2"/>
<rect x="135" y="39" width="20" height="61" fill="#fa8c16" rx="2"/>
<rect x="135" y="100" width="20" height="35" fill="#52c41a" rx="2"/>
<rect x="175" y="32" width="20" height="68" fill="#fa8c16" rx="2"/>
<rect x="175" y="100" width="20" height="38" fill="#52c41a" rx="2"/>
<rect x="215" y="36" width="20" height="64" fill="#fa8c16" rx="2"/>
<rect x="215" y="100" width="20" height="36" fill="#52c41a" rx="2"/>
<rect x="255" y="38" width="20" height="62" fill="#fa8c16" rx="2"/>
<rect x="255" y="100" width="20" height="34" fill="#52c41a" rx="2"/>
</svg>
</div>
<div class="chart-legend">
<div class="chart-legend__item" style="gap:4px;">
<svg width="12" height="12"><rect width="12" height="12" fill="#fa8c16" rx="2"/></svg><span>热量摄入</span>
</div>
<div class="chart-legend__item" style="gap:4px;">
<svg width="12" height="12"><rect width="12" height="12" fill="#52c41a" rx="2"/></svg><span>热量消耗</span>
</div>
</div>
</div>
</div>
<div class="sign-bar" id="signBar">
<button class="sign-btn sign-btn--primary" onclick="location.href='goal-management-v2.html?type=personal&name=2026年二季度个人减脂&startDate=2026-04-01&endDate=2026-08-26'">修改目标</button>
</div>
@@ -414,6 +873,7 @@ function initView() {
});
document.getElementById('viewActivity').classList.toggle('hidden', currentView !== 'activity');
document.getElementById('viewPersonal').classList.toggle('hidden', currentView === 'activity');
document.getElementById('signBar').style.display = currentView === 'activity' ? 'none' : '';
if (currentView === 'activity') {
switchState(currentState);
}
@@ -449,6 +909,27 @@ function switchState(state) {
document.getElementById('stateApproved').classList.toggle('hidden', state !== 'approved');
document.getElementById('stateRejected').classList.toggle('hidden', state !== 'rejected');
document.getElementById('stateSigned').classList.toggle('hidden', state !== 'signed');
document.getElementById('stateEnded').classList.toggle('hidden', state !== 'ended');
}
/* ===== 变化趋势 Tab 切换 ===== */
function switchRecTab(tab) {
var container = document.getElementById('stateEnded');
container.querySelectorAll('.record-tab').forEach(function(t) {
t.classList.toggle('active', t.textContent.indexOf(tab === 'weight' ? '体重' : tab === 'fat' ? '体脂' : '腰围') !== -1);
});
document.getElementById('rec-weight').style.display = tab === 'weight' ? '' : 'none';
document.getElementById('rec-fat').style.display = tab === 'fat' ? '' : 'none';
document.getElementById('rec-waist').style.display = tab === 'waist' ? '' : 'none';
}
function switchRecTabP(tab) {
var container = document.getElementById('viewPersonal');
container.querySelectorAll('.record-tab').forEach(function(t) {
t.classList.toggle('active', t.textContent.indexOf(tab === 'weight' ? '体重' : tab === 'fat' ? '体脂' : '腰围') !== -1);
});
document.getElementById('prec-weight').style.display = tab === 'weight' ? '' : 'none';
document.getElementById('prec-fat').style.display = tab === 'fat' ? '' : 'none';
document.getElementById('prec-waist').style.display = tab === 'waist' ? '' : 'none';
}
initView();
@@ -0,0 +1,274 @@
<!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; position: relative; }
.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; }
/* ===== Tab 切换 ===== */
.tab-bar { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.tab-item { flex: 1; text-align: center; padding: 12px 0 10px; font-size: 15px; font-weight: 600; color: #999; cursor: pointer; position: relative; transition: color .2s; }
.tab-item.active { color: #36cfc9; }
.tab-item.active::after { content: ''; position: absolute; bottom: -1px; left: 50%; transform: translateX(-50%); width: 32px; height: 3px; background: #36cfc9; border-radius: 2px; }
.scroll-content { flex: 1; overflow-y: auto; background: #f5f7fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* ===== 计划卡片 ===== */
.plan-card { background: #fff; border-radius: 16px; margin: 12px 12px 0; padding: 16px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); }
.plan-card__header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 10px; }
.plan-card__name { font-size: 15px; font-weight: 700; color: #1a1a1a; flex: 1; min-width: 0; line-height: 1.4; }
.plan-card__status { font-size: 11px; font-weight: 700; padding: 3px 10px; border-radius: 8px; white-space: nowrap; flex-shrink: 0; margin-left: 8px; }
.plan-card__status--review { background: #fffbe6; color: #faad14; }
.plan-card__status--approved { background: #e6f7ff; color: #1890ff; }
.plan-card__status--signed { background: #f6ffed; color: #52c41a; }
.plan-card__status--rejected { background: #fff1f0; color: #ff4d4f; }
.plan-card__status--active { background: #f6ffed; color: #52c41a; }
.plan-card__status--done { background: #f7f8fa; color: #999; }
.plan-card__meta { display: flex; gap: 12px; font-size: 12px; color: #999; margin-bottom: 8px; }
.plan-card__meta em { font-style: normal; font-weight: 600; color: #666; }
/* 目标数据行 */
.plan-card__data { background: #f7f8fa; border-radius: 10px; padding: 10px 12px; display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.plan-card__data-item { flex: 1; text-align: center; }
.plan-card__data-val { font-size: 14px; font-weight: 700; color: #1a1a1a; line-height: 1; }
.plan-card__data-unit { font-size: 10px; font-weight: 400; color: #999; }
.plan-card__data-label { font-size: 10px; color: #bbb; margin-top: 3px; }
.plan-card__data-arrow { color: #ccc; font-size: 14px; flex-shrink: 0; }
.plan-card__footer { display: flex; align-items: center; justify-content: space-between; }
.plan-card__date { font-size: 11px; color: #bbb; }
.plan-card__link { font-size: 12px; color: #36cfc9; font-weight: 600; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 2px; }
/* 空状态 */
.empty-state { display: none; text-align: center; padding: 60px 0; color: #ccc; }
.empty-state.show { display: block; }
.empty-state__icon { font-size: 48px; margin-bottom: 12px; }
.empty-state__text { font-size: 14px; }
.hidden { display: none !important; }
.bottom-safe { height: 16px; 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-placeholder"></div>
</div>
<!-- Tab 切换 -->
<div class="tab-bar">
<div class="tab-item active" data-tab="activity" onclick="switchTab('activity')">活动计划</div>
<div class="tab-item" data-tab="personal" onclick="switchTab('personal')">个人计划</div>
</div>
<div class="scroll-content">
<!-- ===== 活动计划列表 ===== -->
<div id="tabActivity">
<div class="plan-card">
<div class="plan-card__header">
<span class="plan-card__name">2026年二季度体重管理活动</span>
<span class="plan-card__status plan-card__status--active">进行中</span>
</div>
<div class="plan-card__meta">
<span>起止:<em>2026-04-01 ~ 2026-09-30</em></span>
<span>机构:<em>公司机关</em></span>
</div>
<div class="plan-card__data">
<div class="plan-card__data-item">
<div class="plan-card__data-val">73.5<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">初始体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">65.0<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">目标体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">62.6<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">当前体重</div>
</div>
</div>
<div class="plan-card__footer">
<span class="plan-card__date">签署时间:2026-04-05 09:15</span>
<a class="plan-card__link" href="goal-detail-v2.html?type=activity&state=signed">详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a>
</div>
</div>
<div class="plan-card">
<div class="plan-card__header">
<span class="plan-card__name">2026年一季度减重挑战赛</span>
<span class="plan-card__status plan-card__status--done">已结束</span>
</div>
<div class="plan-card__meta">
<span>起止:<em>2026-01-01 ~ 2026-03-31</em></span>
<span>机构:<em>第一采油厂</em></span>
</div>
<div class="plan-card__data">
<div class="plan-card__data-item">
<div class="plan-card__data-val">76.2<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">初始体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">70.0<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">目标体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">68.5<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">最终体重</div>
</div>
</div>
<div class="plan-card__footer">
<span class="plan-card__date">活动已结束 · 减重 7.7kg</span>
<a class="plan-card__link" href="goal-detail-v2.html?type=activity&state=signed">详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a>
</div>
</div>
<div class="plan-card">
<div class="plan-card__header">
<span class="plan-card__name">全员健康体重管理计划</span>
<span class="plan-card__status plan-card__status--done">已结束</span>
</div>
<div class="plan-card__meta">
<span>起止:<em>2025-10-01 ~ 2026-06-30</em></span>
<span>机构:<em>第一采气厂</em></span>
</div>
<div class="plan-card__data">
<div class="plan-card__data-item">
<div class="plan-card__data-val">78.0<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">初始体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">72.0<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">目标体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">73.5<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">最终体重</div>
</div>
</div>
<div class="plan-card__footer">
<span class="plan-card__date">活动已结束 · 减重 4.5kg</span>
<a class="plan-card__link" href="goal-detail-v2.html?type=activity&state=signed">详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a>
</div>
</div>
<div class="bottom-safe"></div>
</div>
<!-- ===== 个人计划列表 ===== -->
<div id="tabPersonal" class="hidden">
<div class="plan-card">
<div class="plan-card__header">
<span class="plan-card__name">2026年二季度个人减脂</span>
<span class="plan-card__status plan-card__status--active">进行中</span>
</div>
<div class="plan-card__meta">
<span>起止:<em>2026-04-01 ~ 2026-08-26</em></span>
</div>
<div class="plan-card__data">
<div class="plan-card__data-item">
<div class="plan-card__data-val">73.5<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">初始体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">62.0<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">目标体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">62.6<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">当前体重</div>
</div>
</div>
<div class="plan-card__footer">
<span class="plan-card__date">剩余 29 天</span>
<a class="plan-card__link" href="goal-detail-v2.html?type=personal">详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a>
</div>
</div>
<div class="plan-card">
<div class="plan-card__header">
<span class="plan-card__name">2025年四季度塑形计划</span>
<span class="plan-card__status plan-card__status--done">已完成</span>
</div>
<div class="plan-card__meta">
<span>起止:<em>2025-10-01 ~ 2025-12-31</em></span>
</div>
<div class="plan-card__data">
<div class="plan-card__data-item">
<div class="plan-card__data-val">75.0<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">初始体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">68.0<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">目标体重</div>
</div>
<span class="plan-card__data-arrow"></span>
<div class="plan-card__data-item">
<div class="plan-card__data-val">67.5<span class="plan-card__data-unit">kg</span></div>
<div class="plan-card__data-label">最终体重</div>
</div>
</div>
<div class="plan-card__footer">
<span class="plan-card__date">已完成 · 减重 7.5kg · 达成目标 ✅</span>
<a class="plan-card__link" href="goal-detail-v2.html?type=personal">详情 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></a>
</div>
</div>
<div class="bottom-safe"></div>
</div>
</div>
</div>
<script>
/* ===== Tab 切换 ===== */
function switchTab(tab) {
document.querySelectorAll('.tab-item').forEach(function(t) {
t.classList.toggle('active', t.dataset.tab === tab);
});
document.getElementById('tabActivity').classList.toggle('hidden', tab !== 'activity');
document.getElementById('tabPersonal').classList.toggle('hidden', tab !== 'personal');
}
</script>
</body>
</html>
@@ -42,7 +42,8 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
/* 卡片内分区 */
.data-section { background: #f7f8fa; border-radius: 12px; padding: 12px; margin-bottom: 10px; }
.data-section:last-child { margin-bottom: 0; }
.data-section__title { font-size: 12px; font-weight: 700; color: #999; margin-bottom: 10px; letter-spacing: .5px; }
.data-section__title { font-size: 12px; font-weight: 700; color: #999; margin-bottom: 10px; letter-spacing: .5px; display: flex; align-items: center; justify-content: space-between; }
.data-section__extra { font-size: 12px; font-weight: 500; color: #36cfc9; letter-spacing: 0; }
/* 选择器 */
.selector { display: flex; align-items: center; justify-content: space-between; height: 42px; padding: 0 14px; background: #f7f8fa; border-radius: 10px; font-size: 14px; color: #bbb; cursor: pointer; transition: border-color .2s; border: 1.5px solid transparent; }
@@ -73,7 +74,10 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.input-row__input::placeholder { color: #ccc; font-weight: 400; }
.input-row__input:focus { border-color: #36cfc9; }
.input-row__input:read-only { background: #f5f5f5; border-color: #eee; color: #999; }
.input-row__unit { font-size: 12px; color: #999; flex-shrink: 0; width: 24px; text-align: center; }
.input-row__unit { font-size: 12px; color: #999; flex-shrink: 0; width: 24px; text-align: center; }
.input-row__range { font-size: 11px; color: #36cfc9; margin-left: 64px; margin-top: -2px; }
.input-row__range span { font-weight: 600; }
.input-row__explain { font-size: 10px; color: #bbb; margin-left: 64px; margin-bottom: 8px; line-height: 1.5; }
.input-row__select { flex: 1; height: 38px; padding: 0 12px; background: #fff; border-radius: 8px; border: 1.5px solid #e8e8e8; font-size: 14px; font-weight: 600; color: #1a1a1a; outline: none; appearance: none; cursor: pointer; }
.input-row__select:focus { border-color: #36cfc9; }
.input-row__select:disabled { background: #f5f5f5; border-color: #eee; color: #999; cursor: default; }
@@ -234,30 +238,36 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
</div>
<!-- 目标数据 -->
<div class="data-section">
<div class="data-section__title">目标数据</div>
<div class="input-row" style="margin-bottom:8px;">
<span class="input-row__label">体重</span>
<input class="input-row__input" type="number" value="65.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">kg</span>
</div>
<div class="input-row" style="margin-bottom:8px;">
<span class="input-row__label">体脂率</span>
<input class="input-row__input" type="number" value="22.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">%</span>
</div>
<div class="input-row">
<span class="input-row__label">腰围</span>
<input class="input-row__input" type="number" value="78" placeholder="请输入" step="0.1">
<span class="input-row__unit">cm</span>
</div>
</div>
</div>
</div>
<!-- ====== 个人目标模式 ====== -->
<!-- 目标数据 -->
<div class="data-section">
<div class="data-section__title"><span>目标数据</span><span class="data-section__extra" id="actTargetDays">共183天完成</span></div>
<div class="input-row" style="margin-bottom:0;">
<span class="input-row__label">体重</span>
<input class="input-row__input" type="number" value="65.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">kg</span>
</div>
<div class="input-row__range">推荐范围 <span>54.7 ~ 70.7 kg</span></div>
<div class="input-row__explain">按您的身高 172cm 和健康 BMI 标准(18.5~23.9)换算:1.72²×18.5≈54.71.72²×23.9≈70.7。体重超标是高血压、糖尿病等慢性病的主要诱因;183 天周期充裕,每周减 0.5~1kg 即可安全达标。</div>
<div class="input-row" style="margin-bottom:0;">
<span class="input-row__label">体脂率</span>
<input class="input-row__input" type="number" value="22.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">%</span>
</div>
<div class="input-row__range">推荐范围 <span>15% ~ 20%</span></div>
<div class="input-row__explain">按成年男性健康标准,体脂率应控制在 15%~20%。您当前 28.6% 处于肥胖水平,是代谢紊乱和脂肪肝的重要诱因;183 天内配合有氧运动可有效降低 5~8 个百分点。</div>
<div class="input-row">
<span class="input-row__label">腰围</span>
<input class="input-row__input" type="number" value="78" placeholder="请输入" step="0.1">
<span class="input-row__unit">cm</span>
</div>
<div class="input-row__range">推荐范围 <span>65 ~ 85 cm</span></div>
<div class="input-row__explain">按您的身高 172cm,腰围上限取身高×0.5=86cm 与男性中心性肥胖线 85cm 的较严值,下限按身高×0.4≈69cm 取整。腰围超标反映内脏脂肪堆积,是心血管疾病的独立危险因素。</div>
</div>
</div>
</div>
<!-- ====== 个人目标模式 ====== -->
<div id="sectionPersonal" class="hidden">
<!-- 个人目标卡片 -->
@@ -319,28 +329,34 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
</div>
<!-- 目标数据 -->
<div class="data-section">
<div class="data-section__title">目标数据</div>
<div class="input-row" style="margin-bottom:8px;">
<span class="input-row__label">体重</span>
<input class="input-row__input" type="number" value="62.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">kg</span>
</div>
<div class="input-row" style="margin-bottom:8px;">
<span class="input-row__label">体脂率</span>
<input class="input-row__input" type="number" value="20.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">%</span>
</div>
<div class="input-row">
<span class="input-row__label">腰围</span>
<input class="input-row__input" type="number" value="75" placeholder="请输入" step="0.1">
<span class="input-row__unit">cm</span>
</div>
</div>
</div>
</div>
<!-- 目标数据 -->
<div class="data-section">
<div class="data-section__title"><span>目标数据</span><span class="data-section__extra" id="personalTargetDays">共31天完成</span></div>
<div class="input-row" style="margin-bottom:0;">
<span class="input-row__label">体重</span>
<input class="input-row__input" type="number" value="62.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">kg</span>
</div>
<div class="input-row__range">推荐范围 <span>54.7 ~ 70.7 kg</span></div>
<div class="input-row__explain">按您的身高 172cm 和健康 BMI 标准(18.5~23.9)换算:1.72²×18.5≈54.71.72²×23.9≈70.7。体重超标是高血压、糖尿病等慢性病的主要诱因;31 天周期较短,建议目标设在区间偏上位置,周减 0.5~1kg 为宜。</div>
<div class="input-row" style="margin-bottom:0;">
<span class="input-row__label">体脂率</span>
<input class="input-row__input" type="number" value="20.0" placeholder="请输入" step="0.1">
<span class="input-row__unit">%</span>
</div>
<div class="input-row__range">推荐范围 <span>15% ~ 20%</span></div>
<div class="input-row__explain">按成年男性健康标准,体脂率应控制在 15%~20%。您当前 28.6% 处于肥胖水平,是代谢紊乱和脂肪肝的重要诱因;31 天内配合有氧运动可初步改善 2~3 个百分点。</div>
<div class="input-row">
<span class="input-row__label">腰围</span>
<input class="input-row__input" type="number" value="75" placeholder="请输入" step="0.1">
<span class="input-row__unit">cm</span>
</div>
<div class="input-row__range">推荐范围 <span>65 ~ 85 cm</span></div>
<div class="input-row__explain">按您的身高 172cm,腰围上限取身高×0.5=86cm 与男性中心性肥胖线 85cm 的较严值,下限按身高×0.4≈69cm 取整。腰围超标反映内脏脂肪堆积,是心血管疾病的独立危险因素。</div>
</div>
</div>
</div>
<div class="bottom-safe"></div>
</div>
@@ -466,6 +482,9 @@ function confirmActivity() {
// 显示活动详情链接
document.getElementById('actDetailLink').classList.remove('hidden');
// 更新目标天数
updateActTargetDays(period);
closeActivitySheet();
}
@@ -539,7 +558,40 @@ function getParam(name) {
document.getElementById('actPeriod').textContent = actPeriod;
document.getElementById('actOrg').textContent = actOrg;
document.getElementById('actDetailLink').classList.remove('hidden');
updateActTargetDays(actPeriod);
})();
/* ===== 共N天完成 ===== */
function calcDays(periodStr) {
var parts = periodStr.split('~');
if (parts.length !== 2) return null;
var s = new Date(parts[0].trim());
var e = new Date(parts[1].trim());
if (isNaN(s) || isNaN(e)) return null;
return Math.ceil((e - s) / (1000 * 60 * 60 * 24)) + 1;
}
function updateActTargetDays(periodStr) {
var days = calcDays(periodStr);
var el = document.getElementById('actTargetDays');
if (el && days) el.textContent = '共' + days + '天完成';
}
function updatePersonalTargetDays() {
var sd = document.getElementById('personalStartDate').value;
var ed = document.getElementById('personalEndDate').value;
if (!sd || !ed) return;
var days = calcDays(sd + ' ~ ' + ed);
var el = document.getElementById('personalTargetDays');
if (el && days) el.textContent = '共' + days + '天完成';
}
// 监听个人目标日期变化
document.getElementById('personalStartDate').addEventListener('change', updatePersonalTargetDays);
document.getElementById('personalEndDate').addEventListener('change', updatePersonalTargetDays);
// 初始计算个人目标天数
updatePersonalTargetDays();
</script>
</body>
</html>
@@ -14,13 +14,13 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.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; }
.nav-title { flex: 1; display: flex; align-items: center; justify-content: center; gap: 4px; font-size: 17px; font-weight: 600; color: #1a1a1a; }
.nav-placeholder { width: 28px; height: 28px; }
.nav-action { font-size: 13px; color: #36cfc9; font-weight: 600; cursor: pointer; white-space: nowrap; flex-shrink: 0; }
.nav-more { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative; flex-shrink: 0; }
/* 类型切换下拉菜单 */
.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 { display: none; position: absolute; top: 28px; 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; }
@@ -301,18 +301,21 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<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-signed" onclick="setPageType('hasact-signed', event)">已设置-参加活动 · 已签署</div>
<div class="type-menu__item" data-type="hasact-review" onclick="setPageType('hasact-review', event)">已设置-参加活动 · 审核中</div>
<div class="type-menu__item" data-type="hasact-approved" onclick="setPageType('hasact-approved', event)">已设置-参加活动 · 已通过待签署</div>
<div class="type-menu__item" data-type="hasact-rejected" onclick="setPageType('hasact-rejected', 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 class="nav-title">
<span>体重管理</span>
<div class="nav-more" id="navMore" onclick="toggleTypeMenu(event)">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg>
<div class="type-menu" id="typeMenu">
<div class="type-menu__item active" data-type="hasact-signed" onclick="setPageType('hasact-signed', event)">已设置-参加活动 · 已签署</div>
<div class="type-menu__item" data-type="hasact-review" onclick="setPageType('hasact-review', event)">已设置-参加活动 · 审核中</div>
<div class="type-menu__item" data-type="hasact-approved" onclick="setPageType('hasact-approved', event)">已设置-参加活动 · 已通过待签署</div>
<div class="type-menu__item" data-type="hasact-rejected" onclick="setPageType('hasact-rejected', 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>
<span class="nav-action" onclick="location.href='goal-history-v2.html'">历史计划</span>
</div>
<div class="type-mask" id="typeMask" onclick="closeTypeMenu()"></div>
@@ -610,7 +613,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div class="weight-card__header">
<span class="weight-card__title">体重记录 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#bbb" stroke-width="2.5"><polyline points="9 18 15 12 9 6"/></svg></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="event.stopPropagation();location.href='../bluetooth-scale-miniprogram/main.html'">
<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="event.stopPropagation();location.href='bluetooth-scale-v2.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>
@@ -0,0 +1,189 @@
<!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; position: relative; 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; }
/* Tab 栏 */
.report-tabs { display: flex; background: #fff; margin: 12px 12px 0; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.03); }
.report-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 13px; font-weight: 600; color: #999; cursor: pointer; position: relative; transition: color .2s; }
.report-tab.active { color: #36cfc9; }
.report-tab.active::after { content: ''; position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); width: 24px; height: 3px; background: #36cfc9; border-radius: 2px; }
/* 记录列表 */
.record-list { padding: 8px 12px 16px; display: flex; flex-direction: column; gap: 10px; }
.record-item { background: #fff; border-radius: 14px; padding: 14px; box-shadow: 0 2px 8px rgba(0,0,0,0.03); }
.record-item__date { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid #f5f5f5; }
.record-item__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px 4px; }
.record-item__cell { text-align: center; }
.record-item__label { font-size: 11px; color: #999; margin-right: 2px; }
.record-item__val { font-size: 13px; font-weight: 700; color: #1a1a1a; }
.record-item__unit { font-size: 10px; color: #bbb; font-weight: 400; margin-left: 1px; }
.record-empty { text-align: center; padding: 40px 20px; color: #ccc; font-size: 14px; }
.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-placeholder"></div>
</div>
<div class="scroll-content">
<!-- Tab 栏 -->
<div class="report-tabs">
<div class="report-tab active" data-range="week" onclick="switchTab('week')"></div>
<div class="report-tab" data-range="month" onclick="switchTab('month')"></div>
<div class="report-tab" data-range="quarter" onclick="switchTab('quarter')"></div>
<div class="report-tab" data-range="all" onclick="switchTab('all')">全部</div>
<div class="report-tab" data-range="activity" onclick="switchTab('activity')">活动期间</div>
</div>
<!-- 记录列表 -->
<div class="record-list" id="recordList"></div>
<div class="bottom-safe"></div>
</div>
</div>
<script>
/* ===== 模拟数据 ===== */
function calcBMI(weight) { return weight / 2.6569; }
var RECORDS = [
{ date:'2026-08-12', intake:1086, consume:1450, weight:62.6, bmi:calcBMI(62.6), bodyFat:20.0, waist:76.5 },
{ date:'2026-08-09', intake:1520, consume:1680, weight:62.8, bmi:calcBMI(62.8), bodyFat:20.3, waist:76.8 },
{ date:'2026-08-07', intake:1380, consume:1520, weight:63.1, bmi:calcBMI(63.1), bodyFat:20.5, waist:77.0 },
{ date:'2026-08-05', intake:1620, consume:1400, weight:63.5, bmi:calcBMI(63.5), bodyFat:20.8, waist:77.5 },
{ date:'2026-08-02', intake:1280, consume:1560, weight:63.8, bmi:calcBMI(63.8), bodyFat:21.1, waist:78.0 },
{ date:'2026-07-30', intake:1750, consume:1350, weight:64.2, bmi:calcBMI(64.2), bodyFat:21.4, waist:78.5 },
{ date:'2026-07-27', intake:1420, consume:1480, weight:64.5, bmi:calcBMI(64.5), bodyFat:21.6, waist:79.0 },
{ date:'2026-07-24', intake:1560, consume:1420, weight:64.9, bmi:calcBMI(64.9), bodyFat:21.9, waist:79.5 },
{ date:'2026-07-20', intake:1330, consume:1500, weight:65.2, bmi:calcBMI(65.2), bodyFat:22.2, waist:80.0 },
{ date:'2026-07-15', intake:1680, consume:1380, weight:65.8, bmi:calcBMI(65.8), bodyFat:22.6, waist:80.5 },
{ date:'2026-07-10', intake:1450, consume:1400, weight:66.5, bmi:calcBMI(66.5), bodyFat:23.0, waist:81.0 },
{ date:'2026-07-05', intake:1520, consume:1350, weight:67.2, bmi:calcBMI(67.2), bodyFat:23.5, waist:81.5 },
{ date:'2026-06-30', intake:1600, consume:1300, weight:68.0, bmi:calcBMI(68.0), bodyFat:24.0, waist:82.0 },
{ date:'2026-06-25', intake:1480, consume:1280, weight:68.8, bmi:calcBMI(68.8), bodyFat:24.5, waist:83.0 },
{ date:'2026-06-22', intake:1550, consume:1200, weight:69.5, bmi:calcBMI(69.5), bodyFat:25.0, waist:83.5 },
{ date:'2026-06-20', intake:1420, consume:1250, weight:70.0, bmi:calcBMI(70.0), bodyFat:25.5, waist:84.0 },
{ date:'2026-06-18', intake:1580, consume:1180, weight:70.5, bmi:calcBMI(70.5), bodyFat:26.0, waist:84.5 },
{ date:'2026-06-16', intake:1650, consume:1100, weight:71.0, bmi:calcBMI(71.0), bodyFat:26.5, waist:85.5 },
{ date:'2026-06-14', intake:1720, consume:1050, weight:71.5, bmi:calcBMI(71.5), bodyFat:27.0, waist:86.0 },
{ date:'2026-06-12', intake:1800, consume:1000, weight:72.0, bmi:calcBMI(72.0), bodyFat:27.3, waist:86.5 },
{ date:'2026-06-10', intake:1750, consume:980, weight:72.5, bmi:calcBMI(72.5), bodyFat:27.8, waist:87.5 },
{ date:'2026-06-08', intake:1680, consume:1020, weight:72.8, bmi:calcBMI(72.8), bodyFat:28.0, waist:88.0 },
{ date:'2026-06-05', intake:1720, consume:950, weight:73.0, bmi:calcBMI(73.0), bodyFat:28.2, waist:88.5 },
{ date:'2026-06-02', intake:1850, consume:900, weight:73.3, bmi:calcBMI(73.3), bodyFat:28.4, waist:89.0 },
{ date:'2026-06-01', intake:1900, consume:880, weight:73.5, bmi:calcBMI(73.5), bodyFat:28.5, waist:89.5 }
];
var ACTIVITY_START = new Date(2026, 5, 1);
var ACTIVITY_END = new Date(2026, 10, 28);
var TODAY = new Date(2026, 7, 12);
function parseDate(s) { var p = s.split('-'); return new Date(+p[0], +p[1]-1, +p[2]); }
/* ===== Tab 切换 ===== */
var activeTab = 'week';
function switchTab(range) {
activeTab = range;
document.querySelectorAll('.report-tab').forEach(function(t) {
t.classList.toggle('active', t.dataset.range === range);
});
renderRecordList();
}
function getTabDateRange() {
var now = TODAY;
var start, end;
switch (activeTab) {
case 'week':
var dow = now.getDay() || 7;
start = new Date(now); start.setDate(now.getDate() - dow + 1);
end = new Date(start); end.setDate(start.getDate() + 6);
break;
case 'month':
start = new Date(now.getFullYear(), now.getMonth(), 1);
end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
break;
case 'quarter':
var q = Math.floor(now.getMonth() / 3);
start = new Date(now.getFullYear(), q * 3, 1);
end = new Date(now.getFullYear(), (q + 1) * 3, 0);
break;
case 'activity':
start = ACTIVITY_START;
end = ACTIVITY_END;
break;
case 'all':
start = new Date(2000, 0, 1);
end = new Date(2099, 11, 31);
break;
}
return { start: start, end: end };
}
function renderRecordList() {
var range = getTabDateRange();
var filtered = RECORDS.filter(function(r) {
var d = parseDate(r.date);
return d >= range.start && d <= range.end;
});
var container = document.getElementById('recordList');
if (filtered.length === 0) {
container.innerHTML = '<div class="record-empty">该时间段暂无记录</div>';
return;
}
var html = '';
for (var i = 0; i < filtered.length; i++) {
var r = filtered[i];
html += '<div class="record-item">';
html += '<div class="record-item__date">' + r.date + '</div>';
html += '<div class="record-item__grid">';
html += '<div class="record-item__cell"><span class="record-item__label">体重</span><span class="record-item__val">' + r.weight.toFixed(1) + '<span class="record-item__unit">kg</span></span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">BMI</span><span class="record-item__val">' + r.bmi.toFixed(1) + '</span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">体脂率</span><span class="record-item__val">' + r.bodyFat.toFixed(1) + '<span class="record-item__unit">%</span></span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">腰围</span><span class="record-item__val">' + (r.waist !== null ? r.waist.toFixed(1) + '<span class="record-item__unit">cm</span>' : '-') + '</span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">摄入</span><span class="record-item__val">' + r.intake + '<span class="record-item__unit">kcal</span></span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">消耗</span><span class="record-item__val">' + r.consume + '<span class="record-item__unit">kcal</span></span></div>';
html += '</div>';
html += '</div>';
}
container.innerHTML = html;
}
renderRecordList();
</script>
</body>
</html>
+201 -204
View File
@@ -32,44 +32,72 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.scroll-content::-webkit-scrollbar { display: none; }
/* ===== 总览卡片 ===== */
.overview-card { background: linear-gradient(135deg, #36cfc9 0%, #2ec4b6 100%); margin: 12px 12px 0; border-radius: 16px; padding: 20px 18px; color: #fff; position: relative; overflow: hidden; box-shadow: 0 4px 14px rgba(54,207,201,0.25); }
.overview-card::before { content: ''; position: absolute; top: -30px; right: -30px; width: 100px; height: 100px; border-radius: 50%; background: rgba(255,255,255,0.08); pointer-events: none; }
.overview-card::after { content: ''; position: absolute; bottom: -40px; left: -20px; width: 120px; height: 120px; border-radius: 50%; background: rgba(255,255,255,0.05); pointer-events: none; }
.overview-card__title { font-size: 18px; font-weight: 800; margin-bottom: 14px; position: relative; z-index: 1; letter-spacing: 1px; }
.overview-card__info { display: flex; flex-direction: column; gap: 6px; position: relative; z-index: 1; }
.overview-card__row { display: flex; align-items: center; justify-content: space-between; }
.overview-card__label { font-size: 13px; opacity: 0.85; }
.overview-card__val { font-size: 13px; font-weight: 700; }
.overview-card__metrics { display: flex; gap: 12px; margin-top: 14px; position: relative; z-index: 1; }
.overview-card__metric { flex: 1; background: rgba(255,255,255,0.15); border-radius: 10px; padding: 8px 10px; text-align: center; backdrop-filter: blur(4px); }
.overview-card__metric-val { font-size: 22px; font-weight: 800; }
.overview-card__metric-unit { font-size: 12px; font-weight: 500; opacity: 0.8; margin-left: 2px; }
.overview-card__metric-label { font-size: 11px; opacity: 0.75; margin-right: 4px; }
.overview-card { background: linear-gradient(135deg, #36cfc9 0%, #2ec4b6 100%); margin: 12px 12px 0; border-radius: 16px; padding: 14px 18px; color: #fff; position: relative; overflow: hidden; box-shadow: 0 4px 14px rgba(54,207,201,0.25); }
.overview-card::before { content: ''; position: absolute; top: -20px; right: -20px; width: 70px; height: 70px; border-radius: 50%; background: rgba(255,255,255,0.08); pointer-events: none; }
.overview-card::after { content: ''; position: absolute; bottom: -20px; left: -15px; width: 80px; height: 80px; border-radius: 50%; background: rgba(255,255,255,0.05); pointer-events: none; }
.overview-card__row { display: flex; align-items: center; justify-content: space-between; position: relative; z-index: 1; }
.overview-card__label { font-size: 13px; opacity: 0.85; }
.overview-metrics { display: flex; gap: 10px; margin-top: 12px; position: relative; z-index: 1; }
.overview-metric { flex: 1; text-align: center; }
.overview-metric__val { font-size: 22px; font-weight: 800; }
.overview-metric__unit { font-size: 11px; font-weight: 500; opacity: 0.7; margin-left: 1px; }
.overview-metric__desc { font-size: 10px; opacity: 0.65; margin-top: 2px; }
/* ===== 状态缺省(非活动类型) ===== */
.overview-empty { background: #fff; margin: 12px 12px 0; border-radius: 16px; padding: 32px 18px; text-align: center; color: #ccc; box-shadow: 0 2px 8px rgba(0,0,0,0.03); }
.overview-empty__icon { margin-bottom: 12px; }
.overview-empty__text { font-size: 14px; line-height: 1.6; }
/* ===== Tab 栏 ===== */
.report-tabs { display: flex; background: #fff; margin: 12px 12px 0; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.03); }
.report-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 13px; font-weight: 600; color: #999; cursor: pointer; position: relative; transition: color .2s; }
.report-tab.active { color: #36cfc9; }
.report-tab.active::after { content: ''; position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); width: 24px; height: 3px; background: #36cfc9; border-radius: 2px; }
/* 底部按钮 */
.bottom-bar { padding: 16px 12px 12px; flex-shrink: 0; }
.bottom-btn { display: flex; width: 100%; height: 46px; border-radius: 23px; border: 2px solid #36cfc9; font-size: 15px; font-weight: 700; cursor: pointer; background: #fff; color: #36cfc9; align-items: center; justify-content: center; gap: 6px; transition: all .2s; text-decoration: none; }
.bottom-btn:active { background: #e6fffb; }
.bottom-btn__arrow { font-size: 12px; }
/* ===== 记录列表 ===== */
.record-list { padding: 8px 12px 16px; display: flex; flex-direction: column; gap: 10px; }
.record-item { background: #fff; border-radius: 14px; padding: 14px; box-shadow: 0 2px 8px rgba(0,0,0,0.03); }
.record-item__date { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid #f5f5f5; }
.record-item__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px 4px; }
.record-item__cell { text-align: center; }
.record-item__label { font-size: 11px; color: #999; margin-right: 2px; }
.record-item__val { font-size: 13px; font-weight: 700; color: #1a1a1a; }
.record-item__unit { font-size: 10px; color: #bbb; font-weight: 400; margin-left: 1px; }
/* ===== 计划内总结 ===== */
.summary-section { padding: 0 12px; }
.summary-section__title { font-size: 16px; font-weight: 800; color: #1a1a1a; margin: 16px 0 10px; display: flex; align-items: center; gap: 6px; }
.summary-section__title::before { content: ''; width: 4px; height: 16px; background: #36cfc9; border-radius: 2px; }
.record-empty { text-align: center; padding: 40px 20px; color: #ccc; font-size: 14px; }
/* 分析卡片 */
.summary-card { background: #fff; border-radius: 14px; padding: 16px; margin-bottom: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.03); }
.summary-card__title { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 10px; display: flex; align-items: center; gap: 6px; }
.summary-card__icon { font-size: 16px; }
.bottom-safe { height: 20px; flex-shrink: 0; }
/* 趋势文字 */
.summary-trend { font-size: 13px; color: #555; line-height: 1.8; }
.summary-trend em { font-style: normal; font-weight: 700; color: #36cfc9; }
.summary-trend strong { color: #1a1a1a; }
/* 统计数值行 */
.summary-stat-row { display: flex; gap: 8px; margin-bottom: 12px; }
.summary-stat { flex: 1; background: #f7f8fa; border-radius: 10px; padding: 10px 8px; text-align: center; }
.summary-stat__val { font-size: 17px; font-weight: 800; color: #1a1a1a; }
.summary-stat__unit { font-size: 10px; font-weight: 500; color: #999; margin-left: 2px; }
.summary-stat__label { font-size: 11px; color: #999; margin-top: 3px; }
/* 对比表格 */
.summary-compare { width: 100%; border-collapse: collapse; font-size: 12px; }
.summary-compare th { padding: 8px 6px; text-align: center; font-weight: 700; color: #999; font-size: 11px; border-bottom: 2px solid #f0f0f0; }
.summary-compare td { padding: 9px 6px; text-align: center; color: #333; border-bottom: 1px solid #f5f5f5; }
.summary-compare td:first-child { text-align: left; font-weight: 600; color: #666; padding-left: 4px; }
.summary-compare tr:last-child td { border-bottom: none; }
.summary-compare .val-down { color: #36cfc9; font-weight: 700; }
.summary-compare .val-target { color: #faad14; font-weight: 700; }
.summary-compare .val-achieved { color: #36cfc9; font-weight: 700; }
/* 标签 */
.summary-tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: 600; margin-left: 4px; }
.summary-tag--good { background: #e6fffb; color: #36cfc9; }
.summary-tag--warn { background: #fffbe6; color: #faad14; }
.summary-tag--info { background: #e6f7ff; color: #1890ff; }
.bottom-safe { height: 20px; flex-shrink: 0; }
</style>
</head>
<body>
@@ -102,81 +130,135 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div class="type-mask" id="typeMask" onclick="closeTypeMenu()"></div>
<div class="scroll-content">
<!-- 总览卡片 -->
<div class="overview-card" id="overviewCard">
<div class="overview-card__info">
<div class="overview-card__row" id="ovInfoRow">
<span class="overview-card__label">截止至 <span id="ovCutoff">2026-08-12</span></span>
<span class="overview-card__label" id="ovDayWrap"><span id="ovDay">52</span> 天(共 <span id="ovTotal">180</span> 天)</span>
</div>
</div>
<!-- 体重对比行 -->
<div style="display:flex;align-items:center;gap:6px;margin-top:14px;position:relative;z-index:1;">
<div style="flex:1;text-align:center;">
<div style="font-size:16px;font-weight:800;">73.5</div>
<div style="font-size:10px;opacity:0.7;">初始体重 kg</div>
</div>
<span style="color:rgba(255,255,255,0.4);"></span>
<div style="flex:1;text-align:center;">
<div style="font-size:16px;font-weight:800;">62.6</div>
<div style="font-size:10px;opacity:0.7;">当前体重 kg</div>
</div>
<span style="color:rgba(255,255,255,0.4);" id="ovTargetArrow"></span>
<div style="flex:1;text-align:center;" id="ovTargetWeight">
<div style="font-size:16px;font-weight:800;">56.0</div>
<div style="font-size:10px;opacity:0.7;">目标体重 kg</div>
<!-- 总览卡片 -->
<div class="overview-card" id="overviewCard">
<div class="overview-card__row" id="ovInfoRow">
<span class="overview-card__label">截止至 <span id="ovCutoff">2026-08-12</span></span>
<span class="overview-card__label" id="ovDayWrap"><span id="ovDay">52</span> 天(共 <span id="ovTotal">180</span> 天)</span>
</div>
<div class="overview-metrics">
<div class="overview-metric">
<div class="overview-metric__val">-10.9<span class="overview-metric__unit">kg</span></div>
<div class="overview-metric__desc">已减体重</div>
</div>
</div>
<!-- 统计行 -->
<div style="display:flex;gap:8px;margin-top:12px;position:relative;z-index:1;">
<div style="flex:1;background:rgba(255,255,255,0.15);border-radius:10px;padding:8px 6px;text-align:center;">
<div style="font-size:14px;font-weight:800;">-10.9<span style="font-size:10px;font-weight:400;opacity:0.8;">kg</span></div>
<div style="font-size:10px;opacity:0.7;">已减体重</div>
</div>
<div style="flex:1;background:rgba(255,255,255,0.15);border-radius:10px;padding:8px 6px;text-align:center;" id="ovTargetGap">
<div style="font-size:14px;font-weight:800;">6.6<span style="font-size:10px;font-weight:400;opacity:0.8;">kg</span></div>
<div style="font-size:10px;opacity:0.7;">距目标</div>
<div class="overview-metric">
<div class="overview-metric__val">62<span class="overview-metric__unit">%</span></div>
<div class="overview-metric__desc">目标进度</div>
</div>
<div style="flex:1;background:rgba(255,255,255,0.15);border-radius:10px;padding:8px 6px;text-align:center;" id="ovTargetProgress">
<div style="font-size:14px;font-weight:800;">62<span style="font-size:10px;font-weight:400;opacity:0.8;">%</span></div>
<div style="font-size:10px;opacity:0.7;">目标进度</div>
</div>
</div>
<div class="overview-metric">
<div class="overview-metric__val">~1.5<span class="overview-metric__unit"></span></div>
<div class="overview-metric__desc">预计达成</div>
</div>
</div>
</div>
<!-- 进度条 -->
<div style="margin-top:10px;position:relative;z-index:1;" id="ovProgressBar">
<div style="width:100%;height:6px;background:rgba(255,255,255,0.2);border-radius:3px;overflow:hidden;">
<div style="width:62%;height:100%;background:rgba(255,255,255,0.6);border-radius:3px;"></div>
</div>
<div style="display:flex;justify-content:space-between;font-size:10px;opacity:0.6;margin-top:3px;">
<span>0%</span><span>目标 56.0kg</span>
</div>
</div>
</div>
<!-- 非活动类型缺省 -->
<div class="overview-empty" id="overviewEmpty" style="display:none;">
<div class="overview-empty__icon">
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="8" y="6" width="32" height="36" rx="4" stroke="#ddd" stroke-width="2"/><line x1="16" y1="18" x2="32" y2="18" stroke="#ddd" stroke-width="2" stroke-linecap="round"/><line x1="16" y1="24" x2="28" y2="24" stroke="#ddd" stroke-width="2" stroke-linecap="round"/><line x1="16" y1="30" x2="24" y2="30" stroke="#ddd" stroke-width="2" stroke-linecap="round"/></svg>
</div>
<div class="overview-empty__text">暂未参加体重管理活动<br>暂无体重报告数据</div>
</div>
<!-- 非活动类型缺省 -->
<div class="overview-empty" id="overviewEmpty" style="display:none;">
<div class="overview-empty__icon">
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="8" y="6" width="32" height="36" rx="4" stroke="#ddd" stroke-width="2"/><line x1="16" y1="18" x2="32" y2="18" stroke="#ddd" stroke-width="2" stroke-linecap="round"/><line x1="16" y1="24" x2="28" y2="24" stroke="#ddd" stroke-width="2" stroke-linecap="round"/><line x1="16" y1="30" x2="24" y2="30" stroke="#ddd" stroke-width="2" stroke-linecap="round"/></svg>
</div>
<div class="overview-empty__text">暂未参加体重管理活动<br>暂无体重报告数据</div>
</div>
<!-- ===== 计划内总结 ===== -->
<div class="summary-section" id="summarySection">
<div class="summary-section__title">计划内总结</div>
<!-- Tab 栏 -->
<div class="report-tabs" id="reportTabs">
<div class="report-tab active" data-range="week" onclick="switchTab('week')"></div>
<div class="report-tab" data-range="month" onclick="switchTab('month')"></div>
<div class="report-tab" data-range="quarter" onclick="switchTab('quarter')"></div>
<div class="report-tab" data-range="all" onclick="switchTab('all')">全部</div>
<div class="report-tab" data-range="activity" id="tabActivity" onclick="switchTab('activity')">活动期间</div>
</div>
<!-- 健康指标对比 -->
<div class="summary-card">
<div class="summary-card__title">
<span class="summary-card__icon">📊</span>健康指标对比
</div>
<table class="summary-compare">
<thead><tr><th>指标</th><th>初始</th><th>当前</th><th>目标</th><th>变化</th></tr></thead>
<tbody>
<tr>
<td>体重 (kg)</td><td>73.5</td><td>62.6</td><td class="val-target">56.0</td>
<td class="val-down">↓ 10.9</td>
</tr>
<tr>
<td>BMI</td><td>27.7</td><td>23.6</td><td class="val-target">21.1</td>
<td class="val-down">↓ 4.1 <span class="summary-tag summary-tag--good">已正常</span></td>
</tr>
<tr>
<td>体脂率 (%)</td><td>28.5</td><td>20.0</td><td class="val-target">18.0</td>
<td class="val-down">↓ 8.5</td>
</tr>
<tr>
<td>腰围 (cm)</td><td>89.5</td><td>76.5</td><td class="val-target">72.0</td>
<td class="val-down">↓ 13.0 <span class="summary-tag summary-tag--good">已达标</span></td>
</tr>
</tbody>
</table>
</div>
<!-- 记录列表 -->
<div class="record-list" id="recordList"></div>
<!-- 饮食总结 -->
<div class="summary-card">
<div class="summary-card__title">
<span class="summary-card__icon">🥗</span>饮食总结
</div>
<div class="summary-stat-row">
<div class="summary-stat">
<div class="summary-stat__val">1,572<span class="summary-stat__unit">kcal</span></div>
<div class="summary-stat__label">日均摄入</div>
</div>
<div class="summary-stat">
<div class="summary-stat__val">-17.5<span class="summary-stat__unit">%</span></div>
<div class="summary-stat__label">摄入降幅</div>
</div>
<div class="summary-stat">
<div class="summary-stat__val">1,086<span class="summary-stat__unit">kcal</span></div>
<div class="summary-stat__label">最低单日</div>
</div>
</div>
<div class="summary-trend">
饮食控制<strong>持续向好</strong>,月均摄入从 6月 <em>1,669 kcal</em> → 7月 <em>1,530 kcal</em> → 8月 <em>1,377 kcal</em>,呈阶梯式下降。单日最高摄入 <em>1,900 kcal</em>6/1),最低仅 <em>1,086 kcal</em>8/12),差距近一半,说明<strong>饮食习惯已发生显著改变</strong>
</div>
</div>
<div class="bottom-safe"></div>
<!-- 运动总结 -->
<div class="summary-card">
<div class="summary-card__title">
<span class="summary-card__icon">🏃</span>运动总结
</div>
<div class="summary-stat-row">
<div class="summary-stat">
<div class="summary-stat__val">1,263<span class="summary-stat__unit">kcal</span></div>
<div class="summary-stat__label">日均消耗</div>
</div>
<div class="summary-stat">
<div class="summary-stat__val">+40.4<span class="summary-stat__unit">%</span></div>
<div class="summary-stat__label">消耗增幅</div>
</div>
<div class="summary-stat">
<div class="summary-stat__val">1,680<span class="summary-stat__unit">kcal</span></div>
<div class="summary-stat__label">最高单日</div>
</div>
</div>
<div class="summary-trend">
运动消耗<strong>稳步攀升</strong>,月均消耗从 6月 <em>1,084 kcal</em> → 7月 <em>1,411 kcal</em> → 8月 <em>1,522 kcal</em>,增幅达 <em>40.4%</em>。单日最高消耗 <em>1,680 kcal</em>8/9),较初期最低 <em>880 kcal</em>6/1)翻了近一倍,<strong>运动习惯已牢固建立</strong>
</div>
</div>
<!-- 热量差总览 -->
<div class="summary-card">
<div class="summary-card__title">
<span class="summary-card__icon">⚖️</span>热量缺口总览
</div>
<div class="summary-trend">
日均热量缺口约 <em>309 kcal</em>,且<strong>逐月扩大</strong>6月缺口 <em>585 kcal</em> → 7月 <em>119 kcal</em> → 8月 <em>-145 kcal</em>(消耗已反超摄入)。饮食收缩与运动扩张<strong>双向发力</strong>,是体重稳步下降的核心引擎。
</div>
</div>
</div>
<!-- Tab 栏 -->
<div style="padding: 16px 12px 12px;">
<a class="bottom-btn" href="weight-record-detail-v2.html">
数据明细 <span class="bottom-btn__arrow"></span>
</a>
</div>
<div class="bottom-safe"></div>
</div>
</div>
@@ -269,118 +351,33 @@ function applyPageType(type) {
item.classList.toggle('active', item.dataset.type === type);
});
if (type === 'hasact') {
navTitle.textContent = '2026年二季度体重管理活动';
overviewCard.style.display = '';
overviewEmpty.style.display = 'none';
if (ovInfoRow) ovInfoRow.style.display = '';
document.getElementById('ovDayWrap').style.display = '';
document.getElementById('tabActivity').style.display = '';
} else if (type === 'personal') {
navTitle.textContent = '个人减重目标标题';
overviewCard.style.display = '';
overviewEmpty.style.display = 'none';
if (ovInfoRow) ovInfoRow.style.display = '';
document.getElementById('ovDayWrap').style.display = '';
document.getElementById('tabActivity').style.display = '';
} else {
navTitle.textContent = '体重报告';
overviewCard.style.display = '';
overviewEmpty.style.display = 'none';
if (ovInfoRow) ovInfoRow.style.display = 'none';
document.getElementById('ovTargetArrow').style.display = 'none';
document.getElementById('ovTargetWeight').style.display = 'none';
document.getElementById('ovTargetGap').style.display = 'none';
document.getElementById('ovTargetProgress').style.display = 'none';
document.getElementById('ovProgressBar').style.display = 'none';
document.getElementById('ovDayWrap').style.display = 'none';
document.getElementById('tabActivity').style.display = 'none';
}
}
/* ===== 更新总览数据 ===== */
/* ===== Tab 切换 ===== */
var activeTab = 'week';
function switchTab(range) {
activeTab = range;
document.querySelectorAll('.report-tab').forEach(function(t) {
t.classList.toggle('active', t.dataset.range === range);
});
renderRecordList();
}
/* ===== 日期范围计算 ===== */
function getTabDateRange() {
var now = TODAY;
var start, end;
switch (activeTab) {
case 'week':
var dow = now.getDay() || 7;
start = new Date(now); start.setDate(now.getDate() - dow + 1);
end = new Date(start); end.setDate(start.getDate() + 6);
break;
case 'month':
start = new Date(now.getFullYear(), now.getMonth(), 1);
end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
break;
case 'quarter':
var q = Math.floor(now.getMonth() / 3);
start = new Date(now.getFullYear(), q * 3, 1);
end = new Date(now.getFullYear(), (q + 1) * 3, 0);
break;
case 'activity':
start = ACTIVITY_START;
end = ACTIVITY_END;
break;
case 'all':
start = new Date(2000, 0, 1);
end = new Date(2099, 11, 31);
break;
}
return { start: start, end: end };
}
/* ===== 渲染记录列表 ===== */
function renderRecordList() {
var range = getTabDateRange();
var filtered = RECORDS.filter(function(r) {
var d = parseDate(r.date);
return d >= range.start && d <= range.end;
});
var container = document.getElementById('recordList');
if (filtered.length === 0) {
container.innerHTML = '<div class="record-empty">该时间段暂无记录</div>';
return;
}
var html = '';
for (var i = 0; i < filtered.length; i++) {
var r = filtered[i];
html += '<div class="record-item">';
// 日期行
html += '<div class="record-item__date">' + r.date + '</div>';
// 3×2 网格:身体指标优先
html += '<div class="record-item__grid">';
// 第一行:体重 | BMI | 体脂率
html += '<div class="record-item__cell"><span class="record-item__label">体重</span><span class="record-item__val">' + r.weight.toFixed(1) + '<span class="record-item__unit">kg</span></span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">BMI</span><span class="record-item__val">' + r.bmi.toFixed(1) + '</span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">体脂率</span><span class="record-item__val">' + r.bodyFat.toFixed(1) + '<span class="record-item__unit">%</span></span></div>';
// 第二行:腰围 | 摄入 | 消耗
html += '<div class="record-item__cell"><span class="record-item__label">腰围</span><span class="record-item__val">' + (r.waist !== null ? r.waist.toFixed(1) + '<span class="record-item__unit">cm</span>' : '-') + '</span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">摄入</span><span class="record-item__val">' + r.intake + '<span class="record-item__unit">kcal</span></span></div>';
html += '<div class="record-item__cell"><span class="record-item__label">消耗</span><span class="record-item__val">' + r.consume + '<span class="record-item__unit">kcal</span></span></div>';
html += '</div>';
html += '</div>';
}
container.innerHTML = html;
if (type === 'hasact') {
navTitle.textContent = '2026年二季度体重管理活动';
overviewCard.style.display = '';
overviewEmpty.style.display = 'none';
if (ovInfoRow) ovInfoRow.style.display = '';
document.getElementById('ovDayWrap').style.display = '';
document.getElementById('summarySection').style.display = '';
} else if (type === 'personal') {
navTitle.textContent = '个人减重目标标题';
overviewCard.style.display = '';
overviewEmpty.style.display = 'none';
if (ovInfoRow) ovInfoRow.style.display = '';
document.getElementById('ovDayWrap').style.display = '';
document.getElementById('summarySection').style.display = '';
} else {
navTitle.textContent = '体重报告';
overviewCard.style.display = '';
overviewEmpty.style.display = 'none';
if (ovInfoRow) ovInfoRow.style.display = 'none';
document.getElementById('ovDayWrap').style.display = 'none';
document.getElementById('summarySection').style.display = 'none';
}
}
/* ===== 初始化 ===== */
function init() {
applyPageType(currentPageType);
renderRecordList();
}
init();
</script>