feat: 健康体检体检年份筛选控件统一及PRD文档与截图补充
- 管理端健康体检各页体检年份筛选由原生select替换为自定义下拉控件 - 导航标签精简(体检预约/已选项目/已检员工等) - 单位报表未检人数弹窗移除未检原因列 - 补充健康体检管理端与员工端PRD文档、截图脚本及页面截图
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 健康体检(员工端)PRD 截图脚本
|
||||
* 规则(同 health-monitor/doc/screenshot-final.mjs):
|
||||
* - 标准 phone-shell 尺寸 390×844
|
||||
* - 短页面(实测内容 < 844):保持 844 高度,外壳完整
|
||||
* - 长页面(实测内容 > 844):phone-shell 解除高度限制,按真实内容展开
|
||||
* - 结果页(booking/gastro/cta-date-selected)通过导航栏演示下拉切换成功/失败两态
|
||||
*/
|
||||
import { chromium } from 'playwright';
|
||||
import { fileURLToPath } from 'url';
|
||||
import path from 'path';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const docDir = __dirname;
|
||||
const root = path.resolve(__dirname, '..');
|
||||
|
||||
// mode: auto(短页面最低 844 / 长页面真实高度)
|
||||
const tasks = [
|
||||
// ========== 模块主页 ==========
|
||||
{ html: 'index.html', out: 'index' },
|
||||
{ html: 'index-inactive.html', out: 'index-inactive' },
|
||||
|
||||
// ========== 体检预约(通用 + 常规体检流程) ==========
|
||||
{ html: 'booking-type.html', out: 'booking-type' },
|
||||
{ html: 'booking-hospital.html', out: 'booking-hospital' },
|
||||
{ html: 'booking-hospital.html', out: 'booking-hospital-dialog', query: '?from=booking-type' },
|
||||
{ html: 'booking-project.html', out: 'booking-project' },
|
||||
{ html: 'booking-project.html', out: 'booking-project-required', clickText: '必检项目' },
|
||||
{ html: 'booking-project-selected.html', out: 'booking-project-selected' },
|
||||
{ html: 'booking-date.html', out: 'booking-date' },
|
||||
{ html: 'booking-date-selected.html', out: 'booking-date-selected' },
|
||||
{ html: 'booking-date-selected.html', out: 'booking-date-selected-fail', demo: 'fail' },
|
||||
{ html: 'project-detail.html', out: 'project-detail', query: '?id=general' },
|
||||
|
||||
// ========== 胃肠镜体检流程 ==========
|
||||
{ html: 'gastro-hospital.html', out: 'gastro-hospital' },
|
||||
{ html: 'gastro-questionnaire.html', out: 'gastro-questionnaire' },
|
||||
{ html: 'gastro-questionnaire.html', out: 'gastro-questionnaire-tangdu', query: '?hospital=tangdu' },
|
||||
{ html: 'gastro-date.html', out: 'gastro-date' },
|
||||
{ html: 'gastro-date-selected.html', out: 'gastro-date-selected' },
|
||||
{ html: 'gastro-date-selected.html', out: 'gastro-date-selected-fail', demo: 'fail' },
|
||||
{ html: 'gastro-preselect.html', out: 'gastro-preselect' },
|
||||
{ html: 'gastro-preselect-done.html', out: 'gastro-preselect-done' },
|
||||
|
||||
// ========== 冠脉CTA体检流程 ==========
|
||||
{ html: 'cta-hospital.html', out: 'cta-hospital' },
|
||||
{ html: 'cta-date.html', out: 'cta-date' },
|
||||
{ html: 'cta-date-selected.html', out: 'cta-date-selected' },
|
||||
{ html: 'cta-date-selected.html', out: 'cta-date-selected-fail', demo: 'fail' },
|
||||
|
||||
// ========== 现场体检 ==========
|
||||
{ html: 'my-appointments-all.html', out: 'my-appointments-all' },
|
||||
{ html: 'my-appointments-all.html', out: 'my-appointments-all-gastro', query: '?type=gastro&status=pending' },
|
||||
{ html: 'my-appointments-all.html', out: 'my-appointments-all-cta', query: '?type=cta&status=pending' },
|
||||
{ html: 'hospital-checkin.html', out: 'hospital-checkin' },
|
||||
|
||||
// ========== 体检报告 ==========
|
||||
{ html: 'reports.html', out: 'reports' },
|
||||
{ html: 'report-query.html', out: 'report-query' },
|
||||
{ html: 'report-cta.html', out: 'report-cta' },
|
||||
{ html: 'report-gastro.html', out: 'report-gastro' },
|
||||
{ html: 'indicator-compare.html', out: 'indicator-compare' },
|
||||
{ html: 'indicator-compare-detail.html', out: 'indicator-compare-detail', query: '?item=bmi' },
|
||||
|
||||
// ========== 消息 / 咨询 / 操作指引 ==========
|
||||
{ html: 'messages.html', out: 'messages' },
|
||||
{ html: 'message-detail.html', out: 'message-detail', query: '?id=report-2026' },
|
||||
{ html: 'message-detail.html', out: 'message-detail-ai', query: '?id=warn-indicator' },
|
||||
{ html: 'consult.html', out: 'consult' },
|
||||
{ html: 'process-guide.html', out: 'process-guide' },
|
||||
{ html: 'process-guide-detail.html', out: 'process-guide-detail', query: '?type=image&id=booking' },
|
||||
{ html: 'process-guide-detail.html', out: 'process-guide-detail-video', query: '?type=video&id=gastro' },
|
||||
];
|
||||
|
||||
(async () => {
|
||||
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 tasks) {
|
||||
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' });
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
// 演示下拉切换(预约结果页成功/失败两态)
|
||||
if (t.demo) {
|
||||
await page.evaluate((v) => {
|
||||
const sel = document.querySelector('#demoSelect, .demo-select');
|
||||
if (sel) {
|
||||
sel.value = v;
|
||||
sel.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
if (typeof setResult === 'function') setResult(v);
|
||||
}
|
||||
}, t.demo);
|
||||
await page.waitForTimeout(250);
|
||||
}
|
||||
|
||||
// 按文本点击(如「必检项目」Tab)
|
||||
if (t.clickText) {
|
||||
await page.evaluate((text) => {
|
||||
const els = Array.from(document.querySelectorAll('div,span,button,li'));
|
||||
const target = els.filter(el => el.textContent.trim() === text && el.offsetParent).pop();
|
||||
if (target) target.click();
|
||||
}, t.clickText);
|
||||
await page.waitForTimeout(250);
|
||||
}
|
||||
|
||||
// 解除 phone-shell 高度限制:短页面保底 844,长页面按内容展开
|
||||
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`);
|
||||
await page.close();
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
console.log(`\n完成!共截取 ${tasks.length} 张`);
|
||||
})();
|
||||
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 53 KiB |
@@ -675,7 +675,7 @@ stateDiagram-v2
|
||||
- 周历(含月历弹窗):日期用彩色圆环标记来源(自记/蓝牙称/体重秤/体脂仪),圆环下方显示来源文字标签(自记/蓝牙称/体重秤/体脂仪)
|
||||
- 当日最新记录区:体重(大字)+ 较上次变化 + BMI(含偏瘦/正常/超重/肥胖标签)+ 体脂率/腰围 + 时间 + 来源标签
|
||||
- 数据来源卡片:四张来源小卡(体重秤/蓝牙称/体脂仪/自记,各显示该来源最近一次体重值,无记录显示"尚未记录"),点击体重秤/蓝牙称/体脂仪卡片查看当日该来源体重记录,点击自记卡片打开记录体重弹窗
|
||||
- 变化趋势卡片:时间范围(周/月/季/年/活动期间)+ 三 Tab(体重变化/体脂变化/腰围变化),各含统计行(平均/最大/最小/变化)+ 折线图(初始线/目标线/推荐范围/实际趋势 + 数据点悬浮提示)
|
||||
- 变化趋势卡片:时间范围(周/月/季/年/活动期间)+ 三 T························································································································································································································································································································ ab(体重变化/体脂变化/腰围变化),各含统计行(平均/最大/最小/变化)+ 折线图(初始线/目标线/推荐范围/实际趋势 + 数据点悬浮提示)
|
||||
- 记录明细列表:日期 + 时间 + 体重 + 体脂/腰围 + 来源标签;非自记来源带箭头可点击
|
||||
- 记录体重弹窗:记录体重(必填)+ 记录体脂率(开关)+ 记录腰围(开关),滑动尺子调整数值 + 保存
|
||||
|
||||
|
||||