feat: 体重管理员工端/管理端全量弹窗截图重拍与 PRD 弹窗文档补全

员工端:
- 重拍全部弹窗截图(2x 超采样高清,统一 390px 宽),补齐蓝牙秤/饮食/运动/目标/记录等弹窗
- 修复页面缺陷:排行趋势箭头渲染、goal-detail 签署跳转、promise-signing 完成跳转、basic-info 返回、diet-questionnaire 提交跳转
- diet-advice-v2 新增慢病注意提醒条
- PRD 逐页核对修订并补全弹窗截图引用

管理端:
- screenshot.js MODALS 从 6 扩展至 38,新增设备独立弹窗页,弹窗非空校验增强
- PRD 补全报名/行动记录/食谱/历史活动/三测记录/设备管理/公共统计等弹窗文档与截图
- archive-unit-report.html 补充
This commit is contained in:
liuyunqin
2026-08-19 18:08:48 +08:00
parent 585e5fc24c
commit d20f3913f6
202 changed files with 2246 additions and 1220 deletions
@@ -209,13 +209,12 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
</div>
<script>
/* 返回来源页面:优先根据 referrer 判断来源,否则默认目标承诺页 */
/* 返回来源页面:优先回退浏览历史,无历史时回到体重管理主页 */
function goBack() {
var ref = document.referrer;
if (ref && ref.indexOf('goal-management.html') !== -1) {
location.href = 'goal-management.html';
if (history.length > 1) {
history.back();
} else {
location.href = 'goal-commitment.html';
location.href = 'weight-main-v2.html';
}
}
@@ -7,7 +7,7 @@
<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; }
.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; }
@@ -17,6 +17,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.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; }
.nav-action { font-size: 13px; color: #36cfc9; font-weight: 600; cursor: pointer; white-space: nowrap; flex-shrink: 0; }
/* ===== 周日历(页面顶部) ===== */
.calendar-card { background: #fff; border-radius: 16px; margin: 10px 12px 0; padding: 12px 12px 8px; box-shadow: 0 4px 14px rgba(0,0,0,0.04); position: relative; }
@@ -76,6 +77,14 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.advice-summary__body.collapsed { display: none; }
.advice-summary__text { font-size: 13px; color: #555; line-height: 1.7; }
/* ===== 慢病注意提醒(嵌入饮食注意事项卡片内,参考运动建议页) ===== */
.advice-warning { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; background: #fff2f0; border-radius: 8px; margin-top: 8px; border: 1px solid #ffccc7; }
.advice-warning__icon { width: 22px; height: 22px; border-radius: 50%; background: #ff4d4f; color: #fff; display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 11px; font-weight: 800; }
.advice-warning__text { font-size: 12px; color: #666; line-height: 1.65; flex: 1; }
.advice-warning__text strong { color: #333; }
.advice-warning--orange { background: #fffbe6; border-color: #ffe58f; }
.advice-warning--orange .advice-warning__icon { background: #faad14; }
/* Meal advice card */
.meal-advice-card { background: #fff; border-radius: 16px; margin: 10px 12px 0; padding: 14px 16px; box-shadow: 0 2px 10px rgba(0,0,0,0.03); }
.meal-advice-card__header { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
@@ -91,7 +100,8 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.meal-advice-card__kcal span { font-size: 17px; font-weight: 800; }
/* Food item */
.advice-food-item { display: flex; align-items: flex-start; padding: 8px 10px; background: #f7f8fa; border-radius: 10px; gap: 10px; margin-bottom: 6px; }
.advice-food-item { display: flex; align-items: flex-start; padding: 8px 10px; background: #f7f8fa; border-radius: 10px; gap: 10px; margin-bottom: 6px; cursor: pointer; transition: background .2s; }
.advice-food-item:hover { background: #eef1f5; }
.advice-food-item:last-child { margin-bottom: 0; }
.advice-food-item__emoji { font-size: 22px; width: 28px; text-align: center; flex-shrink: 0; line-height: 1.2; }
.advice-food-item__info { flex: 1; min-width: 0; }
@@ -103,6 +113,57 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.advice-food-item__reason { font-size: 11px; color: #888; margin-top: 4px; line-height: 1.5; display: flex; align-items: flex-start; gap: 3px; }
.advice-food-item__reason svg { flex-shrink: 0; margin-top: 1px; }
.advice-food-item__kcal { font-size: 13px; font-weight: 700; color: #fa8c16; white-space: nowrap; flex-shrink: 0; text-align: right; }
.advice-food-item__chevron { flex-shrink: 0; color: #ccc; margin-left: -4px; align-self: center; display: flex; align-items: center; }
/* ===== 餐品详情底部 Sheet ===== */
.food-detail-mask { position: absolute; inset: 0; background: rgba(0,0,0,0.45); z-index: 400; display: none; }
.food-detail-mask.show { display: block; }
.food-detail-sheet { position: absolute; left: 0; right: 0; bottom: 0; background: #fff; border-radius: 18px 18px 0 0; z-index: 401; display: none; padding: 8px 20px 24px; }
.food-detail-sheet.show { display: block; animation: fdSlideUp .25s ease; }
.food-detail-sheet__handle { width: 40px; height: 4px; border-radius: 2px; background: #e5e5e5; margin: 0 auto 14px; }
.food-detail-sheet__head { display: flex; align-items: flex-start; gap: 12px; }
.food-detail-sheet__emoji { width: 52px; height: 52px; border-radius: 14px; background: #f7f8fa; display: flex; align-items: center; justify-content: center; font-size: 28px; flex-shrink: 0; }
.food-detail-sheet__titlewrap { flex: 1; min-width: 0; }
.food-detail-sheet__title { font-size: 18px; font-weight: 800; color: #1a1a1a; }
.food-detail-sheet__tags { display: flex; gap: 6px; margin-top: 6px; }
.food-detail-sheet__tag { font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 8px; white-space: nowrap; }
.food-detail-sheet__tag--canteen { color: #d46b08; background: #fff7e6; }
.food-detail-sheet__tag--ai { color: #0891b2; background: #ecfeff; }
.food-detail-sheet__kcal { font-size: 15px; font-weight: 800; color: #fa8c16; white-space: nowrap; flex-shrink: 0; margin-top: 2px; }
.food-detail-sheet__meta { font-size: 13px; color: #999; margin-top: 12px; }
.food-detail-sheet__section { margin-top: 16px; padding-top: 14px; border-top: 1px solid #f5f5f5; }
.food-detail-sheet__label { font-size: 12px; font-weight: 700; color: #999; margin-bottom: 8px; }
.food-detail-sheet__desc { font-size: 13.5px; color: #444; line-height: 1.7; }
.food-detail-sheet__actions { margin-top: 20px; display: flex; gap: 10px; }
.food-detail-sheet__btn { flex: 1; height: 48px; border-radius: 24px; border: none; font-size: 15px; font-weight: 700; color: #ff4d4f; background: #fff1f0; cursor: pointer; transition: all .2s; }
.food-detail-sheet__btn:active { transform: scale(0.98); }
/* ===== 不再推荐底部 Sheet ===== */
.dislike-mask { position: absolute; inset: 0; background: rgba(0,0,0,0.45); z-index: 500; display: none; }
.dislike-mask.show { display: block; }
.dislike-sheet { position: absolute; left: 0; right: 0; bottom: 0; background: #fff; border-radius: 18px 18px 0 0; z-index: 501; display: none; padding: 8px 20px 24px; }
.dislike-sheet.show { display: block; animation: fdSlideUp .25s ease; }
.dislike-sheet__handle { width: 40px; height: 4px; border-radius: 2px; background: #e5e5e5; margin: 0 auto 14px; }
.dislike-sheet__head { display: flex; align-items: center; justify-content: space-between; }
.dislike-sheet__cancel { font-size: 15px; color: #999; cursor: pointer; }
.dislike-sheet__title { font-size: 16px; font-weight: 800; color: #1a1a1a; }
.dislike-sheet__placeholder { width: 34px; }
.dislike-sheet__body { margin-top: 16px; }
.dislike-sheet__label { font-size: 12px; color: #999; font-weight: 600; margin-bottom: 10px; }
.dislike-sheet__chips { display: flex; flex-wrap: wrap; gap: 8px; }
.dislike-sheet__chip { font-size: 13px; padding: 8px 16px; border-radius: 20px; font-weight: 600; cursor: pointer; border: 1.5px solid #e0e0e0; color: #666; background: #fff; transition: all .2s; user-select: none; }
.dislike-sheet__chip:hover { border-color: #ffa39e; background: #fff7f6; }
.dislike-sheet__chip.active { border-color: #ff4d4f; background: #fff1f0; color: #ff4d4f; }
.dislike-sheet__footer { margin-top: 22px; }
.dislike-sheet__confirm { width: 100%; height: 48px; border-radius: 24px; border: none; font-size: 16px; font-weight: 700; color: #fff; cursor: pointer; background: linear-gradient(135deg, #ff7875 0%, #ff4d4f 100%); box-shadow: 0 6px 20px rgba(255,77,79,0.3); transition: all .2s; }
.dislike-sheet__confirm:active { transform: scale(0.98); }
/* Toast */
.fd-toast { position: absolute; left: 50%; bottom: 90px; transform: translateX(-50%); background: rgba(0,0,0,0.75); color: #fff; font-size: 13px; padding: 9px 18px; border-radius: 20px; z-index: 600; display: none; white-space: nowrap; }
.fd-toast.show { display: block; animation: fdFadeIn .2s ease; }
@keyframes fdSlideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes fdFadeIn { from { opacity: 0; } to { opacity: 1; } }
/* Empty state */
.advice-empty { text-align: center; padding: 40px 0; color: #ccc; }
@@ -282,7 +343,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<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>
<span class="nav-action" onclick="location.href='diet-questionnaire.html'">修改偏好</span>
</div>
<!-- ===== 周日历(页面顶部) ===== -->
@@ -333,6 +394,14 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
<div class="advice-summary__body" id="summaryBody">
<div class="advice-summary__text" id="summaryText"></div>
<div class="advice-warning">
<div class="advice-warning__icon">!</div>
<div class="advice-warning__text"><strong>高血压注意:</strong>严格控制钠盐摄入(每日不超过5g),少吃腌制食品、加工肉制品与重口酱料,多选富含钾的新鲜蔬果和粗杂粮,避免浓汤、辣汤底及高盐外卖。</div>
</div>
<div class="advice-warning advice-warning--orange">
<div class="advice-warning__icon">!</div>
<div class="advice-warning__text"><strong>高尿酸提醒:</strong>避免高嘌呤食物(动物内脏、浓肉汤、贝类海鲜等),少喝含糖饮料与酒精(尤其啤酒),每日饮水2000ml以上促进尿酸排泄,可适当选择低脂奶制品和鸡蛋补充蛋白。</div>
</div>
</div>
</div>
@@ -403,6 +472,54 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
</div>
<!-- ===== 餐品详情底部 Sheet ===== -->
<div class="food-detail-mask" id="foodDetailMask" onclick="closeFoodDetail()"></div>
<div class="food-detail-sheet" id="foodDetailSheet">
<div class="food-detail-sheet__handle"></div>
<div class="food-detail-sheet__head">
<div class="food-detail-sheet__emoji" id="fdEmoji">🥚</div>
<div class="food-detail-sheet__titlewrap">
<div class="food-detail-sheet__title" id="fdName">水煮鸡蛋</div>
<div class="food-detail-sheet__tags" id="fdTags"></div>
</div>
<div class="food-detail-sheet__kcal" id="fdKcal">80 kcal</div>
</div>
<div class="food-detail-sheet__meta" id="fdMeta">×1 · 约50g</div>
<div class="food-detail-sheet__section">
<div class="food-detail-sheet__label">推荐理由</div>
<div class="food-detail-sheet__desc" id="fdReason"></div>
</div>
<div class="food-detail-sheet__actions">
<button class="food-detail-sheet__btn" onclick="showDislikeSheet()">不喜欢</button>
</div>
</div>
<!-- ===== 不再推荐底部 Sheet ===== -->
<div class="dislike-mask" id="dislikeMask" onclick="closeDislikeSheet()"></div>
<div class="dislike-sheet" id="dislikeSheet">
<div class="dislike-sheet__handle"></div>
<div class="dislike-sheet__head">
<div class="dislike-sheet__cancel" onclick="closeDislikeSheet()">取消</div>
<div class="dislike-sheet__title" id="dislikeTitle">不再推荐水煮鸡蛋</div>
<div class="dislike-sheet__placeholder"></div>
</div>
<div class="dislike-sheet__body">
<div class="dislike-sheet__label">选填不喜欢的原因</div>
<div class="dislike-sheet__chips" id="dislikeChips">
<div class="dislike-sheet__chip" onclick="toggleDislikeReason(this)">口味不喜欢</div>
<div class="dislike-sheet__chip" onclick="toggleDislikeReason(this)">吃腻了</div>
<div class="dislike-sheet__chip" onclick="toggleDislikeReason(this)">会过敏 / 不耐受</div>
<div class="dislike-sheet__chip" onclick="toggleDislikeReason(this)">热量太高</div>
<div class="dislike-sheet__chip" onclick="toggleDislikeReason(this)">分量不合适</div>
</div>
</div>
<div class="dislike-sheet__footer">
<button class="dislike-sheet__confirm" onclick="confirmDislike()">确定</button>
</div>
</div>
<div class="fd-toast" id="fdToast"></div>
</div>
<script>
@@ -815,7 +932,11 @@ var DEFAULT_RECIPE_DATA = {
};
/* ===== Recipe tab rendering ===== */
var currentRecipeData = null;
var currentFoodItem = null;
function renderRecipeTab(data) {
currentRecipeData = data;
document.getElementById('summaryText').textContent = data.summary;
var types = ['breakfast','lunch','dinner','snack'];
var caps = {breakfast:'Breakfast',lunch:'Lunch',dinner:'Dinner',snack:'Snack'};
@@ -829,21 +950,21 @@ function renderRecipeTab(data) {
card.style.display = '';
kcalEl.textContent = md.kcal;
var h = '';
md.items.forEach(function(item) {
md.items.forEach(function(item, index) {
var tagHtml = '';
if (item.tag === 'canteen') {
tagHtml = '<span class="advice-food-item__tag advice-food-item__tag--canteen">食堂提供</span>';
} else if (item.tag === 'ai') {
tagHtml = '<span class="advice-food-item__tag advice-food-item__tag--ai">AI推荐</span>';
}
h += '<div class="advice-food-item">' +
h += '<div class="advice-food-item" onclick="openFoodDetail(\'' + t + '\',' + index + ')">' +
'<div class="advice-food-item__emoji">' + item.e + '</div>' +
'<div class="advice-food-item__info">' +
'<div class="advice-food-item__name">' + item.n + tagHtml + '</div>' +
'<div class="advice-food-item__meta">' + item.m + '</div>' +
'<div class="advice-food-item__reason"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#36cfc9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>' + item.reason + '</div>' +
'</div>' +
'<div class="advice-food-item__kcal">' + item.k + ' kcal</div>' +
'<div class="advice-food-item__chevron"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></div>' +
'</div>';
});
container.innerHTML = h;
@@ -853,6 +974,76 @@ function renderRecipeTab(data) {
});
}
/* ===== 餐品详情 / 不喜欢 弹窗 ===== */
function openFoodDetail(mealType, index) {
var data = currentRecipeData;
if (!data || !data.meals || !data.meals[mealType]) return;
var item = data.meals[mealType].items[index];
if (!item) return;
currentFoodItem = item;
document.getElementById('fdEmoji').textContent = item.e;
document.getElementById('fdName').textContent = item.n;
document.getElementById('fdKcal').textContent = item.k + ' kcal';
document.getElementById('fdMeta').textContent = item.m;
document.getElementById('fdReason').textContent = item.reason;
var tagHtml = '';
if (item.tag === 'canteen') {
tagHtml = '<span class="food-detail-sheet__tag food-detail-sheet__tag--canteen">食堂提供</span>';
} else if (item.tag === 'ai') {
tagHtml = '<span class="food-detail-sheet__tag food-detail-sheet__tag--ai">AI推荐</span>';
}
document.getElementById('fdTags').innerHTML = tagHtml;
document.getElementById('foodDetailMask').classList.add('show');
document.getElementById('foodDetailSheet').classList.add('show');
}
function closeFoodDetail() {
document.getElementById('foodDetailMask').classList.remove('show');
document.getElementById('foodDetailSheet').classList.remove('show');
}
function showDislikeSheet() {
var name = currentFoodItem ? currentFoodItem.n : '该餐品';
document.getElementById('dislikeTitle').textContent = '不再推荐' + name;
// 重置已选原因
document.querySelectorAll('.dislike-sheet__chip').forEach(function(c) { c.classList.remove('active'); });
closeFoodDetail();
document.getElementById('dislikeMask').classList.add('show');
document.getElementById('dislikeSheet').classList.add('show');
}
function closeDislikeSheet() {
document.getElementById('dislikeMask').classList.remove('show');
document.getElementById('dislikeSheet').classList.remove('show');
}
function toggleDislikeReason(el) {
el.classList.toggle('active');
}
function confirmDislike() {
var name = currentFoodItem ? currentFoodItem.n : '该餐品';
var selected = [];
document.querySelectorAll('.dislike-sheet__chip.active').forEach(function(c) {
selected.push(c.textContent);
});
closeDislikeSheet();
showToast('已记录,将不再推荐「' + name + '」');
}
function showToast(msg) {
var toast = document.getElementById('fdToast');
toast.textContent = msg;
toast.classList.add('show');
clearTimeout(showToast._t);
showToast._t = setTimeout(function() {
toast.classList.remove('show');
}, 2000);
}
/* ===== Diet analysis card rendering ===== */
var DA_TARGET = 1800; // 每日热量目标 kcal
@@ -438,7 +438,7 @@ function submitQuestionnaire() {
localStorage.setItem('dietPreferences', JSON.stringify(userPreferences));
// 跳转到膳食建议页
location.href = 'diet-advice.html';
location.href = 'diet-advice-v2.html';
}
/* ================================================================
@@ -4,6 +4,137 @@
---
## [2026-08-19] fix: 重拍全部 18 张弹窗截图 — 2x 超采样高清版,解决模糊问题
**涉及文件(20个):**
- `employee-app/weight-management/_reshot.js`(新增,弹窗截图批量重拍脚本)
- `employee-app/weight-management/_downscale.ps1`(新增,PNG 降采样脚本)
- `employee-app/weight-management/doc/CHANGELOG.md`(修改)
- `employee-app/weight-management/doc/screenshots/` 下 18 张弹窗截图(重拍):
weight-main-record / goal-management-activity / goal-management-confirm / basic-info-height / basic-info-activity / promise-signing-giveup / eat-checkin-meal / eat-checkin-gram / eat-checkin-bag / eat-detail-month / exercise-checkin-duration / exercise-checkin-bag / diet-questionnaire-region / diet-questionnaire-avoid / scan-checkin-result / weight-detail-record / bluetooth-device-members-sync / bluetooth-device-members-delete
**问题与原因:**
- 旧弹窗截图普遍模糊:其中 9 张由 1280×980 整屏截屏经 `_crop2.ps1` 裁剪 + 二次 JPEG 重采样而来,清晰度指标仅 2.4~3.5(页面截图为 6.6~11.5);其余也为 DPR=1 直出,文字渲染发虚
**修复方式(对齐 health-monitor PRD 截图规范:统一 390px 宽):**
- `_reshot.js`puppeteer + 本机 Edge):以 deviceScaleFactor=2 渲染,在页面内调用真实弹窗触发函数(openRecordSheet / openActivitySheet / submitGoal / openHeightSheet / openSheet / openGiveup / toggleMealDropdown / openGramPanel / openBagPanel / toggleMonthPicker / openDurPanel / openRegionSheet / openCustomAvoidInput / showResult / confirmDelete,同步进度弹窗固定 66% 中间态),等待过渡动画完成后截取 `.phone-shell` 输出无损 PNG
- `_downscale.ps1`:将 PNG 双三次降采样到 390px 宽(横屏承诺签订页 844px 宽),以质量 90 存为 JPEG
- 18 张全部输出 390×844promise-signing-giveup 为横屏 844×390),与各页面截图及 health-monitor PRD 尺寸规范一致
**验证结果:**
- 同尺度(390px 宽)清晰度指标平均 4.46 → 6.33,原先最糊的 9 张由 2.4~3.5 提升至 5.2~7.9
- 弹层/遮罩亮度抽检确认各弹窗内容均正确呈现(确认提交弹窗遮罩变暗、省市级联/禁忌弹窗遮罩、识别结果弹窗深色取景背景等)
---
## [2026-08-19] docs: PRD 补全全部弹窗截图 — 新拍 8 张 + 引用 18 处
**涉及文件(10个):**
- `employee-app/weight-management/doc/PRD.md`(修改)
- `employee-app/weight-management/doc/screenshots/weight-main-record.jpg`(新增)
- `employee-app/weight-management/doc/screenshots/goal-management-activity.jpg`(新增)
- `employee-app/weight-management/doc/screenshots/goal-management-confirm.jpg`(新增)
- `employee-app/weight-management/doc/screenshots/eat-checkin-meal.jpg`(新增)
- `employee-app/weight-management/doc/screenshots/eat-detail-month.jpg`(新增)
- `employee-app/weight-management/doc/screenshots/bluetooth-device-members-delete.jpg`(新增)
- `employee-app/weight-management/doc/screenshots/bluetooth-device-members-sync.jpg`(新增)
- `employee-app/weight-management/doc/screenshots/promise-signing-giveup.jpg`(重拍,修正横向 844×390 为竖向 390×720
- `employee-app/weight-management/doc/CHANGELOG.md`(修改)
**变更说明:**
**doc/PRD.md**
- 弹窗截图全面嵌入:在 12 个页面的"主要UI元素"弹窗描述条目下补充对应弹窗截图引用(缩进图片行),共 18 处,覆盖全部已描述弹窗 —— 第 1 节记录体重弹窗、第 2 节活动选择/确认提交弹窗、第 6 节身高测量/体力活动选择弹窗、第 7 节放弃签订确认弹窗、第 9 节餐次下拉浮层/克数录入/已选餐品弹窗、第 10 节月历弹窗、第 12 节时长录入/已选运动弹窗、第 16 节省市级联/自定义禁忌弹窗、第 17 节识别结果弹窗、第 18 节记录体重弹窗、第 26 节同步进度/删除确认弹窗
- 此前已有但未引用的 11 张弹窗截图(basic-info-activity / basic-info-height / diet-questionnaire-avoid / diet-questionnaire-region / eat-checkin-bag / eat-checkin-gram / exercise-checkin-bag / exercise-checkin-duration / scan-checkin-result / weight-detail-record / promise-signing-giveup)全部补入对应章节
**doc/screenshots/(新拍 8 张,均为带数据的弹窗状态):**
- weight-main-record.jpg390×884):体重管理主页"+"记录体重弹窗
- goal-management-activity.jpg390×884):目标管理活动选择底部弹层(含 3 条活动数据)
- goal-management-confirm.jpg390×884):确认提交弹窗(已预选"2026年二季度体重管理活动",活动信息/初始数据/目标数据三段完整回填)
- eat-checkin-meal.jpg390×884):饮食录入餐次下拉浮层展开态(早餐高亮)
- eat-detail-month.jpg390×884):饮食记录月历弹窗(日期网格 + 选中态)
- bluetooth-device-members-delete.jpg390×884):用户管理删除确认弹窗(?device=s1,含成员姓名"是否确认删除张建国?")
- bluetooth-device-members-sync.jpg390×884):用户管理同步进度弹窗(?device=s1,捕捉 12% 进度中间态)
- promise-signing-giveup.jpg390×720,重拍):放弃签订确认弹窗,修正原横向截图
---
## [2026-08-19] fix: PRD 与 HTML 全量核对修复 — 6 处页面缺陷修复 + 16 处文档对齐
**涉及文件(8个):**
- `employee-app/weight-management/weight-ranking.html`(修改)
- `employee-app/weight-management/goal-detail-v2.html`(修改)
- `employee-app/weight-management/promise-signing.html`(修改)
- `employee-app/weight-management/basic-info.html`(修改)
- `employee-app/weight-management/diet-questionnaire.html`(修改)
- `employee-app/weight-management/doc/PRD.md`(修改)
- `employee-app/weight-management/doc/screenshots/weight-ranking.jpg`(更新)
- `employee-app/weight-management/doc/CHANGELOG.md`(修改)
**变更说明:**
**HTML 页面缺陷修复(6处):**
- `weight-ranking.html`:排行列表数值后补渲染排名变化趋势箭头(↑绿 / ↓红 / –灰,数据字段已存在但此前未渲染);个人目标模式(type=personal)列表过滤"我"所在行;未组织活动模式(type=none)隐藏整个排行卡片区(此前仅隐藏活动头部与我的排名,Tab 栏与列表仍残留)
- `goal-detail-v2.html`:已通过待签署状态"签署"按钮此前为 alert 占位,改为跳转签订承诺页(promise-signing.html
- `promise-signing.html`:签署"完成"按钮此前跳转 goal-commitment.html(死链,该页已下线),改为跳转我的承诺页(my-promise.html
- `basic-info.html`:返回按钮此前依赖 referrer 判断并跳转 goal-commitment.html(死链),改为优先 history.back()、无历史时回体重管理主页
- `diet-questionnaire.html`:提交问卷后跳转 diet-advice.html(旧版死链),改为 diet-advice-v2.html
**doc/PRD.md26 页逐页核对后修订 16+ 处):**
- 弹窗描述补全:第 1 节补充"记录体重弹窗"内容构成(体重必填滑动尺 + 体脂率/腰围开关 + 保存,交叉引用第 18 节);第 9 节餐次下拉注明为下拉浮层交互;第 10 节展开月历弹窗构成(月份切换箭头 + 日期网格 + 选中态,注明第 11/13/14/15/18 节同款),第 10-15/18 节"点击日历日期/月历切换查看日期"统一细化为周历日期点击与月历弹窗打开/选期的明确交互
- 交互说明全局细化(第 1/2/3/4/9/10/11/13/16/18/20/23/24/25 节):所有跳转类交互写明目标页面名与文件名,消除"对应功能页/对应页面/对应记录页"等模糊表述;第 1 节按"已记录→对应记录页 / 未记录→自记打卡页"规则展开各分支具体页面,"+"按钮、建议/计划/蓝牙称等快捷入口逐个标明跳转目标;配对/WiFi 完成后的返回目标标明 #paired 已配对视图
- 第 1/3 节:"三点菜单"更正为"标题旁下拉菜单"weight-main-v2 / goal-detail-v2 的切换菜单实为标题旁 ▾ 下拉;第 20 节 weight-report 为真三点菜单,保持原文);第 1 节补充周日历日期点击切换当日吃动统计交互
- 第 2 节:目标数据推荐范围拆分为体重(BMI 18.5~23.9 按身高换算)/ 体脂率(按性别标准)/ 腰围(按身高比例与肥胖线取较严值);确认提交弹窗注明个人目标模式下活动信息段为"--"空占位
- 第 6 节:业务规则改为"本页及目标设定中填写的身高/体重/体脂率/腰围均不计入当日打卡;本页仅身高与体力活动可编辑";身高标尺注明原型静态示意
- 第 7 节:"完成"按钮补全跳转目标(我的承诺页);补签名画布为静态示意的原型说明
- 第 9 节:"拍照识别"按钮更正为图标按钮(取景框图标,无文字)
- 第 13/18 节:趋势 Tab 与时间范围 Tab 的职责拆分(前者切换趋势图表、后者切换明细列表时间范围);第 18 节补"首次记录"对比规则与身高秤记录复用 scale 报告模板说明
- 第 14/15 节:慢病提醒条注明原型固定演示两条;第 15 节补"该日期暂无运动计划"空状态
- 第 16 节:补首次进入默认选中口味(清淡/原味、咸鲜)与地区"其他地区"兜底项
- 第 19 节:补页面状态(URL 参数 device 切换,默认 fat)、蓝牙秤头部绿色渐变/其余紫色、身高秤复用 scale 模板
- 第 22 节:补页面状态(URL 参数 type 切换 hasact/personal/none,默认 hasact
- 第 23 节:操作按钮按设备连接状态拆分描述(已连接:设备WIFI/用户/数据补传;未连接:连接设备/用户);补 URL hash #paired 切换说明
- 第 26 节:补页面状态(URL 参数 device 切换 s1/b2,默认 b2)、"一键添加本人"仅空成员设备显示、本人/员工仅可删除与家庭成员可编辑/删除、成员上限以"N/10"展示
**doc/screenshots/weight-ranking.jpg**
- 重新生成整页截图(390×1310),包含新渲染的趋势箭头
---
## [2026-08-19] feat: 今日饮食建议新增慢病注意提醒
**涉及文件(3个):**
- `employee-app/weight-management/diet-advice-v2.html`(修改)
- `employee-app/weight-management/doc/PRD.md`(修改)
- `employee-app/weight-management/doc/screenshots/diet-advice.jpg`(更新)
**变更说明:**
**diet-advice-v2.html**
- "今日饮食注意事项"卡片内新增慢病注意提醒条,复用智能运动计划页(exercise-advice-v2.html)的 `.advice-warning` 卡片样式(红色 + 橙色两档)
- 红色提醒条:高血压注意 —— 控制钠盐每日<5g、少吃腌制/加工食品与重口酱料、多选富含钾的新鲜蔬果和粗杂粮、避免浓汤与高盐外卖
- 橙色提醒条:高尿酸提醒 —— 避免高嘌呤食物(动物内脏、浓肉汤、贝类海鲜等)、少喝含糖饮料与酒精、每日饮水 2000ml 以上、可选低脂奶制品和鸡蛋补充蛋白
- 提醒条随注意事项卡片一起折叠/展开;慢病种类与智能运动计划页保持同一用户设定(高血压、高尿酸)
**doc/PRD.md**
- 第 14 节"今日饮食建议":食谱建议 Tab 主要 UI 元素补充慢病注意提醒条说明,业务规则补充慢病人群提示规则
- 全文描述风格统一:各页"主要UI元素/交互说明"中的原型演示数值(摄入/消耗/体重/排名等具体数字与示例文案)改为元素级描述,仅保留业务规则类阈值(BMI 分档、膳食指南食物种类、设备成员上限等)
**doc/screenshots/diet-advice.jpg**
- 重新生成整页截图(390×1842),包含新增慢病提醒卡片
---
## [2026-08-19] docs: 员工端 PRD 与截图全面更新,对齐当前 HTML 页面
**变更说明:**
- 员工端页面已全面切换为 v2 版本(weight-main-v2 / goal-management-v2 / goal-detail-v2 / eat-detail-v2 / exercise-detail-v2 / diet-advice-v2 等),并新增蓝牙体脂秤、拍照识别、数据明细等页面
- 更新 `doc/PRD.md`:重新梳理页面导航结构与状态流转图,页面清单由 22 个扩展为 26 个,逐页说明同步到当前实现
- 重新生成 `doc/screenshots/` 下全部截图(含各页面多状态演示),并清理已下线页面的过期截图
---
## [2026-06-12] feat: 体重管理子页面补充—饮食/运动/体重打卡与记录、建议页、排行榜、报告页
**涉及文件(13个):**
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Some files were not shown because too many files have changed in this diff Show More