feat: 健康体检体检年份筛选控件统一及PRD文档与截图补充

- 管理端健康体检各页体检年份筛选由原生select替换为自定义下拉控件
- 导航标签精简(体检预约/已选项目/已检员工等)
- 单位报表未检人数弹窗移除未检原因列
- 补充健康体检管理端与员工端PRD文档、截图脚本及页面截图
This commit is contained in:
liuyunqin
2026-09-14 19:20:51 +08:00
parent 39547a8bb6
commit dcacbe289b
160 changed files with 4869 additions and 398 deletions
+38 -4
View File
@@ -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>
+47 -9
View File
@@ -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
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,139 @@
/**
* 健康体检(管理端)PRD 截图生成脚本
*
* 用法:在 web-admin/health-checkup 目录下执行 node doc/screenshot-prd.js
* 依赖:playwrightnpm i playwright && npx playwright install chromium
* 输出:doc/screenshots/*.jpg(与 doc/PRD.md 中 ![页面截图](screenshots/xxx.jpg) 引用一一对应)
*
* 说明:仅做页面级整屏截图(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);
})();
Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

+38 -6
View File
@@ -87,6 +87,15 @@
.crumb-tag--active{color:var(--primary);border-color:#91Caff;background:#F0F7FF;}
/* 按钮行 */
.btn-row{display:flex;gap:12px;margin-bottom:16px;}
/* 体检年份选择控件 */
.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>
@@ -136,12 +145,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:94px;">
<option selected>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:94px;">
<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>
@@ -221,6 +234,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>
+38 -6
View File
@@ -89,6 +89,15 @@
.desc-box strong{color:#5C3D00;}
/* 按钮行 */
.btn-row{display:flex;gap:12px;margin-bottom:16px;}
/* 体检年份选择控件 */
.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>
@@ -143,12 +152,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:94px;">
<option selected>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:94px;">
<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>
@@ -239,6 +252,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>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 员工预约体检跟踪 | 健康CQ原型</title>
<title>健康体检 - 体检预约 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
@@ -111,6 +111,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -148,9 +157,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item active">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item active">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -186,10 +195,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>请选择</option><option selected>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:100px;">
<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>
@@ -283,7 +298,7 @@
<!-- 数据表格 -->
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">员工预约体检跟踪列表</div>
<div class="table-card__title">体检预约列表</div>
</div>
<div class="table-card__content">
<table>
@@ -474,6 +489,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>
@@ -104,6 +104,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -141,9 +150,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -179,10 +188,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>请选择</option><option selected>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:100px;">
<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>
@@ -464,6 +479,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>
@@ -124,9 +124,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -50,6 +50,10 @@
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}
.filter-date:focus{border-color:var(--primary);}
.filter-date::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.6;}
.filter-range-sep{color:var(--text-placeholder);font-size:var(--font-sm);}
.filter-select{height:36px;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 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
@@ -78,6 +82,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -115,9 +128,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item active">医生实时检查情况</a>
@@ -153,10 +166,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -168,6 +187,12 @@
<label>医生姓名:</label>
<input class="filter-input" type="text" placeholder="请输入" style="width:150px;min-width:unset;">
</div>
<div class="filter-item">
<label>日期范围:</label>
<input type="date" class="filter-date" id="filter-date-start">
<span class="filter-range-sep"></span>
<input type="date" class="filter-date" id="filter-date-end">
</div>
<button class="btn btn-primary">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4" stroke="currentColor" stroke-width="1.4"/><path d="M10 10l2.5 2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
查询
@@ -231,6 +256,34 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
if(sub)sub.classList.add('open');
})();
/* 日期范围默认当月 */
(function(){
function pad(n){return n<10?'0'+n:''+n;}
var now=new Date();
var first=now.getFullYear()+'-'+pad(now.getMonth()+1)+'-01';
var last=now.getFullYear()+'-'+pad(now.getMonth()+1)+'-'+pad(new Date(now.getFullYear(),now.getMonth()+1,0).getDate());
document.getElementById('filter-date-start').value=first;
document.getElementById('filter-date-end').value=last;
})();
/* 体检年份选择控件 */
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>
@@ -104,6 +104,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -141,9 +150,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -179,10 +188,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>请选择</option><option selected>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:100px;">
<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>
@@ -464,6 +479,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>
@@ -83,6 +83,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -120,9 +129,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -158,10 +167,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>请选择</option><option selected>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:100px;">
<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>
@@ -294,6 +309,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>
@@ -124,9 +124,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -78,6 +78,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -115,9 +124,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -153,10 +162,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -227,6 +242,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>
@@ -82,6 +82,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -119,9 +128,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item active">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -157,10 +166,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -247,6 +262,25 @@ function toggleSubgroup(header){
document.getElementById('filter-date-start').value=first;
document.getElementById('filter-date-end').value=last;
})();
/* 体检年份选择控件 */
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>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 已检员工信息 | 健康CQ原型</title>
<title>健康体检 - 已检员工 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
@@ -101,6 +101,15 @@
.modal-panel.active{display:block;}
.modal-panel__actions{display:flex;gap:12px;margin-bottom:16px;}
.btn-success{background:var(--success);color:#fff;}.btn-success:hover{background:#73d13d;}
/* 体检年份选择控件 */
.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>
@@ -138,9 +147,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item active">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item active">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -176,10 +185,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:100px;">
<option>2026</option><option>2025</option><option>2024</option><option>2023</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -247,7 +262,7 @@
<!-- 数据表格 -->
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">检员工信息列表</div>
<div class="table-card__title">已检员工列表</div>
</div>
<div class="table-card__content">
<table>
@@ -398,6 +413,25 @@ document.getElementById('checkAll').addEventListener('change',function(){
var checked=this.checked;
document.querySelectorAll('.row-checkbox').forEach(function(cb){cb.checked=checked;});
});
/* 体检年份选择控件 */
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>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 已选项目员工信息 | 健康CQ原型</title>
<title>健康体检 - 已选项目 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
@@ -101,6 +101,15 @@
.modal-panel.active{display:block;}
.modal-panel__actions{display:flex;gap:12px;margin-bottom:16px;}
.btn-success{background:var(--success);color:#fff;}.btn-success:hover{background:#73d13d;}
/* 体检年份选择控件 */
.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>
@@ -138,9 +147,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item active">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item active">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -176,10 +185,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:100px;">
<option>2026</option><option>2025</option><option>2024</option><option>2023</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -269,7 +284,7 @@
<!-- 数据表格 -->
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">已选项目员工信息列表</div>
<div class="table-card__title">已选项目列表</div>
</div>
<div class="table-card__content">
<table>
@@ -452,6 +467,25 @@ document.getElementById('btnBatchUndone').addEventListener('click',function(){
document.getElementById('btnBatchCancel').addEventListener('click',function(){
batchSetRows(function(tr){setRowStatus(tr,10,'已取消预约');},'请先勾选需要操作的员工');
});
/* 体检年份选择控件 */
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>
@@ -87,6 +87,15 @@
/* 三级单位tab下才显示的部门列 */
.col-dept{display:none;}
body.level-3 .col-dept{display:table-cell;}
/* 体检年份选择控件 */
.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>
@@ -124,9 +133,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item active">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -168,10 +177,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option selected>2025</option><option>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2025" style="min-width:100px;">
<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>
@@ -251,6 +266,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>
+41 -18
View File
@@ -67,6 +67,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -104,9 +113,9 @@
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="mid-appointment-track.html" class="sidebar-item">员工预约体检跟踪</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目员工信息</a>
<a href="mid-participation.html" class="sidebar-item">检员工信息</a>
<a href="mid-appointment-track.html" class="sidebar-item">体检预约</a>
<a href="mid-selected-items.html" class="sidebar-item">已选项目</a>
<a href="mid-participation.html" class="sidebar-item">已检员工</a>
<a href="mid-unit-appointment.html" class="sidebar-item">单位预约人数统计</a>
<a href="mid-hospital-realtime.html" class="sidebar-item">医院实时预约人数</a>
<a href="mid-doctor-realtime.html" class="sidebar-item">医生实时检查情况</a>
@@ -142,13 +151,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" id="filter-year" style="min-width:100px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
<option>2023</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -227,14 +239,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
if(sub)sub.classList.add('open');
})();
/* 体检年份默认当年 */
(function(){
var sel=document.getElementById('filter-year');
var year=String(new Date().getFullYear());
for(var i=0;i<sel.options.length;i++){
if(sel.options[i].text===year){sel.selectedIndex=i;break;}
}
})();
/* 体检年份选择控件 */
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>
@@ -80,6 +80,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -179,10 +188,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -268,6 +283,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 体检年份选择控件 */
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>
@@ -80,6 +80,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -179,10 +188,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -258,6 +273,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 体检年份选择控件 */
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>
@@ -93,6 +93,15 @@
.toast{position:fixed;top:76px;left:50%;transform:translateX(-50%) translateY(-16px);background:#fff;box-shadow:var(--shadow-md);border-radius:var(--radius-sm);padding:10px 20px;font-size:var(--font-sm);color:var(--text-primary);opacity:0;pointer-events:none;transition:all .25s;z-index:1000;display:flex;align-items:center;gap:8px;}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0);}
.toast svg{flex-shrink:0;}
/* 体检年份选择控件 */
.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>
@@ -192,10 +201,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>
@@ -446,6 +461,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>
@@ -80,6 +80,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -179,10 +188,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -253,6 +268,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 体检年份选择控件 */
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>
@@ -101,6 +101,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>
@@ -200,10 +209,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>
@@ -445,6 +460,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 体检年份选择控件 */
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>
@@ -80,6 +80,15 @@
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 体检年份选择控件 */
.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>
@@ -179,10 +188,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -248,6 +263,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 体检年份选择控件 */
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>
+169 -14
View File
@@ -77,6 +77,10 @@
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.sub-hint{color:var(--text-placeholder);font-size:var(--font-xs);}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
/* 分页 */
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
@@ -95,6 +99,15 @@
.modal__close:hover{color:var(--text-secondary);}
.modal__body{padding:16px 24px;overflow:auto;}
.modal__footer{display:flex;justify-content:flex-end;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
/* 体检年份选择控件 */
.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>
@@ -200,10 +213,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -243,6 +262,9 @@
<th class="col-dept">部门</th>
<th>总人数</th>
<th>已体检人数</th>
<th>报告完整人数</th>
<th>报告不完整人数</th>
<th>报告缺少项目总数</th>
<th>计划总体检费用(元)</th>
<th>实际总体检费用(元)</th>
<th>体检年份</th>
@@ -250,12 +272,12 @@
</tr>
</thead>
<tbody>
<tr><td>1</td><td>第一采油厂</td><td class="col-dept">采油作业一区</td><td>8000</td><td>7520</td><td>15,510,000.00</td><td>13,432,600.00</td><td>2026</td><td><span class="link" onclick="showCostDetail(0)">员工费用明细</span></td></tr>
<tr><td>2</td><td>第二采油厂</td><td class="col-dept">采油作业二区</td><td>8000</td><td>7310</td><td>15,076,875.00</td><td>13,075,762.50</td><td>2026</td><td><span class="link" onclick="showCostDetail(1)">员工费用明细</span></td></tr>
<tr><td>3</td><td>第三采油厂</td><td class="col-dept">集输作业一区</td><td>6500</td><td>5980</td><td>12,333,750.00</td><td>10,681,775.00</td><td>2026</td><td><span class="link" onclick="showCostDetail(2)">员工费用明细</span></td></tr>
<tr><td>4</td><td>第一采油厂</td><td class="col-dept">采油作业一区</td><td>8000</td><td>7680</td><td>15,840,000.00</td><td>13,737,600.00</td><td>2025</td><td><span class="link" onclick="showCostDetail(3)">员工费用明细</span></td></tr>
<tr><td>5</td><td>第二采油厂</td><td class="col-dept">采油作业二区</td><td>8000</td><td>7450</td><td>15,365,625.00</td><td>13,307,562.50</td><td>2025</td><td><span class="link" onclick="showCostDetail(4)">员工费用明细</span></td></tr>
<tr><td>6</td><td>第三采油厂</td><td class="col-dept">集输作业一区</td><td>6500</td><td>6120</td><td>12,622,500.00</td><td>10,947,150.00</td><td>2025</td><td><span class="link" onclick="showCostDetail(5)">员工费用明细</span></td></tr>
<tr><td>1</td><td>第一采油厂</td><td class="col-dept">采油作业一区</td><td>8000</td><td><span class="link" onclick="showStatDetail(0,'checked')">7520</span></td><td><span class="link" onclick="showStatDetail(0,'complete')">7186</span></td><td><span class="link" onclick="showStatDetail(0,'incomplete')">334</span></td><td><span class="link" onclick="showStatDetail(0,'missing')">1503</span></td><td>15,510,000.00</td><td>13,432,600.00</td><td>2026</td><td><span class="link" onclick="showCostDetail(0)">员工费用明细</span></td></tr>
<tr><td>2</td><td>第二采油厂</td><td class="col-dept">采油作业二区</td><td>8000</td><td><span class="link" onclick="showStatDetail(1,'checked')">7310</span></td><td><span class="link" onclick="showStatDetail(1,'complete')">6987</span></td><td><span class="link" onclick="showStatDetail(1,'incomplete')">323</span></td><td><span class="link" onclick="showStatDetail(1,'missing')">1195</span></td><td>15,076,875.00</td><td>13,075,762.50</td><td>2026</td><td><span class="link" onclick="showCostDetail(1)">员工费用明细</span></td></tr>
<tr><td>3</td><td>第三采油厂</td><td class="col-dept">集输作业一区</td><td>6500</td><td><span class="link" onclick="showStatDetail(2,'checked')">5980</span></td><td><span class="link" onclick="showStatDetail(2,'complete')">5745</span></td><td><span class="link" onclick="showStatDetail(2,'incomplete')">235</span></td><td><span class="link" onclick="showStatDetail(2,'missing')">869</span></td><td>12,333,750.00</td><td>10,681,775.00</td><td>2026</td><td><span class="link" onclick="showCostDetail(2)">员工费用明细</span></td></tr>
<tr><td>4</td><td>第一采油厂</td><td class="col-dept">采油作业一区</td><td>8000</td><td><span class="link" onclick="showStatDetail(3,'checked')">7680</span></td><td><span class="link" onclick="showStatDetail(3,'complete')">7412</span></td><td><span class="link" onclick="showStatDetail(3,'incomplete')">268</span></td><td><span class="link" onclick="showStatDetail(3,'missing')">1099</span></td><td>15,840,000.00</td><td>13,737,600.00</td><td>2025</td><td><span class="link" onclick="showCostDetail(3)">员工费用明细</span></td></tr>
<tr><td>5</td><td>第二采油厂</td><td class="col-dept">采油作业二区</td><td>8000</td><td><span class="link" onclick="showStatDetail(4,'checked')">7450</span></td><td><span class="link" onclick="showStatDetail(4,'complete')">7181</span></td><td><span class="link" onclick="showStatDetail(4,'incomplete')">269</span></td><td><span class="link" onclick="showStatDetail(4,'missing')">995</span></td><td>15,365,625.00</td><td>13,307,562.50</td><td>2025</td><td><span class="link" onclick="showCostDetail(4)">员工费用明细</span></td></tr>
<tr><td>6</td><td>第三采油厂</td><td class="col-dept">集输作业一区</td><td>6500</td><td><span class="link" onclick="showStatDetail(5,'checked')">6120</span></td><td><span class="link" onclick="showStatDetail(5,'complete')">5925</span></td><td><span class="link" onclick="showStatDetail(5,'incomplete')">195</span></td><td><span class="link" onclick="showStatDetail(5,'missing')">722</span></td><td>12,622,500.00</td><td>10,947,150.00</td><td>2025</td><td><span class="link" onclick="showCostDetail(5)">员工费用明细</span></td></tr>
</tbody>
</table>
</div>
@@ -275,7 +297,7 @@
<div class="modal__body">
<table>
<thead>
<tr><th>序号</th><th>姓名</th><th>员工编号</th><th>部门</th><th>体检日期</th><th>体检医院</th><th>应检项目数</th><th>已检项目数</th><th>计划体检费用(元)</th><th>实际体检费用(元)</th></tr>
<tr><th>序号</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="cost-detail-body"></tbody>
</table>
@@ -304,6 +326,46 @@
</div>
</div>
</div>
<!-- 统计明细弹窗(已体检/报告完整/报告不完整/报告缺少项目总数) -->
<div class="modal-mask" id="stat-modal" style="display:none;z-index:300;" onclick="if(event.target===this)hideStatModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title" id="stat-modal-title">统计明细</div>
<span class="modal__close" onclick="hideStatModal()">×</span>
</div>
<div class="modal__body">
<table>
<thead id="stat-modal-head"></thead>
<tbody id="stat-modal-body"></tbody>
</table>
</div>
<div class="modal__footer">
<span class="sub-hint" id="stat-modal-count" style="margin-right:auto;"></span>
<button class="btn btn-default" onclick="hideStatModal()">关闭</button>
</div>
</div>
</div>
<!-- 员工缺少项目弹窗(叠在统计明细弹窗之上) -->
<div class="modal-mask" id="emp-missing-modal" style="display:none;z-index:400;" onclick="if(event.target===this)hideEmpMissing()">
<div class="modal modal--narrow">
<div class="modal__header">
<div class="modal__title" id="emp-missing-title">体检报告缺少体检项目信息</div>
<span class="modal__close" onclick="hideEmpMissing()">×</span>
</div>
<div class="modal__body">
<table>
<thead><tr><th>序号</th><th>项目名称</th><th>项目编码</th></tr></thead>
<tbody id="emp-missing-body"></tbody>
</table>
</div>
<div class="modal__footer">
<span class="sub-hint" id="emp-missing-count" style="margin-right:auto;"></span>
<button class="btn btn-default" onclick="hideEmpMissing()">关闭</button>
</div>
</div>
</div>
</main>
@@ -364,16 +426,20 @@ function buildPlan(rowIdx,empIdx){
var CUR_ROW=null;
function showCostDetail(rowIdx){
CUR_ROW=ROWS[rowIdx];
var html='',pSum=0,aSum=0,cnSum=0,pnSum=0;
var html='',pSum=0,aSum=0,cnSum=0,pnSum=0,mnSum=0;
EMP_POOL.forEach(function(e,i){
var d=buildPlan(rowIdx,i);
var complete=reportComplete(rowIdx,i);
pSum+=d.plan;aSum+=d.actual;cnSum+=d.checkedCnt;pnSum+=d.planN;
if(!complete)mnSum+=d.dropN;
html+='<tr><td>'+(i+1)+'</td><td>'+e.name+'</td><td>'+e.id+'</td><td>'+CUR_ROW.dept+'</td><td>'+CUR_ROW.year+'-'+(6+(i%3))+'-'+(11+i*2)+'</td><td>'+e.hospital+'</td>'+
'<td><span class="link" onclick="showItems('+rowIdx+','+i+',\'plan\')">'+d.planN+'</span></td>'+
'<td><span class="link" onclick="showItems('+rowIdx+','+i+',\'checked\')">'+d.checkedCnt+' <span class="sub-hint">(含未检/弃检'+d.dropN+')</span></span></td>'+
'<td>'+(complete?'<span class="tag tag-green">完整</span>':'<span class="tag tag-orange">不完整</span>')+'</td>'+
'<td>'+(complete?0:d.dropN)+'</td>'+
'<td>'+fmtMoney(d.plan)+'</td><td>'+fmtMoney(d.actual)+'</td></tr>';
});
html+='<tr style="font-weight:600;"><td></td><td>合计</td><td></td><td></td><td></td><td></td><td>'+pnSum+'</td><td>'+cnSum+'</td><td>'+fmtMoney(pSum)+'</td><td>'+fmtMoney(aSum)+'</td></tr>';
html+='<tr style="font-weight:600;"><td></td><td>合计</td><td></td><td></td><td></td><td></td><td>'+pnSum+'</td><td>'+cnSum+'</td><td></td><td>'+mnSum+'</td><td>'+fmtMoney(pSum)+'</td><td>'+fmtMoney(aSum)+'</td></tr>';
document.getElementById('cost-detail-title').textContent='「'+CUR_ROW.unit+'」'+CUR_ROW.year+'年 员工费用明细';
document.getElementById('cost-detail-body').innerHTML=html;
document.getElementById('cost-detail-modal').style.display='flex';
@@ -402,11 +468,81 @@ function hideCostDetail(){
document.getElementById('cost-detail-modal').style.display='none';
hideItemModal();
}
/* Esc 关闭弹窗:先关上层项目弹窗,再关员工费用明细 */
/* 统计明细弹窗:点击已体检/报告完整/报告不完整/报告缺少项目总数数字查看
* mode = checked 已体检人员 / complete 报告完整人员 / incomplete 报告不完整人员 / missing 报告缺少项目明细 */
/* 报告是否完整:与缺少项目数联动——偶数序员工报告完整,奇数序员工缺少 buildPlan 派生出的未检/弃检项 */
function reportComplete(rowIdx,empIdx){return (empIdx+rowIdx)%2===0;}
function showStatDetail(rowIdx,mode){
CUR_ROW=ROWS[rowIdx];
var head='',body='',cn=0;
if(mode==='missing'){
head='<tr><th>序号</th><th>姓名</th><th>员工编号</th><th>部门</th><th>体检医院</th><th>报告缺少项目</th><th>项目总数</th></tr>';
EMP_POOL.forEach(function(e,i){
if(reportComplete(rowIdx,i))return;
var names=buildPlan(rowIdx,i).items.filter(function(it){return it.status!=='已检';}).map(function(it){return it.name;});
if(names.length===0)return;
cn++;
body+='<tr><td>'+cn+'</td><td>'+e.name+'</td><td>'+e.id+'</td><td>'+CUR_ROW.dept+'</td><td>'+e.hospital+'</td><td>'+names.join('')+'</td><td>'+names.length+'</td></tr>';
});
document.getElementById('stat-modal-count').textContent='共 '+cn+' 人(示例数据)';
} else {
var onlyIncomplete=(mode==='incomplete');
var showMissing=(mode!=='complete');
head='<tr><th>序号</th><th>姓名</th><th>员工编号</th><th>部门</th><th>体检日期</th><th>体检医院</th><th>已检/应检项目数</th><th>报告状态</th>'+(showMissing?'<th>缺少项目数</th>':'')+'</tr>';
EMP_POOL.forEach(function(e,i){
var complete=reportComplete(rowIdx,i);
if(mode==='complete'&&!complete)return;
if(onlyIncomplete&&complete)return;
var d=buildPlan(rowIdx,i);
cn++;
body+='<tr><td>'+cn+'</td><td>'+e.name+'</td><td>'+e.id+'</td><td>'+CUR_ROW.dept+'</td><td>'+CUR_ROW.year+'-'+(6+(i%3))+'-'+(11+i*2)+'</td><td>'+e.hospital+'</td>'+
'<td>'+d.checkedCnt+' / '+d.planN+'</td>'+
'<td>'+(complete?'<span class="tag tag-green">完整</span>':'<span class="tag tag-orange">不完整</span>')+'</td>'+
(showMissing?(complete?'<td></td>':'<td><span class="link" onclick="showEmpMissing('+rowIdx+','+i+')">'+d.dropN+'</span></td>'):'')+
'</tr>';
});
document.getElementById('stat-modal-count').textContent='共 '+cn+' 人(示例数据)';
}
var TITLES={checked:'已体检人员明细',complete:'报告完整人员明细',incomplete:'报告不完整人员明细',missing:'报告缺少项目明细'};
document.getElementById('stat-modal-title').textContent='「'+CUR_ROW.unit+'」'+CUR_ROW.year+'年 '+TITLES[mode];
document.getElementById('stat-modal-head').innerHTML=head;
document.getElementById('stat-modal-body').innerHTML=body;
document.getElementById('stat-modal').style.display='flex';
}
function hideStatModal(){
document.getElementById('stat-modal').style.display='none';
}
/* 项目编码:按项目名确定性生成,同一项目编码保持稳定 */
function itemCode(name){
var h=0;
for(var i=0;i<name.length;i++){h=(h*31+name.charCodeAt(i))%9000;}
return 'XM'+(1000+h);
}
/* 第三层弹窗:点击缺少项目数,查看该员工缺少的具体项目 */
function showEmpMissing(rowIdx,empIdx){
var e=EMP_POOL[empIdx],html='',n=0;
buildPlan(rowIdx,empIdx).items.forEach(function(it){
if(it.status==='已检')return;
n++;
html+='<tr><td>'+n+'</td><td>'+it.name+'</td><td>'+itemCode(it.name)+'</td></tr>';
});
document.getElementById('emp-missing-title').textContent='体检报告缺少体检项目信息';
document.getElementById('emp-missing-body').innerHTML=html;
document.getElementById('emp-missing-count').textContent='「'+e.name+'」共 '+n+' 项';
document.getElementById('emp-missing-modal').style.display='flex';
}
function hideEmpMissing(){
document.getElementById('emp-missing-modal').style.display='none';
}
/* Esc 关闭弹窗:先关上层员工缺少项目/项目/统计弹窗,再关员工费用明细 */
document.addEventListener('keydown',function(e){
if(e.key!=='Escape')return;
var em=document.getElementById('emp-missing-modal');
if(em.style.display==='flex'){hideEmpMissing();return;}
var im=document.getElementById('item-modal');
if(im.style.display==='flex'){hideItemModal();return;}
var sm=document.getElementById('stat-modal');
if(sm.style.display==='flex'){hideStatModal();return;}
hideCostDetail();
});
/* 侧边栏展开/折叠交互 */
@@ -420,6 +556,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 体检年份选择控件 */
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>
+38 -4
View File
@@ -110,6 +110,15 @@
.modal__body{padding:8px 24px;max-height:60vh;overflow-y:auto;}
.modal__footer{display:flex;justify-content:flex-end;padding:12px 24px;border-top:1px solid var(--border);}
.cell-link{margin-left:8px;}
/* 体检年份选择控件 */
.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>
@@ -216,10 +225,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>2024</option><option>2025</option><option selected>2026</option><option>2027</option>
</select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly value="2026" style="min-width:100px;">
<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>
@@ -382,6 +397,25 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 体检年份选择控件 */
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>
+58 -32
View File
@@ -211,6 +211,15 @@
.drawer__close:hover{background:#F5F5F5;}
.drawer__body{flex:1;overflow-y:auto;padding:20px 24px;}
.drawer__footer{display:flex;justify-content:flex-end;gap:12px;padding:14px 24px;border-top:1px solid var(--border);flex-shrink:0;}
/* 体检年份选择控件 */
.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>
@@ -328,8 +337,16 @@
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select plan-year"></select>
<label>体检年份:</label>
<div class="year-picker">
<input class="filter-input" type="text" readonly placeholder="请选择" style="min-width:100px;">
<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 onclick="pickYear(this)">2025</div>
<div onclick="pickYear(this)">2024</div>
</div>
</div>
</div>
<div class="filter-item">
<label>计划名称:</label>
@@ -395,9 +412,9 @@
<div class="drawer__body">
<div class="form-grid">
<div class="form-item">
<div class="form-label"><span class="req">*</span> 单位</div>
<select class="form-input" id="planUnit">
<option value="">请选择单位</option>
<div class="form-label"><span class="req">*</span> 组织单位</div>
<select class="form-input" id="planUnit" onchange="onPlanUnitChange()">
<option value="">请选择组织单位</option>
</select>
</div>
<div class="form-item">
@@ -425,20 +442,11 @@
</div>
</div>
<!-- 参加人员范围 -->
<!-- 参加人员范围:固定为指定人员,直接展示指定区域 -->
<div class="form-item">
<div class="form-label"><span class="req">*</span> 参加人员范围</div>
<div class="radio-group">
<label class="radio-item">
<input type="radio" name="personType" value="all" checked onchange="togglePersonPanel()">
全体人员
</label>
<label class="radio-item">
<input type="radio" name="personType" value="specific" onchange="togglePersonPanel()">
指定人员
</label>
</div>
<div class="person-panel" id="personPanel">
<!-- [交互] 指定机构默认为组织单位,可额外勾选其他单位/部门 -->
<div class="person-panel show" id="personPanel" style="margin-top:0;">
<div class="person-panel__row">
<div class="person-panel__label">指定机构</div>
<div class="tree-select" id="orgSelect">
@@ -676,10 +684,7 @@ function openPlanEdit(el){
updateHospitalTrigger();
document.getElementById('planDateFrom').value = d.planFrom;
document.getElementById('planDateTo').value = d.planTo;
/* 参加人员范围 */
var radio = document.querySelector('input[name="personType"][value="' + d.personType + '"]');
if(radio) radio.checked = true;
togglePersonPanel();
/* 参加人员范围:固定为指定人员,直接回填指定机构与员工 */
selectedInstitutions = (d.institutions || []).slice();
renderOrgTree();
updateOrgTrigger();
@@ -714,8 +719,6 @@ function resetPlanForm(){
document.getElementById('planDateTo').value = '';
document.getElementById('apptDateFrom').value = '';
document.getElementById('apptDateTo').value = '';
document.querySelector('input[name="personType"][value="all"]').checked = true;
document.getElementById('personPanel').classList.remove('show');
/* 预约默认开启 */
document.getElementById('switchAppt').classList.add('on');
document.getElementById('switchApptLabel').textContent = '已开启';
@@ -782,12 +785,16 @@ function removeHospitalTag(e, val){
updateHospitalTrigger();
}
/* ===== 参加人员范围 ===== */
function togglePersonPanel(){
var val = document.querySelector('input[name="personType"]:checked').value;
var panel = document.getElementById('personPanel');
if(val === 'specific'){ panel.classList.add('show'); }
else{ panel.classList.remove('show'); }
/* ===== 参加人员范围 =====
* 范围固定为指定人员;指定机构默认为组织单位,可再额外勾选其他单位/部门 */
function onPlanUnitChange(){
var unit = document.getElementById('planUnit').value;
if(!unit) return;
selectedInstitutions = [unit];
syncEmpFilterOrg();
renderOrgTree();
updateOrgTrigger();
filterEmployeesByInstitutions();
}
/* ===== 指定机构:单位-部门两级树状多选 =====
@@ -1096,7 +1103,7 @@ function toggleAppointment(){
/* ===== 保存 ===== */
function savePlan(){
var unit = document.getElementById('planUnit').value;
if(!unit){ showToast('请选择单位'); return; }
if(!unit){ showToast('请选择组织单位'); return; }
var year = document.querySelector('#plan-drawer .plan-year').value;
if(selectedExamHospitals.length === 0){ showToast('请选择承检医院'); return; }
var examHospital = selectedExamHospitals.join('、');
@@ -1106,8 +1113,8 @@ function savePlan(){
var dateTo = document.getElementById('planDateTo').value;
if(!dateFrom || !dateTo){ showToast('请选择体检计划日期范围'); return; }
if(dateFrom > dateTo){ showToast('体检计划开始日期不能晚于结束日期'); return; }
var personType = document.querySelector('input[name="personType"]:checked').value;
if(personType === 'specific' && selectedInstitutions.length === 0 && selectedEmployees.length === 0){
var personType = 'specific';
if(selectedInstitutions.length === 0 && selectedEmployees.length === 0){
showToast('请至少选择指定机构或指定员工'); return;
}
var apptOn = document.getElementById('switchAppt').classList.contains('on');
@@ -1280,6 +1287,25 @@ document.getElementById('emp-modal-overlay').addEventListener('click', function(
document.getElementById('detail-modal-overlay').addEventListener('click', function(e){
if(e.target === this) closePlanDetail();
});
/* 体检年份选择控件 */
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>

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