diff --git a/index.html b/index.html
index 4e668a4..93ffedb 100644
--- a/index.html
+++ b/index.html
@@ -238,10 +238,10 @@ const SITE_MAP = [
{ file:'pre-cta-plan-mgmt.html', label:'冠脉CTA单位体检计划管理' },
{ file:'pre-special-cta.html', label:'冠脉CTA体检人员' },
{ file:'pre-special-hospital.html', label:'指定员工体检医院' },
- { file:'mid-appointment-track.html', label:'体检预约' },
+ // { file:'mid-appointment-track.html', label:'体检预约' },
{ file:'mid-appointment-track2.html', label:'体检预约跟踪' },
- { file:'mid-selected-items.html', label:'已选项目' },
- { file:'mid-participation.html', label:'已检员工' },
+ // { file:'mid-selected-items.html', label:'已选项目' },
+ // { file:'mid-participation.html', label:'已检员工' },
{ file:'mid-unit-appointment.html', label:'单位预约人数统计' },
{ file:'mid-hospital-realtime.html', label:'医院实时预约人数' },
{ file:'mid-doctor-realtime.html', label:'医生实时检查情况' },
diff --git a/web-admin/health-checkup/archive-personal.html b/web-admin/health-checkup/archive-personal.html
index df355fa..d0dd56f 100644
--- a/web-admin/health-checkup/archive-personal.html
+++ b/web-admin/health-checkup/archive-personal.html
@@ -168,6 +168,21 @@
.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;}
+/* 高级查询 */
+.adv-panel{background:#fff;border-radius:var(--radius-md);padding:16px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:none;}
+.adv-panel.open{display:block;}
+.adv-panel__head{font-size:var(--font-base);font-weight:600;margin-bottom:12px;}
+#advConditions{display:grid;grid-template-columns:1fr 1fr;gap:10px 16px;}
+.adv-cond-row{display:flex;align-items:center;gap:8px;margin-bottom:0;min-width:0;}
+.adv-field{min-width:140px;flex:1;}
+.adv-op{min-width:72px;flex:none;}
+.adv-value-wrap{display:flex;align-items:center;gap:8px;flex:1;min-width:0;max-width:none;}
+.adv-value{flex:1;min-width:0;}
+.adv-range-sep{color:var(--text-secondary);flex-shrink:0;}
+.adv-del{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;color:var(--text-secondary);cursor:pointer;flex-shrink:0;font-size:var(--font-sm);line-height:1;}
+.adv-del:hover{color:var(--danger);border-color:var(--danger);}
+.adv-actions{display:flex;gap:12px;margin-top:2px;}
+.adv-arrow{font-size:10px;}
@@ -237,16 +252,20 @@
-
-
-
-
+
+
+
+
+
+
高级查询
+
+
+
+
+
+
@@ -585,21 +604,135 @@ function hasAbnormal(r){
for(var k in r.r){if(r.r[k][1])return true;}
return false;
}
-/* 按筛选条件取当前展示行:异常员工 + 姓名/员工编号/身份证号模糊匹配 */
+/* 按筛选条件取当前展示行:姓名模糊匹配 + 高级查询条件 */
function getDisplayRows(){
- var v=document.getElementById('abnormalFilter').value;
var name=document.getElementById('fName').value.trim();
var empNo=document.getElementById('fEmpNo').value.trim();
var idCard=document.getElementById('fIdCard').value.trim();
+ var conds=readAdvancedConditions();
return MASTER_ROWS.filter(function(r){
- if(v==='abnormal'&&!hasAbnormal(r))return false;
- if(v==='normal'&&hasAbnormal(r))return false;
if(name&&r.name.indexOf(name)<0)return false;
if(empNo&&r.empNo.indexOf(empNo)<0)return false;
if(idCard&&r.idCard.indexOf(idCard)<0)return false;
+ for(var i=0;i','>=','<','<=','范围'];
+var ADV_FIELD_OPTS='';
+/* 字段下拉选项:基本信息 + 全部体检项目(按一级分类分组,二级分类·项目名 去重) */
+function buildAdvFieldOpts(){
+ var o='';
+ ITEM_TREE.forEach(function(g){
+ o+='';
+ });
+ return o;
+}
+function advConditionRowHTML(){
+ return ''
+ +''
+ +''
+ +''
+ +''
+ +'
';
+}
+/* 运算符切换为"范围"时,值区域变成最小/最大两个输入框 */
+function onAdvOpChange(sel){
+ var wrap=sel.parentElement.querySelector('.adv-value-wrap');
+ var isRange=sel.value==='范围';
+ var alreadyRange=!!wrap.querySelector('.adv-range-from');
+ if(isRange&&!alreadyRange){
+ wrap.innerHTML=''
+ +'~'
+ +'';
+ }else if(!isRange&&alreadyRange){
+ wrap.innerHTML='';
+ }
+}
+function addAdvCondition(){
+ document.getElementById('advConditions').insertAdjacentHTML('beforeend',advConditionRowHTML());
+}
+function removeAdvCondition(el){el.parentElement.remove();}
+function toggleAdvanced(){
+ var p=document.getElementById('advPanel');
+ var open=p.classList.toggle('open');
+ var arr=document.getElementById('advToggle').querySelector('.adv-arrow');
+ if(arr)arr.textContent=open?'▴':'▾';
+ if(open&&!p.querySelector('.adv-cond-row'))addAdvCondition();
+}
+function clearAdvanced(){
+ document.getElementById('advConditions').innerHTML='';
+ renderBigTable();
+ showToast('已清空高级查询条件');
+}
+/* 读取面板中已填值的条件(忽略值为空的行;范围条件任一边有值即计入) */
+function readAdvancedConditions(){
+ var conds=[];
+ document.querySelectorAll('#advConditions .adv-cond-row').forEach(function(row){
+ var field=row.querySelector('.adv-field').value;
+ var op=row.querySelector('.adv-op').value;
+ if(op==='范围'){
+ var from=row.querySelector('.adv-range-from').value.trim();
+ var to=row.querySelector('.adv-range-to').value.trim();
+ if(from!==''||to!=='')conds.push({field:field,op:op,from:from,to:to});
+ }else{
+ var value=row.querySelector('.adv-value').value.trim();
+ if(value!=='')conds.push({field:field,op:op,value:value});
+ }
+ });
+ return conds;
+}
+/* 取某字段在某员工上的值:基本信息直接用 key,项目结果取"结果"字符串 */
+function getFieldRaw(row,field){
+ if(field.indexOf('|')>=0){
+ var i=field.indexOf('|');
+ var cat=field.slice(0,i),name=field.slice(i+1);
+ var val=row.r[cat+'|'+name]||row.r[name];
+ if(!val)val=[(CAT_DEFAULTS[cat]||['-'])[0]];
+ return val[0];
+ }
+ return row[field];
+}
+/* 数值化:取结果中的首个数字 */
+function numericOf(v){
+ var m=String(v).match(/[-+]?\d+(?:\.\d+)?/);
+ return m?parseFloat(m[0]):null;
+}
+/* 单条条件匹配:包含/=/!= 按字符串,>、>=、<、<=、范围 按数值 */
+function matchCondition(row,cond){
+ var raw=getFieldRaw(row,cond.field);
+ var str=String(raw==null?'':raw);
+ if(cond.op==='包含')return str.indexOf(cond.value)>=0;
+ if(cond.op==='=')return str===cond.value;
+ if(cond.op==='!=')return str!==cond.value;
+ var n=numericOf(str);
+ if(n===null)return false;
+ if(cond.op==='范围'){
+ if(cond.from!==''){
+ var lo=parseFloat(cond.from);
+ if(!isNaN(lo)&&nhi)return false;
+ }
+ return true;
+ }
+ var c=parseFloat(cond.value);
+ if(isNaN(c))return false;
+ if(cond.op==='>')return n>c;
+ if(cond.op==='>=')return n>=c;
+ if(cond.op==='<')return n
@@ -184,6 +203,18 @@
+
+
+
+
+
+
高级查询
+
+
+
+
+
+
@@ -399,6 +430,114 @@ document.querySelectorAll('.year-picker>input').forEach(function(inp){
document.addEventListener('click',function(){
document.querySelectorAll('.year-picker__dropdown.open').forEach(function(d){d.classList.remove('open');});
});
+/* ============ 高级查询 ============ */
+var ADV_OPS=['包含','=','!=','>','>=','<','<=','范围'];
+var ADV_ROW_SELECTOR='#unitTable tbody tr';
+var ADV_FIELDS=[
+ {key:'unit',label:'单位',idx:1},{key:'dept',label:'部门',idx:2},{key:'year',label:'体检年份',idx:3},
+ {key:'signHospital',label:'签约医院',idx:4},{key:'hospital',label:'承检医院',idx:5},{key:'range',label:'体检计划日期范围',idx:6},
+ {key:'total',label:'总人数',idx:7},{key:'should',label:'应检人数',idx:8},{key:'selected',label:'已选项目人数',idx:9},
+ {key:'booked',label:'已预约人数',idx:10},{key:'checked',label:'已检人数',idx:11},{key:'unchecked',label:'未检人数',idx:12},
+ {key:'rate',label:'受检率',idx:13},{key:'detectRate',label:'检出率',idx:14},{key:'keyAbn',label:'重点指标异常人数',idx:15},
+ {key:'ctaAbn',label:'冠脉CTA异常人数',idx:16},{key:'cancerAbn',label:'防癌筛查异常人数',idx:17},
+ {key:'planFee',label:'计划总费用(元)',idx:18},{key:'actualFee',label:'实际总费用(元)',idx:19},{key:'perFee',label:'人均费用(元)',idx:20}
+];
+var ADV_FIELD_OPTS=ADV_FIELDS.map(function(f){return '';}).join('');
+function advConditionRowHTML(){
+ return ''
+ +''
+ +''
+ +''
+ +''
+ +'
';
+}
+function onAdvOpChange(sel){
+ var wrap=sel.parentElement.querySelector('.adv-value-wrap');
+ var isRange=sel.value==='范围';
+ var alreadyRange=!!wrap.querySelector('.adv-range-from');
+ if(isRange&&!alreadyRange){
+ wrap.innerHTML=''
+ +'~'
+ +'';
+ }else if(!isRange&&alreadyRange){
+ wrap.innerHTML='';
+ }
+}
+function addAdvCondition(){document.getElementById('advConditions').insertAdjacentHTML('beforeend',advConditionRowHTML());}
+function removeAdvCondition(el){el.parentElement.remove();}
+function toggleAdvanced(){
+ var p=document.getElementById('advPanel');
+ var open=p.classList.toggle('open');
+ var arr=document.getElementById('advToggle').querySelector('.adv-arrow');
+ if(arr)arr.textContent=open?'▴':'▾';
+ if(open&&!p.querySelector('.adv-cond-row'))addAdvCondition();
+}
+function readAdvancedConditions(){
+ var conds=[];
+ document.querySelectorAll('#advConditions .adv-cond-row').forEach(function(row){
+ var field=row.querySelector('.adv-field').value;
+ var op=row.querySelector('.adv-op').value;
+ if(op==='范围'){
+ var from=row.querySelector('.adv-range-from').value.trim();
+ var to=row.querySelector('.adv-range-to').value.trim();
+ if(from!==''||to!=='')conds.push({field:field,op:op,from:from,to:to});
+ }else{
+ var value=row.querySelector('.adv-value').value.trim();
+ if(value!=='')conds.push({field:field,op:op,value:value});
+ }
+ });
+ return conds;
+}
+function fieldByKey(key){for(var i=0;i=0;
+ if(cond.op==='=')return str===cond.value;
+ if(cond.op==='!=')return str!==cond.value;
+ var n=numericOf(str);
+ if(n===null)return false;
+ if(cond.op==='范围'){
+ if(cond.from!==''){var lo=parseFloat(cond.from);if(!isNaN(lo)&&nhi)return false;}
+ return true;
+ }
+ var c=parseFloat(cond.value);if(isNaN(c))return false;
+ if(cond.op==='>')return n>c;
+ if(cond.op==='>=')return n>=c;
+ if(cond.op==='<')return n
+
+