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(体重变化/体脂变化/腰围变化),各含统计行(平均/最大/最小/变化)+ 折线图(初始线/目标线/推荐范围/实际趋势 + 数据点悬浮提示)
|
||||
- 记录明细列表:日期 + 时间 + 体重 + 体脂/腰围 + 来源标签;非自记来源带箭头可点击
|
||||
- 记录体重弹窗:记录体重(必填)+ 记录体脂率(开关)+ 记录腰围(开关),滑动尺子调整数值 + 保存
|
||||
|
||||
|
||||
@@ -237,9 +237,9 @@ const SITE_MAP = [
|
||||
{ file:'pre-cta-plan-mgmt.html', label:'冠脉CTA单位体检计划管理' },
|
||||
{ file:'pre-special-cta.html', label:'冠脉CTA体检人员' },
|
||||
{ file:'pre-special-hospital.html', label:'指定员工体检医院' },
|
||||
{ file:'mid-appointment-track.html', label:'员工预约跟踪' },
|
||||
{ file:'mid-selected-items.html', label:'已选项目员工信息' },
|
||||
{ file:'mid-participation.html', label:'员工参检情况' },
|
||||
{ file:'mid-appointment-track.html', label:'体检预约' },
|
||||
{ file:'mid-selected-items.html', label:'已选项目' },
|
||||
{ file:'mid-participation.html', label:'已检员工' },
|
||||
{ file:'mid-unit-appointment.html', label:'单位预约人数统计' },
|
||||
{ file:'mid-hospital-realtime.html', label:'医院实时预约人数' },
|
||||
{ file:'mid-doctor-realtime.html', label:'医生实时检查情况' },
|
||||
@@ -659,7 +659,7 @@ const SITE_MAP = [
|
||||
{ name:'应用主页', dir:'employee-app/home', entry:'index.html', pages:[
|
||||
{n:'应用主页(收起态)',f:'index.html'},
|
||||
] },
|
||||
{ name:'健康体检', dir:'employee-app/health-checkup', entry:'index.html', pages:[
|
||||
{ name:'健康体检', dir:'employee-app/health-checkup', entry:'index.html', prd:'employee-app/health-checkup/doc/PRD.md', pages:[
|
||||
{ file:'index.html', label:'健康体检主页' },
|
||||
{ file:'index-inactive.html', label:'健康体检-未开展' },
|
||||
{ file:'booking-type.html', label:'选择体检类型' },
|
||||
|
||||
@@ -119,6 +119,15 @@
|
||||
.report-sub__title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:14px 0 8px;}
|
||||
.report-sub:first-of-type .report-sub__title{margin-top:0;}
|
||||
.result-abnormal{color:var(--danger);font-weight:600;}
|
||||
/* 体检年份选择控件 */
|
||||
.year-picker{position:relative;}
|
||||
.year-picker .filter-input{padding-right:30px;cursor:pointer;}
|
||||
.year-picker>svg{position:absolute;right:9px;top:50%;transform:translateY(-50%);pointer-events:none;}
|
||||
.year-picker__dropdown{display:none;position:absolute;top:40px;left:0;width:120px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-md);z-index:50;max-height:180px;overflow-y:auto;}
|
||||
.year-picker__dropdown.open{display:block;}
|
||||
.year-picker__dropdown div{padding:8px 14px;font-size:var(--font-sm);cursor:pointer;}
|
||||
.year-picker__dropdown div:hover{background:var(--primary-light);}
|
||||
.year-picker__dropdown div.selected{color:var(--primary);font-weight:600;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -159,10 +168,16 @@
|
||||
<!-- 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>体检年份:</label>
|
||||
<select class="filter-select" style="min-width:90px;">
|
||||
<option>2026</option><option>2025</option><option>2024</option>
|
||||
</select>
|
||||
<label>体检年份:</label>
|
||||
<div class="year-picker">
|
||||
<input class="filter-input" type="text" readonly value="2026" style="min-width:90px;">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="1.5" y="2.5" width="11" height="10" rx="1.5" stroke="#999" stroke-width="1.2"/><path d="M1.5 5.5h11M4.5 1v3M9.5 1v3" stroke="#999" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||||
<div class="year-picker__dropdown">
|
||||
<div class="selected" onclick="pickYear(this)">2026</div>
|
||||
<div onclick="pickYear(this)">2025</div>
|
||||
<div onclick="pickYear(this)">2024</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>单位部门:</label>
|
||||
@@ -573,6 +588,25 @@ function resetFilter(){
|
||||
showToast('已重置筛选条件');
|
||||
}
|
||||
renderBigTable();
|
||||
/* 体检年份选择控件 */
|
||||
function pickYear(el){
|
||||
var dp=el.parentElement,input=dp.parentElement.querySelector('input');
|
||||
input.value=el.textContent;
|
||||
dp.querySelectorAll('div').forEach(function(d){d.classList.toggle('selected',d===el);});
|
||||
dp.classList.remove('open');
|
||||
}
|
||||
document.querySelectorAll('.year-picker>input').forEach(function(inp){
|
||||
inp.addEventListener('click',function(e){
|
||||
e.stopPropagation();
|
||||
var dp=inp.parentElement.querySelector('.year-picker__dropdown');
|
||||
var wasOpen=dp.classList.contains('open');
|
||||
document.querySelectorAll('.year-picker__dropdown.open').forEach(function(d){d.classList.remove('open');});
|
||||
if(!wasOpen)dp.classList.add('open');
|
||||
});
|
||||
});
|
||||
document.addEventListener('click',function(){
|
||||
document.querySelectorAll('.year-picker__dropdown.open').forEach(function(d){d.classList.remove('open');});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -110,6 +110,15 @@
|
||||
.modal__footer{display:flex;align-items:center;justify-content:space-between;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.pager{display:flex;align-items:center;gap:6px;}
|
||||
.pager .page-btn{width:28px;height:28px;}
|
||||
/* 体检年份选择控件 */
|
||||
.year-picker{position:relative;}
|
||||
.year-picker .filter-input{padding-right:30px;cursor:pointer;}
|
||||
.year-picker>svg{position:absolute;right:9px;top:50%;transform:translateY(-50%);pointer-events:none;}
|
||||
.year-picker__dropdown{display:none;position:absolute;top:40px;left:0;width:120px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-md);z-index:50;max-height:180px;overflow-y:auto;}
|
||||
.year-picker__dropdown.open{display:block;}
|
||||
.year-picker__dropdown div{padding:8px 14px;font-size:var(--font-sm);cursor:pointer;}
|
||||
.year-picker__dropdown div:hover{background:var(--primary-light);}
|
||||
.year-picker__dropdown div.selected{color:var(--primary);font-weight:600;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -156,10 +165,16 @@
|
||||
<!-- 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>体检年份</label>
|
||||
<select class="filter-select" style="min-width:90px;">
|
||||
<option>2025</option><option>2024</option><option>2023</option>
|
||||
</select>
|
||||
<label>体检年份</label>
|
||||
<div class="year-picker">
|
||||
<input class="filter-input" type="text" readonly value="2025" style="min-width:90px;">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="1.5" y="2.5" width="11" height="10" rx="1.5" stroke="#999" stroke-width="1.2"/><path d="M1.5 5.5h11M4.5 1v3M9.5 1v3" stroke="#999" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||||
<div class="year-picker__dropdown">
|
||||
<div onclick="pickYear(this)">2026</div>
|
||||
<div class="selected" onclick="pickYear(this)">2025</div>
|
||||
<div onclick="pickYear(this)">2024</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>单位</label>
|
||||
@@ -261,7 +276,6 @@ var PERSON_EXTRA={
|
||||
9:['已选项目数',function(row,i){return 15+i%6;}],
|
||||
10:['预约日期',function(row,i){return personDate(row,i+5);}],
|
||||
11:['体检状态',function(){return '<span class="tag tag-green">已检</span>';}],
|
||||
12:['未检原因',function(row,i){return ['未预约','已预约未体检','弃检'][i%3];}],
|
||||
16:['异常指标',function(row,i){return ['血压 158/96 mmHg↑','尿酸 428 μmol/L↑','甘油三酯 1.80 mmol/L↑','总胆固醇 5.96 mmol/L↑','空腹血糖 8.2 mmol/L↑','BMI 28.4↑','低密度胆固醇 3.96 mmol/L↑','高密度胆固醇 0.89 mmol/L↓'][i%8];}],
|
||||
17:['CTA结论',function(row,i){return ['LAD 中段狭窄 25%(CAD-RADS 2)','钙化积分 Agatston 156(中度)','RCA 近段非钙化斑块、轻度狭窄','LCX 远段钙化斑块、CAD-RADS 2'][i%4];}],
|
||||
18:['筛查异常项',function(row,i){return ['Septin9 基因甲基化 阳性','CA724 ↑(38.6 U/mL)','便潜血 阳性','CEA ↑(6.2 ng/mL)'][i%4];}]
|
||||
@@ -297,17 +311,21 @@ function personRowData(i){
|
||||
var sex=(seed+i)%2?'女':'男';
|
||||
var name=SURNAMES[(seed*7+i)%10]+(sex==='男'?GIVEN_M[(seed+i)%8]:GIVEN_F[(seed+i)%8]);
|
||||
var code='CQ'+String(100000+PERSON_LIST.col*1000+i*13+Math.floor(i/10));
|
||||
var cells=[''+(i+1),name,code,sex,''+(28+(seed*7+i*11)%30),DEPTS[(seed+i*3)%8],row.hospital,personDate(row,i+1)];
|
||||
var extra=PERSON_EXTRA[PERSON_LIST.col];
|
||||
return [''+(i+1),name,code,sex,''+(28+(seed*7+i*11)%30),DEPTS[(seed+i*3)%8],row.hospital,personDate(row,i+1),String(extra[1](row,i)).replace(/<[^>]+>/g,'')];
|
||||
if(extra)cells.push(String(extra[1](row,i)).replace(/<[^>]+>/g,''));
|
||||
return cells;
|
||||
}
|
||||
function renderPersonPage(){
|
||||
var extra=PERSON_EXTRA[PERSON_LIST.col];
|
||||
document.getElementById('person-modal-head').innerHTML='<tr><th>序号</th><th>姓名</th><th>员工编号</th><th>性别</th><th>年龄</th><th>部门</th><th>体检医院</th><th>体检日期</th><th>'+extra[0]+'</th></tr>';
|
||||
var head='<tr><th>序号</th><th>姓名</th><th>员工编号</th><th>性别</th><th>年龄</th><th>部门</th><th>体检医院</th><th>体检日期</th>';
|
||||
if(extra)head+='<th>'+extra[0]+'</th>';
|
||||
document.getElementById('person-modal-head').innerHTML=head+'</tr>';
|
||||
var start=PERSON_LIST.page*10,html='';
|
||||
for(var i=start;i<Math.min(start+10,PERSON_LIST.total);i++){
|
||||
var cells=personRowData(i);
|
||||
/* 体检状态列回挂绿色标签样式 */
|
||||
if(PERSON_LIST.col===11)cells[8]='<span class="tag tag-green">'+cells[8]+'</span>';
|
||||
if(PERSON_LIST.col===11)cells[cells.length-1]='<span class="tag tag-green">'+cells[cells.length-1]+'</span>';
|
||||
html+='<tr><td>'+cells.join('</td><td>')+'</td></tr>';
|
||||
}
|
||||
document.getElementById('person-modal-body').innerHTML=html;
|
||||
@@ -321,7 +339,8 @@ function hidePersonList(){document.getElementById('person-modal').style.display=
|
||||
/* 导出当前口径全量人员名单(CSV,Excel 兼容) */
|
||||
function exportPersonList(){
|
||||
var extra=PERSON_EXTRA[PERSON_LIST.col];
|
||||
var head=['序号','姓名','员工编号','性别','年龄','部门','体检医院','体检日期',extra[0]];
|
||||
var head=['序号','姓名','员工编号','性别','年龄','部门','体检医院','体检日期'];
|
||||
if(extra)head.push(extra[0]);
|
||||
var rows=[head];
|
||||
for(var i=0;i<PERSON_LIST.total;i++)rows.push(personRowData(i));
|
||||
var csv=''+rows.map(function(r){return r.map(function(c){return '"'+String(c).replace(/"/g,'""')+'"';}).join(',');}).join('\r\n');
|
||||
@@ -362,6 +381,25 @@ function toggleSubgroup(header){
|
||||
var sub=active.closest('.sidebar-subgroup');
|
||||
if(sub)sub.classList.add('open');
|
||||
})();
|
||||
/* 体检年份选择控件 */
|
||||
function pickYear(el){
|
||||
var dp=el.parentElement,input=dp.parentElement.querySelector('input');
|
||||
input.value=el.textContent;
|
||||
dp.querySelectorAll('div').forEach(function(d){d.classList.toggle('selected',d===el);});
|
||||
dp.classList.remove('open');
|
||||
}
|
||||
document.querySelectorAll('.year-picker>input').forEach(function(inp){
|
||||
inp.addEventListener('click',function(e){
|
||||
e.stopPropagation();
|
||||
var dp=inp.parentElement.querySelector('.year-picker__dropdown');
|
||||
var wasOpen=dp.classList.contains('open');
|
||||
document.querySelectorAll('.year-picker__dropdown.open').forEach(function(d){d.classList.remove('open');});
|
||||
if(!wasOpen)dp.classList.add('open');
|
||||
});
|
||||
});
|
||||
document.addEventListener('click',function(){
|
||||
document.querySelectorAll('.year-picker__dropdown.open').forEach(function(d){d.classList.remove('open');});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -99,6 +99,18 @@
|
||||
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
.form-textarea{width:100%;min-height:84px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;resize:vertical;font-family:inherit;line-height:1.6;}
|
||||
.form-textarea:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
.form-item__hint{font-size:var(--font-xs);color:#999;margin-top:6px;}
|
||||
/* 富文本编辑器 */
|
||||
.rich-editor{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;background:#fff;}
|
||||
.rich-editor:focus-within{border-color:var(--primary);}
|
||||
.rich-editor__toolbar{display:flex;align-items:center;gap:2px;padding:8px;border-bottom:1px solid var(--border);background:#FAFAFA;flex-wrap:wrap;}
|
||||
.rich-tool{width:28px;height:28px;border:none;background:transparent;border-radius:var(--radius-sm);cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:14px;line-height:1;transition:all .15s;}
|
||||
.rich-tool:hover{background:var(--primary-light);color:var(--primary);}
|
||||
.rich-tool--wide{width:34px;font-size:12px;font-weight:600;}
|
||||
.rich-editor__divider{width:1px;height:16px;background:var(--border);margin:0 4px;flex-shrink:0;}
|
||||
.rich-editor__body{min-height:120px;padding:12px;font-size:var(--font-sm);color:var(--text-primary);line-height:1.8;outline:none;overflow-y:auto;max-height:260px;}
|
||||
.rich-editor__body:empty:before{content:attr(data-placeholder);color:#999;pointer-events:none;}
|
||||
.rich-editor__body ol,.rich-editor__body ul{padding-left:20px;margin:6px 0;}
|
||||
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 12px center;appearance:none;cursor:pointer;}
|
||||
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
/* 单选按钮 */
|
||||
@@ -200,6 +212,7 @@
|
||||
<div class="type-tabs">
|
||||
<div class="type-tab active" onclick="switchType('normal')">常规体检</div>
|
||||
<div class="type-tab" onclick="switchType('gastro')">胃肠镜体检</div>
|
||||
<div class="type-tab" onclick="switchType('cta')">冠脉CTA体检</div>
|
||||
</div>
|
||||
|
||||
<!-- 常规体检 -->
|
||||
@@ -224,12 +237,12 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th><th>医院名称</th><th>医院类型</th><th>医院地址</th><th>医院图片</th><th>医院简介</th><th>开启职业体检</th><th>开启冠脉CTA体检</th><th>排序序号</th><th>操作</th>
|
||||
<th>序号</th><th>医院名称</th><th>医院类型</th><th>医院地址</th><th>医院图片</th><th>医院简介</th><th>开启职业体检</th><th>排序序号</th><th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="normal-tbody">
|
||||
<tr><td>1</td><td>泾河医院</td><td>普通医院</td><td>西安市高陵区西安泾河开发区CQ西路20号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>西安宝石花CQ医院(高陵)</td><td>是</td><td>是</td><td>1</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
|
||||
<tr><td>2</td><td>庆阳医院</td><td>指定医院</td><td>甘肃省庆阳市西峰区岐黄大道18号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>庆阳市人民医院体检中心</td><td>是</td><td>否</td><td>2</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
|
||||
<tr><td>1</td><td>泾河医院</td><td>普通医院</td><td>西安市高陵区西安泾河开发区CQ西路20号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>西安宝石花CQ医院(高陵)</td><td>是</td><td>1</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
|
||||
<tr><td>2</td><td>庆阳医院</td><td>指定医院</td><td>甘肃省庆阳市西峰区岐黄大道18号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>庆阳市人民医院体检中心</td><td>是</td><td>2</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -280,6 +293,46 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 冠脉CTA体检 -->
|
||||
<div class="tab-pane" id="pane-cta">
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>医院名称</label>
|
||||
<input class="filter-input" type="text" placeholder="请输入" style="width:180px;">
|
||||
</div>
|
||||
<button class="btn btn-primary">查询</button>
|
||||
<button class="btn btn-default">重置</button>
|
||||
</div>
|
||||
<div style="display:flex;gap:12px;margin-bottom:16px;">
|
||||
<button class="btn btn-primary" onclick="openDrawer()">+ 新增</button>
|
||||
<button class="btn btn-default">导出列表数据</button>
|
||||
</div>
|
||||
<div class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div class="table-card__title">冠脉CTA体检医院信息</div>
|
||||
</div>
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th><th>医院名称</th><th>医院地址</th><th>医院图片</th><th>医院简介</th><th>排序序号</th><th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="cta-tbody">
|
||||
<tr><td>1</td><td>泾河医院</td><td>西安市高陵区西安泾河开发区CQ西路20号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>西安宝石花CQ医院(高陵)</td><td>1</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
|
||||
<tr><td>2</td><td>庆阳医院</td><td>甘肃省庆阳市西峰区岐黄大道18号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>庆阳市人民医院体检中心</td><td>2</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<span>显示 10 条,共 56 条</span>
|
||||
<button class="page-btn active">1</button>
|
||||
<span>每页</span>
|
||||
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>20条</option><option>50条</option></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 新增医院抽屉 -->
|
||||
@@ -321,13 +374,6 @@
|
||||
<span class="switch-label">是否开启职业体检</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">开启冠脉CTA体检</div>
|
||||
<div class="switch-row">
|
||||
<div class="switch" id="switch-cta" onclick="this.classList.toggle('on')"></div>
|
||||
<span class="switch-label">是否开启冠脉CTA体检</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">排序序号</div>
|
||||
<input class="form-input" id="form-sort-normal" type="number" placeholder="数字越小越靠前">
|
||||
@@ -349,13 +395,34 @@
|
||||
</div>
|
||||
<div class="form-item" id="card-reg-item" style="display:none;">
|
||||
<div class="form-label">就诊卡号注册说明</div>
|
||||
<textarea class="form-textarea" id="form-card-reg" placeholder="请输入就诊卡号注册说明"></textarea>
|
||||
<div class="rich-editor">
|
||||
<div class="rich-editor__toolbar">
|
||||
<button type="button" class="rich-tool" onmousedown="event.preventDefault()" onclick="richCmd('bold')" title="加粗" style="font-weight:700;">B</button>
|
||||
<button type="button" class="rich-tool" onmousedown="event.preventDefault()" onclick="richCmd('italic')" title="斜体" style="font-style:italic;">I</button>
|
||||
<button type="button" class="rich-tool" onmousedown="event.preventDefault()" onclick="richCmd('underline')" title="下划线" style="text-decoration:underline;">U</button>
|
||||
<span class="rich-editor__divider"></span>
|
||||
<button type="button" class="rich-tool rich-tool--wide" onmousedown="event.preventDefault()" onclick="richCmd('insertOrderedList')" title="编号列表">1.</button>
|
||||
<button type="button" class="rich-tool rich-tool--wide" onmousedown="event.preventDefault()" onclick="richCmd('insertUnorderedList')" title="项目符号">•</button>
|
||||
<span class="rich-editor__divider"></span>
|
||||
<button type="button" class="rich-tool rich-tool--wide" onmousedown="event.preventDefault()" onclick="richCmd('removeFormat')" title="清除格式">Tx</button>
|
||||
</div>
|
||||
<div class="rich-editor__body" id="form-card-reg" contenteditable="true" data-placeholder="请输入就诊卡号注册说明"></div>
|
||||
</div>
|
||||
<div class="form-item__hint">支持加粗、列表等富文本格式,员工端将按此展示</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">排序序号</div>
|
||||
<input class="form-input" id="form-sort-gastro" type="number" placeholder="数字越小越靠前">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 冠脉CTA体检字段 -->
|
||||
<div id="cta-fields" style="display:none;">
|
||||
<div class="form-item">
|
||||
<div class="form-label">排序序号</div>
|
||||
<input class="form-input" id="form-sort-cta" type="number" placeholder="数字越小越靠前">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
|
||||
@@ -420,21 +487,23 @@ function resetDrawerFields(){
|
||||
document.getElementById('hospital-info').classList.remove('show');
|
||||
document.getElementById('form-sort-normal').value = '';
|
||||
document.getElementById('form-sort-gastro').value = '';
|
||||
document.getElementById('form-sort-cta').value = '';
|
||||
document.querySelectorAll('input[name="hos-type"]').forEach(function(r){ r.checked = false; });
|
||||
document.getElementById('switch-oc').classList.remove('on');
|
||||
document.getElementById('switch-cta').classList.remove('on');
|
||||
document.getElementById('switch-card').classList.remove('on');
|
||||
document.getElementById('card-reg-item').style.display = 'none';
|
||||
document.getElementById('form-gastro-notice').value = '';
|
||||
document.getElementById('form-card-reg').value = '';
|
||||
document.getElementById('form-card-reg').innerHTML = '';
|
||||
}
|
||||
|
||||
function openDrawer(){
|
||||
editingRow = null;
|
||||
var isNormal = currentType === 'normal';
|
||||
document.getElementById('drawer-title').textContent = isNormal ? '新增常规体检医院' : '新增胃肠镜体检医院';
|
||||
var isCta = currentType === 'cta';
|
||||
document.getElementById('drawer-title').textContent = isNormal ? '新增常规体检医院' : (isCta ? '新增冠脉CTA体检医院' : '新增胃肠镜体检医院');
|
||||
document.getElementById('normal-fields').style.display = isNormal ? '' : 'none';
|
||||
document.getElementById('gastro-fields').style.display = isNormal ? 'none' : '';
|
||||
document.getElementById('gastro-fields').style.display = currentType === 'gastro' ? '' : 'none';
|
||||
document.getElementById('cta-fields').style.display = isCta ? '' : 'none';
|
||||
resetDrawerFields();
|
||||
setHospitalLocked(false);
|
||||
document.getElementById('hospital-drawer').classList.add('open');
|
||||
@@ -451,6 +520,7 @@ function readTd(tr, i){
|
||||
function openEditDrawer(btn){
|
||||
editingRow = btn.closest('tr');
|
||||
var isNormal = currentType === 'normal';
|
||||
var isCta = currentType === 'cta';
|
||||
resetDrawerFields();
|
||||
if(isNormal){
|
||||
document.getElementById('drawer-title').textContent = '编辑常规体检医院';
|
||||
@@ -459,8 +529,14 @@ function openEditDrawer(btn){
|
||||
setHospitalLocked(true, readTd(editingRow, 1), readTd(editingRow, 3));
|
||||
document.querySelectorAll('input[name="hos-type"]').forEach(function(r){ r.checked = (r.value === readTd(editingRow, 2)); });
|
||||
document.getElementById('switch-oc').classList.toggle('on', readTd(editingRow, 6) === '是');
|
||||
document.getElementById('switch-cta').classList.toggle('on', readTd(editingRow, 7) === '是');
|
||||
document.getElementById('form-sort-normal').value = readTd(editingRow, 8);
|
||||
document.getElementById('form-sort-normal').value = readTd(editingRow, 7);
|
||||
} else if(isCta){
|
||||
document.getElementById('drawer-title').textContent = '编辑冠脉CTA体检医院';
|
||||
document.getElementById('normal-fields').style.display = 'none';
|
||||
document.getElementById('gastro-fields').style.display = 'none';
|
||||
document.getElementById('cta-fields').style.display = '';
|
||||
setHospitalLocked(true, readTd(editingRow, 1), readTd(editingRow, 2));
|
||||
document.getElementById('form-sort-cta').value = readTd(editingRow, 5);
|
||||
} else {
|
||||
document.getElementById('drawer-title').textContent = '编辑胃肠镜体检医院';
|
||||
document.getElementById('normal-fields').style.display = 'none';
|
||||
@@ -471,7 +547,7 @@ function openEditDrawer(btn){
|
||||
document.getElementById('card-reg-item').style.display = needCard ? '' : 'none';
|
||||
document.getElementById('form-sort-gastro').value = readTd(editingRow, 6);
|
||||
document.getElementById('form-gastro-notice').value = editingRow.dataset.notice || '';
|
||||
document.getElementById('form-card-reg').value = editingRow.dataset.cardreg || '';
|
||||
document.getElementById('form-card-reg').innerHTML = editingRow.dataset.cardreg || '';
|
||||
}
|
||||
document.getElementById('hospital-drawer').classList.add('open');
|
||||
document.getElementById('drawer-overlay').classList.add('open');
|
||||
@@ -482,6 +558,12 @@ function closeDrawer(){
|
||||
document.getElementById('drawer-overlay').classList.remove('open');
|
||||
}
|
||||
|
||||
/* 富文本编辑器命令 */
|
||||
function richCmd(cmd){
|
||||
document.execCommand(cmd, false, null);
|
||||
document.getElementById('form-card-reg').focus();
|
||||
}
|
||||
|
||||
function toggleCardSwitch(el){
|
||||
el.classList.toggle('on');
|
||||
var on = el.classList.contains('on');
|
||||
@@ -563,7 +645,7 @@ function refreshSeq(tbody){
|
||||
}
|
||||
|
||||
/* 生成常规体检行 HTML */
|
||||
function buildNormalRow(data, hosType, oc, cta, sort){
|
||||
function buildNormalRow(data, hosType, oc, sort){
|
||||
return '<td></td>'
|
||||
+ '<td>' + data.name + '</td>'
|
||||
+ '<td>' + hosType + '</td>'
|
||||
@@ -571,7 +653,17 @@ function buildNormalRow(data, hosType, oc, cta, sort){
|
||||
+ '<td><img class="hospital-img" src="' + HOSPITAL_IMG + '" alt="医院图片"></td>'
|
||||
+ '<td>' + data.intro + '</td>'
|
||||
+ '<td>' + (oc ? '是' : '否') + '</td>'
|
||||
+ '<td>' + (cta ? '是' : '否') + '</td>'
|
||||
+ '<td>' + sort + '</td>'
|
||||
+ ROW_ACTIONS;
|
||||
}
|
||||
|
||||
/* 生成冠脉CTA体检行 HTML */
|
||||
function buildCtaRow(data, sort){
|
||||
return '<td></td>'
|
||||
+ '<td>' + data.name + '</td>'
|
||||
+ '<td>' + data.address + '</td>'
|
||||
+ '<td><img class="hospital-img" src="' + HOSPITAL_IMG + '" alt="医院图片"></td>'
|
||||
+ '<td>' + data.intro + '</td>'
|
||||
+ '<td>' + sort + '</td>'
|
||||
+ ROW_ACTIONS;
|
||||
}
|
||||
@@ -591,27 +683,29 @@ function buildGastroRow(data, needCard, sort){
|
||||
/* 保存(新增或编辑) */
|
||||
function saveHospital(){
|
||||
var isNormal = currentType === 'normal';
|
||||
var tbody = document.getElementById(isNormal ? 'normal-tbody' : 'gastro-tbody');
|
||||
var isCta = currentType === 'cta';
|
||||
var tbody = document.getElementById(isNormal ? 'normal-tbody' : (isCta ? 'cta-tbody' : 'gastro-tbody'));
|
||||
|
||||
if(editingRow){
|
||||
/* 编辑:医院不变,更新可变列 */
|
||||
if(isNormal){
|
||||
var hosTypeEl = document.querySelector('input[name="hos-type"]:checked');
|
||||
if(!hosTypeEl){ alert('请选择医院类型'); return; }
|
||||
var sort = document.getElementById('form-sort-normal').value.trim() || editingRow.children[8].textContent.trim();
|
||||
var sort = document.getElementById('form-sort-normal').value.trim() || editingRow.children[7].textContent.trim();
|
||||
var oc = document.getElementById('switch-oc').classList.contains('on');
|
||||
var cta = document.getElementById('switch-cta').classList.contains('on');
|
||||
editingRow.children[2].textContent = hosTypeEl.value;
|
||||
editingRow.children[6].textContent = oc ? '是' : '否';
|
||||
editingRow.children[7].textContent = cta ? '是' : '否';
|
||||
editingRow.children[8].textContent = sort;
|
||||
editingRow.children[7].textContent = sort;
|
||||
} else if(isCta){
|
||||
var sortC = document.getElementById('form-sort-cta').value.trim() || editingRow.children[5].textContent.trim();
|
||||
editingRow.children[5].textContent = sortC;
|
||||
} else {
|
||||
var needCard = document.getElementById('switch-card').classList.contains('on');
|
||||
var sortG = document.getElementById('form-sort-gastro').value.trim() || editingRow.children[6].textContent.trim();
|
||||
editingRow.children[5].textContent = needCard ? '是' : '否';
|
||||
editingRow.children[6].textContent = sortG;
|
||||
editingRow.dataset.notice = document.getElementById('form-gastro-notice').value;
|
||||
editingRow.dataset.cardreg = document.getElementById('form-card-reg').value;
|
||||
editingRow.dataset.cardreg = document.getElementById('form-card-reg').innerHTML;
|
||||
}
|
||||
closeDrawer();
|
||||
return;
|
||||
@@ -627,13 +721,16 @@ function saveHospital(){
|
||||
var hosTypeEl = document.querySelector('input[name="hos-type"]:checked');
|
||||
if(!hosTypeEl){ alert('请选择医院类型'); return; }
|
||||
var sort = document.getElementById('form-sort-normal').value.trim() || String(seq);
|
||||
tr.innerHTML = buildNormalRow(data, hosTypeEl.value, document.getElementById('switch-oc').classList.contains('on'), document.getElementById('switch-cta').classList.contains('on'), sort);
|
||||
tr.innerHTML = buildNormalRow(data, hosTypeEl.value, document.getElementById('switch-oc').classList.contains('on'), sort);
|
||||
} else if(isCta){
|
||||
var sortC = document.getElementById('form-sort-cta').value.trim() || String(seq);
|
||||
tr.innerHTML = buildCtaRow(data, sortC);
|
||||
} else {
|
||||
var needCard = document.getElementById('switch-card').classList.contains('on');
|
||||
var sortG = document.getElementById('form-sort-gastro').value.trim() || String(seq);
|
||||
tr.innerHTML = buildGastroRow(data, needCard, sortG);
|
||||
tr.dataset.notice = document.getElementById('form-gastro-notice').value;
|
||||
tr.dataset.cardreg = document.getElementById('form-card-reg').value;
|
||||
tr.dataset.cardreg = document.getElementById('form-card-reg').innerHTML;
|
||||
}
|
||||
tbody.appendChild(tr);
|
||||
tr.children[0].textContent = seq;
|
||||
|
||||
@@ -296,11 +296,11 @@ function toggleSubgroup(header){
|
||||
})();
|
||||
|
||||
/* ===== 组合配置交互 ===== */
|
||||
/* 各医院体检项目 */
|
||||
/* 各医院体检项目(实际项目名称) */
|
||||
var comboHospitals = {
|
||||
'泾河医院': ['一般检查','血常规','尿常规','肝功能','肾功能','血脂四项','空腹血糖','心电图','胸部X光','腹部B超','甲状腺彩超','肿瘤标志物','胃镜检查','肠镜检查'],
|
||||
'庆阳医院': ['一般检查','血常规','尿常规','肝功能','肾功能','血脂四项','空腹血糖','心电图','胸部X光','腹部B超','甲状腺彩超'],
|
||||
'长安胃肠镜医院': ['胃镜检查','肠镜检查','幽门螺杆菌检测','无痛胃镜','无痛肠镜','胶囊内镜']
|
||||
'泾河医院': ['乙肝六项','肝功十一项','胸部CT平扫','小心肌酶四项','甲状腺彩超','颈部血管彩超(颈动脉、椎动脉、锁骨下动脉)','心电图检查','甲胎蛋白','癌胚抗原','糖类抗原199'],
|
||||
'庆阳医院': ['乙肝六项','肝功十一项','小心肌酶四项','甲状腺彩超','心电图检查','甲胎蛋白','癌胚抗原','糖类抗原199'],
|
||||
'长安胃肠镜医院': ['普通胃镜检查','无痛胃镜检查','普通肠镜检查','无痛肠镜检查','胶囊内镜检查','幽门螺杆菌碳13呼气试验']
|
||||
};
|
||||
|
||||
var editingComboRow = null; // 新增/编辑组合对应的行
|
||||
@@ -364,6 +364,10 @@ function openItemsDrawer(btn){
|
||||
configuringRow = btn.closest('tr');
|
||||
currentHospital = configuringRow.dataset.hospital || '';
|
||||
selectedItems = configuringRow.dataset.items ? configuringRow.dataset.items.split('|') : [];
|
||||
/* 未配置过时默认勾选前3项 */
|
||||
if(!selectedItems.length){
|
||||
selectedItems = (comboHospitals[currentHospital] || []).slice(0, 3);
|
||||
}
|
||||
document.getElementById('items-drawer-title').textContent = '配置组合项 - ' + (configuringRow.dataset.name || '');
|
||||
document.getElementById('items-hospital-label').textContent = currentHospital;
|
||||
document.getElementById('items-search').value = '';
|
||||
|
||||
@@ -234,28 +234,28 @@
|
||||
<table id="guide-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>排序</th><th>标题</th><th>讲解类型</th><th>简介</th><th>操作</th>
|
||||
<th>标题</th><th>讲解类型</th><th>排序</th><th>简介</th><th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr data-title="体检预约流程" data-type="image" data-desc="选择医院、项目、日期,完成体检预约" data-sort="1" data-content="<ol><li>打开「健康体检」,点击「体检预约」进入预约页面</li><li>选择体检医院与体检项目(常规体检 / 胃肠镜体检)</li><li>选择体检日期与时间段</li><li>确认预约信息,预约成功后可在「我的预约」中查看</li></ol>">
|
||||
<td>1</td><td>体检预约流程</td><td><span class="tag tag-blue">图文讲解</span></td><td>选择医院、项目、日期,完成体检预约</td>
|
||||
<td>体检预约流程</td><td><span class="tag tag-blue">图文讲解</span></td><td>1</td><td>选择医院、项目、日期,完成体检预约</td>
|
||||
<td><span class="link" onclick="previewGuide(this)">预览</span> <span class="link" onclick="editRow(this)" style="margin-left:8px;">编辑</span> <span class="link" onclick="deleteRow(this)" style="margin-left:8px;">删除</span></td>
|
||||
</tr>
|
||||
<tr data-title="到院体检流程" data-type="image" data-desc="前台登记、逐项检查、领取报告" data-sort="2" data-content="<ol><li>前台登记:携带身份证到体检中心前台登记</li><li>缴费确认:核对单位信息与体检项目</li><li>逐项检查:按指引单到各科室完成检查</li><li>交回指引单:检查完成后将指引单交回前台</li><li>领取报告:报告生成后在线查看或到院领取</li></ol>">
|
||||
<td>2</td><td>到院体检流程</td><td><span class="tag tag-blue">图文讲解</span></td><td>前台登记、逐项检查、领取报告</td>
|
||||
<td>到院体检流程</td><td><span class="tag tag-blue">图文讲解</span></td><td>2</td><td>前台登记、逐项检查、领取报告</td>
|
||||
<td><span class="link" onclick="previewGuide(this)">预览</span> <span class="link" onclick="editRow(this)" style="margin-left:8px;">编辑</span> <span class="link" onclick="deleteRow(this)" style="margin-left:8px;">删除</span></td>
|
||||
</tr>
|
||||
<tr data-title="报告查询流程" data-type="image" data-desc="查看报告列表与指标解读详情" data-sort="3" data-content="<ol><li>进入「体检报告」页面</li><li>查看报告列表与最新报告</li><li>点击查看报告详情与指标解读</li></ol>">
|
||||
<td>3</td><td>报告查询流程</td><td><span class="tag tag-blue">图文讲解</span></td><td>查看报告列表与指标解读详情</td>
|
||||
<td>报告查询流程</td><td><span class="tag tag-blue">图文讲解</span></td><td>3</td><td>查看报告列表与指标解读详情</td>
|
||||
<td><span class="link" onclick="previewGuide(this)">预览</span> <span class="link" onclick="editRow(this)" style="margin-left:8px;">编辑</span> <span class="link" onclick="deleteRow(this)" style="margin-left:8px;">删除</span></td>
|
||||
</tr>
|
||||
<tr data-title="胃肠镜检查流程" data-type="video" data-desc="检查前准备与检查过程讲解" data-sort="4" data-cover="">
|
||||
<td>4</td><td>胃肠镜检查流程</td><td><span class="tag tag-green">视频讲解</span></td><td>检查前准备与检查过程讲解</td>
|
||||
<td>胃肠镜检查流程</td><td><span class="tag tag-green">视频讲解</span></td><td>4</td><td>检查前准备与检查过程讲解</td>
|
||||
<td><span class="link" onclick="previewGuide(this)">预览</span> <span class="link" onclick="editRow(this)" style="margin-left:8px;">编辑</span> <span class="link" onclick="deleteRow(this)" style="margin-left:8px;">删除</span></td>
|
||||
</tr>
|
||||
<tr data-title="体检注意事项" data-type="video" data-desc="体检前饮食、作息等准备事项讲解" data-sort="5" data-cover="">
|
||||
<td>5</td><td>体检注意事项</td><td><span class="tag tag-green">视频讲解</span></td><td>体检前饮食、作息等准备事项讲解</td>
|
||||
<td>体检注意事项</td><td><span class="tag tag-green">视频讲解</span></td><td>5</td><td>体检前饮食、作息等准备事项讲解</td>
|
||||
<td><span class="link" onclick="previewGuide(this)">预览</span> <span class="link" onclick="editRow(this)" style="margin-left:8px;">编辑</span> <span class="link" onclick="deleteRow(this)" style="margin-left:8px;">删除</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -546,9 +546,9 @@ function saveGuide(){
|
||||
tr.dataset.cover = data.cover || '';
|
||||
delete tr.dataset.content;
|
||||
}
|
||||
tr.innerHTML = '<td>'+data.sort+'</td>'
|
||||
+ '<td>'+data.title+'</td>'
|
||||
tr.innerHTML = '<td>'+data.title+'</td>'
|
||||
+ '<td>'+renderTypeTag(data.type)+'</td>'
|
||||
+ '<td>'+data.sort+'</td>'
|
||||
+ '<td>'+data.desc+'</td>'
|
||||
+ '<td><span class="link" onclick="previewGuide(this)">预览</span> <span class="link" onclick="editRow(this)" style="margin-left:8px;">编辑</span> <span class="link" onclick="deleteRow(this)" style="margin-left:8px;">删除</span></td>';
|
||||
closeModal();
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>触发时间</th><th>同步人</th><th>状态</th>
|
||||
<th>触发时间</th><th>同步人</th><th>状态</th><th>同步数据信息</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sync-task-tbody"></tbody>
|
||||
@@ -272,6 +272,30 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 同步数据信息弹窗 -->
|
||||
<div class="modal-overlay" id="sync-detail-modal" onclick="if(event.target===this)closeSyncDetailModal()">
|
||||
<div class="modal modal--wide">
|
||||
<div class="modal__header">
|
||||
<div class="modal__title">同步数据信息</div>
|
||||
<button class="modal__close" onclick="closeSyncDetailModal()">✕</button>
|
||||
</div>
|
||||
<div class="modal__body">
|
||||
<div id="sync-detail-meta" style="font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:12px;"></div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th><th>医院</th><th>体检项目编码</th><th>体检项目名称</th><th>关联体检基本项</th><th>关联医院系统项目</th><th>同步结果</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sync-detail-tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeSyncDetailModal()">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* 侧边栏展开/折叠交互 */
|
||||
function toggleSubgroup(header){
|
||||
@@ -360,10 +384,29 @@ function todayStr(){
|
||||
|
||||
/* ===== 同步医院体检项目 & 同步任务记录 ===== */
|
||||
var syncTasks = [
|
||||
{ time: '2026-08-28 09:12:30', user: '系统管理员', status: 'success' },
|
||||
{ time: '2026-08-20 14:05:12', user: '系统管理员', status: 'success' }
|
||||
{ time: '2026-08-28 09:12:30', user: '系统管理员', status: 'success', items: [
|
||||
{ hospital: '泾河医院', code: 'JH-XM012', name: '胃镜检查', basic: 'XM012(胃镜)', sys: '胃镜检查套餐', action: '新增' },
|
||||
{ hospital: '泾河医院', code: 'JH-XM013', name: '肠镜检查', basic: 'XM013(肠镜)', sys: '肠镜检查套餐', action: '新增' },
|
||||
{ hospital: '泾河医院', code: 'JH-XM002', name: '体重测量', basic: 'XM002(体重)', sys: '身高体重检测, 基础体检套餐', action: '更新' }
|
||||
]},
|
||||
{ time: '2026-08-20 14:05:12', user: '系统管理员', status: 'success', items: [
|
||||
{ hospital: '泾河医院', code: 'JH-XM010', name: '甲状腺彩超', basic: 'XM010(甲状腺)', sys: '甲状腺检查套餐', action: '新增' },
|
||||
{ hospital: '庆阳医院', code: 'QY-XM003', name: '血压检测', basic: 'XM004(血压)', sys: '内科常规, 深度体检套餐', action: '更新' }
|
||||
]}
|
||||
];
|
||||
|
||||
/* 模拟一次同步拉取到的增量项目 */
|
||||
function makeSyncItems(){
|
||||
var pool = [
|
||||
{ hospital: '泾河医院', code: 'JH-XM015', name: '糖类抗原199', basic: 'XM015(糖类抗原)', sys: '肿瘤标志物套餐', action: '新增' },
|
||||
{ hospital: '泾河医院', code: 'JH-XM016', name: '甲胎蛋白', basic: 'XM016(甲胎蛋白)', sys: '肿瘤标志物套餐', action: '新增' },
|
||||
{ hospital: '泾河医院', code: 'JH-XM001', name: '身高测量', basic: 'XM001(身高)', sys: '身高体重检测, 基础体检套餐', action: '更新' },
|
||||
{ hospital: '庆阳医院', code: 'QY-XM008', name: '癌胚抗原', basic: 'XM008(癌胚抗原)', sys: '肿瘤标志物套餐', action: '新增' }
|
||||
];
|
||||
var n = 2 + Math.floor(Math.random() * 3);
|
||||
return pool.slice(0, n);
|
||||
}
|
||||
|
||||
function nowTimeStr(){
|
||||
var d = new Date();
|
||||
var p = function(n){ return String(n).padStart(2, '0'); };
|
||||
@@ -377,21 +420,45 @@ function syncStatusTag(status){
|
||||
return '<span class="tag tag-green">成功</span>';
|
||||
}
|
||||
|
||||
function syncActionTag(action){
|
||||
if(action === '更新') return '<span class="tag tag-green">更新</span>';
|
||||
if(action === '失败') return '<span class="tag tag-red">失败</span>';
|
||||
return '<span class="tag tag-blue">新增</span>';
|
||||
}
|
||||
|
||||
function renderSyncTasks(){
|
||||
var tbody = document.getElementById('sync-task-tbody');
|
||||
if(!tbody) return;
|
||||
if(!syncTasks.length){
|
||||
tbody.innerHTML = '<tr><td colspan="3" style="text-align:center;color:var(--text-placeholder);">暂无同步任务</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="4" style="text-align:center;color:var(--text-placeholder);">暂无同步任务</td></tr>';
|
||||
return;
|
||||
}
|
||||
tbody.innerHTML = syncTasks.map(function(t){
|
||||
return '<tr><td>' + t.time + '</td><td>' + t.user + '</td><td>' + syncStatusTag(t.status) + '</td></tr>';
|
||||
tbody.innerHTML = syncTasks.map(function(t, i){
|
||||
return '<tr><td>' + t.time + '</td><td>' + t.user + '</td><td>' + syncStatusTag(t.status) + '</td>'
|
||||
+ '<td><span class="link" onclick="openSyncDetail(' + i + ')">查看详情</span></td></tr>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
/* 查看某次同步的具体项目信息 */
|
||||
function openSyncDetail(idx){
|
||||
var t = syncTasks[idx];
|
||||
if(!t) return;
|
||||
var items = t.items || [];
|
||||
document.getElementById('sync-detail-meta').textContent = '触发时间:' + t.time + ' 同步人:' + t.user + ' 共同步 ' + items.length + ' 条';
|
||||
document.getElementById('sync-detail-tbody').innerHTML = items.length
|
||||
? items.map(function(it, i){
|
||||
return '<tr><td>' + (i + 1) + '</td><td>' + it.hospital + '</td><td>' + it.code + '</td><td>' + it.name + '</td><td>' + it.basic + '</td><td>' + it.sys + '</td><td>' + syncActionTag(it.action) + '</td></tr>';
|
||||
}).join('')
|
||||
: '<tr><td colspan="7" style="text-align:center;color:var(--text-placeholder);">暂无同步数据</td></tr>';
|
||||
document.getElementById('sync-detail-modal').classList.add('open');
|
||||
}
|
||||
function closeSyncDetailModal(){
|
||||
document.getElementById('sync-detail-modal').classList.remove('open');
|
||||
}
|
||||
|
||||
function syncHospitalItems(){
|
||||
if(!confirm('是否从医院同步增量体检项目?')) return;
|
||||
var task = { time: nowTimeStr(), user: '系统管理员', status: 'running' };
|
||||
var task = { time: nowTimeStr(), user: '系统管理员', status: 'running', items: makeSyncItems() };
|
||||
syncTasks.unshift(task);
|
||||
renderSyncTasks();
|
||||
/* 模拟异步同步:2 秒后完成 */
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 健康体检模块 CHANGELOG
|
||||
|
||||
## [Unreleased] 2026-09-14
|
||||
|
||||
### Changed
|
||||
- `archive-unit.html`(档案/单位报表数据):未检人数人员弹窗移除"未检原因"附加列——PERSON_EXTRA 删除 12 号口径映射,弹窗表头与行数据不再包含该列(未检人数口径仅展示序号/姓名/员工编号/性别/年龄/部门/体检医院/体检日期 8 列基础信息);personRowData/renderPersonPage/exportPersonList 改为按 PERSON_EXTRA 是否存在附加列动态拼装表头、行与导出 CSV(已检人数的"已检"绿标签改挂末列,不受列数变化影响),其余 7 个可点击口径弹窗行为不变;mock DOM 回归(未检 8 列、已检 9 列含绿标签、导出 CSV 表头/数据行均 8 字段且无"未检原因")与内联脚本语法校验通过
|
||||
|
||||
## [Unreleased] 2026-09-08
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* 健康体检(管理端)PRD 截图生成脚本
|
||||
*
|
||||
* 用法:在 web-admin/health-checkup 目录下执行 node doc/screenshot-prd.js
|
||||
* 依赖:playwright(npm i playwright && npx playwright install chromium)
|
||||
* 输出:doc/screenshots/*.jpg(与 doc/PRD.md 中  引用一一对应)
|
||||
*
|
||||
* 说明:仅做页面级整屏截图(1440×900 视口),不模拟任何点击交互;
|
||||
* 页面为纯静态原型,file:// 直接加载即可完整渲染。
|
||||
*/
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { chromium } = require('playwright');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const OUT_DIR = path.join(__dirname, 'screenshots');
|
||||
|
||||
const TASKS = [
|
||||
// 一、档案
|
||||
{ page: 'archive-personal.html', output: 'archive-personal.jpg' },
|
||||
{ page: 'archive-unit.html', output: 'archive-unit.jpg' },
|
||||
// 二、基础配置
|
||||
{ page: 'config-material-notice.html', output: 'config-material-notice.jpg' },
|
||||
{ page: 'config-material-video.html', output: 'config-material-video.jpg' },
|
||||
{ page: 'config-hospital-basic.html', output: 'config-hospital-basic.jpg' },
|
||||
{ page: 'config-hospital-combo.html', output: 'config-hospital-combo.jpg' },
|
||||
{ page: 'config-report-template.html', output: 'config-report-template.jpg' },
|
||||
{ page: 'config-standard-category.html', output: 'config-standard-category.jpg' },
|
||||
{ page: 'config-standard-basic.html', output: 'config-standard-basic.jpg' },
|
||||
{ page: 'config-standard-hospital.html', output: 'config-standard-hospital.jpg' },
|
||||
// 三、检前 · 常规体检
|
||||
{ page: 'pre-hospital-scope.html', output: 'pre-hospital-scope.jpg' },
|
||||
{ page: 'pre-plan.html', output: 'pre-plan.jpg' },
|
||||
{ page: 'pre-quota-group.html', output: 'pre-quota-group.jpg' },
|
||||
{ page: 'pre-quota-personal.html', output: 'pre-quota-personal.jpg' },
|
||||
{ page: 'pre-item-hospital-fee.html', output: 'pre-item-hospital-fee.jpg' },
|
||||
{ page: 'pre-item-unit-fee.html', output: 'pre-item-unit-fee.jpg' },
|
||||
{ page: 'pre-item-combo-template.html', output: 'pre-item-combo-template.jpg' },
|
||||
{ page: 'pre-item-exception.html', output: 'pre-item-exception.jpg' },
|
||||
{ page: 'pre-item-required.html', output: 'pre-item-required.jpg' },
|
||||
{ page: 'pre-special-cancer.html', output: 'pre-special-cancer.jpg' },
|
||||
{ page: 'pre-special-occupation.html', output: 'pre-special-occupation.jpg' },
|
||||
{ page: 'pre-special-hospital.html', output: 'pre-special-hospital.jpg' },
|
||||
// 三、检前 · 胃肠镜体检
|
||||
{ page: 'pre-gastro-plan.html', output: 'pre-gastro-plan.jpg' },
|
||||
{ page: 'pre-gastro-employee.html', output: 'pre-gastro-employee.jpg' },
|
||||
{ page: 'pre-gastro-stat.html', output: 'pre-gastro-stat.jpg' },
|
||||
{ page: 'pre-gastro-hospital-scope.html', output: 'pre-gastro-hospital-scope.jpg' },
|
||||
{ page: 'pre-gastro-plan-mgmt.html', output: 'pre-gastro-plan-mgmt.jpg' },
|
||||
{ page: 'pre-special-gastro.html', output: 'pre-special-gastro.jpg' },
|
||||
// 三、检前 · 冠脉CTA体检
|
||||
{ page: 'pre-cta-hospital-scope.html', output: 'pre-cta-hospital-scope.jpg' },
|
||||
{ page: 'pre-cta-plan-mgmt.html', output: 'pre-cta-plan-mgmt.jpg' },
|
||||
{ page: 'pre-special-cta.html', output: 'pre-special-cta.jpg' },
|
||||
// 四、检中 · 常规体检
|
||||
{ page: 'mid-appointment-track.html', output: 'mid-appointment-track.jpg' },
|
||||
{ page: 'mid-selected-items.html', output: 'mid-selected-items.jpg' },
|
||||
{ page: 'mid-participation.html', output: 'mid-participation.jpg' },
|
||||
{ page: 'mid-unit-appointment.html', output: 'mid-unit-appointment.jpg' },
|
||||
{ page: 'mid-hospital-realtime.html', output: 'mid-hospital-realtime.jpg' },
|
||||
{ page: 'mid-doctor-realtime.html', output: 'mid-doctor-realtime.jpg' },
|
||||
{ page: 'mid-hospital-appointment.html', output: 'mid-hospital-appointment.jpg' },
|
||||
{ page: 'mid-unit-expected.html', output: 'mid-unit-expected.jpg' },
|
||||
// 四、检中 · 胃肠镜体检
|
||||
{ page: 'mid-gastro-appointment-track.html', output: 'mid-gastro-appointment-track.jpg' },
|
||||
{ page: 'mid-gastro-unit-appointment.html', output: 'mid-gastro-unit-appointment.jpg' },
|
||||
{ page: 'mid-gastro-questionnaire.html', output: 'mid-gastro-questionnaire.jpg' },
|
||||
// 四、检中 · 冠脉CTA体检
|
||||
{ page: 'mid-cta-appointment-track.html', output: 'mid-cta-appointment-track.jpg' },
|
||||
{ page: 'mid-cta-unit-appointment.html', output: 'mid-cta-unit-appointment.jpg' },
|
||||
// 五、检后 · 常规体检
|
||||
{ page: 'post-report-employee.html', output: 'post-report-employee.jpg' },
|
||||
{ page: 'post-employee-master.html', output: 'post-employee-master.jpg' },
|
||||
{ page: 'post-illness-personnel.html', output: 'post-illness-personnel.jpg' },
|
||||
{ page: 'post-indicator-notify.html', output: 'post-indicator-notify.jpg' },
|
||||
{ page: 'post-report-unmatched.html', output: 'post-report-unmatched.jpg' },
|
||||
// 五、检后 · 体检统计汇总
|
||||
{ page: 'post-unit-count.html', output: 'post-unit-count.jpg' },
|
||||
{ page: 'post-unit-cost-stat.html', output: 'post-unit-cost-stat.jpg' },
|
||||
{ page: 'post-hospital-count.html', output: 'post-hospital-count.jpg' },
|
||||
{ page: 'post-doctor-count.html', output: 'post-doctor-count.jpg' },
|
||||
{ page: 'post-item-stat.html', output: 'post-item-stat.jpg' },
|
||||
{ page: 'post-cancer-screening.html', output: 'post-cancer-screening.jpg' },
|
||||
{ page: 'post-standard-stat.html', output: 'post-standard-stat.jpg' },
|
||||
{ page: 'post-contracted-hospital.html', output: 'post-contracted-hospital.jpg' },
|
||||
{ page: 'post-key-indicator-stat.html', output: 'post-key-indicator-stat.jpg' },
|
||||
// 五、检后 · 病种信息管理
|
||||
{ page: 'post-disease-info.html', output: 'post-disease-info.jpg' },
|
||||
{ page: 'post-conclusion-disease.html', output: 'post-conclusion-disease.jpg' },
|
||||
{ page: 'post-auto-select-disease.html', output: 'post-auto-select-disease.jpg' },
|
||||
// 五、检后 · 胃肠镜体检
|
||||
{ page: 'post-report-gastro.html', output: 'post-report-gastro.jpg' },
|
||||
{ page: 'post-gastro-stat.html', output: 'post-gastro-stat.jpg' },
|
||||
// 五、检后 · 冠脉CTA体检
|
||||
{ page: 'post-cta-report.html', output: 'post-cta-report.jpg' },
|
||||
{ page: 'post-cta-stat.html', output: 'post-cta-stat.jpg' },
|
||||
// 六、异常事件
|
||||
{ page: 'exception-dirty.html', output: 'exception-dirty.jpg' },
|
||||
{ page: 'exception-result.html', output: 'exception-result.jpg' },
|
||||
];
|
||||
|
||||
(async () => {
|
||||
fs.mkdirSync(OUT_DIR, { recursive: true });
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1440, height: 900 },
|
||||
deviceScaleFactor: 1,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
|
||||
let failed = 0;
|
||||
for (const task of TASKS) {
|
||||
const file = path.join(ROOT, task.page);
|
||||
if (!fs.existsSync(file)) {
|
||||
console.error('✗ 缺少文件:', task.page);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
const url = 'file:///' + file.replace(/\\/g, '/');
|
||||
try {
|
||||
await page.goto(url, { waitUntil: 'load' });
|
||||
await page.waitForTimeout(300); // 等待字体/布局稳定
|
||||
await page.screenshot({
|
||||
path: path.join(OUT_DIR, task.output),
|
||||
type: 'jpeg',
|
||||
quality: 85,
|
||||
fullPage: true,
|
||||
});
|
||||
console.log('✓', task.output);
|
||||
} catch (err) {
|
||||
console.error('✗ 截图失败:', task.page, err.message);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
console.log(`\n完成:成功 ${TASKS.length - failed} / ${TASKS.length} 张 → ${OUT_DIR}`);
|
||||
if (failed > 0) process.exit(1);
|
||||
})();
|
||||
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 81 KiB |