211 lines
14 KiB
JavaScript
211 lines
14 KiB
JavaScript
/**
|
|
* 体重管理模块统一截图脚本
|
|
* 规则(参考健康监测 screenshot-final.mjs):
|
|
* - phone-shell 尺寸 390 宽
|
|
* - 'fixed':弹窗/浮层类截图,严格 390×844,弹窗叠在当前页面之上
|
|
* - 'auto' :纯页面截图,短页面最低 844,长页面按真实内容展开
|
|
* 用法:node screenshot-weight.mjs [输出名子串过滤...]
|
|
*/
|
|
import { chromium } from 'playwright';
|
|
import { fileURLToPath } from 'url';
|
|
import path from 'path';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const docDir = path.join(__dirname, 'employee-app', 'weight-management', 'doc');
|
|
const root = path.join(__dirname, 'employee-app', 'weight-management');
|
|
|
|
const tasks = [
|
|
// ========== 目标承诺与签署 ==========
|
|
{ html: 'goal-management-v2.html', out: 'goal-management', mode: 'auto' },
|
|
{ html: 'goal-management-v2.html', out: 'goal-management-personal', mode: 'auto', eval: "switchType('personal')" },
|
|
{ html: 'goal-management-v2.html', out: 'goal-management-activity', mode: 'fixed', eval: 'openActivitySheet()' },
|
|
{ html: 'goal-management-v2.html', out: 'goal-management-confirm', mode: 'fixed', eval: "openActivitySheet();var i=document.querySelector('#actSheet .sheet-item');i.click();confirmActivity();closeActivitySheet();submitGoal()" },
|
|
{ html: 'goal-management-v2.html', out: 'goal-management-confirm-personal', mode: 'fixed', eval: "switchType('personal');submitGoal()" },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail', mode: 'auto', query: '?type=activity&state=review' },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail-approved', mode: 'auto', query: '?type=activity&state=approved' },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail-rejected', mode: 'auto', query: '?type=activity&state=rejected' },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail-signed', mode: 'auto', query: '?type=activity&state=signed' },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail-ended', mode: 'auto', query: '?type=activity&state=ended' },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail-personal', mode: 'auto', query: '?type=personal' },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail-edit', mode: 'fixed', query: '?type=personal', eval: 'openEditGoalModal()' },
|
|
{ html: 'goal-detail-v2.html', out: 'goal-detail-menu', mode: 'fixed', query: '?type=activity&state=signed', eval: "document.getElementById('navMore').click()" },
|
|
{ html: 'promise-signing.html', out: 'promise-signing', mode: 'auto', landscape: true },
|
|
{ html: 'promise-signing.html', out: 'promise-signing-giveup', mode: 'fixed', landscape: true, eval: 'openGiveup()' },
|
|
{ html: 'my-promise.html', out: 'my-promise', mode: 'auto' },
|
|
{ html: 'goal-history-v2.html', out: 'goal-history', mode: 'auto' },
|
|
{ html: 'goal-history-v2.html', out: 'goal-history-personal', mode: 'auto', eval: "switchTab('personal')" },
|
|
{ html: 'activity-detail.html', out: 'activity-detail', mode: 'auto' },
|
|
{ html: 'basic-info.html', out: 'basic-info', mode: 'auto' },
|
|
{ html: 'basic-info.html', out: 'basic-info-height', mode: 'fixed', eval: 'openHeightSheet()' },
|
|
{ html: 'basic-info.html', out: 'basic-info-activity', mode: 'fixed', eval: 'openSheet()' },
|
|
|
|
// ========== 体重管理主页 ==========
|
|
{ html: 'weight-main-v2.html', out: 'weight-main', mode: 'auto', query: '?type=hasact-signed' },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-review', mode: 'auto', query: '?type=hasact-review' },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-approved', mode: 'auto', query: '?type=hasact-approved' },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-rejected', mode: 'auto', query: '?type=hasact-rejected' },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-personal', mode: 'auto', query: '?type=personal' },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-none', mode: 'auto', query: '?type=none' },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-record', mode: 'fixed', query: '?type=hasact-signed', eval: 'openRecordSheet()' },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-record-success', mode: 'fixed', query: '?type=hasact-signed', eval: "openRecordSheet();submitRecord()" },
|
|
{ html: 'weight-main-v2.html', out: 'weight-main-menu', mode: 'fixed', query: '?type=hasact-signed', eval: "document.getElementById('navMore').click()" },
|
|
|
|
// ========== 每日打卡(吃/动/体重) ==========
|
|
{ html: 'eat-checkin-v2.html', out: 'eat-checkin', mode: 'auto' },
|
|
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-lunch', mode: 'auto', query: '?meal=lunch' },
|
|
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-recorded', mode: 'auto', eval: "selectCategory('recorded')" },
|
|
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-bag', mode: 'fixed', eval: 'openBagPanel()' },
|
|
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-gram', mode: 'fixed', eval: "var d;Object.keys(foodData).some(function(k){return foodData[k].items.some(function(it){if(it.name){d=it;return true}})});openGramPanel(d.id)" },
|
|
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-success', mode: 'fixed', eval: 'submitCheckin()' },
|
|
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-meals', mode: 'fixed', eval: "document.querySelector('.filter-row__meal-btn').click()" },
|
|
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin', mode: 'auto' },
|
|
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-recorded', mode: 'auto', eval: "selectCategory('recorded')" },
|
|
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-bag', mode: 'fixed', eval: 'openBagPanel()' },
|
|
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-duration', mode: 'fixed', eval: "var d;Object.keys(exerciseData).some(function(k){return exerciseData[k].items.some(function(it){if(it.name){d=it;return true}})});openDurPanel(d.id)" },
|
|
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-success', mode: 'fixed', eval: 'submitCheckin()' },
|
|
{ html: 'scan-checkin.html', out: 'scan-checkin', mode: 'fixed' },
|
|
{ html: 'scan-checkin.html', out: 'scan-checkin-analyzing', mode: 'fixed', eval: "takePhoto();clearInterval(analyzeTimer);analyzeTimer=null;setTimeout(function(){document.getElementById('analyzingBar').style.width='45%';document.getElementById('analyzingSub').textContent='正在匹配食物数据库...'},300)", wait: 900 },
|
|
{ html: 'scan-checkin.html', out: 'scan-checkin-result', mode: 'fixed', eval: 'showResult()' },
|
|
|
|
// ========== 历史记录 ==========
|
|
{ html: 'weight-record-detail-v2.html', out: 'weight-record-detail', mode: 'auto' },
|
|
{ html: 'weight-record-detail-v2.html', out: 'weight-record-detail-activity', mode: 'auto', eval: "switchTab('activity')" },
|
|
{ html: 'eat-detail-v2.html', out: 'eat-detail', mode: 'auto' },
|
|
{ html: 'eat-detail-v2.html', out: 'eat-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
|
{ html: 'exercise-detail-v2.html', out: 'exercise-detail', mode: 'auto' },
|
|
{ html: 'exercise-detail-v2.html', out: 'exercise-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
|
{ html: 'exercise-detail-v2.html', out: 'exercise-detail-tip', mode: 'fixed', eval: "document.querySelector('.chart-dot').click()" },
|
|
{ html: 'eat-exercise-detail-v2.html', out: 'eat-exercise-detail', mode: 'auto' },
|
|
{ html: 'eat-exercise-detail-v2.html', out: 'eat-exercise-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
|
{ html: 'weight-detail-v2.html', out: 'weight-detail', mode: 'auto' },
|
|
{ html: 'weight-detail-v2.html', out: 'weight-detail-record', mode: 'fixed', eval: 'openRecordSheet()' },
|
|
{ html: 'weight-detail-v2.html', out: 'weight-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
|
{ html: 'weight-detail-v2.html', out: 'weight-detail-tip', mode: 'fixed', eval: "document.querySelector('.chart-dot').click()" },
|
|
{ html: 'report-detail.html', out: 'report-detail-fat', mode: 'auto', query: '?device=fat' },
|
|
{ html: 'report-detail.html', out: 'report-detail-scale', mode: 'auto', query: '?device=scale' },
|
|
{ html: 'report-detail.html', out: 'report-detail-bluetooth', mode: 'auto', query: '?device=bluetooth' },
|
|
{ html: 'body-fat-report.html', out: 'body-fat-report', mode: 'auto' },
|
|
{ html: 'height-scale-report.html', out: 'height-scale-report', mode: 'auto' },
|
|
|
|
// ========== 建议与报告 ==========
|
|
{ html: 'diet-advice-v2.html', out: 'diet-advice', mode: 'auto' },
|
|
{ html: 'diet-advice-v2.html', out: 'diet-advice-detail', mode: 'fixed', eval: "openFoodDetail('breakfast',0)" },
|
|
{ html: 'diet-advice-v2.html', out: 'diet-advice-dislike', mode: 'fixed', eval: 'showDislikeSheet()' },
|
|
{ html: 'diet-advice-v2.html', out: 'diet-advice-nutrition', mode: 'fixed', eval: 'showNutritionEmpty(true)' },
|
|
{ html: 'diet-advice-v2.html', out: 'diet-advice-nutrition-tab', mode: 'auto', eval: "switchTab('nutrition')" },
|
|
{ html: 'diet-advice-v2.html', out: 'diet-advice-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
|
{ html: 'exercise-advice-v2.html', out: 'exercise-advice', mode: 'auto' },
|
|
{ html: 'exercise-advice-v2.html', out: 'exercise-advice-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
|
{ html: 'weight-report.html', out: 'weight-report', mode: 'auto', query: '?type=hasact' },
|
|
{ html: 'weight-report.html', out: 'weight-report-personal', mode: 'auto', query: '?type=personal' },
|
|
{ html: 'weight-report.html', out: 'weight-report-none', mode: 'auto', query: '?type=none' },
|
|
{ html: 'weight-ranking.html', out: 'weight-ranking', mode: 'auto', query: '?type=hasact' },
|
|
{ html: 'weight-ranking.html', out: 'weight-ranking-personal', mode: 'auto', query: '?type=personal' },
|
|
{ html: 'weight-ranking.html', out: 'weight-ranking-none', mode: 'auto', query: '?type=none' },
|
|
|
|
// ========== 蓝牙设备 ==========
|
|
{ html: 'bluetooth-scale-v2.html', out: 'bluetooth-scale', mode: 'auto' },
|
|
{ html: 'bluetooth-scale-v2.html', out: 'bluetooth-scale-empty', mode: 'auto', eval: "document.getElementById('deviceListArea').classList.remove('show');document.getElementById('emptyState').style.display=''" },
|
|
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members', mode: 'auto', query: '?device=s1' },
|
|
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members-empty', mode: 'auto', query: '?device=b2' },
|
|
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members-delete', mode: 'fixed', query: '?device=s1', eval: "document.querySelector('.action-btn--delete').click()" },
|
|
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members-sync', mode: 'fixed', query: '?device=s1', eval: 'syncMembers()', wait: 1600 },
|
|
{ html: 'bluetooth-search-v2.html', out: 'bluetooth-search', mode: 'auto' },
|
|
{ html: 'bluetooth-wifi-v2.html', out: 'bluetooth-wifi', mode: 'auto' },
|
|
];
|
|
|
|
(async () => {
|
|
const filters = process.argv.slice(2);
|
|
const runTasks = filters.length ? tasks.filter(t => filters.some(f => t.out.includes(f))) : tasks;
|
|
|
|
const browser = await chromium.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
|
|
const context = await browser.newContext({ viewport: { width: 390, height: 4000 } });
|
|
|
|
for (const t of runTasks) {
|
|
const page = await context.newPage();
|
|
const filePath = path.join(root, t.html);
|
|
const url = `file:///${filePath.replace(/\\/g, '/')}${t.query || ''}`;
|
|
await page.goto(url, { waitUntil: 'networkidle' });
|
|
|
|
if (t.eval) {
|
|
await page.evaluate(t.eval).catch(e => console.log(`! eval failed [${t.out}]: ${e.message}`));
|
|
await page.waitForTimeout(t.wait || 300);
|
|
}
|
|
|
|
if (t.landscape) {
|
|
// 横屏页:phone-shell 固定 844×390,不展开、按元素原尺寸截取
|
|
await page.evaluate(() => {
|
|
const shell = document.querySelector('.phone-shell');
|
|
if (shell) {
|
|
shell.style.borderRadius = '0';
|
|
shell.style.boxShadow = 'none';
|
|
}
|
|
document.body.style.padding = '0';
|
|
document.body.style.margin = '0';
|
|
document.body.style.minHeight = 'auto';
|
|
document.body.style.background = '#fff';
|
|
document.documentElement.style.display = 'block';
|
|
});
|
|
await page.setViewportSize({ width: 844, height: 390 });
|
|
await page.waitForTimeout(200);
|
|
} else if (t.mode === 'fixed') {
|
|
await page.evaluate(() => {
|
|
const shell = document.querySelector('.phone-shell');
|
|
if (shell) {
|
|
shell.style.borderRadius = '0';
|
|
shell.style.boxShadow = 'none';
|
|
}
|
|
document.body.style.padding = '0';
|
|
document.body.style.minHeight = 'auto';
|
|
document.body.style.background = '#fff';
|
|
});
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
await page.waitForTimeout(200);
|
|
} else {
|
|
await page.evaluate(() => {
|
|
const shell = document.querySelector('.phone-shell');
|
|
if (shell) {
|
|
shell.style.height = 'auto';
|
|
shell.style.minHeight = '844px';
|
|
shell.style.maxHeight = 'none';
|
|
shell.style.borderRadius = '0';
|
|
shell.style.boxShadow = 'none';
|
|
shell.style.overflow = 'visible';
|
|
shell.style.display = 'block';
|
|
}
|
|
document.querySelectorAll('.scroll-content, .page-content, .main-content, .list-wrap, .content').forEach(c => {
|
|
c.style.overflow = 'visible';
|
|
c.style.maxHeight = 'none';
|
|
c.style.height = 'auto';
|
|
c.style.flex = 'none';
|
|
});
|
|
document.body.style.padding = '0';
|
|
document.body.style.minHeight = 'auto';
|
|
document.body.style.background = '#fff';
|
|
});
|
|
await page.waitForTimeout(300);
|
|
const measured = await page.evaluate(() => {
|
|
const shell = document.querySelector('.phone-shell');
|
|
if (!shell) return document.body.scrollHeight;
|
|
return Math.ceil(shell.getBoundingClientRect().height);
|
|
});
|
|
const h = Math.max(measured, 844);
|
|
await page.setViewportSize({ width: 390, height: h });
|
|
await page.waitForTimeout(150);
|
|
}
|
|
|
|
const shell = await page.$('.phone-shell');
|
|
const target = shell || page;
|
|
await target.screenshot({
|
|
path: path.join(docDir, 'screenshots', `${t.out}.jpg`),
|
|
type: 'jpeg',
|
|
quality: 85,
|
|
});
|
|
console.log(`✓ ${t.out}.jpg [${t.mode}]`);
|
|
await page.close();
|
|
}
|
|
|
|
await browser.close();
|
|
console.log(`\n完成!共截取 ${runTasks.length} 张`);
|
|
})();
|