feat:一线医疗点后台原型-细节对齐和菜单重组
This commit is contained in:
+7
-8
@@ -600,12 +600,12 @@ const SITE_MAP = [
|
||||
{ file:'config-ambulance.html', label:'基础配置 · 救护车列表' },
|
||||
{ file:'daily-treatment-staff.html', label:'日常业务 · 员工就诊' },
|
||||
{ file:'daily-treatment-nonstaff.html', label:'日常业务 · 非员工就诊' },
|
||||
{ file:'daily-stock-in.html', label:'日常业务 · 入库记录' },
|
||||
{ file:'daily-stock-out.html', label:'日常业务 · 出库记录' },
|
||||
{ file:'daily-ambulance-attendance.html', label:'日常业务 · 救护车出勤' },
|
||||
{ file:'daily-follow.html', label:'日常业务 · 随访管理' },
|
||||
{ file:'daily-chronic.html', label:'日常业务 · 慢病管理' },
|
||||
{ file:'daily-chronic-intervention.html', label:'日常业务 · 慢病干预(二级页)' },
|
||||
{ file:'daily-employee-search.html', label:'日常业务 · 员工档案' },
|
||||
{ file:'daily-employee-file.html', label:'日常业务 · 健康档案(二级页)' },
|
||||
{ file:'daily-follow-task.html', label:'日常业务 · 随访任务' },
|
||||
{ file:'daily-interpret.html', label:'日常业务 · 解读任务' },
|
||||
{ file:'daily-education.html', label:'日常业务 · 健康宣教管理' },
|
||||
@@ -620,12 +620,11 @@ const SITE_MAP = [
|
||||
{ file:'bed-call-record.html', label:'床头呼叫 · 呼叫记录' },
|
||||
{ file:'bed-timeout-alarm.html', label:'床头呼叫 · 告警记录' },
|
||||
{ file:'bed-stat.html', label:'床头呼叫 · 汇总统计' },
|
||||
{ file:'stat-clinic-chart.html', label:'数据统计 · 医疗点统计-图表' },
|
||||
{ file:'stat-clinic-table.html', label:'数据统计 · 医疗点统计-报表' },
|
||||
{ file:'stat-ambulance-chart.html', label:'数据统计 · 救护车统计-图表' },
|
||||
{ file:'stat-ambulance-table.html', label:'数据统计 · 救护车统计-报表' },
|
||||
{ file:'stat-rescue-chart.html', label:'数据统计 · 救助物品统计-图表' },
|
||||
{ file:'stat-rescue-table.html', label:'数据统计 · 救助物品统计-报表' },
|
||||
{ file:'stat-clinic-chart.html', label:'数据统计 · 医疗点统计-统计图表' },
|
||||
{ file:'stat-clinic-table.html', label:'数据统计 · 医疗点统计-统计报表' },
|
||||
{ file:'stat-ambulance-chart.html', label:'数据统计 · 救护车统计-统计图表' },
|
||||
{ file:'stat-ambulance-table.html', label:'数据统计 · 救护车统计-统计报表' },
|
||||
{ file:'stat-rescue-chart.html', label:'数据统计 · 救助物品统计' },
|
||||
{ file:'hut-banner.html', label:'健康小屋 · 轮播图配置' },
|
||||
{ file:'hut-room.html', label:'健康小屋 · 健康室管理' },
|
||||
{ file:'hut-appointment.html', label:'健康小屋 · 预约管理' },
|
||||
|
||||
@@ -54,7 +54,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.tab-item{padding:10px 18px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;}
|
||||
.tab-item.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1300px;}
|
||||
@@ -205,7 +205,6 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title" id="cardTitle">设备分配记录</span>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="showToast('导出任务已提交,完成后可在「查看导出任务」下载')"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openTaskRecord()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
@@ -303,7 +302,6 @@ function renderAll(){
|
||||
}).join('')||'<tr><td class="td-empty" colspan="8">没有符合条件的分配记录</td></tr>';
|
||||
document.getElementById('thead').innerHTML=headDev();
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 条 · 未解除 '+list.filter(function(r){return !r.unbind;}).length+' 条';
|
||||
document.getElementById('cardTitle').textContent='设备分配记录';
|
||||
}else{
|
||||
var b2=document.getElementById('filterEBuilding').value,d2=document.getElementById('filterEDorm').value;
|
||||
var en=document.getElementById('filterEName').value.trim(),eo=document.getElementById('filterENo').value.trim().toUpperCase();
|
||||
@@ -318,7 +316,6 @@ function renderAll(){
|
||||
}).join('')||'<tr><td class="td-empty" colspan="10">没有符合条件的分配记录</td></tr>';
|
||||
document.getElementById('thead').innerHTML=headEmp();
|
||||
document.getElementById('totalTip').textContent='共 '+list2.length+' 条 · 未解除 '+list2.filter(function(r){return !r.unbind;}).length+' 条';
|
||||
document.getElementById('cardTitle').textContent='床位分配记录';
|
||||
}
|
||||
document.getElementById('tbody').innerHTML=rows;
|
||||
}
|
||||
|
||||
@@ -52,9 +52,9 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.btn-link--danger{background:none;color:var(--danger);padding:0 4px;height:auto;}.btn-link--danger:hover{color:#ff7875;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;margin-top:16px;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__head .btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;}
|
||||
.table-card__head .btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-start;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1300px;}
|
||||
thead th{background:#FAFAFA;padding:10px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
@@ -198,7 +198,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title">床位列表</span>
|
||||
<div class="btns">
|
||||
<button class="btn btn-primary" onclick="openEdit(-1)">
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none"><path d="M6.5 2v9M2 6.5h9" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新增
|
||||
|
||||
@@ -52,7 +52,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.btn-link--danger{background:none;color:var(--danger);padding:0 4px;height:auto;}.btn-link--danger:hover{color:#ff7875;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;margin-top:16px;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1300px;}
|
||||
@@ -185,7 +185,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title">楼栋列表</span>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="openEdit(-1)">
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none"><path d="M6.5 2v9M2 6.5h9" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新增
|
||||
|
||||
@@ -53,7 +53,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.tab-item{padding:10px 18px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;}
|
||||
.tab-item.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__ops{display:flex;align-items:center;gap:8px;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
@@ -208,7 +208,6 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title" id="cardTitle">员工呼入记录</span>
|
||||
<!-- [交互] 导出/查看导出任务仅员工呼入 TAB 提供,终端呼出不支持导出 -->
|
||||
<div class="table-card__ops" id="inBtns">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
@@ -311,7 +310,6 @@ function renderAll(){
|
||||
+'<td>'+r.station+'</td><td>'+r.space+'</td><td><button class="btn btn-link" onclick="openDetailIn('+i+')">详细信息</button></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="11">没有符合条件的呼叫记录</td></tr>';
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 条记录';
|
||||
document.getElementById('cardTitle').textContent='员工呼入记录';
|
||||
}else{
|
||||
var kf=document.getElementById('outFrom').value.trim().toUpperCase();
|
||||
var kt=document.getElementById('outTo').value.trim().toUpperCase();
|
||||
@@ -325,7 +323,6 @@ function renderAll(){
|
||||
+'<td><button class="btn btn-link" onclick="openDetailOut('+i+')">详细信息</button></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="9">没有符合条件的呼叫记录</td></tr>';
|
||||
document.getElementById('totalTip').textContent='共 '+list2.length+' 条记录';
|
||||
document.getElementById('cardTitle').textContent='终端呼出记录';
|
||||
}
|
||||
}
|
||||
/* [交互] TAB 切换:呼入/呼出各自独立筛选组与导出按钮组 */
|
||||
|
||||
@@ -52,7 +52,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.btn-link--danger{background:none;color:var(--danger);padding:0 4px;height:auto;}.btn-link--danger:hover{color:#ff7875;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;margin-top:16px;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1250px;}
|
||||
@@ -178,7 +178,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title">设备分配</span>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="openAllocImport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 9V2M4.5 4.5L7 2l2.5 2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>批量导入数据</button>
|
||||
<button class="btn btn-default" onclick="openTaskRecord('alloc')"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导入任务</button>
|
||||
|
||||
@@ -55,9 +55,9 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.tab-item{padding:10px 18px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;}
|
||||
.tab-item.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__head .btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;}
|
||||
.table-card__head .btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-start;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1560px;}
|
||||
thead th{background:#FAFAFA;padding:10px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
@@ -187,7 +187,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title" id="cardTitle">呼叫设备</span>
|
||||
<div class="btns">
|
||||
<button class="btn btn-primary" onclick="openEdit(-1)">
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none"><path d="M6.5 2v9M2 6.5h9" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新增
|
||||
@@ -376,7 +375,6 @@ function renderAll(){
|
||||
+'<td><button class="btn btn-link" onclick="openEdit('+i+')">编辑</button><button class="btn btn-link--danger" onclick="askDelete('+i+')">删除</button></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="14">没有符合条件的设备</td></tr>';
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 台(正常 '+list.filter(function(r){return r.status==='0';}).length+' / 故障 '+list.filter(function(r){return r.status==='1';}).length+' / 停用 '+list.filter(function(r){return r.status==='2';}).length+')';
|
||||
document.getElementById('cardTitle').textContent=tabName();
|
||||
}
|
||||
function switchTab(t){
|
||||
curTab=t;
|
||||
|
||||
@@ -52,7 +52,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.btn-link--danger{background:none;color:var(--danger);padding:0 4px;height:auto;}.btn-link--danger:hover{color:#ff7875;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;margin-top:16px;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1300px;}
|
||||
@@ -177,7 +177,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title">宿舍列表</span>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="openEdit(-1)">
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none"><path d="M6.5 2v9M2 6.5h9" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新增
|
||||
|
||||
@@ -57,7 +57,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.tab-item{padding:10px 18px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;}
|
||||
.tab-item.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1350px;}
|
||||
@@ -169,7 +169,6 @@ tfoot td{padding:10px 7px;text-align:center;font-size:var(--font-sm);font-weight
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title" id="cardTitle">部门统计</span>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openTaskRecord()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
@@ -242,7 +241,6 @@ function render(){
|
||||
var tv=list.length?'<tr><td></td><td class="td-name">合计</td><td class="td-name">'+list.length+' 个'+(dim==='dep'?'部门':'站点')+'</td>'
|
||||
+num(sum('dev'))+num(sum('alloc'))+num(sum('calls'))+num(sum('ok'))+num(sum('miss'))+num(sum('done'))+num(sum('undone'))+num(sum('alarm'))+'</tr>':'';
|
||||
document.getElementById('tfoot').innerHTML=tv;
|
||||
document.getElementById('cardTitle').textContent=dim==='dep'?'部门统计':'站点统计';
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 行 · 统计区间 '+(f||'—')+' 至 '+(t||'—');
|
||||
}
|
||||
/* [交互] 周期切换:非选时隐藏时间范围并即时出数,选时默认展示上一周期区间 */
|
||||
|
||||
@@ -52,7 +52,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.btn-link--danger{background:none;color:var(--danger);padding:0 4px;height:auto;}.btn-link--danger:hover{color:#ff7875;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;margin-top:16px;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1300px;}
|
||||
@@ -175,7 +175,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title">站点列表</span>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="openEdit(-1)">
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none"><path d="M6.5 2v9M2 6.5h9" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新增
|
||||
|
||||
@@ -49,7 +49,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;margin-top:16px;}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__head{display:flex;align-items:center;justify-content:flex-start;padding:12px 16px;border-bottom:1px solid var(--border);}
|
||||
.table-card__title{font-size:var(--font-sm);font-weight:600;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1280px;}
|
||||
@@ -158,7 +158,6 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
<!-- [交互] 告警列表:纯记录查询,无行内操作 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__head">
|
||||
<span class="table-card__title">告警记录</span>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openTaskRecord()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
|
||||
@@ -168,15 +168,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<a href="config-allocate-stat.html" class="sidebar-item active">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -215,7 +207,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<table>
|
||||
<thead>
|
||||
<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><th>医疗点地址</th><th>合作医院</th><th>设立时间</th><th>医护人员数量</th><th>已分配员工数量</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableBody"></tbody>
|
||||
@@ -320,7 +312,7 @@ function renderTable(){
|
||||
document.getElementById('prevBtn').disabled=currentPage<=1;
|
||||
document.getElementById('nextBtn').disabled=currentPage>=totalPages;
|
||||
var tbody=document.getElementById('tableBody');
|
||||
if(!pageData.length){tbody.innerHTML='<tr><td colspan="9" class="td-empty">暂无匹配数据</td></tr>';return;}
|
||||
if(!pageData.length){tbody.innerHTML='<tr><td colspan="8" class="td-empty">暂无匹配数据</td></tr>';return;}
|
||||
var html='';
|
||||
pageData.forEach(function(p,i){
|
||||
var hosp=p.hospital?p.hospital:'<span class="badge badge--muted">未指定</span>';
|
||||
@@ -334,7 +326,6 @@ function renderTable(){
|
||||
+'<td>'+p.found+'</td>'
|
||||
+'<td class="td-num">'+p.staff+'</td>'
|
||||
+'<td><button class="btn '+allocCls+'" onclick="openRoster(\''+p.name+'\')">'+p.roster.length+'</button></td>'
|
||||
+'<td class="td-actions"><button class="btn btn-link" onclick="openRoster(\''+p.name+'\')">查看名册</button></td>'
|
||||
+'</tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
|
||||
@@ -181,15 +181,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="config-allocate-stat.html" class="sidebar-item">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -329,18 +321,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 取消分配确认弹窗 -->
|
||||
<div class="modal-mask" id="delMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="9" stroke="#FAAD14" stroke-width="1.6"/><path d="M10 5.5v6M10 13.5v1" stroke="#FAAD14" stroke-width="1.8" stroke-linecap="round"/></svg> 取消分配确认</div>
|
||||
<div class="modal__text" id="delText">确认取消分配?</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('delMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="confirmCancel()">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
@@ -384,7 +364,7 @@ var unalloc=[
|
||||
{id:108,name:'邓成',sex:'男',age:43,code:'CQ024778',tel:'133****9481',unit:'采气一厂',dept:'苏里格南作业区'},
|
||||
{id:109,name:'苏文斌',sex:'男',age:27,code:'CQ051027',tel:'155****6703',unit:'采油一厂',dept:'工会办公室'}
|
||||
];
|
||||
var nextId=200,curAllocTab=true,allocTargets=[],allocRealloc=false,cancelId=null;
|
||||
var nextId=200,curAllocTab=true,allocTargets=[],allocRealloc=false;
|
||||
|
||||
/* ===== Tab 切换 ===== */
|
||||
function switchTab(toAlloc){
|
||||
@@ -475,8 +455,7 @@ function renderTable(){
|
||||
+'<td>'+p.age+'</td><td>'+p.code+'</td><td>'+p.tel+'</td>';
|
||||
if(curAllocTab){
|
||||
html+='<td>'+p.mUnit+'</td><td>'+p.mPoint+'</td><td>'+p.date+'</td>'
|
||||
+'<td class="td-actions"><button class="btn btn-link" onclick="openAllocate(['+p.id+'],true)">重新分配</button>'
|
||||
+'<button class="btn btn-link btn-link--danger" onclick="askCancel('+p.id+')">取消分配</button></td>';
|
||||
+'<td class="td-actions"><button class="btn btn-link" onclick="openAllocate(['+p.id+'],true)">重新分配</button></td>';
|
||||
}else{
|
||||
html+='<td class="td-actions"><button class="btn btn-link" onclick="openAllocate(['+p.id+'])">分配医疗点</button></td>';
|
||||
}
|
||||
@@ -548,21 +527,6 @@ function confirmAllocate(){
|
||||
closeModal('allocMask');renderTable();
|
||||
showToast('已为 '+allocTargets.length+' 人'+(allocRealloc?'重新':'')+'分配「'+point+'」');
|
||||
}
|
||||
function askCancel(id){
|
||||
cancelId=id;
|
||||
var p=alloc.find(function(x){return x.id===id;});
|
||||
document.getElementById('delText').textContent='确认取消员工「'+p.name+'」在「'+p.mPoint+'」的分配?取消后其 PAD 端任务将转回医疗点驻点医护。';
|
||||
document.getElementById('delMask').classList.add('open');
|
||||
}
|
||||
function confirmCancel(){
|
||||
var idx=alloc.findIndex(function(x){return x.id===cancelId;});
|
||||
var p=alloc.splice(idx,1)[0];
|
||||
delete p.mUnit;delete p.mPoint;delete p.date;
|
||||
unalloc.push(p);
|
||||
closeModal('delMask');renderTable();
|
||||
showToast('员工「'+p.name+'」已取消分配');
|
||||
}
|
||||
|
||||
/* ===== 批量导入 ===== */
|
||||
function openImport(){
|
||||
document.getElementById('iUnit').value='';
|
||||
|
||||
@@ -144,31 +144,13 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
.drop-zone{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:16px;text-align:center;color:var(--text-placeholder);font-size:var(--font-sm);cursor:pointer;line-height:1.8;}
|
||||
.drop-zone:hover{border-color:var(--primary);color:var(--primary);background:#F8FBFF;}
|
||||
|
||||
/* 数据管理(出勤记录)所需样式 */
|
||||
/* 导入任务所需样式 */
|
||||
.badge--warning{background:#FFFBE6;color:#D48806;border:1px solid #FFE58F;}
|
||||
.form-control[readonly]{background:#FAFAFA;color:var(--text-secondary);}
|
||||
.radio--disabled{color:var(--text-placeholder);}
|
||||
.radio--disabled input{cursor:not-allowed;}
|
||||
.radio .opt-tip{font-size:var(--font-xs);color:var(--text-placeholder);}
|
||||
.radio-wrap{flex-wrap:wrap;height:auto;align-items:flex-start;gap:8px 20px;}
|
||||
.chips{display:flex;gap:8px;flex-wrap:wrap;}
|
||||
.chip{padding:5px 14px;border:1px solid var(--border);border-radius:16px;font-size:var(--font-xs);color:var(--text-secondary);cursor:pointer;user-select:none;background:#fff;}
|
||||
.chip.active{border-color:var(--primary);color:var(--primary);background:var(--primary-light);}
|
||||
.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;min-width:120px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.modal--wide{width:680px;max-height:80vh;display:flex;flex-direction:column;}
|
||||
.form-item .with-btn{display:flex;gap:8px;}
|
||||
.table-holder{overflow:auto;border:1px solid var(--border);border-radius:var(--radius-sm);}
|
||||
.modal--wide .table-holder{flex:1;}
|
||||
.record-table{width:100%;min-width:0;border-collapse:collapse;font-size:var(--font-sm);margin-bottom:16px;}
|
||||
.record-table th{background:#FAFAFA;padding:8px 10px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.record-table td{padding:10px;border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.record-table th:last-child,.record-table td:last-child{position:static;box-shadow:none;}
|
||||
.table-holder table{min-width:0;}
|
||||
.table-holder thead tr th:last-child,.table-holder tbody td:last-child{position:static;box-shadow:none;}
|
||||
.mini-table td{white-space:normal;font-size:var(--font-sm);}
|
||||
.duty-toolbar{display:flex;align-items:center;gap:8px;margin-bottom:12px;}
|
||||
.duty-toolbar__hint{margin-left:auto;font-size:var(--font-sm);color:var(--text-placeholder);}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -217,15 +199,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="config-allocate-stat.html" class="sidebar-item">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup open">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item active">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item active">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -373,121 +347,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<div class="drawer__footer"><button class="btn btn-default" onclick="closeDrawer('detail')">关闭</button></div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 数据管理抽屉(单车出勤记录台账,由列表行操作打开) -->
|
||||
<div class="drawer-mask" id="dutyMask" onclick="closeDrawer('duty')"></div>
|
||||
<div class="drawer" id="dutyDrawer">
|
||||
<div class="drawer__header"><span id="dutyTitle">出勤记录</span><button class="drawer__close" onclick="closeDrawer('duty')">×</button></div>
|
||||
<div class="drawer__body">
|
||||
<div class="duty-toolbar">
|
||||
<button class="btn btn-primary" onclick="openDutyForm()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>登记出勤
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="showToast('导出该救护车出勤记录功能演示')">导出</button>
|
||||
<span class="duty-toolbar__hint" id="dutyHint"></span>
|
||||
</div>
|
||||
<div class="table-holder" style="max-height:calc(100vh - 300px);">
|
||||
<table class="mini-table">
|
||||
<thead>
|
||||
<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="dutyBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer__footer"><button class="btn btn-default" onclick="closeDrawer('duty')">关闭</button></div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 出勤登记/编辑抽屉(固定为当前车辆) -->
|
||||
<div class="drawer-mask" id="dutyFormMask" onclick="closeDrawer('dutyForm')"></div>
|
||||
<div class="drawer" id="dutyFormDrawer">
|
||||
<div class="drawer__header"><span id="dutyFormTitle">登记出勤</span><button class="drawer__close" onclick="closeDrawer('dutyForm')">×</button></div>
|
||||
<div class="drawer__body">
|
||||
<div class="form-section">救护车信息(自动带出)</div>
|
||||
<div class="form-grid">
|
||||
<div class="form-item"><span class="form-label">所属医疗点</span><input class="form-control" id="dfPoint" readonly></div>
|
||||
<div class="form-item"><span class="form-label">救护车车牌</span><input class="form-control" id="dfPlate" readonly></div>
|
||||
<div class="form-item"><span class="form-label">出勤司机</span><input class="form-control" id="dfDriver" readonly></div>
|
||||
<div class="form-item"><span class="form-label">司机电话</span><input class="form-control" id="dfTel" readonly></div>
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 出勤日期</span>
|
||||
<input class="form-control" type="date" id="dfDate"></div>
|
||||
</div>
|
||||
<div class="form-item form-item--full"><span class="form-label"><span class="req">*</span> 出勤类型</span>
|
||||
<div class="radio-group radio-wrap">
|
||||
<label class="radio radio--disabled"><input type="radio" name="dfType" value="一键呼叫" disabled>一键呼叫<span class="opt-tip">(由 PAD 端床头/随身呼叫自动生成,不可手动选择)</span></label>
|
||||
<label class="radio"><input type="radio" name="dfType" value="急救出车" checked>急救出车</label>
|
||||
<label class="radio"><input type="radio" name="dfType" value="计划转运">计划转运</label>
|
||||
<label class="radio"><input type="radio" name="dfType" value="日常巡诊">日常巡诊</label>
|
||||
<label class="radio"><input type="radio" name="dfType" value="应急戒备">应急戒备</label>
|
||||
</div></div>
|
||||
|
||||
<div class="form-section">救助信息</div>
|
||||
<div class="form-grid">
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 救助员工</span>
|
||||
<div class="with-btn">
|
||||
<input class="form-control" id="dfEmp" readonly placeholder="点击下方按钮选人" style="flex:1;">
|
||||
<button class="btn btn-default" onclick="openEmpPick()">选择员工</button>
|
||||
</div></div>
|
||||
<div class="form-item"><span class="form-label">员工工号</span>
|
||||
<input class="form-control" id="dfEmpCode" readonly placeholder="--"></div>
|
||||
</div>
|
||||
<div class="form-item form-item--full"><span class="form-label"><span class="req">*</span> 救助信息</span>
|
||||
<textarea class="form-control" id="dfInfo" placeholder="简述伤情/病情与处置过程"></textarea></div>
|
||||
|
||||
<div class="form-section">随车医护与地点</div>
|
||||
<div class="form-item form-item--full"><span class="form-label"><span class="req">*</span> 随车医护(可多选)</span>
|
||||
<div class="chips" id="dfStaff"></div></div>
|
||||
<div class="form-grid">
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 出勤地点</span>
|
||||
<input class="form-control" id="dfFrom" placeholder="出车起点,如:樊学作业区3号井场"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 到达地点</span>
|
||||
<input class="form-control" id="dfTo" placeholder="到达终点,如:樊学作业区医疗点"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer('dutyForm')">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveDutyForm()">保存登记</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 救助员工选人弹窗(出勤登记表单内) -->
|
||||
<div class="modal-mask" id="empMask">
|
||||
<div class="modal modal--wide">
|
||||
<div class="modal__title">选择救助员工</div>
|
||||
<div class="filter-bar" style="box-shadow:none;padding:0;margin-bottom:14px;border-radius:var(--radius-sm);">
|
||||
<div class="filter-item">
|
||||
<label>姓名/工号</label>
|
||||
<input class="filter-input" id="empQ" placeholder="输入姓名或工号过滤" style="min-width:150px;" oninput="renderEmpPick()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-holder" style="max-height:320px;">
|
||||
<table>
|
||||
<thead><tr><th style="width:40px"></th><th>姓名</th><th>员工工号</th><th>所属单位</th><th>所属部门</th></tr></thead>
|
||||
<tbody id="empBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__footer" style="margin-top:14px;">
|
||||
<button class="btn btn-default" onclick="closeModal('empMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="confirmEmp()">确认选择</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 出勤记录删除确认弹窗 -->
|
||||
<div class="modal-mask" id="dutyDelMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="9" stroke="#FAAD14" stroke-width="1.6"/><path d="M10 5.5v6M10 13.5v1" stroke="#FAAD14" stroke-width="1.8" stroke-linecap="round"/></svg> 删除确认</div>
|
||||
<div class="modal__text" id="dutyDelText">确认删除该条出勤记录?</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('dutyDelMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="confirmDutyDelete()">确认删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 批量导入弹窗 -->
|
||||
<div class="modal-mask" id="importMask">
|
||||
<div class="modal">
|
||||
@@ -595,7 +454,6 @@ function renderTable(){
|
||||
+'<td>'+gpsBadge+'</td>'
|
||||
+'<td class="td-actions">'
|
||||
+'<button class="btn btn-link" onclick="openDetail('+a.id+')">详情</button>'
|
||||
+'<button class="btn btn-link" onclick="openDuty('+a.id+')">数据管理</button>'
|
||||
+'<button class="btn btn-link" onclick="openForm('+a.id+')">编辑</button>'
|
||||
+'<button class="btn btn-link btn-link--danger" onclick="askDelete(['+a.id+'])">删除</button>'
|
||||
+'</td></tr>';
|
||||
@@ -738,7 +596,7 @@ function askDelete(ids){
|
||||
if(!ids.length){showToast('请先勾选要删除的救护车');return;}
|
||||
pendingDel=ids;
|
||||
var names=ids.map(function(id){return ambulances.find(function(a){return a.id===id;}).plate;});
|
||||
document.getElementById('delText').textContent='确认删除救护车「'+names.slice(0,3).join('、')+(names.length>3?' 等 '+names.length+' 辆':'')+'」?其历史出勤记录保留快照,对应车辆的「数据管理」入口将随之移除。';
|
||||
document.getElementById('delText').textContent='确认删除救护车「'+names.slice(0,3).join('、')+(names.length>3?' 等 '+names.length+' 辆':'')+'」?';
|
||||
document.getElementById('delMask').classList.add('open');
|
||||
}
|
||||
function confirmDelete(){
|
||||
@@ -769,173 +627,6 @@ function doImport(){
|
||||
/* [交互] 查看导入任务(异步任务演示) */
|
||||
function openImportTasks(){document.getElementById('taskMask').classList.add('open');}
|
||||
|
||||
/* ===== 数据管理(单车出勤记录,原「救护车值班」页功能并入) ===== */
|
||||
var staffPool=['石维国','李桂芳','曲志明','张秀兰','高建军','闫婷','刘玉梅','徐立成'];
|
||||
/* 可选的救助员工(与员工分配页已分配名单一致) */
|
||||
var empPool=[
|
||||
{name:'石维国',code:'CQ021578',unit:'采油一厂',dept:'樊学作业区'},
|
||||
{name:'李桂芳',code:'CQ032144',unit:'采油一厂',dept:'樊学作业区'},
|
||||
{name:'白瑞',code:'CQ044871',unit:'采油一厂',dept:'生产技术部'},
|
||||
{name:'曲志明',code:'CQ019203',unit:'采油二厂',dept:'姬圪台联合站'},
|
||||
{name:'张秀兰',code:'CQ027710',unit:'采油二厂',dept:'姬圪台联合站'},
|
||||
{name:'赵万福',code:'CQ033096',unit:'采油二厂',dept:'桐园作业区'},
|
||||
{name:'高建军',code:'CQ010564',unit:'第四采油厂',dept:'基地管理处'},
|
||||
{name:'闫婷',code:'CQ041822',unit:'第四采油厂',dept:'健康管理部'},
|
||||
{name:'刘玉梅',code:'CQ036441',unit:'采气一厂',dept:'靖边净化厂'},
|
||||
{name:'呼建国',code:'CQ029905',unit:'采气一厂',dept:'靖边净化厂'},
|
||||
{name:'徐立成',code:'CQ022317',unit:'采气一厂',dept:'苏里格南作业区'},
|
||||
{name:'杨慧敏',code:'CQ045130',unit:'采油一厂',dept:'樊学作业区'}
|
||||
];
|
||||
var duties=[
|
||||
{id:1,date:'2026-09-06',point:'樊学作业区医疗点',plate:'CQ·0712A',type:'急救出车',driver:'田震',tel:'139****5218',staff:['石维国','李桂芳'],emp:'白瑞',empCode:'CQ044871',info:'井场触电致左前臂灼伤,现场处置后接回医疗点换药',from:'樊学作业区3号井场',to:'樊学作业区医疗点'},
|
||||
{id:2,date:'2026-09-05',point:'西峰基地医疗点',plate:'CQ·0208C',type:'计划转运',driver:'罗建平',tel:'150****8357',staff:['闫婷'],emp:'高建军',empCode:'CQ010564',info:'每周常规血透转运,途中生命体征平稳',from:'西峰基地医疗点',to:'第四采油厂总医院'},
|
||||
{id:3,date:'2026-09-03',point:'靖边气田医疗点',plate:'CQ·1533D',type:'一键呼叫',driver:'邓成',tel:'133****9481',staff:['刘玉梅'],emp:'呼建国',empCode:'CQ029905',info:'净化厂装置区气体报警疏散,一名员工头晕请求救护(PAD端一键呼叫自动生成)',from:'靖边净化厂中控区',to:'靖边气田医疗点',auto:true},
|
||||
{id:4,date:'2026-08-29',point:'姬圪台作业区医疗点',plate:'CQ·1366B',type:'急救出车',driver:'冯保山',tel:'135****6174',staff:['曲志明','张秀兰'],emp:'张秀兰',empCode:'CQ027710',info:'泵房高温中暑晕厥,物理降温后补液观察',from:'姬圪台联合站泵房',to:'姬圪台作业区医疗点'},
|
||||
{id:5,date:'2026-08-26',point:'西峰基地医疗点',plate:'CQ·0208C',type:'日常巡诊',driver:'罗建平',tel:'150****8357',staff:['高建军','闫婷'],emp:'高建军',empCode:'CQ010564',info:'基地夏季巡诊送药,无异常处置',from:'西峰基地综合服务区',to:'西峰基地机关办公楼'},
|
||||
{id:6,date:'2026-08-22',point:'安塞采油队长住点医疗室',plate:'CQ·0917E',type:'计划转运',driver:'苏文斌',tel:'155****6703',staff:['石维国'],emp:'白瑞',empCode:'CQ044871',info:'骨折术后拆线复查陪同转运',from:'安塞常驻点医疗室',to:'吴起油田医院'},
|
||||
{id:7,date:'2026-08-18',point:'乌审旗采气区医疗点',plate:'CQ·2201F',type:'应急戒备',driver:'曹雪芹',tel:'186****2940',staff:['徐立成'],emp:'徐立成',empCode:'CQ022317',info:'汛期营地应急戒备值守,车辆人员全时待命',from:'乌审旗医疗点',to:'苏里格南作业区营地'},
|
||||
{id:8,date:'2026-08-15',point:'靖边气田医疗点',plate:'CQ·1533D',type:'急救出车',driver:'邓成',tel:'133****9481',staff:['刘玉梅'],emp:'刘玉梅',empCode:'CQ036441',info:'高血压危象,协同降压后转送县级医院',from:'靖边气田医疗点',to:'靖边县人民医院'},
|
||||
{id:9,date:'2026-09-01',point:'樊学作业区医疗点',plate:'CQ·0712A',type:'急救出车',driver:'田震',tel:'139****5218',staff:['李桂芳'],emp:'杨慧敏',empCode:'CQ045130',info:'高处坠落致踝关节扭伤,固定后接回',from:'姬塬先导试验区12号井场',to:'樊学作业区医疗点'}
|
||||
];
|
||||
var curAmb=null,dutyNextId=10,dutyEditingId=null,pendingDutyDel=null,curStaff=[],curEmp=null;
|
||||
|
||||
function typeBadge(t){
|
||||
var cls={'一键呼叫':'badge--danger','急救出车':'badge--warning','计划转运':'badge--info','日常巡诊':'badge--success','应急戒备':'badge--muted'}[t]||'badge--muted';
|
||||
return '<span class="badge '+cls+'">'+t+'</span>';
|
||||
}
|
||||
function dutyList(){
|
||||
if(!curAmb)return [];
|
||||
return duties.filter(function(d){return d.plate===curAmb.plate;})
|
||||
.sort(function(a,b){return a.date<b.date?1:(a.date>b.date?-1:b.id-a.id);});
|
||||
}
|
||||
function openDuty(id){
|
||||
curAmb=ambulances.find(function(a){return a.id===id;});
|
||||
if(!curAmb)return;
|
||||
document.getElementById('dutyTitle').textContent='出勤记录 · '+curAmb.plate+'('+curAmb.point+')';
|
||||
renderDutyTable();
|
||||
document.getElementById('dutyMask').classList.add('open');
|
||||
document.getElementById('dutyDrawer').classList.add('open');
|
||||
}
|
||||
function renderDutyTable(){
|
||||
var list=dutyList();
|
||||
document.getElementById('dutyHint').textContent='本车共 '+list.length+' 条出勤记录';
|
||||
var tbody=document.getElementById('dutyBody');
|
||||
if(!list.length){tbody.innerHTML='<tr><td colspan="12" class="td-empty">该救护车暂无出勤记录,点击「登记出勤」补录</td></tr>';return;}
|
||||
var html='';
|
||||
list.forEach(function(d,i){
|
||||
var ops=d.auto
|
||||
?'<span class="badge badge--muted">系统生成</span>'
|
||||
:('<button class="btn btn-link" onclick="openDutyForm('+d.id+')">编辑</button>'
|
||||
+'<button class="btn btn-link btn-link--danger" onclick="askDutyDelete('+d.id+')">删除</button>');
|
||||
html+='<tr>'
|
||||
+'<td>'+(i+1)+'</td>'
|
||||
+'<td>'+d.date+'</td>'
|
||||
+'<td>'+typeBadge(d.type)+'</td>'
|
||||
+'<td>'+d.driver+'</td>'
|
||||
+'<td>'+d.tel+'</td>'
|
||||
+'<td>'+d.staff.join('、')+'</td>'
|
||||
+'<td>'+d.emp+'</td>'
|
||||
+'<td>'+d.empCode+'</td>'
|
||||
+'<td style="min-width:200px;">'+d.info+'</td>'
|
||||
+'<td style="min-width:140px;">'+d.from+'</td>'
|
||||
+'<td style="min-width:140px;">'+d.to+'</td>'
|
||||
+'<td>'+ops+'</td>'
|
||||
+'</tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
}
|
||||
function renderStaffChips(){
|
||||
document.getElementById('dfStaff').innerHTML=staffPool.map(function(n){
|
||||
return '<span class="chip'+(curStaff.indexOf(n)!==-1?' active':'')+'" onclick="toggleStaff(\''+n+'\')">'+n+'</span>';
|
||||
}).join('');
|
||||
}
|
||||
function toggleStaff(n){
|
||||
var i=curStaff.indexOf(n);
|
||||
if(i===-1)curStaff.push(n);else curStaff.splice(i,1);
|
||||
renderStaffChips();
|
||||
}
|
||||
function openDutyForm(id){
|
||||
dutyEditingId=id||null;
|
||||
var d=id?duties.find(function(x){return x.id===id;}):null;
|
||||
document.getElementById('dutyFormTitle').textContent=id?('编辑出勤记录 · '+d.date):('登记出勤 · '+curAmb.plate);
|
||||
document.getElementById('dfPoint').value=curAmb.point;
|
||||
document.getElementById('dfPlate').value=curAmb.plate;
|
||||
document.getElementById('dfDriver').value=curAmb.driver;
|
||||
document.getElementById('dfTel').value=curAmb.tel;
|
||||
document.getElementById('dfDate').value=d?d.date:'2026-09-07';
|
||||
setRadio('dfType',d?d.type:'急救出车');
|
||||
document.getElementById('dfEmp').value=d?d.emp:'';
|
||||
document.getElementById('dfEmpCode').value=d?d.empCode:'';
|
||||
document.getElementById('dfInfo').value=d?d.info:'';
|
||||
document.getElementById('dfFrom').value=d?d.from:'';
|
||||
document.getElementById('dfTo').value=d?d.to:'';
|
||||
curStaff=d?d.staff.slice():[];
|
||||
curEmp=d?{name:d.emp,code:d.empCode}:null;
|
||||
renderStaffChips();
|
||||
document.getElementById('dutyFormMask').classList.add('open');
|
||||
document.getElementById('dutyFormDrawer').classList.add('open');
|
||||
}
|
||||
function saveDutyForm(){
|
||||
var date=document.getElementById('dfDate').value;
|
||||
var emp=document.getElementById('dfEmp').value;
|
||||
var info=document.getElementById('dfInfo').value.trim();
|
||||
var from=document.getElementById('dfFrom').value.trim();
|
||||
var to=document.getElementById('dfTo').value.trim();
|
||||
if(!date){showToast('请选择出勤日期');return;}
|
||||
if(date>'2026-09-07'){showToast('出勤日期不能晚于今天');return;}
|
||||
if(!emp){showToast('请选择救助员工');return;}
|
||||
if(!info){showToast('请填写救助信息');return;}
|
||||
if(!curStaff.length){showToast('请至少选择一名随车医护');return;}
|
||||
if(!from){showToast('请填写出勤地点');return;}
|
||||
if(!to){showToast('请填写到达地点');return;}
|
||||
var obj={
|
||||
id:dutyEditingId||dutyNextId++,date:date,point:curAmb.point,plate:curAmb.plate,
|
||||
type:getRadio('dfType'),driver:curAmb.driver,tel:curAmb.tel,
|
||||
staff:curStaff.slice(),emp:emp,empCode:document.getElementById('dfEmpCode').value,
|
||||
info:info,from:from,to:to
|
||||
};
|
||||
if(dutyEditingId){
|
||||
duties.splice(duties.findIndex(function(x){return x.id===dutyEditingId;}),1,obj);
|
||||
}else{
|
||||
duties.push(obj);
|
||||
}
|
||||
closeDrawer('dutyForm');renderDutyTable();
|
||||
showToast(dutyEditingId?'出勤记录已更新':'出勤记录已登记');
|
||||
}
|
||||
function openEmpPick(){
|
||||
document.getElementById('empQ').value='';
|
||||
renderEmpPick();
|
||||
document.getElementById('empMask').classList.add('open');
|
||||
}
|
||||
function renderEmpPick(){
|
||||
var q=document.getElementById('empQ').value.trim();
|
||||
var list=empPool.filter(function(e){return !q||e.name.indexOf(q)!==-1||e.code.toLowerCase().indexOf(q.toLowerCase())!==-1;});
|
||||
document.getElementById('empBody').innerHTML=list.length?list.map(function(e){
|
||||
return '<tr><td><input type="radio" name="empSel" value="'+e.code+'"'+(curEmp&&curEmp.code===e.code?' checked':'')+'></td>'
|
||||
+'<td style="font-weight:600;">'+e.name+'</td><td>'+e.code+'</td><td>'+e.unit+'</td><td>'+e.dept+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="5" class="td-empty">未找到匹配员工</td></tr>';
|
||||
}
|
||||
function confirmEmp(){
|
||||
var r=document.querySelector('input[name="empSel"]:checked');
|
||||
if(!r){showToast('请选择一名员工');return;}
|
||||
var e=empPool.find(function(x){return x.code===r.value;});
|
||||
curEmp=e;
|
||||
document.getElementById('dfEmp').value=e.name;
|
||||
document.getElementById('dfEmpCode').value=e.code;
|
||||
closeModal('empMask');
|
||||
}
|
||||
function askDutyDelete(id){
|
||||
pendingDutyDel=id;
|
||||
var d=duties.find(function(x){return x.id===id;});
|
||||
document.getElementById('dutyDelText').textContent='确认删除「'+d.date+' '+d.plate+'」的出勤记录?删除后「数据统计」模块的救护车出勤口径将同步回落。';
|
||||
document.getElementById('dutyDelMask').classList.add('open');
|
||||
}
|
||||
function confirmDutyDelete(){
|
||||
duties=duties.filter(function(d){return d.id!==pendingDutyDel;});
|
||||
closeModal('dutyDelMask');renderDutyTable();
|
||||
showToast('出勤记录已删除');
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
function closeDrawer(k){
|
||||
document.getElementById(k+'Mask').classList.remove('open');
|
||||
|
||||
@@ -227,15 +227,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="config-allocate-stat.html" class="sidebar-item">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -10,7 +10,8 @@ body{font-family:"Microsoft YaHei","PingFang SC",sans-serif;font-size:var(--font
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.top-bar{position:fixed;top:0;left:0;right:0;height:56px;background:#001529;display:flex;align-items:center;padding:0 24px;z-index:100;}
|
||||
.top-bar__logo{color:#fff;font-size:var(--font-lg);font-weight:600;display:flex;align-items:center;gap:10px;margin-right:40px;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:200px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 14px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
@@ -169,15 +170,7 @@ textarea.form-control{height:72px;padding:8px 10px;resize:vertical;}
|
||||
<a href="config-allocate-stat.html" class="sidebar-item">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -184,15 +184,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<a href="config-allocate-stat.html" class="sidebar-item">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -196,15 +196,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="config-allocate-stat.html" class="sidebar-item">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -172,15 +172,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="config-allocate-stat.html" class="sidebar-item">分配统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车配置
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车列表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="config-ambulance.html" class="sidebar-item">救护车配置</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -0,0 +1,690 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>救护车出勤 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.10);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:200px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 14px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;padding-bottom:24px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
/* 统计卡片 */
|
||||
.stat-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:16px;}
|
||||
.stat-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:18px 20px;display:flex;align-items:center;gap:14px;}
|
||||
.stat-card__icon{width:44px;height:44px;border-radius:var(--radius-md);display:flex;align-items:center;justify-content:center;font-size:20px;flex-shrink:0;}
|
||||
.stat-card__icon--blue{background:var(--primary-light);}
|
||||
.stat-card__icon--green{background:#F6FFED;}
|
||||
.stat-card__icon--orange{background:#FFFBE6;}
|
||||
.stat-card__icon--red{background:#FFF1F0;}
|
||||
.stat-card__label{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.stat-card__value{font-size:24px;font-weight:600;color:var(--text-primary);line-height:1.3;font-variant-numeric:tabular-nums;}
|
||||
.stat-card__extra{font-size:var(--font-xs);color:var(--text-placeholder);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-select{height:36px;min-width:140px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);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 8px center;cursor:pointer;outline:none;appearance:none;-webkit-appearance:none;}
|
||||
.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;min-width:120px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.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;white-space:nowrap;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.btn-link--danger{color:var(--danger);}
|
||||
.action-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;background:#fff;margin-top:16px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1560px;}
|
||||
thead th{background:#FAFAFA;padding:10px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:12px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
thead tr th:last-child,tbody td:last-child{position:sticky;right:0;z-index:5;background:#fff;box-shadow:-4px 0 8px rgba(0,0,0,0.04);}
|
||||
thead tr th:last-child{z-index:8;background:#FAFAFA;}
|
||||
tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.td-empty{text-align:center;padding:48px 0;color:var(--text-placeholder);}
|
||||
.badge{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.badge--danger{background:#FFF1F0;color:#CF1322;border:1px solid #FFCCC7;}
|
||||
.badge--info{background:#E6F7FF;color:#096DD9;border:1px solid #91D5FF;}
|
||||
.badge--warning{background:#FFFBE6;color:#D48806;border:1px solid #FFE58F;}
|
||||
.badge--success{background:#F6FFED;color:#389E0D;border:1px solid #B7EB8F;}
|
||||
.badge--muted{background:#F5F5F5;color:var(--text-secondary);border:1px solid var(--border);}
|
||||
.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);}
|
||||
.page-btn{min-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;padding:0 6px;transition:all .2s;}
|
||||
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.page-btn:disabled{opacity:.4;cursor:not-allowed;background:#fff;color:var(--text-placeholder);border-color:var(--border);}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
.drawer-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:900;}
|
||||
.drawer-mask.open{display:block;}
|
||||
.drawer{position:fixed;top:56px;right:-760px;bottom:0;width:720px;background:#fff;z-index:910;box-shadow:-8px 0 24px rgba(0,0,0,.12);transition:right .25s ease;display:flex;flex-direction:column;}
|
||||
.drawer.open{right:0;}
|
||||
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-lg);font-weight:600;flex-shrink:0;}
|
||||
.drawer__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.drawer__close:hover{color:var(--text-primary);}
|
||||
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
|
||||
.drawer__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 12px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 16px;}
|
||||
.form-item{display:flex;flex-direction:column;gap:6px;margin-bottom:14px;}
|
||||
.form-item--full{grid-column:1/-1;}
|
||||
.form-label{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.form-label .req{color:var(--danger);}
|
||||
.form-control{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;width:100%;}
|
||||
.form-control:focus{border-color:var(--primary);}
|
||||
.form-control:disabled{background:#F5F5F5;color:var(--text-secondary);cursor:not-allowed;}
|
||||
select.form-control{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;-webkit-appearance:none;padding-right:28px;cursor:pointer;}
|
||||
.radio-group{display:flex;gap:20px;height:36px;align-items:center;flex-wrap:wrap;}
|
||||
.radio{display:flex;align-items:center;gap:6px;font-size:var(--font-sm);color:var(--text-primary);cursor:pointer;}
|
||||
.radio input{accent-color:var(--primary);cursor:pointer;}
|
||||
.chip-wrap{display:flex;flex-wrap:wrap;gap:6px;min-height:20px;}
|
||||
.chip{display:inline-flex;align-items:center;gap:6px;background:#E6F7FF;border:1px solid #91D5FF;color:#096DD9;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.chip .chip-del{cursor:pointer;font-weight:700;color:#69A8E8;}
|
||||
.chip .chip-del:hover{color:var(--danger);}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid var(--border);}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:130px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:440px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:8px;}
|
||||
.modal__text{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:20px;line-height:1.6;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;}
|
||||
.modal--wide{width:680px;max-height:82vh;display:flex;flex-direction:column;padding:0;}
|
||||
.modal--wide .modal__head{padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-base);font-weight:600;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;}
|
||||
.modal--wide .modal__body{flex:1;overflow-y:auto;padding:20px 24px;}
|
||||
.modal--wide .modal__foot{padding:12px 24px;border-top:1px solid var(--border);display:flex;justify-content:flex-end;gap:8px;flex-shrink:0;}
|
||||
.record-table{width:100%;min-width:0;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
.record-table th{background:#FAFAFA;padding:8px 10px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.record-table td{padding:10px;border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.record-table th:last-child,.record-table td:last-child{position:static;box-shadow:none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M14 6.5l7 3.5v4.5c0 4.2-2.9 6.8-7 7.5-4.1-.7-7-3.3-7-7.5V10l7-3.5z" stroke="#fff" stroke-width="1.8" fill="none"/><path d="M11 13.5h6M14 10.5v6" stroke="#fff" stroke-width="1.8" stroke-linecap="round"/></svg> 一线医疗</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-visit-data.html">档案</a>
|
||||
<a href="config-medical-point.html">基础配置</a>
|
||||
<a href="daily-treatment-staff.html" class="active">日常业务</a>
|
||||
<a href="bed-device.html">床头呼叫</a>
|
||||
<a href="stat-clinic-chart.html">数据统计</a>
|
||||
<a href="hut-banner.html">健康小屋</a>
|
||||
<a href="alert-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏(当前一级分组「日常业务」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">日常业务</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>日常诊疗</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-treatment-staff.html" class="sidebar-item">员工就诊</a>
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item active">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>任务管理</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-follow-task.html" class="sidebar-item">随访任务</a>
|
||||
<a href="daily-interpret.html" class="sidebar-item">解读任务</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-education.html" class="sidebar-item">健康宣教管理</a>
|
||||
<a href="daily-interpret-manage.html" class="sidebar-item">报告解读管理</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
|
||||
<!-- [状态] 统计卡片 -->
|
||||
<div class="stat-cards">
|
||||
<div class="stat-card"><div class="stat-card__icon stat-card__icon--blue">📅</div><div><div class="stat-card__label">当周出勤</div><div class="stat-card__value" id="kWeek">0</div><div class="stat-card__extra" id="kWeekExtra">本周</div></div></div>
|
||||
<div class="stat-card"><div class="stat-card__icon stat-card__icon--green">🗓️</div><div><div class="stat-card__label">当月出勤</div><div class="stat-card__value" id="kMonth">0</div><div class="stat-card__extra" id="kMonthExtra">本月</div></div></div>
|
||||
<div class="stat-card"><div class="stat-card__icon stat-card__icon--orange">📆</div><div><div class="stat-card__label">年度出勤</div><div class="stat-card__value" id="kYear">0</div><div class="stat-card__extra" id="kYearExtra">本年度</div></div></div>
|
||||
<div class="stat-card"><div class="stat-card__icon stat-card__icon--red">📊</div><div><div class="stat-card__label">累计出勤</div><div class="stat-card__value" id="kTotal">0</div><div class="stat-card__extra">历史累计</div></div></div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 筛选栏:医疗点→救护车级联 + 出勤类型 + 日期区间 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>所属医疗点</label>
|
||||
<select class="filter-select" id="filterPoint" onchange="onFilterPoint()" style="min-width:170px;">
|
||||
<option value="">全部医疗点</option>
|
||||
<option>樊学作业区医疗点</option><option>安塞采油队长住点医疗室</option><option>姬塬作业区医疗点</option><option>姬圪台作业区医疗点</option><option>桐园作业区医疗点</option><option>西峰基地医疗点</option><option>靖边气田医疗点</option><option>乌审旗采气区医疗点</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>救护车</label>
|
||||
<select class="filter-select" id="filterAmb" style="min-width:130px;">
|
||||
<option value="">全部救护车</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>出勤类型</label>
|
||||
<select class="filter-select" id="filterType" style="min-width:110px;">
|
||||
<option value="">全部类型</option>
|
||||
<option>病情急救</option><option>伤情急救</option><option>日常巡诊</option><option>应急戒备</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>出勤日期</label>
|
||||
<input class="filter-input" type="date" id="filterFrom" style="min-width:130px;">
|
||||
<span style="color:var(--text-placeholder);">至</span>
|
||||
<input class="filter-input" type="date" id="filterTo" style="min-width:130px;">
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="applyFilter()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.3"/><path d="M9.5 9.5L13 13" stroke="#fff" stroke-width="1.3" stroke-linecap="round"/></svg>查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="resetFilter()">重置</button>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 操作栏 -->
|
||||
<div class="action-bar">
|
||||
<button class="btn btn-primary" onclick="openForm()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新增出勤
|
||||
</button>
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openExportTasks()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<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="tableBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<span id="pageInfo"></span>
|
||||
<button class="page-btn" id="prevBtn" onclick="turnPage(-1)">上一页</button>
|
||||
<span id="pageNum" style="min-width:64px;text-align:center;"></span>
|
||||
<button class="page-btn" id="nextBtn" onclick="turnPage(1)">下一页</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 新增/编辑抽屉 -->
|
||||
<div class="drawer-mask" id="formMask" onclick="closeDrawer('form')"></div>
|
||||
<div class="drawer" id="formDrawer">
|
||||
<div class="drawer__header"><span id="formTitle">新增出勤</span><button class="drawer__close" onclick="closeDrawer('form')">×</button></div>
|
||||
<div class="drawer__body">
|
||||
<div class="form-section">救护车归属</div>
|
||||
<div class="form-grid">
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 所属医疗点</span>
|
||||
<select class="form-control" id="fPoint" onchange="onFormPoint()"><option value="">请选择医疗点</option><option>樊学作业区医疗点</option><option>安塞采油队长住点医疗室</option><option>姬塬作业区医疗点</option><option>姬圪台作业区医疗点</option><option>桐园作业区医疗点</option><option>西峰基地医疗点</option><option>靖边气田医疗点</option><option>乌审旗采气区医疗点</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 救护车</span>
|
||||
<select class="form-control" id="fAmb" onchange="onFormAmb()"><option value="">请先选择医疗点</option></select></div>
|
||||
<div class="form-item"><span class="form-label">救护类型</span>
|
||||
<input class="form-control" id="fAmbulanceType" disabled placeholder="选择救护车后自动带出"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">出勤信息</div>
|
||||
<div class="form-grid">
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 出勤日期</span>
|
||||
<input class="form-control" type="date" id="fDate"></div>
|
||||
<div class="form-item form-item--full"><span class="form-label"><span class="req">*</span> 出勤类型</span>
|
||||
<div class="radio-group">
|
||||
<label class="radio"><input type="radio" name="fDispatch" value="病情急救" checked>病情急救</label>
|
||||
<label class="radio"><input type="radio" name="fDispatch" value="伤情急救">伤情急救</label>
|
||||
<label class="radio"><input type="radio" name="fDispatch" value="日常巡诊">日常巡诊</label>
|
||||
<label class="radio"><input type="radio" name="fDispatch" value="应急戒备">应急戒备</label>
|
||||
</div></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 出勤司机</span>
|
||||
<select class="form-control" id="fDriver" onchange="onFormDriver()"><option value="">请选择司机</option></select></div>
|
||||
<div class="form-item"><span class="form-label">司机电话</span>
|
||||
<input class="form-control" id="fTel" disabled placeholder="选择司机后自动带出"></div>
|
||||
<div class="form-item form-item--full"><span class="form-label"><span class="req">*</span> 随车医护</span>
|
||||
<div class="chip-wrap" id="fStaffChips"></div>
|
||||
<div style="margin-top:2px;"><button class="btn btn-default" onclick="openStaffModal()" style="height:32px;">+ 添加医护</button></div></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 出勤地点</span>
|
||||
<input class="form-control" id="fOut" placeholder="如:樊学作业区 7#井站"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 到达地点</span>
|
||||
<input class="form-control" id="fTo" placeholder="如:CQ油田总医院"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer('form')">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 详情抽屉 -->
|
||||
<div class="drawer-mask" id="detailMask" onclick="closeDrawer('detail')"></div>
|
||||
<div class="drawer" id="detailDrawer">
|
||||
<div class="drawer__header"><span id="detailTitle">出勤详情</span><button class="drawer__close" onclick="closeDrawer('detail')">×</button></div>
|
||||
<div class="drawer__body" id="detailBody"></div>
|
||||
<div class="drawer__footer"><button class="btn btn-default" onclick="closeDrawer('detail')">关闭</button></div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 随车医护选择弹窗 -->
|
||||
<div class="modal-mask" id="staffMask">
|
||||
<div class="modal modal--wide">
|
||||
<div class="modal__head"><span>选择随车医护</span><button class="drawer__close" onclick="closeModal('staffMask')">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="filter-item" style="margin-bottom:12px;">
|
||||
<label>姓名</label>
|
||||
<input class="filter-input" id="staffKeyword" placeholder="请输入姓名" onkeyup="if(event.key==='Enter')renderStaffList()">
|
||||
<button class="btn btn-primary" onclick="renderStaffList()">查询</button>
|
||||
</div>
|
||||
<table class="record-table">
|
||||
<thead><tr><th style="width:40px;"></th><th>姓名</th><th>职称</th><th>岗位</th><th>所属医疗点</th></tr></thead>
|
||||
<tbody id="staffListBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__foot">
|
||||
<button class="btn btn-default" onclick="closeModal('staffMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="confirmStaff()">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导出任务弹窗 -->
|
||||
<div class="modal-mask" id="taskMask">
|
||||
<div class="modal modal--wide">
|
||||
<div class="modal__head"><span>救护车出勤导出任务</span><button class="drawer__close" onclick="closeModal('taskMask')">×</button></div>
|
||||
<div class="modal__body">
|
||||
<table class="record-table">
|
||||
<thead><tr><th>文件名称</th><th>时间</th><th>状态</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>救护车出勤-2026年9月.xlsx</td><td>2026-09-08 17:20:11</td><td><span class="badge badge--success">成功</span></td><td><button class="btn btn-link" onclick="showToast('文件下载中…')">下载</button></td></tr>
|
||||
<tr><td>救护车出勤-2026年8月.xlsx</td><td>2026-08-31 09:05:47</td><td><span class="badge badge--success">成功</span></td><td><button class="btn btn-link" onclick="showToast('文件下载中…')">下载</button></td></tr>
|
||||
<tr><td>救护车出勤-近7天.xlsx</td><td>2026-09-08 08:41:33</td><td><span class="badge badge--warning">导出中…</span></td><td>—</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__foot"><button class="btn btn-default" onclick="closeModal('taskMask')">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 删除确认弹窗 -->
|
||||
<div class="modal-mask" id="delMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="9" stroke="#FAAD14" stroke-width="1.6"/><path d="M10 5.5v6M10 13.5v1" stroke="#FAAD14" stroke-width="1.8" stroke-linecap="round"/></svg> 删除确认</div>
|
||||
<div class="modal__text" id="delText">确认删除该条出勤记录?</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('delMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="confirmDelete()">确认删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* ===== 基础数据(脱敏) ===== */
|
||||
var points=['樊学作业区医疗点','安塞采油队长住点医疗室','姬塬作业区医疗点','姬圪台作业区医疗点','桐园作业区医疗点','西峰基地医疗点','靖边气田医疗点','乌审旗采气区医疗点'];
|
||||
/* 救护车台账:与「基础配置·救护车配置」一致 */
|
||||
var ambulances=[
|
||||
{plate:'CQ·0712A',point:'樊学作业区医疗点',type:'急救型',model:'江铃轻型监护型救护车',driver:'田震',tel:'139****5218'},
|
||||
{plate:'CQ·1366B',point:'姬圪台作业区医疗点',type:'急救型',model:'福田图雅诺监护型救护车',driver:'冯保山',tel:'135****6174'},
|
||||
{plate:'CQ·0208C',point:'西峰基地医疗点',type:'转运型',model:'福特全顺转运型救护车',driver:'罗建平',tel:'150****8357'},
|
||||
{plate:'CQ·1533D',point:'靖边气田医疗点',type:'急救型',model:'东风轻型救护车',driver:'邓成',tel:'133****9481'},
|
||||
{plate:'CQ·0917E',point:'安塞采油队长住点医疗室',type:'转运型',model:'江淮瑞风转运型救护车',driver:'苏文斌',tel:'155****6703'},
|
||||
{plate:'CQ·2201F',point:'乌审旗采气区医疗点',type:'急救型',model:'红旗轻型监护型救护车',driver:'曹雪芹',tel:'186****2940'}
|
||||
];
|
||||
/* 救护车司机列表:从救护车台账驾驶员去重提取 */
|
||||
var drivers=[];
|
||||
(function(){
|
||||
var seen={};
|
||||
ambulances.forEach(function(a){
|
||||
if(!seen[a.driver]){seen[a.driver]=true;drivers.push({name:a.driver,tel:a.tel});}
|
||||
});
|
||||
})();
|
||||
/* 医护人员池:与「基础配置·医护人员管理」一致 */
|
||||
var medStaff=[
|
||||
{id:1,name:'韩东学',job:'主治医师',post:'医生',point:'樊学作业区医疗点'},
|
||||
{id:2,name:'兰小娟',job:'主管护师',post:'护士',point:'樊学作业区医疗点'},
|
||||
{id:3,name:'白宇峰',job:'副主任医师',post:'医生',point:'安塞采油队长住点医疗室'},
|
||||
{id:4,name:'温亚丽',job:'主治医师',post:'医生',point:'姬塬作业区医疗点'},
|
||||
{id:5,name:'窦志远',job:'主任医师',post:'医生',point:'姬圪台作业区医疗点'},
|
||||
{id:6,name:'苗慧敏',job:'护师',post:'护士',point:'姬圪台作业区医疗点'},
|
||||
{id:7,name:'屈二娃',job:'住院医师',post:'医生',point:'桐园作业区医疗点'},
|
||||
{id:8,name:'霍静怡',job:'技师',post:'检验人员',point:'西峰基地医疗点'},
|
||||
{id:9,name:'康永强',job:'主治医师',post:'放射人员',point:'靖边气田医疗点'},
|
||||
{id:10,name:'花灵芝',job:'主管护师',post:'护士',point:'乌审旗采气区医疗点'},
|
||||
{id:11,name:'荣大海',job:'副主任医师',post:'医生',point:'乌审旗采气区医疗点'},
|
||||
{id:12,name:'牛玉洁',job:'护师',post:'药师',point:'姬塬作业区医疗点'}
|
||||
];
|
||||
/* 救护车出勤记录:多救护车混合,覆盖四类出勤类型 */
|
||||
var attendances=[
|
||||
{id:1,date:'2026-09-08',point:'樊学作业区医疗点',plate:'CQ·0712A',type:'急救型',dispatch:'病情急救',driver:'田震',tel:'139****5218',staff:['韩东学','兰小娟'],out:'樊学作业区 7#井站',to:'CQ油田总医院'},
|
||||
{id:2,date:'2026-09-08',point:'姬圪台作业区医疗点',plate:'CQ·1366B',type:'急救型',dispatch:'伤情急救',driver:'冯保山',tel:'135****6174',staff:['窦志远','苗慧敏'],out:'姬圪台联合站',to:'庆阳市人民医院'},
|
||||
{id:3,date:'2026-09-07',point:'西峰基地医疗点',plate:'CQ·0208C',type:'转运型',dispatch:'日常巡诊',driver:'罗建平',tel:'150****8357',staff:['霍静怡'],out:'西峰基地机关',to:'西峰基地卫生室'},
|
||||
{id:4,date:'2026-09-07',point:'靖边气田医疗点',plate:'CQ·1533D',type:'急救型',dispatch:'应急戒备',driver:'邓成',tel:'133****9481',staff:['康永强','花灵芝'],out:'靖边净化厂',to:'现场应急指挥部'},
|
||||
{id:5,date:'2026-09-06',point:'安塞采油队长住点医疗室',plate:'CQ·0917E',type:'转运型',dispatch:'日常巡诊',driver:'苏文斌',tel:'155****6703',staff:['白宇峰'],out:'安塞基地队部',to:'吴起油田医院'},
|
||||
{id:6,date:'2026-09-06',point:'乌审旗采气区医疗点',plate:'CQ·2201F',type:'急救型',dispatch:'伤情急救',driver:'曹雪芹',tel:'186****2940',staff:['荣大海','花灵芝'],out:'苏里格南作业区营地',to:'乌审旗人民医院'},
|
||||
{id:7,date:'2026-09-05',point:'樊学作业区医疗点',plate:'CQ·0712A',type:'急救型',dispatch:'应急戒备',driver:'田震',tel:'139****5218',staff:['韩东学'],out:'樊学作业区应急演练现场',to:'演练指挥部'},
|
||||
{id:8,date:'2026-09-05',point:'姬圪台作业区医疗点',plate:'CQ·1366B',type:'急救型',dispatch:'病情急救',driver:'冯保山',tel:'135****6174',staff:['窦志远','屈二娃'],out:'姬圪台作业区 3#站',to:'庆阳市人民医院'},
|
||||
{id:9,date:'2026-09-04',point:'西峰基地医疗点',plate:'CQ·0208C',type:'转运型',dispatch:'病情急救',driver:'罗建平',tel:'150****8357',staff:['霍静怡'],out:'西峰基地生活区',to:'第四采油厂总医院'},
|
||||
{id:10,date:'2026-09-04',point:'靖边气田医疗点',plate:'CQ·1533D',type:'急救型',dispatch:'日常巡诊',driver:'邓成',tel:'133****9481',staff:['康永强'],out:'靖边气田井场巡诊',to:'靖边气田医疗点'},
|
||||
{id:11,date:'2026-09-03',point:'安塞采油队长住点医疗室',plate:'CQ·0917E',type:'转运型',dispatch:'日常巡诊',driver:'苏文斌',tel:'155****6703',staff:['白宇峰','牛玉洁'],out:'安塞基地各井站',to:'安塞采油队长住点医疗室'},
|
||||
{id:12,date:'2026-09-03',point:'乌审旗采气区医疗点',plate:'CQ·2201F',type:'急救型',dispatch:'病情急救',driver:'曹雪芹',tel:'186****2940',staff:['荣大海'],out:'乌审旗采气区集气站',to:'乌审旗人民医院'}
|
||||
];
|
||||
var nextId=13,editingId=null,pendingDelId=null;
|
||||
var dispatchBadge={'病情急救':'badge--danger','伤情急救':'badge--warning','日常巡诊':'badge--info','应急戒备':'badge--success'};
|
||||
var typeBadge={'急救型':'badge--danger','转运型':'badge--info'};
|
||||
|
||||
/* ===== 筛选与渲染 ===== */
|
||||
var pageSize=10,currentPage=1;
|
||||
function onFilterPoint(){
|
||||
var point=document.getElementById('filterPoint').value;
|
||||
var sel=document.getElementById('filterAmb');
|
||||
sel.innerHTML='<option value="">全部救护车</option>';
|
||||
ambulances.filter(function(a){return !point||a.point===point;}).forEach(function(a){
|
||||
var o=document.createElement('option');o.textContent=a.plate;sel.appendChild(o);
|
||||
});
|
||||
}
|
||||
function currentData(){
|
||||
var point=document.getElementById('filterPoint').value;
|
||||
var amb=document.getElementById('filterAmb').value;
|
||||
var type=document.getElementById('filterType').value;
|
||||
var from=document.getElementById('filterFrom').value;
|
||||
var to=document.getElementById('filterTo').value;
|
||||
return attendances.filter(function(r){
|
||||
return (!point||r.point===point)&&(!amb||r.plate===amb)
|
||||
&&(!type||r.dispatch===type)&&(!from||r.date>=from)&&(!to||r.date<=to);
|
||||
});
|
||||
}
|
||||
var TODAY='2026-09-09';
|
||||
function pad(n){return n<10?'0'+n:''+n;}
|
||||
function fmtDate(d){return d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate());}
|
||||
function weekRange(){
|
||||
var base=new Date(TODAY+'T00:00:00');
|
||||
var dow=base.getDay();
|
||||
var monOffset=dow===0?-6:1-dow;
|
||||
var mon=new Date(base);mon.setDate(base.getDate()+monOffset);
|
||||
var sun=new Date(mon);sun.setDate(mon.getDate()+6);
|
||||
return {start:fmtDate(mon),end:fmtDate(sun)};
|
||||
}
|
||||
function renderStats(){
|
||||
var list=attendances;
|
||||
var wk=weekRange();
|
||||
var week=list.filter(function(r){return r.date>=wk.start&&r.date<=wk.end;}).length;
|
||||
var month=list.filter(function(r){return r.date.slice(0,7)===TODAY.slice(0,7);}).length;
|
||||
var year=list.filter(function(r){return r.date.slice(0,4)===TODAY.slice(0,4);}).length;
|
||||
document.getElementById('kWeek').textContent=week;
|
||||
document.getElementById('kWeekExtra').textContent=wk.start+' ~ '+wk.end;
|
||||
document.getElementById('kMonth').textContent=month;
|
||||
document.getElementById('kMonthExtra').textContent=parseInt(TODAY.slice(5,7),10)+'月';
|
||||
document.getElementById('kYear').textContent=year;
|
||||
document.getElementById('kYearExtra').textContent=TODAY.slice(0,4)+'年度';
|
||||
document.getElementById('kTotal').textContent=list.length;
|
||||
}
|
||||
function renderTable(){
|
||||
var list=currentData();
|
||||
var start=(currentPage-1)*pageSize,pageData=list.slice(start,start+pageSize);
|
||||
var totalPages=Math.ceil(list.length/pageSize)||1;
|
||||
document.getElementById('pageInfo').textContent='共 '+list.length+' 条记录';
|
||||
document.getElementById('pageNum').textContent=currentPage+'/'+totalPages;
|
||||
document.getElementById('prevBtn').disabled=currentPage<=1;
|
||||
document.getElementById('nextBtn').disabled=currentPage>=totalPages;
|
||||
var tbody=document.getElementById('tableBody');
|
||||
if(!pageData.length){tbody.innerHTML='<tr><td colspan="12" class="td-empty">暂无匹配数据</td></tr>';return;}
|
||||
var html='';
|
||||
pageData.forEach(function(r,i){
|
||||
html+='<tr>'
|
||||
+'<td>'+(start+i+1)+'</td>'
|
||||
+'<td>'+r.date+'</td>'
|
||||
+'<td style="text-align:left;">'+r.point+'</td>'
|
||||
+'<td style="font-weight:600;">'+r.plate+'</td>'
|
||||
+'<td><span class="badge '+typeBadge[r.type]+'">'+r.type+'</span></td>'
|
||||
+'<td><span class="badge '+dispatchBadge[r.dispatch]+'">'+r.dispatch+'</span></td>'
|
||||
+'<td>'+r.driver+'</td>'
|
||||
+'<td>'+r.tel+'</td>'
|
||||
+'<td style="text-align:left;">'+(r.staff.join('、'))+'</td>'
|
||||
+'<td style="text-align:left;max-width:180px;overflow:hidden;text-overflow:ellipsis;">'+r.out+'</td>'
|
||||
+'<td style="text-align:left;max-width:180px;overflow:hidden;text-overflow:ellipsis;">'+r.to+'</td>'
|
||||
+'<td class="td-actions">'
|
||||
+'<button class="btn btn-link" onclick="openDetail('+r.id+')">详情</button>'
|
||||
+'<button class="btn btn-link" onclick="openForm('+r.id+')">编辑</button>'
|
||||
+'<button class="btn btn-link btn-link--danger" onclick="askDelete('+r.id+')">删除</button>'
|
||||
+'</td></tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
}
|
||||
function applyFilter(){currentPage=1;renderTable();}
|
||||
function resetFilter(){
|
||||
document.getElementById('filterPoint').value='';onFilterPoint();
|
||||
document.getElementById('filterType').value='';
|
||||
document.getElementById('filterFrom').value='';
|
||||
document.getElementById('filterTo').value='';
|
||||
applyFilter();
|
||||
}
|
||||
function turnPage(d){
|
||||
var totalPages=Math.ceil(currentData().length/pageSize)||1;
|
||||
currentPage=Math.min(Math.max(1,currentPage+d),totalPages);
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ===== 新增/编辑抽屉 ===== */
|
||||
function fillAmb(point,keep){
|
||||
var sel=document.getElementById('fAmb');
|
||||
sel.innerHTML='<option value="">请选择救护车</option>';
|
||||
ambulances.filter(function(a){return !point||a.point===point;}).forEach(function(a){
|
||||
var o=document.createElement('option');o.textContent=a.plate;
|
||||
if(keep&&a.plate===keep)o.selected=true;
|
||||
sel.appendChild(o);
|
||||
});
|
||||
}
|
||||
function fillDriverSel(keep){
|
||||
var sel=document.getElementById('fDriver');
|
||||
sel.innerHTML='<option value="">请选择司机</option>';
|
||||
drivers.forEach(function(d){
|
||||
var o=document.createElement('option');o.textContent=d.name;
|
||||
if(keep&&d.name===keep)o.selected=true;
|
||||
sel.appendChild(o);
|
||||
});
|
||||
}
|
||||
function onFormPoint(){fillAmb(document.getElementById('fPoint').value);clearAmbType();}
|
||||
function onFormAmb(){
|
||||
var plate=document.getElementById('fAmb').value;
|
||||
var a=ambulances.find(function(x){return x.plate===plate;});
|
||||
document.getElementById('fAmbulanceType').value=a?a.type:'';
|
||||
}
|
||||
function clearAmbType(){document.getElementById('fAmbulanceType').value='';}
|
||||
function onFormDriver(){
|
||||
var name=document.getElementById('fDriver').value;
|
||||
var d=drivers.find(function(x){return x.name===name;});
|
||||
document.getElementById('fTel').value=d?d.tel:'';
|
||||
}
|
||||
var selectedStaffIds=[];
|
||||
function setRadio(name,val){
|
||||
document.querySelectorAll('input[name="'+name+'"]').forEach(function(r){r.checked=(r.value===val);});
|
||||
}
|
||||
function getRadio(name){
|
||||
var r=document.querySelector('input[name="'+name+'"]:checked');
|
||||
return r?r.value:'';
|
||||
}
|
||||
function renderStaffChips(){
|
||||
var names=selectedStaffIds.map(function(id){return medStaff.find(function(m){return m.id===id;}).name;});
|
||||
document.getElementById('fStaffChips').innerHTML=names.map(function(n){
|
||||
return '<span class="chip">'+n+'<span class="chip-del" onclick="removeStaffByName(\''+n+'\')">×</span></span>';
|
||||
}).join('');
|
||||
}
|
||||
function removeStaffByName(name){
|
||||
var m=medStaff.find(function(x){return x.name===name;});
|
||||
selectedStaffIds=selectedStaffIds.filter(function(id){return id!==m.id;});
|
||||
renderStaffChips();
|
||||
}
|
||||
function openForm(id){
|
||||
editingId=id||null;
|
||||
document.getElementById('formTitle').textContent=id?'编辑出勤记录':'新增出勤';
|
||||
var r=id?attendances.find(function(x){return x.id===id;}):null;
|
||||
document.getElementById('fPoint').value=r?r.point:'';
|
||||
fillAmb(r?r.point:'',r?r.plate:'');
|
||||
if(!r)document.getElementById('fAmb').innerHTML='<option value="">请先选择医疗点</option>';
|
||||
fillDriverSel(r?r.driver:'');
|
||||
document.getElementById('fDate').value=r?r.date:'';
|
||||
setRadio('fDispatch',r?r.dispatch:'病情急救');
|
||||
selectedStaffIds=(r?r.staff.slice():[]).map(function(n){var m=medStaff.find(function(x){return x.name===n;});return m?m.id:null;}).filter(function(id){return id!=null;});
|
||||
renderStaffChips();
|
||||
document.getElementById('fOut').value=r?r.out:'';
|
||||
document.getElementById('fTo').value=r?r.to:'';
|
||||
if(r){onFormAmb();onFormDriver();}else{clearAmbType();document.getElementById('fTel').value='';}
|
||||
document.getElementById('formMask').classList.add('open');
|
||||
document.getElementById('formDrawer').classList.add('open');
|
||||
}
|
||||
function saveForm(){
|
||||
var point=document.getElementById('fPoint').value;
|
||||
var plate=document.getElementById('fAmb').value;
|
||||
var date=document.getElementById('fDate').value;
|
||||
var dispatch=getRadio('fDispatch');
|
||||
var driver=document.getElementById('fDriver').value;
|
||||
var out=document.getElementById('fOut').value.trim();
|
||||
var to=document.getElementById('fTo').value.trim();
|
||||
if(!point){showToast('请选择所属医疗点');return;}
|
||||
if(!plate){showToast('请选择救护车');return;}
|
||||
if(!date){showToast('请选择出勤日期');return;}
|
||||
if(!driver){showToast('请选择出勤司机');return;}
|
||||
if(!selectedStaffIds.length){showToast('请选择随车医护');return;}
|
||||
if(!out){showToast('请填写出勤地点');return;}
|
||||
if(!to){showToast('请填写到达地点');return;}
|
||||
var a=ambulances.find(function(x){return x.plate===plate;});
|
||||
var d=drivers.find(function(x){return x.name===driver;});
|
||||
var staffNames=selectedStaffIds.map(function(id){return medStaff.find(function(m){return m.id===id;}).name;});
|
||||
var obj={
|
||||
id:editingId||nextId++,
|
||||
date:date,point:point,plate:plate,type:a.type,dispatch:dispatch,
|
||||
driver:driver,tel:d.tel,staff:staffNames,out:out,to:to
|
||||
};
|
||||
if(editingId){
|
||||
attendances.splice(attendances.findIndex(function(x){return x.id===editingId;}),1,obj);
|
||||
}else{
|
||||
attendances.push(obj);
|
||||
}
|
||||
closeDrawer('form');renderStats();renderTable();
|
||||
showToast(editingId?'出勤记录已更新':'出勤记录已新增');
|
||||
}
|
||||
|
||||
/* ===== 详情抽屉 ===== */
|
||||
function openDetail(id){
|
||||
var r=attendances.find(function(x){return x.id===id;});
|
||||
document.getElementById('detailTitle').textContent='出勤详情 · '+r.date+' '+r.plate;
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v===''||v==null?'—':v)+'</div></div>';}
|
||||
document.getElementById('detailBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">救护车信息</div>'
|
||||
+'<div class="detail-grid">'+d('所属医疗点',r.point)+d('救护车',r.plate)+d('救护类型','<span class="badge '+typeBadge[r.type]+'">'+r.type+'</span>')+'</div>'
|
||||
+'<div class="form-section">出勤信息</div>'
|
||||
+'<div class="detail-grid">'
|
||||
+d('出勤日期',r.date)
|
||||
+d('出勤类型','<span class="badge '+dispatchBadge[r.dispatch]+'">'+r.dispatch+'</span>')
|
||||
+d('出勤司机',r.driver)
|
||||
+d('司机电话',r.tel)
|
||||
+d('随车医护',r.staff.join('、'),true)
|
||||
+d('出勤地点',r.out,true)
|
||||
+d('到达地点',r.to,true)
|
||||
+'</div>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
document.getElementById('detailDrawer').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 随车医护选择弹窗 ===== */
|
||||
function renderStaffList(){
|
||||
var kw=document.getElementById('staffKeyword').value.trim();
|
||||
var list=medStaff.filter(function(m){return !kw||m.name.indexOf(kw)!==-1;});
|
||||
var body=document.getElementById('staffListBody');
|
||||
if(!list.length){body.innerHTML='<tr><td colspan="5" class="td-empty">暂无匹配人员</td></tr>';return;}
|
||||
body.innerHTML=list.map(function(m){
|
||||
var checked=selectedStaffIds.indexOf(m.id)!==-1?'checked':'';
|
||||
return '<tr>'
|
||||
+'<td><input type="checkbox" class="staff-check" value="'+m.id+'" '+checked+'></td>'
|
||||
+'<td>'+m.name+'</td><td>'+m.job+'</td><td>'+m.post+'</td><td>'+m.point+'</td>'
|
||||
+'</tr>';
|
||||
}).join('');
|
||||
}
|
||||
function openStaffModal(){
|
||||
document.getElementById('staffKeyword').value='';
|
||||
renderStaffList();
|
||||
document.getElementById('staffMask').classList.add('open');
|
||||
}
|
||||
function confirmStaff(){
|
||||
selectedStaffIds=[].slice.call(document.querySelectorAll('.staff-check:checked')).map(function(c){return +c.value;});
|
||||
closeModal('staffMask');
|
||||
renderStaffChips();
|
||||
}
|
||||
|
||||
/* ===== 删除 ===== */
|
||||
function askDelete(id){
|
||||
pendingDelId=id;
|
||||
var r=attendances.find(function(x){return x.id===id;});
|
||||
document.getElementById('delText').textContent='确认删除「'+r.date+' '+r.plate+' '+r.dispatch+'」这条出勤记录?';
|
||||
document.getElementById('delMask').classList.add('open');
|
||||
}
|
||||
function confirmDelete(){
|
||||
attendances=attendances.filter(function(r){return r.id!==pendingDelId;});
|
||||
closeModal('delMask');renderStats();renderTable();
|
||||
showToast('出勤记录已删除');
|
||||
pendingDelId=null;
|
||||
}
|
||||
|
||||
/* ===== 导出 ===== */
|
||||
function doExport(){showToast('导出任务已提交,完成后可在「查看导出任务」下载');}
|
||||
function openExportTasks(){document.getElementById('taskMask').classList.add('open');}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
function closeDrawer(k){
|
||||
document.getElementById(k+'Mask').classList.remove('open');
|
||||
document.getElementById(k+'Drawer').classList.remove('open');
|
||||
}
|
||||
function closeModal(id){document.getElementById(id).classList.remove('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
|
||||
onFilterPoint();renderStats();renderTable();
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -60,10 +60,6 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
.badge--info{background:#E6F7FF;color:#096DD9;border:1px solid #91D5FF;}
|
||||
.badge--muted{background:#F5F5F5;color:var(--text-secondary);border:1px solid var(--border);}
|
||||
.chip{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);background:#FFF1F0;color:#CF1322;border:1px solid #FFCCC7;margin-right:6px;}
|
||||
.plan-blocks{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:16px 24px 24px;}
|
||||
.plan-block{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;}
|
||||
.plan-block__title{padding:10px 16px;background:#FAFAFA;font-size:var(--font-sm);font-weight:600;border-bottom:1px solid var(--border);}
|
||||
.plan-block table{min-width:0;}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
</style>
|
||||
@@ -98,13 +94,7 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item active">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -128,12 +118,11 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
<!-- 员工信息卡(由列表页URL参数带入) -->
|
||||
<div class="emp-card" id="empCard"></div>
|
||||
|
||||
<!-- [交互] Tab 切换:就诊/随访/用药/干预计划 -->
|
||||
<!-- [交互] Tab 切换:就诊/随访/用药 -->
|
||||
<div class="tabs-bar">
|
||||
<button class="tab-btn active" data-tab="visit" onclick="switchTab('visit')">就诊记录</button>
|
||||
<button class="tab-btn" data-tab="follow" onclick="switchTab('follow')">随访记录</button>
|
||||
<button class="tab-btn" data-tab="med" onclick="switchTab('med')">用药记录</button>
|
||||
<button class="tab-btn" data-tab="plan" onclick="switchTab('plan')">干预计划</button>
|
||||
</div>
|
||||
|
||||
<div class="table-card" id="paneVisit">
|
||||
@@ -163,25 +152,6 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-card" id="panePlan" style="display:none;">
|
||||
<div class="plan-blocks">
|
||||
<div class="plan-block">
|
||||
<div class="plan-block__title">一周膳食计划</div>
|
||||
<table>
|
||||
<thead><tr><th style="width:64px;">周期</th><th>早餐</th><th>午餐</th><th>晚餐</th></tr></thead>
|
||||
<tbody id="mealBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="plan-block">
|
||||
<div class="plan-block__title">运动处方</div>
|
||||
<table style="min-width:0;">
|
||||
<thead><tr><th style="width:64px;">序号</th><th>运动项目</th><th>单次时长(分钟)</th><th>频率</th></tr></thead>
|
||||
<tbody id="sportBody"></tbody>
|
||||
</table>
|
||||
<div style="padding:12px 16px;font-size:var(--font-xs);color:var(--text-placeholder);line-height:1.7;" id="planAdvice"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
@@ -304,7 +274,7 @@ function renderHead(){
|
||||
}
|
||||
function switchTab(k){
|
||||
document.querySelectorAll('.tab-btn').forEach(function(b){b.classList.toggle('active',b.dataset.tab===k);});
|
||||
['Visit','Follow','Med','Plan'].forEach(function(p){document.getElementById('pane'+p).style.display=(p.toLowerCase()===k)?'':'none';});
|
||||
['Visit','Follow','Med'].forEach(function(p){document.getElementById('pane'+p).style.display=(p.toLowerCase()===k)?'':'none';});
|
||||
}
|
||||
function renderAll(){
|
||||
document.getElementById('visitBody').innerHTML=emp.visits.length?emp.visits.map(function(v,i){
|
||||
@@ -317,13 +287,6 @@ function renderAll(){
|
||||
return '<tr><td>'+(i+1)+'</td><td style="text-align:left;">'+m.name+'</td><td>'+m.spec+'</td><td>'+m.dose+'</td><td>'+m.freq+'</td><td>'+m.start+'</td><td>'+m.end+'</td>'
|
||||
+'<td>'+(m.using?'<span class="badge badge--success">在用</span>':'<span class="badge badge--muted">已停</span>')+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="8" class="td-empty">该员工目前无需用药</td></tr>';
|
||||
document.getElementById('mealBody').innerHTML=emp.meals.map(function(m){
|
||||
return '<tr><td>'+m.w+'</td><td style="text-align:left;">'+m.b+'</td><td style="text-align:left;">'+m.l+'</td><td style="text-align:left;">'+m.d+'</td></tr>';
|
||||
}).join('');
|
||||
document.getElementById('sportBody').innerHTML=emp.sports.map(function(s,i){
|
||||
return '<tr><td>'+(i+1)+'</td><td>'+s.n+'</td><td>'+s.t+'</td><td>'+s.f+'</td></tr>';
|
||||
}).join('');
|
||||
document.getElementById('planAdvice').textContent='干预要点:'+emp.advice;
|
||||
}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
|
||||
@@ -97,13 +97,6 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.drawer__close:hover{color:var(--text-primary);}
|
||||
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
|
||||
.drawer__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 12px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid var(--border);}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:110px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:440px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
@@ -147,13 +140,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item active">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -242,7 +229,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px"><input type="checkbox" id="checkAll" onchange="toggleAll(this)"></th><th>序号</th><th>姓名</th><th>员工编号</th><th>性别</th><th>年龄</th><th>慢病类型</th><th>入组日期</th><th>员工单位</th><th>部门</th><th>分配医疗点</th><th>操作</th>
|
||||
<th style="width:40px"><input type="checkbox" id="checkAll" onchange="toggleAll(this)"></th><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="tableBody"></tbody>
|
||||
@@ -258,17 +245,6 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 查看详情抽屉 -->
|
||||
<div class="drawer-mask" id="viewMask" onclick="closeDrawer('view')"></div>
|
||||
<div class="drawer" id="viewDrawer">
|
||||
<div class="drawer__header"><span id="viewTitle">慢病员工详情</span><button class="drawer__close" onclick="closeDrawer('view')">×</button></div>
|
||||
<div class="drawer__body" id="viewBody"></div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer('view')">关闭</button>
|
||||
<button class="btn btn-primary" id="viewGoIntervention">查看干预记录</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 修改慢病弹窗 -->
|
||||
<div class="modal-mask" id="typeMask">
|
||||
<div class="modal">
|
||||
@@ -294,6 +270,17 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 体检报告弹窗 -->
|
||||
<div class="modal-mask" id="reportMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title" id="reportTitle">体检报告</div>
|
||||
<div style="font-size:var(--font-sm);color:var(--text-secondary);line-height:1.6;">同健康体检模块体检报告(最新)</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('reportMask')">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导出任务抽屉(异步导出任务列表) -->
|
||||
<div class="drawer-mask" id="exportMask" onclick="closeDrawer('export')"></div>
|
||||
<div class="drawer drawer--narrow" id="exportDrawer">
|
||||
@@ -331,7 +318,7 @@ var chronics=[
|
||||
{code:'CQ036441',name:'刘玉梅',sex:'女',age:40,unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',type:['高血压'],join:'2026-04-18',doctor:'呼建国',note:'体检血压 142/88mmHg,复测确认',advice:'限盐减重,规律服药,月度随访'},
|
||||
{code:'CQ029905',name:'呼建国',sex:'男',age:36,unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',type:['其他'],join:'2026-07-02',doctor:'刘玉梅',note:'颈椎病史,反复上肢麻木',advice:'工间操干预,避免久坐,季度随访'}
|
||||
];
|
||||
var editingCode=null,viewCode=null;
|
||||
var editingCode=null;
|
||||
|
||||
/* ===== 单位部门双列筛选 ===== */
|
||||
var deptMap={
|
||||
@@ -454,7 +441,7 @@ function renderTable(){
|
||||
document.getElementById('prevBtn').disabled=currentPage<=1;
|
||||
document.getElementById('nextBtn').disabled=currentPage>=totalPages;
|
||||
var tbody=document.getElementById('tableBody');
|
||||
if(!pageData.length){tbody.innerHTML='<tr><td colspan="12" class="td-empty">暂无匹配数据</td></tr>';return;}
|
||||
if(!pageData.length){tbody.innerHTML='<tr><td colspan="13" class="td-empty">暂无匹配数据</td></tr>';return;}
|
||||
var html='';
|
||||
pageData.forEach(function(c,i){
|
||||
html+='<tr>'
|
||||
@@ -464,10 +451,11 @@ function renderTable(){
|
||||
+'<td>'+c.code+'</td><td>'+c.sex+'</td><td>'+c.age+'</td>'
|
||||
+'<td style="white-space:normal;min-width:150px;">'+typeChips(c.type)+'</td>'
|
||||
+'<td>'+c.join+'</td><td>'+c.unit+'</td><td>'+c.dept+'</td><td>'+c.point+'</td>'
|
||||
+'<td><button class="btn btn-link" onclick="openReport(\''+c.code+'\')">查看</button></td>'
|
||||
+'<td class="td-actions">'
|
||||
+'<button class="btn btn-link" onclick="openView(\''+c.code+'\')">详情</button>'
|
||||
+'<button class="btn btn-link" onclick="goIntervention(\''+c.code+'\')">干预记录</button>'
|
||||
+'<button class="btn btn-link" onclick="openTypeModal(\''+c.code+'\')">修改慢病</button>'
|
||||
+'<button class="btn btn-link btn-link--danger" onclick="askDelete(\''+c.code+'\')">删除</button>'
|
||||
+'</td></tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
@@ -488,41 +476,26 @@ function turnPage(d){
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ===== 详情抽屉 ===== */
|
||||
function openView(code){
|
||||
/* ===== 体检报告弹窗 ===== */
|
||||
function openReport(code){
|
||||
var c=chronics.find(function(x){return x.code===code;});
|
||||
viewCode=code;
|
||||
document.getElementById('viewTitle').textContent='慢病员工详情 · '+c.name;
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v||'—')+'</div></div>';}
|
||||
document.getElementById('viewBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">基础信息</div>'
|
||||
+'<div class="detail-grid">'+d('姓名',c.name)+d('员工编号',c.code)+d('性别/年龄',c.sex+' / '+c.age+'岁')+d('所属单位',c.unit)+d('所属部门',c.dept)+d('分配医疗点',c.point+'('+pointUnit[c.point]+')')+'</div>'
|
||||
+'<div class="form-section">慢病管理信息</div>'
|
||||
+'<div class="detail-grid">'+d('入组日期',c.join)+d('管理医生',c.doctor)+d('慢病类型',typeChips(c.type),true)+d('入组依据',c.note,true)+d('干预建议',c.advice,true)+'</div>'
|
||||
+'<div class="form-section">最近一次随访摘要</div>'
|
||||
+'<div style="font-size:var(--font-sm);color:var(--text-secondary);line-height:1.7;background:#FAFAFA;border-radius:var(--radius-sm);padding:12px 16px;">'+latestFollow(c)+'</div>';
|
||||
document.getElementById('viewGoIntervention').onclick=function(){goIntervention(code);};
|
||||
document.getElementById('viewMask').classList.add('open');
|
||||
document.getElementById('viewDrawer').classList.add('open');
|
||||
}
|
||||
function latestFollow(c){
|
||||
var map={
|
||||
'CQ033096':'2026-09-05 门诊随访:头晕较前减轻,血压 146/92mmHg 仍未达标,已强化用药依从性管理。',
|
||||
'CQ010564':'2026-09-03 门诊随访:口渴乏力减轻,空腹血糖 8.9mmol/L,两周复查并强化饮食管理。',
|
||||
'CQ027710':'2026-09-01 电话随访:腰痛缓解,血脂复查提醒,减重为核心干预目标。',
|
||||
'CQ021578':'2026-08-28 门诊随访:无头晕头痛,血压 138/86mmHg 临界,生活方式干预中。',
|
||||
'CQ022317':'2026-08-26 巡诊随访:中暑后恢复,乏力减轻,注意摄盐与高温作业防护。',
|
||||
'CQ019203':'2026-08-19 电话随访:无胸闷胸痛,规律服用他汀,避免超强度作业。',
|
||||
'CQ036441':'2026-08-21 门诊随访:血压 134/84mmHg 达标,维持现有方案。',
|
||||
'CQ029905':'2026-08-14 门诊随访:上肢麻木发作减少,坚持工间操。'
|
||||
};
|
||||
return map[c.code]||'近两个月内暂无随访记录,请安排下次随访。';
|
||||
document.getElementById('reportTitle').textContent='体检报告 · '+c.name;
|
||||
document.getElementById('reportMask').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 跳转干预记录 ===== */
|
||||
function goIntervention(code){
|
||||
closeDrawer('view');
|
||||
location.href='daily-chronic-intervention.html?emp='+code;
|
||||
}
|
||||
|
||||
/* ===== 删除单条台账 ===== */
|
||||
function askDelete(code){
|
||||
var c=chronics.find(function(x){return x.code===code;});
|
||||
window._batchCodes=[code];
|
||||
document.getElementById('clearText').textContent='确认删除「'+c.name+'」的慢病台账记录?该员工将移出慢病管理台账,历史干预记录保留备查。';
|
||||
document.getElementById('clearMask').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 修改慢病 ===== */
|
||||
function openTypeModal(code){
|
||||
window._batchCodes=null;
|
||||
@@ -550,7 +523,7 @@ function confirmClear(){
|
||||
chronics=chronics.filter(function(c){return window._batchCodes.indexOf(c.code)===-1;});
|
||||
var n=window._batchCodes.length;window._batchCodes=null;
|
||||
closeModal('clearMask');renderTable();
|
||||
showToast('已批量删除 '+n+' 条慢病台账记录');
|
||||
showToast(n>1?'已批量删除 '+n+' 条慢病台账记录':'已删除慢病台账记录');
|
||||
return;
|
||||
}
|
||||
applyTypes([]);
|
||||
|
||||
@@ -151,13 +151,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -254,10 +248,8 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<div class="form-item form-item--full"><span class="form-label"><span class="req">*</span> <span id="lblTheme">宣教主题</span></span><input class="form-control" id="eTheme" placeholder="如:全国高血压日专题宣教"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> <span id="lblDate">宣教日期</span></span><input class="form-control" type="date" id="eDate"></div>
|
||||
<div class="form-item"><span class="form-label">主讲人</span><input class="form-control" id="eLecturer" placeholder="医护人员姓名"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 医疗点所属单位</span>
|
||||
<select class="form-control" id="eUnit" onchange="onFormUnit()"><option value="">请选择单位</option><option>采油一厂</option><option>采油二厂</option><option>第四采油厂</option><option>采气一厂</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 开展医疗点</span>
|
||||
<select class="form-control" id="ePoint"><option value="">请先选择单位</option></select></div>
|
||||
<select class="form-control" id="ePoint"><option value="">请选择医疗点</option></select></div>
|
||||
<div class="form-item"><span class="form-label">覆盖区域</span><input class="form-control" id="eArea" placeholder="如:桐园作业区各井站"></div>
|
||||
<div class="form-item"><span class="form-label">参加人数</span><input class="form-control" type="number" id="eNum" placeholder="现场签到人数"></div>
|
||||
<div class="form-item form-item--full"><span class="form-label"><span class="req">*</span> <span id="lblContent">宣教内容</span></span><textarea class="form-control" id="eContent" placeholder="活动内容与要点摘要"></textarea></div>
|
||||
@@ -278,6 +270,12 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<svg width="18" height="18" viewBox="0 0 20 20" fill="none"><path d="M3 17c2-4 4 3 6-2s3 4 8-1" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round"/></svg>
|
||||
参加人员在 PAD 端签到屏完成电子确认签字,签到记录自动回传关联本宣教活动
|
||||
</div>
|
||||
<div class="form-section">签字图片</div>
|
||||
<div class="photo-row" id="signImgRow">
|
||||
<div class="photo-ph" id="signImgPh" onclick="showToast('签字图片上传功能演示')">
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none"><path d="M9 4v10M4 9h10" stroke="#bbb" stroke-width="1.5" stroke-linecap="round"/></svg>上传签字图片
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer('form')">取消</button>
|
||||
@@ -329,6 +327,12 @@ var pointMap={
|
||||
'第四采油厂':['西峰基地医疗点'],
|
||||
'采气一厂':['靖边气田医疗点','乌审旗采气区医疗点']
|
||||
};
|
||||
/* 全量医疗点(新增/编辑直接选择,不依赖单位联动) */
|
||||
var allPoints=[];
|
||||
Object.keys(pointMap).forEach(function(u){pointMap[u].forEach(function(p){allPoints.push(p);});});
|
||||
/* 签字图片回显与占位(纯静态原型,用内联 SVG 模拟签字图片) */
|
||||
var SIGN_IMG_THUMB='<svg width="34" height="20" viewBox="0 0 40 22" fill="none"><path d="M4 17c4-6 8 4 11-3s6 5 12-1 5 2 9-2" stroke="#1890FF" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg><span>签字图片</span>';
|
||||
var SIGN_IMG_PLACEHOLDER='<svg width="18" height="18" viewBox="0 0 18 18" fill="none"><path d="M9 4v10M4 9h10" stroke="#bbb" stroke-width="1.5" stroke-linecap="round"/></svg>上传签字图片';
|
||||
/* type:1=健康宣教 0=急救培训(与老系统 publicityType 口径一致) */
|
||||
var edus=[
|
||||
{id:1,type:1,theme:'全国高血压日:减盐降血压专题宣教',date:'2026-09-02',point:'桐园作业区医疗点',area:'桐园作业区各井站、联合站',num:86,lecturer:'曲志明',content:'讲解高血压危害与低盐饮食要点,现场免费测血压42人次,发放限盐勺与宣教折页。'},
|
||||
@@ -494,11 +498,18 @@ function turnPage(d){
|
||||
}
|
||||
|
||||
/* ===== 新增/编辑 ===== */
|
||||
function onFormUnit(){
|
||||
var unit=document.getElementById('eUnit').value;
|
||||
function initPointOptions(){
|
||||
var sel=document.getElementById('ePoint');
|
||||
sel.innerHTML='<option value="">请选择医疗点</option>';
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
allPoints.forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});
|
||||
}
|
||||
function renderSignImg(hasImg){
|
||||
var row=document.getElementById('signImgRow');
|
||||
if(hasImg){
|
||||
row.innerHTML='<div class="photo-ph" style="border-color:#1890FF;background:#fff;cursor:pointer;" onclick="showToast(\'签字图片查看演示\')">'+SIGN_IMG_THUMB+'</div>';
|
||||
}else{
|
||||
row.innerHTML='<div class="photo-ph" id="signImgPh" onclick="showToast(\'签字图片上传功能演示\')">'+SIGN_IMG_PLACEHOLDER+'</div>';
|
||||
}
|
||||
}
|
||||
function openForm(id){
|
||||
editingId=id||null;
|
||||
@@ -507,23 +518,23 @@ function openForm(id){
|
||||
document.getElementById('eTheme').value=e?e.theme:'';
|
||||
document.getElementById('eDate').value=e?e.date:'2026-09-07';
|
||||
document.getElementById('eLecturer').value=e?e.lecturer:'';
|
||||
document.getElementById('eUnit').value=e?pointUnit[e.point]:'';onFormUnit();
|
||||
initPointOptions();
|
||||
document.getElementById('ePoint').value=e?e.point:'';
|
||||
document.getElementById('eArea').value=e?e.area:'';
|
||||
document.getElementById('eNum').value=e?e.num:'';
|
||||
document.getElementById('eContent').value=e?e.content:'';
|
||||
renderSignImg(!!e);
|
||||
document.getElementById('formMask').classList.add('open');
|
||||
document.getElementById('formDrawer').classList.add('open');
|
||||
}
|
||||
function saveForm(){
|
||||
var theme=document.getElementById('eTheme').value.trim();
|
||||
var date=document.getElementById('eDate').value;
|
||||
var unit=document.getElementById('eUnit').value;
|
||||
var point=document.getElementById('ePoint').value;
|
||||
var content=document.getElementById('eContent').value.trim();
|
||||
if(!theme){showToast('请填写'+T('宣教主题','培训标题'));return;}
|
||||
if(!date){showToast('请选择'+T('宣教日期','培训日期'));return;}
|
||||
if(!unit||!point){showToast('请选择开展医疗点');return;}
|
||||
if(!point){showToast('请选择开展医疗点');return;}
|
||||
if(!content){showToast('请填写'+T('宣教内容','培训内容'));return;}
|
||||
var obj={
|
||||
id:editingId||nextId++,type:curTab,theme:theme,date:date,point:point,
|
||||
@@ -549,7 +560,11 @@ function openView(id){
|
||||
+'<div class="form-section">'+T('现场照片','现场培训照片')+'</div>'
|
||||
+'<div class="photo-row"><div class="photo-ph">照片 1</div><div class="photo-ph">照片 2</div></div>'
|
||||
+'<div class="form-section">'+T('宣教资料','培训资料')+'</div>'
|
||||
+'<div class="upload-box"><svg width="16" height="16" viewBox="0 0 20 20" fill="none"><path d="M4 2h8l4 4v12H4z" stroke="#999" stroke-width="1.4" fill="none"/><path d="M12 2v4h4" stroke="#999" stroke-width="1.4"/></svg>《'+e.theme+'》'+T('宣教手册','培训资料')+'.pdf(演示附件)</div>';
|
||||
+'<div class="upload-box"><svg width="16" height="16" viewBox="0 0 20 20" fill="none"><path d="M4 2h8l4 4v12H4z" stroke="#999" stroke-width="1.4" fill="none"/><path d="M12 2v4h4" stroke="#999" stroke-width="1.4"/></svg>《'+e.theme+'》'+T('宣教手册','培训资料')+'.pdf(演示附件)</div>'
|
||||
+'<div class="form-section">员工确认签字</div>'
|
||||
+'<div class="upload-box"><svg width="16" height="16" viewBox="0 0 20 20" fill="none"><path d="M3 17c2-4 4 3 6-2s3 4 8-1" stroke="#999" stroke-width="1.5" fill="none" stroke-linecap="round"/></svg>参加人员在 PAD 端签到屏完成电子确认签字,签到记录自动回传关联本'+T('宣教活动','培训活动')+'</div>'
|
||||
+'<div class="form-section">签字图片</div>'
|
||||
+'<div class="photo-row"><div class="photo-ph" style="border-color:#1890FF;background:#fff;cursor:pointer;" onclick="showToast(\'签字图片查看演示\')">'+SIGN_IMG_THUMB+'</div></div>';
|
||||
document.getElementById('viewMask').classList.add('open');
|
||||
document.getElementById('viewDrawer').classList.add('open');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,645 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>健康档案 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.10);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:200px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 14px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;padding-bottom:24px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.page-header{margin-bottom:16px;display:flex;align-items:center;gap:12px;}
|
||||
.page-header__back{display:inline-flex;align-items:center;gap:4px;font-size:var(--font-sm);color:var(--primary);text-decoration:none;padding:4px 10px;border:1px solid var(--primary);border-radius:var(--radius-sm);background:#fff;}
|
||||
.page-header__back:hover{background:var(--primary-light);}
|
||||
.emp-card{display:grid;grid-template-columns:repeat(4,1fr);gap:6px 12px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-md);padding:14px 18px;margin-bottom:16px;font-size:var(--font-sm);color:var(--text-secondary);box-shadow:var(--shadow-sm);}
|
||||
.emp-card b{color:var(--text-primary);font-weight:600;}
|
||||
/* 主 Tab */
|
||||
.tabs-bar{display:flex;gap:4px;background:#fff;padding:8px 12px 0;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.tab-btn{padding:10px 18px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border:none;background:none;border-bottom:2px solid transparent;transition:all .2s;}
|
||||
.tab-btn:hover{color:var(--primary);}
|
||||
.tab-btn.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
|
||||
/* 面板通用 */
|
||||
.panel{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);padding:20px 24px;}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:900px;}
|
||||
thead th{background:#FAFAFA;padding:10px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:12px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
.td-empty{text-align:center;padding:48px 0;color:var(--text-placeholder);}
|
||||
.td-left{text-align:left;}
|
||||
.badge{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.badge--success{background:#F6FFED;color:#389E0D;border:1px solid #B7EB8F;}
|
||||
.badge--warning{background:#FFFBE6;color:#D48806;border:1px solid #FFE58F;}
|
||||
.badge--danger{background:#FFF1F0;color:#CF1322;border:1px solid #FFCCC7;}
|
||||
.badge--info{background:#E6F7FF;color:#096DD9;border:1px solid #91D5FF;}
|
||||
.badge--muted{background:#F5F5F5;color:var(--text-secondary);border:1px solid var(--border);}
|
||||
.btn{height:30px;padding:0 14px;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;white-space:nowrap;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
/* Tab1 左侧子 Tab */
|
||||
.sub-tabs{display:flex;gap:16px;}
|
||||
.sub-tabs__nav{width:120px;flex-shrink:0;border-right:1px solid var(--border);padding-right:4px;}
|
||||
.sub-tab{display:block;width:100%;text-align:left;padding:10px 12px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border:none;background:none;border-radius:var(--radius-sm);transition:all .15s;margin-bottom:2px;}
|
||||
.sub-tab:hover{color:var(--primary);background:var(--background);}
|
||||
.sub-tab.active{color:var(--primary);background:var(--primary-light);font-weight:600;}
|
||||
.sub-tabs__content{flex:1;min-width:0;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:16px 0 12px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid #F0F0F0;}
|
||||
.detail-item:nth-last-child(-n+2){border-bottom:none;}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:120px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
/* 头像/证照占位 */
|
||||
.avatar-box{width:64px;height:64px;border-radius:50%;background:#E6F7FF;border:1px dashed #91D5FF;display:flex;align-items:center;justify-content:center;color:#1890FF;font-size:var(--font-sm);}
|
||||
.cert-box{width:120px;height:76px;border-radius:var(--radius-sm);background:#FAFAFA;border:1px dashed var(--border);display:flex;align-items:center;justify-content:center;color:var(--text-placeholder);font-size:var(--font-xs);}
|
||||
/* 弹窗 */
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:900;}
|
||||
.modal-mask.open{display:block;}
|
||||
.modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:680px;max-width:92vw;max-height:82vh;background:#fff;z-index:910;border-radius:var(--radius-md);box-shadow:var(--shadow-md);display:none;flex-direction:column;}
|
||||
.modal.open{display:flex;}
|
||||
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:14px 20px;border-bottom:1px solid var(--border);font-size:var(--font-base);font-weight:600;flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.modal__close:hover{color:var(--text-primary);}
|
||||
.modal__body{flex:1;overflow-y:auto;padding:20px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
/* 问卷详情 */
|
||||
.q-item{padding:12px 0;border-bottom:1px solid #F0F0F0;}
|
||||
.q-item:last-child{border-bottom:none;}
|
||||
.q-title{font-size:var(--font-sm);color:var(--text-primary);font-weight:600;margin-bottom:8px;}
|
||||
.q-opts{display:flex;flex-wrap:wrap;gap:8px;}
|
||||
.q-opt{padding:4px 12px;border-radius:var(--radius-sm);font-size:var(--font-xs);background:var(--background);color:var(--text-secondary);border:1px solid var(--border);}
|
||||
.q-opt.answer{background:var(--primary-light);color:var(--primary);border-color:#91D5FF;}
|
||||
/* 体检分析报告 */
|
||||
.analysis-wrap{display:flex;height:560px;background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.analysis-tree{width:220px;flex-shrink:0;border-right:1px solid var(--border);overflow-y:auto;padding:8px 0;}
|
||||
.analysis-tree__title{padding:10px 20px;font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
|
||||
.tree-node{display:flex;align-items:center;gap:6px;padding:8px 20px;font-size:var(--font-sm);color:var(--text-primary);cursor:pointer;transition:background .15s;}
|
||||
.tree-node:hover{background:var(--background);}
|
||||
.tree-node.active{background:#EAF3FC;color:var(--primary);}
|
||||
.tree-node .arrow{width:9px;height:9px;stroke:currentColor;transition:transform .2s;flex-shrink:0;}
|
||||
.tree-node.open .arrow{transform:rotate(90deg);}
|
||||
.tree-node--leaf{padding-left:40px;}
|
||||
.analysis-content{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden;}
|
||||
.analysis-head{height:45px;line-height:45px;padding:0 16px;box-shadow:0 2px 8px #F0F1F2;display:flex;justify-content:space-between;align-items:center;flex-shrink:0;}
|
||||
.analysis-head__title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);}
|
||||
.analysis-head__info{font-size:var(--font-sm);color:var(--text-secondary);display:flex;align-items:center;gap:10px;}
|
||||
.analysis-body{flex:1;overflow-y:auto;padding:16px;display:flex;gap:16px;}
|
||||
.analysis-col{flex:1;min-width:0;display:flex;flex-direction:column;gap:12px;}
|
||||
.indicator-card{border:1px solid #F0F0F0;padding:10px 0;border-radius:var(--radius-sm);}
|
||||
.indicator-card__title{margin-left:16px;margin-bottom:6px;}
|
||||
.indicator-card__name{font-size:var(--font-base);color:var(--text-primary);font-weight:600;display:flex;align-items:center;}
|
||||
.indicator-card__name:before{content:'';width:4px;height:15px;margin-right:6px;border-radius:2px;background:var(--primary);}
|
||||
.indicator-card__ref{margin-top:4px;font-size:var(--font-xs);color:var(--text-secondary);}
|
||||
.indicator-card__table{display:flex;padding:0 16px;}
|
||||
.indicator-card__labels{display:flex;flex-direction:column;min-width:80px;}
|
||||
.indicator-card__labels div{height:34px;line-height:34px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);background:#F9F9F9;border:1px solid #F0F0F0;border-left:none;}
|
||||
.indicator-card__values{flex:1;display:flex;flex-direction:column;overflow-x:auto;}
|
||||
.indicator-card__valrow{display:flex;flex:1;}
|
||||
.indicator-card__valrow div{flex:1;min-width:90px;height:34px;line-height:34px;text-align:center;font-size:var(--font-xs);color:var(--text-primary);border:1px solid #F0F0F0;border-left:none;border-bottom:none;white-space:nowrap;padding:0 4px;}
|
||||
.indicator-card__chart{padding:8px 16px 4px;}
|
||||
.indicator-card__desc{padding:0 16px 12px;}
|
||||
.indicator-card__desc .desc-row{display:flex;gap:8px;padding:6px 0;font-size:var(--font-sm);}
|
||||
.indicator-card__desc .desc-label{width:60px;flex-shrink:0;color:var(--text-secondary);}
|
||||
.indicator-card__desc .desc-text{flex:1;color:var(--text-primary);line-height:1.6;}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M14 6.5l7 3.5v4.5c0 4.2-2.9 6.8-7 7.5-4.1-.7-7-3.3-7-7.5V10l7-3.5z" stroke="#fff" stroke-width="1.8" fill="none"/><path d="M11 13.5h6M14 10.5v6" stroke="#fff" stroke-width="1.8" stroke-linecap="round"/></svg> 一线医疗</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-visit-data.html">档案</a>
|
||||
<a href="config-medical-point.html">基础配置</a>
|
||||
<a href="daily-treatment-staff.html" class="active">日常业务</a>
|
||||
<a href="bed-device.html">床头呼叫</a>
|
||||
<a href="stat-clinic-chart.html">数据统计</a>
|
||||
<a href="hut-banner.html">健康小屋</a>
|
||||
<a href="alert-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏(当前一级分组「日常业务」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">日常业务</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>日常诊疗</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-treatment-staff.html" class="sidebar-item">员工就诊</a>
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item active">员工档案</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>任务管理</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-follow-task.html" class="sidebar-item">随访任务</a>
|
||||
<a href="daily-interpret.html" class="sidebar-item">解读任务</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-education.html" class="sidebar-item">健康宣教管理</a>
|
||||
<a href="daily-interpret-manage.html" class="sidebar-item">报告解读管理</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<div class="page-header">
|
||||
<a class="page-header__back" href="daily-employee-search.html">← 返回员工档案</a>
|
||||
</div>
|
||||
|
||||
<!-- 员工信息卡(由列表页URL参数带入) -->
|
||||
<div class="emp-card" id="empCard"></div>
|
||||
|
||||
<!-- [交互] 主 Tab 切换:健康档案/体检报告/心理评估/健康评估/体检分析报告 -->
|
||||
<div class="tabs-bar">
|
||||
<button class="tab-btn active" data-tab="basic" onclick="switchTab('basic')">健康档案</button>
|
||||
<button class="tab-btn" data-tab="exam" onclick="switchTab('exam')">体检报告</button>
|
||||
<button class="tab-btn" data-tab="psych" onclick="switchTab('psych')">心理评估</button>
|
||||
<button class="tab-btn" data-tab="health" onclick="switchTab('health')">健康评估</button>
|
||||
<button class="tab-btn" data-tab="analysis" onclick="switchTab('analysis')">体检分析报告</button>
|
||||
</div>
|
||||
|
||||
<!-- Tab1 健康档案 -->
|
||||
<div class="panel" id="pane-basic" style="border-radius:0 0 var(--radius-md) var(--radius-md);">
|
||||
<div class="sub-tabs">
|
||||
<div class="sub-tabs__nav" id="subNav">
|
||||
<button class="sub-tab active" data-sub="base" onclick="switchSub('base')">基本信息</button>
|
||||
<button class="sub-tab" data-sub="extend" onclick="switchSub('extend')">扩展信息</button>
|
||||
<button class="sub-tab" data-sub="contact" onclick="switchSub('contact')">紧急联系人</button>
|
||||
</div>
|
||||
<div class="sub-tabs__content">
|
||||
<div id="sub-base"></div>
|
||||
<div id="sub-extend" style="display:none;"></div>
|
||||
<div id="sub-contact" style="display:none;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab2 体检报告 -->
|
||||
<div class="table-card" id="pane-exam" style="display:none;">
|
||||
<div class="table-card__content">
|
||||
<table style="min-width:820px;">
|
||||
<thead><tr><th>序号</th><th>体检日期</th><th>体检年度</th><th>体检医院</th><th>审核时间</th><th>报告上传时间</th><th>操作</th></tr></thead>
|
||||
<tbody id="examBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab3 心理评估 -->
|
||||
<div class="table-card" id="pane-psych" style="display:none;">
|
||||
<div style="padding:12px 20px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);">累计评估:<b id="psychTotal"></b> 次</div>
|
||||
<div class="table-card__content">
|
||||
<table style="min-width:700px;">
|
||||
<thead><tr><th>序号</th><th>评估日期</th><th>健康评分</th><th>评分等级</th><th>操作</th></tr></thead>
|
||||
<tbody id="psychBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab4 健康评估 -->
|
||||
<div class="table-card" id="pane-health" style="display:none;">
|
||||
<div style="padding:12px 20px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);">累计评估:<b id="healthTotal"></b> 次</div>
|
||||
<div class="table-card__content">
|
||||
<table style="min-width:900px;">
|
||||
<thead><tr><th>序号</th><th>评估日期</th><th>体重指数</th><th>缺血性心血管病</th><th>糖尿病</th><th>肺癌</th><th>高血压</th><th>代谢综合征</th><th>操作</th></tr></thead>
|
||||
<tbody id="healthBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab5 体检分析报告 -->
|
||||
<div class="analysis-wrap" id="pane-analysis" style="display:none;">
|
||||
<div class="analysis-tree">
|
||||
<div class="analysis-tree__title">检查类别</div>
|
||||
<div id="treeBox"></div>
|
||||
</div>
|
||||
<div class="analysis-content">
|
||||
<div class="analysis-head">
|
||||
<div class="analysis-head__title" id="analysisTitle"></div>
|
||||
<div class="analysis-head__info">报告最新年份:<b>2026</b>,生成时间:<span>2026-04-30 10:22</span></div>
|
||||
</div>
|
||||
<div class="analysis-body" id="analysisBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 通用弹窗 -->
|
||||
<div class="modal-mask" id="modalMask" onclick="closeModal()"></div>
|
||||
<div class="modal" id="modal">
|
||||
<div class="modal__header"><span id="modalTitle"></span><button class="modal__close" onclick="closeModal()">×</button></div>
|
||||
<div class="modal__body" id="modalBody"></div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeModal()">关闭</button></div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* ===== 医疗点单位映射 ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂'};
|
||||
|
||||
/* ===== 员工身份基础映射(与「员工档案」列表页 12 人一致,身份字段随点击员工变化) ===== */
|
||||
var empBase={
|
||||
'CQ021578':{name:'石维国',sex:'男',age:46,unit:'采油一厂',dept:'樊学作业区',tel:'139****2051',point:'樊学作业区医疗点'},
|
||||
'CQ032144':{name:'李桂芳',sex:'女',age:38,unit:'采油一厂',dept:'樊学作业区',tel:'138****7742',point:'樊学作业区医疗点'},
|
||||
'CQ045130':{name:'杨慧敏',sex:'女',age:33,unit:'采油一厂',dept:'樊学作业区',tel:'188****7214',point:'樊学作业区医疗点'},
|
||||
'CQ019203':{name:'曲志明',sex:'男',age:42,unit:'采油二厂',dept:'姬圪台联合站',tel:'137****8890',point:'姬圪台作业区医疗点'},
|
||||
'CQ027710':{name:'张秀兰',sex:'女',age:45,unit:'采油二厂',dept:'姬圪台联合站',tel:'136****2248',point:'姬圪台作业区医疗点'},
|
||||
'CQ033096':{name:'赵万福',sex:'男',age:39,unit:'采油二厂',dept:'桐园作业区',tel:'150****6127',point:'桐园作业区医疗点'},
|
||||
'CQ010564':{name:'高建军',sex:'男',age:50,unit:'第四采油厂',dept:'基地管理处',tel:'139****0086',point:'西峰基地医疗点'},
|
||||
'CQ041822':{name:'闫婷',sex:'女',age:34,unit:'第四采油厂',dept:'健康管理部',tel:'186****5527',point:'西峰基地医疗点'},
|
||||
'CQ036441':{name:'刘玉梅',sex:'女',age:40,unit:'采气一厂',dept:'靖边净化厂',tel:'135****7719',point:'靖边气田医疗点'},
|
||||
'CQ029905':{name:'呼建国',sex:'男',age:36,unit:'采气一厂',dept:'靖边净化厂',tel:'147****9003',point:'靖边气田医疗点'},
|
||||
'CQ044871':{name:'白瑞',sex:'男',age:31,unit:'采油一厂',dept:'生产技术部',tel:'155****3316',point:'安塞采油队长住点医疗室'},
|
||||
'CQ022317':{name:'徐立成',sex:'男',age:44,unit:'采气一厂',dept:'苏里格南作业区',tel:'133****4860',point:'乌审旗采气区医疗点'}
|
||||
};
|
||||
|
||||
/* ===== 共享演示档案数据(所有员工共用一套,原型演示用) ===== */
|
||||
var SHARED={
|
||||
/* 基本信息(除身份字段外,共用) */
|
||||
basic:{
|
||||
username:'CQ021578', idCard:'6127011980********', email:'shiweiguo@cqoil.com', empNo:'CQ021578',
|
||||
job:'采油工', title:'工程师', position:'班组长', level:'科员', group:'采油一组', status:'在岗',
|
||||
workType:'井下作业', examForm:'在岗体检', hazardDate:'2020-03-01', hazard:'噪声、粉尘'
|
||||
},
|
||||
/* 扩展信息(共用) */
|
||||
extend:{
|
||||
height:'172', weight:'72', birthday:'1980-03-15', bloodType:'O型', nation:'汉族', marriage:'已婚',
|
||||
political:'中共党员', degree:'本科', nativeplace:'陕西延安', worktime:'2003-07-01', empType:'合同制',
|
||||
listed:'是', workSpace:'樊学作业区', liveSpace:'CQ油田生活基地', healthType:'一般', jkState:'健康'
|
||||
},
|
||||
/* 紧急联系人(共用) */
|
||||
contacts:[
|
||||
{name:'石丽华', relation:'配偶', phone:'139****1234', idCard:'6127011982********'},
|
||||
{name:'石建军', relation:'父子', phone:'138****5678', idCard:'6127012005********'}
|
||||
],
|
||||
/* 体检报告(共用) */
|
||||
examReports:[
|
||||
{date:'2026-04-18', year:'2026', hospital:'CQ油田总医院', auditDate:'2026-04-25', uploadDate:'2026-04-26'},
|
||||
{date:'2025-04-10', year:'2025', hospital:'CQ油田总医院', auditDate:'2025-04-17', uploadDate:'2025-04-18'},
|
||||
{date:'2024-04-06', year:'2024', hospital:'吴起油田医院', auditDate:'2024-04-12', uploadDate:'2024-04-13'}
|
||||
],
|
||||
/* 体检报告详情(查看报告弹窗,共用) */
|
||||
examDetail:{
|
||||
year:'2026', hospital:'CQ油田总医院', date:'2026-04-18',
|
||||
items:[
|
||||
{name:'血压(mmHg)', value:'138/86', ref:'<140 / <90', flag:'关注'},
|
||||
{name:'空腹血糖(mmol/L)', value:'5.8', ref:'3.9 - 6.1', flag:'正常'},
|
||||
{name:'BMI', value:'24.6', ref:'18.5 - 23.9', flag:'关注'},
|
||||
{name:'总胆固醇(mmol/L)', value:'5.9', ref:'<5.2', flag:'关注'}
|
||||
],
|
||||
conclusion:'总体良好,血压处于正常高值,建议低盐饮食并定期监测。',
|
||||
suggest:'每季度复测血压;控制体重。'
|
||||
},
|
||||
/* 心理评估(共用) */
|
||||
psychAssessments:[
|
||||
{date:'2026-06-12', grade:'82', level:'良好'},
|
||||
{date:'2025-12-03', grade:'76', level:'一般'},
|
||||
{date:'2025-06-20', grade:'85', level:'良好'}
|
||||
],
|
||||
psychQuestion:[
|
||||
{q:'1. 最近两周是否经常感到紧张、焦虑或烦躁?', opts:['从不','偶尔','经常','总是'], answer:'偶尔'},
|
||||
{q:'2. 入睡是否困难,整体睡眠质量如何?', opts:['很好','一般','较差','很差'], answer:'一般'},
|
||||
{q:'3. 是否容易因小事发脾气或情绪低落?', opts:['从不','偶尔','经常','总是'], answer:'偶尔'},
|
||||
{q:'4. 与同事、家人的沟通交流是否顺畅?', opts:['顺畅','一般','较少','几乎不'], answer:'顺畅'}
|
||||
],
|
||||
/* 健康评估(共用) */
|
||||
healthAssessments:[
|
||||
{date:'2026-05-20', bmi:'24.6(超重)', icvd:'低风险', diabetes:'低风险', lung:'低风险', hypertension:'中风险', metabolic:'低风险'},
|
||||
{date:'2025-11-08', bmi:'24.1(超重)', icvd:'低风险', diabetes:'低风险', lung:'低风险', hypertension:'低风险', metabolic:'低风险'}
|
||||
],
|
||||
healthQuestion:[
|
||||
{q:'1. 是否吸烟(含二手烟暴露)?', opts:['不吸烟','偶尔','经常','每天'], answer:'偶尔'},
|
||||
{q:'2. 每周进行中等强度运动(如快走)的天数?', opts:['0天','1-2天','3-4天','5天以上'], answer:'3-4天'},
|
||||
{q:'3. 日常食盐摄入量是否偏高?', opts:['清淡','适中','偏咸','很咸'], answer:'适中'},
|
||||
{q:'4. 是否有高血压、糖尿病等家族史?', opts:['无','有(一级亲属)','有(二级亲属)','不清楚'], answer:'有(一级亲属)'}
|
||||
]
|
||||
};
|
||||
|
||||
/* ===== 体检分析报告:检查类别树 + 指标数据(共用) ===== */
|
||||
var treeData=[
|
||||
{id:'c1', name:'一般检查', children:[
|
||||
{id:'i1', name:'身高'},
|
||||
{id:'i2', name:'体重'},
|
||||
{id:'i3', name:'血压'}
|
||||
]},
|
||||
{id:'c2', name:'血常规', children:[
|
||||
{id:'i4', name:'白细胞计数'},
|
||||
{id:'i5', name:'红细胞计数'},
|
||||
{id:'i6', name:'血红蛋白'}
|
||||
]},
|
||||
{id:'c3', name:'生化检查', children:[
|
||||
{id:'i7', name:'空腹血糖'},
|
||||
{id:'i8', name:'总胆固醇'},
|
||||
{id:'i9', name:'甘油三酯'}
|
||||
]},
|
||||
{id:'c4', name:'结论建议', children:[
|
||||
{id:'i10', name:'体检结论', isConclusion:true}
|
||||
]}
|
||||
];
|
||||
var indicatorData={
|
||||
'i1':{name:'身高', unit:'cm', ref:'—', type:'chart', list:[{year:'2024',value:172},{year:'2025',value:172},{year:'2026',value:172}]},
|
||||
'i2':{name:'体重', unit:'kg', ref:'—', type:'chart', list:[{year:'2024',value:76},{year:'2025',value:74},{year:'2026',value:72}]},
|
||||
'i3':{name:'血压', unit:'mmHg', ref:'<140 / <90', type:'text', list:[{year:'2024',value:'135/85'},{year:'2025',value:'132/84'},{year:'2026',value:'138/86'}]},
|
||||
'i4':{name:'白细胞计数', unit:'×10⁹/L', ref:'3.5 - 9.5', type:'chart', list:[{year:'2024',value:6.2},{year:'2025',value:5.8},{year:'2026',value:6.5}]},
|
||||
'i5':{name:'红细胞计数', unit:'×10¹²/L', ref:'4.3 - 5.8', type:'chart', list:[{year:'2024',value:5.1},{year:'2025',value:5.0},{year:'2026',value:4.9}]},
|
||||
'i6':{name:'血红蛋白', unit:'g/L', ref:'130 - 175', type:'chart', list:[{year:'2024',value:148},{year:'2025',value:146},{year:'2026',value:145}]},
|
||||
'i7':{name:'空腹血糖', unit:'mmol/L', ref:'3.9 - 6.1', type:'chart', list:[{year:'2024',value:5.6},{year:'2025',value:5.7},{year:'2026',value:5.8}]},
|
||||
'i8':{name:'总胆固醇', unit:'mmol/L', ref:'<5.2', type:'chart', list:[{year:'2024',value:5.4},{year:'2025',value:5.6},{year:'2026',value:5.9}]},
|
||||
'i9':{name:'甘油三酯', unit:'mmol/L', ref:'<1.7', type:'chart', list:[{year:'2024',value:1.6},{year:'2025',value:1.8},{year:'2026',value:1.9}]},
|
||||
'i10':{name:'体检结论', type:'conclusion', list:[{year:'2026', conclusion:'总体良好,血压处于正常高值,建议低盐饮食并定期监测。', suggest:'每季度复测血压;控制体重。'}]}
|
||||
};
|
||||
|
||||
/* ===== 读取 URL 参数定位员工 ===== */
|
||||
var params=new URLSearchParams(location.search);
|
||||
var code=params.get('emp')||'CQ021578';
|
||||
var emp=empBase[code]||empBase['CQ021578'];
|
||||
|
||||
/* ===== 渲染员工信息卡 ===== */
|
||||
function renderHead(){
|
||||
document.title='健康档案 · '+emp.name+' | 一线医疗';
|
||||
document.getElementById('empCard').innerHTML=
|
||||
'<div>姓名 <b>'+emp.name+'</b></div><div>工号 <b>'+code+'</b></div><div>性别/年龄 <b>'+emp.sex+' / '+emp.age+'岁</b></div><div>联系电话 <b>'+emp.tel+'</b></div>'
|
||||
+'<div>所属单位 <b>'+emp.unit+'</b></div><div>所属部门 <b>'+emp.dept+'</b></div><div>分配医疗点 <b>'+emp.point+'('+pointUnit[emp.point]+')</b></div>';
|
||||
}
|
||||
|
||||
/* ===== 键值对渲染工具 ===== */
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v||'—')+'</div></div>';}
|
||||
function grid(items){return '<div class="detail-grid">'+items+'</div>';}
|
||||
|
||||
/* ===== Tab1 健康档案:基本信息 ===== */
|
||||
function renderBasic(){
|
||||
var b=SHARED.basic;
|
||||
var html=
|
||||
grid(d('用户账号',b.username)+d('姓名',emp.name)+d('性别',emp.sex)+d('手机号码',emp.tel)
|
||||
+d('身份证号',b.idCard)+d('邮箱',b.email)+d('编号',b.empNo)+d('单位',emp.unit)
|
||||
+d('部门',emp.dept)+d('职务',b.job)+d('职称',b.title)+d('职位',b.position)
|
||||
+d('行政级别',b.level)+d('子组',b.group)+d('工作状态',b.status)+d('工种',b.workType)
|
||||
+d('体检形式',b.examForm)+d('接害时间',b.hazardDate)+d('危害因素',b.hazard));
|
||||
document.getElementById('sub-base').innerHTML=html;
|
||||
}
|
||||
|
||||
/* ===== Tab1 健康档案:扩展信息 ===== */
|
||||
function renderExtend(){
|
||||
var x=SHARED.extend;
|
||||
var html=
|
||||
'<div class="detail-grid">'
|
||||
+'<div class="detail-item"><div class="dk">头像</div><div class="dv"><div class="avatar-box">'+emp.name.charAt(0)+'</div></div></div>'
|
||||
+'<div class="detail-item"><div class="dk">身高</div><div class="dv">'+x.height+' cm</div></div>'
|
||||
+'<div class="detail-item"><div class="dk">身份证正面</div><div class="dv"><div class="cert-box">证件正面</div></div></div>'
|
||||
+'<div class="detail-item"><div class="dk">体重</div><div class="dv">'+x.weight+' kg</div></div>'
|
||||
+'<div class="detail-item"><div class="dk">身份证反面</div><div class="dv"><div class="cert-box">证件反面</div></div></div>'
|
||||
+'<div class="detail-item"><div class="dk">出生日期</div><div class="dv">'+x.birthday+'</div></div>'
|
||||
+d('年龄',emp.age+'岁')+d('血型',x.bloodType)+d('民族',x.nation)+d('婚姻状况',x.marriage)
|
||||
+d('政治面貌',x.political)+d('学历',x.degree)+d('籍贯',x.nativeplace)+d('入职时间',x.worktime)
|
||||
+d('用工形式',x.empType)+d('是否上市员工',x.listed)+d('工作地点',x.workSpace)+d('居住地点',x.liveSpace)
|
||||
+d('健康类型',x.healthType)+d('健康状态',x.jkState)
|
||||
+'</div>';
|
||||
document.getElementById('sub-extend').innerHTML=html;
|
||||
}
|
||||
|
||||
/* ===== Tab1 健康档案:紧急联系人 ===== */
|
||||
function renderContact(){
|
||||
var rows=SHARED.contacts.map(function(c,i){
|
||||
return '<tr><td>'+(i+1)+'</td><td>'+c.name+'</td><td>'+c.relation+'</td><td>'+c.phone+'</td><td>'+c.idCard+'</td></tr>';
|
||||
}).join('');
|
||||
document.getElementById('sub-contact').innerHTML=
|
||||
'<table style="min-width:0;"><thead><tr><th>序号</th><th>姓名</th><th>与员工关系</th><th>联系电话</th><th>身份证号</th></tr></thead><tbody>'+rows+'</tbody></table>';
|
||||
}
|
||||
|
||||
/* ===== Tab2 体检报告 ===== */
|
||||
function renderExam(){
|
||||
var rows=SHARED.examReports.map(function(r,i){
|
||||
return '<tr><td>'+(i+1)+'</td><td>'+r.date+'</td><td>'+r.year+'</td><td>'+r.hospital+'</td><td>'+r.auditDate+'</td><td>'+r.uploadDate+'</td>'
|
||||
+'<td><button class="btn btn-link" onclick="openExamDetail()">查看报告</button></td></tr>';
|
||||
}).join('');
|
||||
document.getElementById('examBody').innerHTML=rows;
|
||||
}
|
||||
|
||||
/* ===== Tab3 心理评估 ===== */
|
||||
function renderPsych(){
|
||||
var flag={'良好':'badge--success','一般':'badge--warning','较差':'badge--danger'};
|
||||
var rows=SHARED.psychAssessments.map(function(r,i){
|
||||
return '<tr><td>'+(i+1)+'</td><td>'+r.date+'</td><td>'+r.grade+'</td><td><span class="badge '+(flag[r.level]||'badge--muted')+'">'+r.level+'</span></td>'
|
||||
+'<td><button class="btn btn-link" onclick="openPsychQuestion()">问卷详情</button><button class="btn btn-link" onclick="showToast(\'心理评估报告已导出(演示)\')">导出报告</button></td></tr>';
|
||||
}).join('');
|
||||
document.getElementById('psychTotal').textContent=SHARED.psychAssessments.length;
|
||||
document.getElementById('psychBody').innerHTML=rows;
|
||||
}
|
||||
|
||||
/* ===== Tab4 健康评估 ===== */
|
||||
function renderHealth(){
|
||||
function riskBadge(v){return v.indexOf('高')!==-1?'badge--danger':(v.indexOf('中')!==-1?'badge--warning':'badge--success');}
|
||||
var rows=SHARED.healthAssessments.map(function(r,i){
|
||||
return '<tr><td>'+(i+1)+'</td><td>'+r.date+'</td><td>'+r.bmi+'</td>'
|
||||
+'<td><span class="badge '+riskBadge(r.icvd)+'">'+r.icvd+'</span></td>'
|
||||
+'<td><span class="badge '+riskBadge(r.diabetes)+'">'+r.diabetes+'</span></td>'
|
||||
+'<td><span class="badge '+riskBadge(r.lung)+'">'+r.lung+'</span></td>'
|
||||
+'<td><span class="badge '+riskBadge(r.hypertension)+'">'+r.hypertension+'</span></td>'
|
||||
+'<td><span class="badge '+riskBadge(r.metabolic)+'">'+r.metabolic+'</span></td>'
|
||||
+'<td><button class="btn btn-link" onclick="openHealthQuestion()">问卷详情</button><button class="btn btn-link" onclick="showToast(\'健康评估报告已导出(演示)\')">导出报告</button></td></tr>';
|
||||
}).join('');
|
||||
document.getElementById('healthTotal').textContent=SHARED.healthAssessments.length;
|
||||
document.getElementById('healthBody').innerHTML=rows;
|
||||
}
|
||||
|
||||
/* ===== Tab5 体检分析报告 ===== */
|
||||
function renderTree(){
|
||||
function nodeHtml(n, level){
|
||||
var hasChild=n.children&&n.children.length;
|
||||
var arrow=hasChild?'<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>':'';
|
||||
var cls='tree-node'+(hasChild?'':' tree-node--leaf');
|
||||
return '<div class="'+cls+'" data-id="'+n.id+'" onclick="onTreeNode(this,\''+n.id+'\',event)" style="'+(level?'padding-left:40px;':'')+'">'+arrow+'<span>'+n.name+'</span></div>'
|
||||
+(hasChild?'<div class="tree-children" data-parent="'+n.id+'">'+n.children.map(function(c){return nodeHtml(c,1);}).join('')+'</div>':'');
|
||||
}
|
||||
document.getElementById('treeBox').innerHTML=treeData.map(function(n){return nodeHtml(n,0);}).join('');
|
||||
// 默认展开第一类、收起其余
|
||||
treeData.forEach(function(cat,idx){
|
||||
var childrenEl=document.querySelector('.tree-children[data-parent="'+cat.id+'"]');
|
||||
var nodeEl=document.querySelector('.tree-node[data-id="'+cat.id+'"]');
|
||||
if(childrenEl){
|
||||
if(idx===0){childrenEl.style.display='';if(nodeEl)nodeEl.classList.add('open');}
|
||||
else{childrenEl.style.display='none';}
|
||||
}
|
||||
});
|
||||
// 默认选中第一个叶子
|
||||
var firstLeaf=treeData[0].children[0];
|
||||
selectIndicator(firstLeaf.id);
|
||||
document.querySelectorAll('.tree-node--leaf').forEach(function(el){el.classList.remove('active');});
|
||||
var activeEl=document.querySelector('.tree-node--leaf[data-id="'+firstLeaf.id+'"]');
|
||||
if(activeEl)activeEl.classList.add('active');
|
||||
}
|
||||
function onTreeNode(el,id,event){
|
||||
event.stopPropagation();
|
||||
var parent=el.parentElement.querySelector('.tree-children[data-parent="'+id+'"]');
|
||||
if(parent){
|
||||
el.classList.toggle('open');
|
||||
parent.style.display=parent.style.display==='none'?'':'none';
|
||||
}else{
|
||||
document.querySelectorAll('.tree-node--leaf').forEach(function(x){x.classList.remove('active');});
|
||||
el.classList.add('active');
|
||||
selectIndicator(id);
|
||||
}
|
||||
}
|
||||
function selectIndicator(id){
|
||||
var it=indicatorData[id];
|
||||
if(!it)return;
|
||||
var parentName='';
|
||||
treeData.forEach(function(cat){cat.children.forEach(function(c){if(c.id===id)parentName=cat.name;});});
|
||||
document.getElementById('analysisTitle').textContent=parentName+' / '+it.name;
|
||||
if(it.type==='conclusion'){
|
||||
var c=it.list[0];
|
||||
document.getElementById('analysisBody').innerHTML=
|
||||
'<div class="analysis-col"><div class="indicator-card"><div class="indicator-card__title"><div class="indicator-card__name">'+it.name+'</div></div>'
|
||||
+'<div class="indicator-card__desc"><div class="desc-row"><div class="desc-label">结论</div><div class="desc-text">'+c.conclusion+'</div></div>'
|
||||
+'<div class="desc-row"><div class="desc-label">建议</div><div class="desc-text">'+c.suggest+'</div></div></div></div></div>';
|
||||
return;
|
||||
}
|
||||
document.getElementById('analysisBody').innerHTML=renderIndicatorCard(it);
|
||||
}
|
||||
function renderIndicatorCard(it){
|
||||
var labels=it.list.map(function(x){return '<div>'+x.year+'</div>';}).join('');
|
||||
var values=it.list.map(function(x){return '<div>'+x.value+'</div>';}).join('');
|
||||
var chart=it.type==='chart'?renderChart(it.list):'';
|
||||
var refHtml=it.ref&&it.ref!=='—'?'<div class="indicator-card__ref">参考值:<span>'+it.ref+'</span> <span>'+it.unit+'</span></div>':'';
|
||||
return '<div class="analysis-col"><div class="indicator-card">'
|
||||
+'<div class="indicator-card__title"><div class="indicator-card__name">'+it.name+'</div>'+refHtml+'</div>'
|
||||
+'<div class="indicator-card__table"><div class="indicator-card__labels"><div>时间</div><div>数值</div></div>'
|
||||
+'<div class="indicator-card__values"><div class="indicator-card__valrow">'+labels+'</div><div class="indicator-card__valrow">'+values+'</div></div></div>'
|
||||
+(chart?'<div class="indicator-card__chart">'+chart+'</div>':'')
|
||||
+'</div></div>';
|
||||
}
|
||||
function renderChart(list){
|
||||
var w=460,h=140,padX=30,padTop=16,padBottom=24;
|
||||
var vals=list.map(function(x){return x.value;});
|
||||
var min=Math.min.apply(null,vals),max=Math.max.apply(null,vals);
|
||||
var range=(max-min)||1;
|
||||
var stepX=list.length>1?(w-padX*2)/(list.length-1):0;
|
||||
var pts=vals.map(function(v,i){
|
||||
var x=padX+i*stepX;
|
||||
var y=padTop+(h-padTop-padBottom)*(1-(v-min)/range);
|
||||
return {x:x,y:y,v:v};
|
||||
});
|
||||
var polyline=list.length>1?'<polyline points="'+pts.map(function(p){return p.x+','+p.y;}).join(' ')+'" fill="none" stroke="#1890FF" stroke-width="2"/>':'';
|
||||
var dots=pts.map(function(p){return '<circle cx="'+p.x+'" cy="'+p.y+'" r="3.5" fill="#1890FF"/>';}).join('');
|
||||
var valLabels=pts.map(function(p){return '<text x="'+p.x+'" y="'+(p.y-8)+'" font-size="10" fill="#666" text-anchor="middle">'+p.v+'</text>';}).join('');
|
||||
var xLabels=pts.map(function(p,i){return '<text x="'+p.x+'" y="'+(h-6)+'" font-size="10" fill="#999" text-anchor="middle">'+list[i].year+'</text>';}).join('');
|
||||
return '<svg viewBox="0 0 '+w+' '+h+'" width="100%" height="140">'
|
||||
+'<line x1="'+padX+'" y1="'+padTop+'" x2="'+(w-padX)+'" y2="'+padTop+'" stroke="#F0F0F0"/>'
|
||||
+'<line x1="'+padX+'" y1="'+(h-padBottom)+'" x2="'+(w-padX)+'" y2="'+(h-padBottom)+'" stroke="#E0E0E0"/>'
|
||||
+polyline+dots+valLabels+xLabels+'</svg>';
|
||||
}
|
||||
|
||||
/* ===== 弹窗 ===== */
|
||||
function openModal(title, bodyHtml){
|
||||
document.getElementById('modalTitle').textContent=title;
|
||||
document.getElementById('modalBody').innerHTML=bodyHtml;
|
||||
document.getElementById('modalMask').classList.add('open');
|
||||
document.getElementById('modal').classList.add('open');
|
||||
}
|
||||
function closeModal(){
|
||||
document.getElementById('modalMask').classList.remove('open');
|
||||
document.getElementById('modal').classList.remove('open');
|
||||
}
|
||||
function openExamDetail(){
|
||||
var x=SHARED.examDetail;
|
||||
var flag={'正常':'badge--success','关注':'badge--warning','异常':'badge--danger'};
|
||||
var itemRows=x.items.map(function(it){
|
||||
return '<tr><td>'+it.name+'</td><td>'+it.value+'</td><td>'+it.ref+'</td><td><span class="badge '+(flag[it.flag]||'badge--muted')+'">'+it.flag+'</span></td></tr>';
|
||||
}).join('');
|
||||
openModal('体检报告 · '+x.year+'年度',
|
||||
'<div class="detail-grid" style="margin-bottom:12px;">'+d('体检年度',x.year)+d('体检机构',x.hospital)+d('体检日期',x.date)+'</div>'
|
||||
+'<table style="min-width:0;margin-bottom:16px;"><thead><tr><th>指标</th><th>结果</th><th>参考范围</th><th>结论</th></tr></thead><tbody>'+itemRows+'</tbody></table>'
|
||||
+'<div class="form-section">总体结论</div><div style="font-size:var(--font-sm);color:var(--text-primary);line-height:1.7;">'+x.conclusion+'</div>'
|
||||
+'<div class="form-section">管理建议</div><div style="font-size:var(--font-sm);color:var(--text-primary);line-height:1.7;">'+x.suggest+'</div>');
|
||||
}
|
||||
function renderQuestion(questions){
|
||||
return questions.map(function(q){
|
||||
var opts=q.opts.map(function(o){return '<span class="q-opt'+(o===q.answer?' answer':'')+'">'+o+'</span>';}).join('');
|
||||
return '<div class="q-item"><div class="q-title">'+q.q+'</div><div class="q-opts">'+opts+'</div></div>';
|
||||
}).join('');
|
||||
}
|
||||
function openPsychQuestion(){
|
||||
openModal('心理评估 · 问卷详情', renderQuestion(SHARED.psychQuestion));
|
||||
}
|
||||
function openHealthQuestion(){
|
||||
openModal('健康评估 · 问卷详情', renderQuestion(SHARED.healthQuestion));
|
||||
}
|
||||
|
||||
/* ===== 主 Tab 切换 ===== */
|
||||
function switchTab(k){
|
||||
document.querySelectorAll('.tab-btn').forEach(function(b){b.classList.toggle('active',b.dataset.tab===k);});
|
||||
['basic','exam','psych','health','analysis'].forEach(function(p){
|
||||
var el=document.getElementById('pane-'+p);
|
||||
if(el)el.style.display=(p===k)?'':'none';
|
||||
});
|
||||
}
|
||||
function switchSub(k){
|
||||
document.querySelectorAll('.sub-tab').forEach(function(b){b.classList.toggle('active',b.dataset.sub===k);});
|
||||
['base','extend','contact'].forEach(function(p){
|
||||
document.getElementById('sub-'+p).style.display=(p===k)?'':'none';
|
||||
});
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
|
||||
/* ===== 初始化 ===== */
|
||||
renderHead();
|
||||
renderBasic();
|
||||
renderExtend();
|
||||
renderContact();
|
||||
renderExam();
|
||||
renderPsych();
|
||||
renderHealth();
|
||||
renderTree();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -74,25 +74,6 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.page-btn:disabled{opacity:.4;cursor:not-allowed;background:#fff;color:var(--text-placeholder);border-color:var(--border);}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
.drawer-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:900;}
|
||||
.drawer-mask.open{display:block;}
|
||||
.drawer{position:fixed;top:56px;right:-760px;bottom:0;width:720px;background:#fff;z-index:910;box-shadow:-8px 0 24px rgba(0,0,0,.12);transition:right .25s ease;display:flex;flex-direction:column;}
|
||||
.drawer.open{right:0;}
|
||||
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-lg);font-weight:600;flex-shrink:0;}
|
||||
.drawer__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.drawer__close:hover{color:var(--text-primary);}
|
||||
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
|
||||
.drawer__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 12px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid var(--border);}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:110px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
.mini-table{width:100%;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;min-width:0;}
|
||||
.mini-table thead th{background:#FAFAFA;position:sticky;top:0;font-size:var(--font-sm);}
|
||||
.mini-table td{white-space:normal;font-size:var(--font-sm);}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -125,13 +106,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item active">员工档案</a>
|
||||
@@ -208,17 +183,6 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 员工档案详情抽屉 -->
|
||||
<div class="drawer-mask" id="viewMask" onclick="closeDrawer()"></div>
|
||||
<div class="drawer" id="viewDrawer">
|
||||
<div class="drawer__header"><span id="viewTitle">员工健康档案</span><button class="drawer__close" onclick="closeDrawer()">×</button></div>
|
||||
<div class="drawer__body" id="viewBody"></div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer()">关闭</button>
|
||||
<button class="btn btn-primary" onclick="showToast('跳转至该员工的就诊登记(演示)')">去登记就诊</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
@@ -270,12 +234,6 @@ var emps=[
|
||||
visits:[{time:'2026-08-28 13:30',disease:'中暑(先兆)',doctor:'刘玉梅'}]}
|
||||
];
|
||||
|
||||
/* 指标结论按阈值实时计算(演示规则) */
|
||||
function bpFlag(s){var p=s.split('/'),a=+p[0],b=+p[1];if(a>=140||b>=90)return '异常';if(a>=130||b>=85)return '关注';return '正常';}
|
||||
function gluFlag(v){if(v>=7.0)return '异常';if(v>=6.1)return '关注';return '正常';}
|
||||
function bmiFlag(v){if(v>=28)return '异常';if(v>=24)return '关注';return '正常';}
|
||||
function tcFlag(v){if(v>=6.2)return '异常';if(v>=5.2)return '关注';return '正常';}
|
||||
var flagBadge={'正常':'badge--success','关注':'badge--warning','异常':'badge--danger'};
|
||||
var riskBadge={'低':'badge--success','中':'badge--warning','高':'badge--danger'};
|
||||
|
||||
/* ===== 列表 ===== */
|
||||
@@ -315,7 +273,7 @@ function renderTable(){
|
||||
+'<td>'+e.unit+'</td><td>'+e.dept+'</td>'
|
||||
+'<td>'+pointUnit[e.point]+'</td><td>'+e.point+'</td>'
|
||||
+'<td><span class="badge '+riskBadge[e.exam.risk]+'">'+e.exam.risk+'风险</span></td>'
|
||||
+'<td class="td-actions"><button class="btn btn-link" onclick="openView(\''+e.code+'\')">详情</button></td></tr>';
|
||||
+'<td class="td-actions"><a class="btn btn-link" href="daily-employee-file.html?emp='+e.code+'" style="text-decoration:none;">健康档案</a></td></tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
}
|
||||
@@ -332,39 +290,7 @@ function turnPage(d){
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ===== 档案详情抽屉 ===== */
|
||||
function openView(code){
|
||||
var e=emps.find(function(x){return x.code===code;});
|
||||
document.getElementById('viewTitle').textContent='员工健康档案 · '+e.name;
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v||'—')+'</div></div>';}
|
||||
var x=e.exam;
|
||||
var indRows=[
|
||||
{n:'血压(mmHg)',v:x.bp,f:bpFlag(x.bp),ref:'<140 / <90'},
|
||||
{n:'空腹血糖(mmol/L)',v:x.glu.toFixed(1),f:gluFlag(x.glu),ref:'3.9-6.1'},
|
||||
{n:'BMI',v:x.bmi.toFixed(1),f:bmiFlag(x.bmi),ref:'18.5-23.9'},
|
||||
{n:'总胆固醇(mmol/L)',v:x.tc.toFixed(1),f:tcFlag(x.tc),ref:'<5.2'}
|
||||
].map(function(r){return '<tr><td>'+r.n+'</td><td>'+r.v+'</td><td>'+r.ref+'</td><td><span class="badge '+flagBadge[r.f]+'">'+r.f+'</span></td></tr>';}).join('');
|
||||
var chronicHtml=x.chronic.length?x.chronic.map(function(c){return '<span class="badge badge--muted" style="margin-right:6px;">'+c+'</span>';}).join(''):'<span style="color:var(--text-placeholder);font-size:var(--font-sm);">无</span>';
|
||||
var visitsHtml=e.visits.length?'<table class="mini-table"><thead><tr><th>就诊时间</th><th>诊断疾病</th><th>就诊医生</th></tr></thead><tbody>'+e.visits.map(function(v){return '<tr><td>'+v.time+'</td><td>'+v.disease+'</td><td>'+v.doctor+'</td></tr>';}).join('')+'</tbody></table>':'<span style="color:var(--text-placeholder);font-size:var(--font-sm);">本统计周期内暂无就诊记录</span>';
|
||||
document.getElementById('viewBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">基础信息</div>'
|
||||
+'<div class="detail-grid">'+d('员工姓名',e.name)+d('员工工号',e.code)+d('性别/年龄',e.sex+' / '+e.age+'岁')+d('联系电话',e.tel)+d('所属单位',e.unit)+d('所属部门',e.dept)+d('分配医疗点',e.point+'('+pointUnit[e.point]+')')+d('分配日期',e.since)+'</div>'
|
||||
+'<div class="form-section">最近年度体检('+x.date.slice(0,4)+'年度)</div>'
|
||||
+'<div class="detail-grid">'+d('体检日期',x.date)+d('体检机构',x.hospital)+d('总体结论',x.summary,true)+'</div>'
|
||||
+'<div style="height:8px;"></div>'
|
||||
+'<table class="mini-table"><thead><tr><th>指标</th><th>结果</th><th>参考范围</th><th>结论</th></tr></thead><tbody>'+indRows+'</tbody></table>'
|
||||
+'<div class="form-section">健康风险评估</div>'
|
||||
+'<div class="detail-grid">'+d('风险等级','<span class="badge '+riskBadge[x.risk]+'">'+x.risk+'风险</span>')+d('慢病标签',chronicHtml)+d('管理建议',x.advice,true)+'</div>'
|
||||
+'<div class="form-section">就诊记录</div>'+visitsHtml;
|
||||
document.getElementById('viewMask').classList.add('open');
|
||||
document.getElementById('viewDrawer').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
function closeDrawer(){
|
||||
document.getElementById('viewMask').classList.remove('open');
|
||||
document.getElementById('viewDrawer').classList.remove('open');
|
||||
}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
|
||||
@@ -80,7 +80,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.tab-btn.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
|
||||
.tab-btn .cnt{display:inline-block;min-width:18px;height:18px;line-height:18px;text-align:center;border-radius:9px;background:#F0F0F0;color:var(--text-secondary);font-size:var(--font-xs);padding:0 5px;}
|
||||
.tab-btn.active .cnt{background:var(--primary-light);color:var(--primary);}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.action-bar{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 24px;background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.action-bar__left{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
|
||||
.seg{display:inline-flex;border:1px solid var(--primary);border-radius:var(--radius-sm);overflow:hidden;flex-shrink:0;}
|
||||
.seg button{height:32px;padding:0 16px;border:none;background:#fff;color:var(--primary);font-size:var(--font-sm);cursor:pointer;border-right:1px solid var(--primary);transition:all .15s;}
|
||||
.seg button:last-child{border-right:none;}
|
||||
.seg button:hover{background:var(--primary-light);}
|
||||
.seg button.active{background:var(--primary);color:#fff;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;margin-top:0;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1500px;}
|
||||
thead th{background:#FAFAFA;padding:10px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
@@ -105,17 +112,35 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.modal{width:520px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;max-height:82vh;overflow-y:auto;}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;margin-bottom:16px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:12px;}
|
||||
.modal--wide{width:1200px;max-width:94vw;max-height:84vh;display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);}
|
||||
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-base);font-weight:600;flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.modal__close:hover{color:var(--text-primary);}
|
||||
.modal__body{flex:1;overflow-y:auto;padding:20px 24px;}
|
||||
.form-item{display:flex;flex-direction:column;gap:6px;margin-bottom:14px;}
|
||||
.form-label{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.form-label .req{color:var(--danger);}
|
||||
.form-control{height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);color:var(--text-primary);outline:none;width:100%;}
|
||||
.form-control:focus{border-color:var(--primary);}
|
||||
.form-control[readonly]{background:#FAFAFA;color:var(--text-secondary);}
|
||||
textarea.form-control{height:56px;padding:8px 10px;resize:vertical;line-height:1.5;}
|
||||
select.form-control{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;-webkit-appearance:none;padding-right:28px;cursor:pointer;}
|
||||
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 16px;}
|
||||
.radio-group{display:flex;gap:16px;min-height:32px;align-items:center;flex-wrap:wrap;}
|
||||
.radio{display:flex;align-items:center;gap:6px;font-size:var(--font-sm);cursor:pointer;}
|
||||
.radio input{accent-color:var(--primary);cursor:pointer;}
|
||||
.emp-pick{display:flex;gap:8px;align-items:center;}
|
||||
.emp-pick .form-control{flex:1;}
|
||||
.emp-card{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px 16px;background:#F7F9FC;border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px 16px;margin:8px 0 4px;}
|
||||
.emp-card div{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.emp-card b{color:var(--text-primary);font-weight:600;margin-left:4px;}
|
||||
.pick-table{width:100%;border-collapse:separate;border-spacing:0;min-width:0;}
|
||||
.pick-table thead th{background:#FAFAFA;padding:8px 12px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.pick-table tbody td{padding:10px 12px;text-align:center;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.pick-table tbody tr:hover{background:#F8FBFF;}
|
||||
.pick-table__wrap{max-height:320px;overflow-y:auto;border:1px solid var(--border);border-radius:var(--radius-sm);}
|
||||
.section-title{display:flex;align-items:center;gap:8px;font-size:var(--font-base);font-weight:600;color:var(--text-primary);margin:16px 0 10px;}
|
||||
.section-title::before{content:'';width:4px;height:16px;background:var(--primary);border-radius:2px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -148,13 +173,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -211,84 +230,173 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<option value="">全部医疗点</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item" id="filterDateItem">
|
||||
<label>计划随访日期</label>
|
||||
<input class="filter-input" type="date" id="filterFrom" style="min-width:130px;">
|
||||
<span style="color:var(--text-placeholder);">至</span>
|
||||
<input class="filter-input" type="date" id="filterTo" style="min-width:130px;">
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="applyFilter()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.3"/><path d="M9.5 9.5L13 13" stroke="#fff" stroke-width="1.3" stroke-linecap="round"/></svg>查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="resetFilter()">重置</button>
|
||||
</div>
|
||||
|
||||
<!-- [交互] Tab:单次任务 / 频次任务 / 申请任务 -->
|
||||
<!-- [交互] Tab:单次巡诊 / 频次巡诊 / 申请巡诊 -->
|
||||
<div class="tabs-bar">
|
||||
<button class="tab-btn active" id="tabOnce" onclick="switchTab('once')">单次任务 <span class="cnt" id="cntOnce"></span></button>
|
||||
<button class="tab-btn" id="tabFreq" onclick="switchTab('freq')">频次任务 <span class="cnt" id="cntFreq"></span></button>
|
||||
<button class="tab-btn" id="tabApply" onclick="switchTab('apply')">申请任务 <span class="cnt" id="cntApply"></span></button>
|
||||
<span style="margin-left:auto;font-size:var(--font-xs);color:var(--text-placeholder);align-self:center;padding-right:12px;">
|
||||
单次/频次任务由系统按慢病干预方案自动派发,也可手工新建
|
||||
</span>
|
||||
<button class="tab-btn active" id="tabOnce" onclick="switchTab('once')">单次巡诊 <span class="cnt" id="cntOnce"></span></button>
|
||||
<button class="tab-btn" id="tabFreq" onclick="switchTab('freq')">频次巡诊 <span class="cnt" id="cntFreq"></span></button>
|
||||
<button class="tab-btn" id="tabApply" onclick="switchTab('apply')">申请巡诊 <span class="cnt" id="cntApply"></span></button>
|
||||
</div>
|
||||
|
||||
<!-- 单次任务 -->
|
||||
<div class="table-card" id="paneOnce">
|
||||
<!-- [交互] 操作栏:按钮 + 状态分组 -->
|
||||
<div class="action-bar">
|
||||
<div class="action-bar__left">
|
||||
<button class="btn btn-primary" id="btnAdd" onclick="openCreate()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新增
|
||||
</button>
|
||||
<button class="btn btn-primary" id="btnFreqCfg" style="display:none;" onclick="openFreqConfig()">频次配置信息</button>
|
||||
<button class="btn btn-primary" onclick="doExport()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="openExport()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出记录
|
||||
</button>
|
||||
</div>
|
||||
<div class="seg" id="segNormal">
|
||||
<button class="active" data-v="0" onclick="setGroup(this,'0')">全部</button>
|
||||
<button data-v="1" onclick="setGroup(this,'1')">待随访</button>
|
||||
<button data-v="2" onclick="setGroup(this,'2')">已逾期</button>
|
||||
<button data-v="3" onclick="setGroup(this,'3')">已完成</button>
|
||||
</div>
|
||||
<div class="seg" id="segApply" style="display:none;">
|
||||
<button class="active" data-v="0" onclick="setGroup(this,'0')">全部</button>
|
||||
<button data-v="1" onclick="setGroup(this,'1')">待随访</button>
|
||||
<button data-v="3" onclick="setGroup(this,'3')">已完成</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 单次巡诊 -->
|
||||
<div class="table-card" id="paneOnce" style="margin-top:16px;">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead><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><th>任务状态</th><th>操作</th></tr></thead>
|
||||
<thead><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><th>操作</th></tr></thead>
|
||||
<tbody id="onceBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 频次任务 -->
|
||||
<div class="table-card" id="paneFreq" style="display:none;">
|
||||
<!-- 频次巡诊 -->
|
||||
<div class="table-card" id="paneFreq" style="display:none;margin-top:16px;">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead><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>
|
||||
<thead><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><th>操作</th></tr></thead>
|
||||
<tbody id="freqBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 申请任务 -->
|
||||
<div class="table-card" id="paneApply" style="display:none;">
|
||||
<!-- 申请巡诊 -->
|
||||
<div class="table-card" id="paneApply" style="display:none;margin-top:16px;">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead><tr><th>序号</th><th>申请员工</th><th>员工编号</th><th>性别</th><th>年龄</th><th>员工单位</th><th>部门</th><th>分配医疗点</th><th>申请内容</th><th>申请日期</th><th>操作</th></tr></thead>
|
||||
<thead><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><th>状态</th><th>操作</th></tr></thead>
|
||||
<tbody id="applyBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 操作栏 -->
|
||||
<div class="tabs-bar" style="padding:0;border-radius:var(--radius-md);margin-top:16px;">
|
||||
<button class="btn btn-primary" style="margin:12px 8px 12px 16px;" onclick="openCreate()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>新建随访任务
|
||||
</button>
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 新建任务弹窗 -->
|
||||
<div class="modal-mask" id="createMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title">新建随访任务</div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 随访员工(仅已分配员工)</span>
|
||||
<select class="form-control" id="cEmp"><option value="">请选择员工</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 任务类型</span>
|
||||
<div class="radio-group">
|
||||
<label class="radio"><input type="radio" name="cType" value="once" checked onchange="onTypeRadio()">单次任务</label>
|
||||
<label class="radio"><input type="radio" name="cType" value="freq" onchange="onTypeRadio()">频次任务</label>
|
||||
</div></div>
|
||||
<div class="form-item" id="boxOnceDate"><span class="form-label"><span class="req">*</span> 计划随访日期</span><input class="form-control" type="date" id="cDate"></div>
|
||||
<div class="form-grid" id="boxFreq" style="display:none;">
|
||||
<div class="form-item"><span class="form-label">人员类型</span>
|
||||
<select class="form-control" id="cGroup"><option>高血压</option><option>冠心病</option><option>糖尿病</option><option>肥胖</option><option>其他</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 随访频次</span>
|
||||
<select class="form-control" id="cFreq"><option>每月</option><option>每季度</option><option>每半年</option></select></div>
|
||||
<!-- [交互] 新增/编辑随访任务抽屉 -->
|
||||
<div class="drawer-mask" id="taskMask" onclick="closeDrawer('task')"></div>
|
||||
<div class="drawer" id="taskDrawer">
|
||||
<div class="drawer__header"><span id="taskTitle">新增</span><button class="drawer__close" onclick="closeDrawer('task')">×</button></div>
|
||||
<div class="drawer__body">
|
||||
<div class="form-item">
|
||||
<span class="form-label"><span class="req">*</span> 员工</span>
|
||||
<div class="emp-pick">
|
||||
<input class="form-control" id="tEmp" readonly placeholder="请选择员工">
|
||||
<button class="btn btn-primary" id="tEmpBtn" onclick="openEmpPick()">选择</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="emp-card" id="tEmpCard" style="display:none;"></div>
|
||||
<div class="section-title">随访信息</div>
|
||||
<div class="form-item">
|
||||
<span class="form-label"><span class="req">*</span> 随访日期</span>
|
||||
<input class="form-control" type="date" id="tDate">
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer('task')">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveTask()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 选择员工弹窗 -->
|
||||
<div class="modal-mask" id="empPickMask">
|
||||
<div class="modal" style="width:760px;">
|
||||
<div class="modal__title">选择员工</div>
|
||||
<div style="display:flex;gap:8px;margin-bottom:12px;">
|
||||
<input class="form-control" id="empQ" placeholder="请输入姓名或工号" oninput="renderEmpPick()">
|
||||
<button class="btn btn-primary" onclick="renderEmpPick()">查询</button>
|
||||
</div>
|
||||
<div class="pick-table__wrap">
|
||||
<table class="pick-table">
|
||||
<thead><tr><th></th><th>姓名</th><th>工号</th><th>性别</th><th>年龄</th><th>员工所属单位</th><th>分配医疗点</th></tr></thead>
|
||||
<tbody id="empPickBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="form-item form-item--full"><span class="form-label">任务说明</span><textarea class="form-control" id="cNote" placeholder="随访重点与注意事项"></textarea></div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('createMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveCreate()">保存</button>
|
||||
<button class="btn btn-default" onclick="closeModal('empPickMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="confirmEmpPick()">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 频次配置信息弹窗 -->
|
||||
<div class="modal-mask" id="freqCfgMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal__header"><span>频次配置信息</span><button class="modal__close" onclick="closeModal('freqCfgMask')">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div style="display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:16px;">
|
||||
<div class="filter-item">
|
||||
<label>员工姓名</label>
|
||||
<input class="filter-input" id="fcName" placeholder="请输入姓名">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>单位</label>
|
||||
<select class="filter-select" id="fcUnit" onchange="onFcUnit()" style="min-width:120px;">
|
||||
<option value="">全部单位</option>
|
||||
<option>采油一厂</option><option>采油二厂</option><option>第四采油厂</option><option>采气一厂</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>所属医疗点</label>
|
||||
<select class="filter-select" id="fcPoint" style="min-width:160px;">
|
||||
<option value="">全部医疗点</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="renderFreqConfig()">查询</button>
|
||||
<button class="btn btn-default" onclick="resetFreqConfig()">重置</button>
|
||||
</div>
|
||||
<div class="table-card__content" style="overflow-x:auto;">
|
||||
<table style="min-width:1100px;">
|
||||
<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 id="fcBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 删除确认弹窗 -->
|
||||
<div class="modal-mask" id="delMask">
|
||||
<div class="modal" style="width:440px;">
|
||||
<div class="modal__title">确认删除</div>
|
||||
<div style="font-size:var(--font-sm);color:var(--text-secondary);" id="delText">是否删除该数据</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('delMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="confirmDelete()">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -310,7 +418,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<script>
|
||||
/* ===== 演示数据(脱敏):与员工分配名册/慢病台账/随访管理勾稽 ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂'};
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂','姬塬作业区医疗点':'采油一厂'};
|
||||
var pointMap={
|
||||
'采油一厂':['樊学作业区医疗点','安塞采油队长住点医疗室','姬塬作业区医疗点'],
|
||||
'采油二厂':['姬圪台作业区医疗点','桐园作业区医疗点'],
|
||||
@@ -318,47 +426,55 @@ var pointMap={
|
||||
'采气一厂':['靖边气田医疗点','乌审旗采气区医疗点']
|
||||
};
|
||||
var empPool=[
|
||||
{code:'CQ021578',name:'石维国',sex:'男',age:46,tel:'139****2051',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',group:'高血压'},
|
||||
{code:'CQ027710',name:'张秀兰',sex:'女',age:45,tel:'136****2248',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',group:'肥胖'},
|
||||
{code:'CQ019203',name:'曲志明',sex:'男',age:42,tel:'137****8890',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',group:'冠心病'},
|
||||
{code:'CQ033096',name:'赵万福',sex:'男',age:39,tel:'150****6127',unit:'采油二厂',dept:'桐园作业区',point:'桐园作业区医疗点',group:'高血压'},
|
||||
{code:'CQ010564',name:'高建军',sex:'男',age:50,tel:'139****0086',unit:'第四采油厂',dept:'基地管理处',point:'西峰基地医疗点',group:'糖尿病'},
|
||||
{code:'CQ036441',name:'刘玉梅',sex:'女',age:40,tel:'135****7719',unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',group:'高血压'},
|
||||
{code:'CQ029905',name:'呼建国',sex:'男',age:36,tel:'147****9003',unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',group:'其他'},
|
||||
{code:'CQ044871',name:'白瑞',sex:'男',age:31,tel:'155****3316',unit:'采油一厂',dept:'生产技术部',point:'安塞采油队长住点医疗室',group:'其他'},
|
||||
{code:'CQ022317',name:'徐立成',sex:'男',age:44,tel:'133****4860',unit:'采气一厂',dept:'苏里格南作业区',point:'乌审旗采气区医疗点',group:'肥胖'}
|
||||
{code:'CQ021578',name:'石维国',sex:'男',age:46,tel:'139****2051',idcard:'6101**********0011',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',group:'高血压'},
|
||||
{code:'CQ027710',name:'张秀兰',sex:'女',age:45,tel:'136****2248',idcard:'6101**********0022',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',group:'肥胖'},
|
||||
{code:'CQ019203',name:'曲志明',sex:'男',age:42,tel:'137****8890',idcard:'6101**********0033',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',group:'冠心病'},
|
||||
{code:'CQ033096',name:'赵万福',sex:'男',age:39,tel:'150****6127',idcard:'6101**********0044',unit:'采油二厂',dept:'桐园作业区',point:'桐园作业区医疗点',group:'高血压'},
|
||||
{code:'CQ010564',name:'高建军',sex:'男',age:50,tel:'139****0086',idcard:'6101**********0055',unit:'第四采油厂',dept:'基地管理处',point:'西峰基地医疗点',group:'糖尿病'},
|
||||
{code:'CQ036441',name:'刘玉梅',sex:'女',age:40,tel:'135****7719',idcard:'6101**********0066',unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',group:'高血压'},
|
||||
{code:'CQ029905',name:'呼建国',sex:'男',age:36,tel:'147****9003',idcard:'6101**********0077',unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',group:'其他'},
|
||||
{code:'CQ044871',name:'白瑞',sex:'男',age:31,tel:'155****3316',idcard:'6101**********0088',unit:'采油一厂',dept:'生产技术部',point:'安塞采油队长住点医疗室',group:'其他'},
|
||||
{code:'CQ022317',name:'徐立成',sex:'男',age:44,tel:'133****4860',idcard:'6101**********0099',unit:'采气一厂',dept:'苏里格南作业区',point:'乌审旗采气区医疗点',group:'肥胖'},
|
||||
{code:'CQ041822',name:'闫婷',sex:'女',age:34,tel:'186****5527',idcard:'6101**********0100',unit:'第四采油厂',dept:'健康管理部',point:'西峰基地医疗点',group:'其他'}
|
||||
];
|
||||
function E(code){return empPool.find(function(e){return e.code===code;});}
|
||||
/* 单次任务:plan=计划 actual=实际(空为未执行) */
|
||||
/* 单次巡诊任务:status 1待随访 2已逾期 3已完成 */
|
||||
var onceTasks=[
|
||||
{id:1,code:'CQ033096',plan:'2026-10-05',actual:'',status:'待随访',note:'血压未达标复查,重点评估用药依从性'},
|
||||
{id:2,code:'CQ010564',plan:'2026-09-17',actual:'',status:'待随访',note:'血糖两周复查,评估换药后反应'},
|
||||
{id:3,code:'CQ021578',plan:'2026-10-28',actual:'',status:'待随访',note:''},
|
||||
{id:4,code:'CQ027710',plan:'2026-11-01',actual:'',status:'待随访',note:''},
|
||||
{id:5,code:'CQ036441',plan:'2026-09-01',actual:'',status:'已逾期',note:''},
|
||||
{id:6,code:'CQ029905',plan:'2026-08-14',actual:'2026-08-14',status:'已完成',note:''},
|
||||
{id:7,code:'CQ019203',plan:'2026-08-19',actual:'2026-08-19',status:'已完成',note:''}
|
||||
{id:1,code:'CQ033096',plan:'2026-09-15',actual:'',status:1},
|
||||
{id:2,code:'CQ010564',plan:'2026-09-17',actual:'',status:1},
|
||||
{id:3,code:'CQ021578',plan:'2026-10-28',actual:'',status:1},
|
||||
{id:4,code:'CQ027710',plan:'2026-09-01',actual:'',status:2},
|
||||
{id:5,code:'CQ036441',plan:'2026-08-14',actual:'2026-08-14',status:3},
|
||||
{id:6,code:'CQ019203',plan:'2026-08-19',actual:'2026-08-19',status:3}
|
||||
];
|
||||
/* 频次任务:freq=随访频次 run=启用/暂停 */
|
||||
/* 频次巡诊任务 */
|
||||
var freqTasks=[
|
||||
{id:1,code:'CQ033096',freq:'每月',run:'启用'},
|
||||
{id:2,code:'CQ010564',freq:'每月',run:'启用'},
|
||||
{id:3,code:'CQ019203',freq:'每季度',run:'启用'},
|
||||
{id:4,code:'CQ027710',freq:'每半年',run:'暂停'},
|
||||
{id:5,code:'CQ021578',freq:'每季度',run:'启用'},
|
||||
{id:6,code:'CQ022317',freq:'每季度',run:'启用'},
|
||||
{id:7,code:'CQ036441',freq:'每月',run:'启用'}
|
||||
{id:1,code:'CQ033096',plan:'2026-09-20',actual:'',status:1},
|
||||
{id:2,code:'CQ010564',plan:'2026-09-10',actual:'',status:1},
|
||||
{id:3,code:'CQ029905',plan:'2026-08-30',actual:'',status:2},
|
||||
{id:4,code:'CQ027710',plan:'2026-08-25',actual:'2026-08-25',status:3}
|
||||
];
|
||||
/* 申请任务 */
|
||||
/* 申请巡诊任务 */
|
||||
var applyTasks=[
|
||||
{id:1,code:'CQ029905',content:'最近手脚麻木偶有发作,希望安排一次健康随访评估',date:'2026-09-02'},
|
||||
{id:2,code:'CQ044871',content:'体检报告提示脂肪肝,咨询是否需要纳入慢病随访管理',date:'2026-08-30'},
|
||||
{id:3,code:'CQ041822',content:'家人血压问题想约门诊随访指导家庭监测',date:'2026-09-04'}
|
||||
{id:1,code:'CQ029905',content:'最近手脚麻木偶有发作,希望安排一次健康随访评估',date:'2026-09-02',actual:'',status:1},
|
||||
{id:2,code:'CQ044871',content:'体检报告提示脂肪肝,咨询是否需要纳入慢病随访管理',date:'2026-08-30',actual:'',status:1},
|
||||
{id:3,code:'CQ041822',content:'家人血压问题想约门诊随访指导家庭监测',date:'2026-09-04',actual:'',status:2},
|
||||
{id:4,code:'CQ021578',content:'上次随访后血压仍偏高,申请复诊',date:'2026-08-20',actual:'2026-08-21',status:3}
|
||||
];
|
||||
/* 闫婷未入empPool简表,补基础字段 */
|
||||
empPool.push({code:'CQ041822',name:'闫婷',sex:'女',age:34,tel:'186****5527',unit:'第四采油厂',dept:'健康管理部',point:'西峰基地医疗点',group:'其他'});
|
||||
var nextId=99,curTab='once';
|
||||
var statusBadge={'待随访':'badge--warning','已完成':'badge--success','已逾期':'badge--danger','启用':'badge--success','暂停':'badge--muted'};
|
||||
/* 频次配置信息(人员类型=慢病类型,随访频次) */
|
||||
var freqConfig=[
|
||||
{code:'CQ033096',name:'赵万福',sex:'男',age:39,tel:'150****6127',unit:'采油二厂',point:'桐园作业区医疗点',group:'高血压',freq:'每月'},
|
||||
{code:'CQ010564',name:'高建军',sex:'男',age:50,tel:'139****0086',unit:'第四采油厂',point:'西峰基地医疗点',group:'糖尿病',freq:'每月'},
|
||||
{code:'CQ021578',name:'石维国',sex:'男',age:46,tel:'139****2051',unit:'采油一厂',point:'樊学作业区医疗点',group:'高血压',freq:'每季度'},
|
||||
{code:'CQ019203',name:'曲志明',sex:'男',age:42,tel:'137****8890',unit:'采油二厂',point:'姬圪台作业区医疗点',group:'冠心病',freq:'每季度'},
|
||||
{code:'CQ027710',name:'张秀兰',sex:'女',age:45,tel:'136****2248',unit:'采油二厂',point:'姬圪台作业区医疗点',group:'肥胖',freq:'每半年'},
|
||||
{code:'CQ022317',name:'徐立成',sex:'男',age:44,tel:'133****4860',unit:'采气一厂',point:'乌审旗采气区医疗点',group:'肥胖',freq:'每季度'},
|
||||
{code:'CQ036441',name:'刘玉梅',sex:'女',age:40,tel:'135****7719',unit:'采气一厂',point:'靖边气田医疗点',group:'高血压',freq:'每月'},
|
||||
{code:'CQ029905',name:'呼建国',sex:'男',age:36,tel:'147****9003',unit:'采气一厂',point:'靖边气田医疗点',group:'其他',freq:'每半年'}
|
||||
];
|
||||
var nextId=99,curTab='once',groupValue='0';
|
||||
var statusMap={1:'待随访',2:'已逾期',3:'已完成'};
|
||||
var statusBadge={1:'badge--warning',2:'badge--danger',3:'badge--success'};
|
||||
|
||||
/* ===== 单位部门双列筛选 ===== */
|
||||
var deptMap={
|
||||
@@ -433,7 +549,7 @@ function nowHM(){
|
||||
}
|
||||
function doExport(){
|
||||
exportLogs.unshift({file:'随访任务导出_'+nowHM()+'.xlsx',status:'ing',time:'—'});
|
||||
showToast('导出任务已提交,完成后可在「查看导出任务」下载');
|
||||
showToast('导出任务已提交,完成后可在「查看导出记录」下载');
|
||||
if(document.getElementById('exportDrawer').classList.contains('open'))renderExportList();
|
||||
setTimeout(function(){
|
||||
var e=exportLogs[0];
|
||||
@@ -459,17 +575,22 @@ function onFilterUnit(){
|
||||
sel.innerHTML='<option value="">全部医疗点</option>';
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
}
|
||||
function matchFilter(e){
|
||||
function matchTask(t){
|
||||
var e=E(t.code);
|
||||
var name=document.getElementById('filterName').value.trim();
|
||||
var unit=document.getElementById('filterUnit').value;
|
||||
var point=document.getElementById('filterPoint').value;
|
||||
var from=document.getElementById('filterFrom').value;
|
||||
var to=document.getElementById('filterTo').value;
|
||||
var plan=curTab==='apply'?t.date:t.plan;
|
||||
return (!name||e.name.indexOf(name)!==-1)
|
||||
&&(!selUnit||e.unit===selUnit)&&(!selDept||e.dept===selDept)
|
||||
&&(!unit||pointUnit[e.point]===unit)&&(!point||e.point===point);
|
||||
&&(!unit||pointUnit[e.point]===unit)&&(!point||e.point===point)
|
||||
&&(!from||plan>=from)&&(!to||plan<=to);
|
||||
}
|
||||
function currentOnce(){return onceTasks.filter(function(t){return matchFilter(E(t.code));});}
|
||||
function currentFreq(){return freqTasks.filter(function(t){return matchFilter(E(t.code));});}
|
||||
function currentApply(){return applyTasks.filter(function(t){return matchFilter(E(t.code));});}
|
||||
function currentOnce(){return onceTasks.filter(matchTask);}
|
||||
function currentFreq(){return freqTasks.filter(matchTask);}
|
||||
function currentApply(){return applyTasks.filter(matchTask);}
|
||||
|
||||
/* ===== Tab 与渲染 ===== */
|
||||
function switchTab(k){
|
||||
@@ -478,130 +599,209 @@ function switchTab(k){
|
||||
document.getElementById('tab'+p.charAt(0).toUpperCase()+p.slice(1)).classList.toggle('active',p===k);
|
||||
document.getElementById('pane'+p.charAt(0).toUpperCase()+p.slice(1)).style.display=p===k?'':'none';
|
||||
});
|
||||
document.getElementById('btnAdd').style.display=k==='once'?'':'none';
|
||||
document.getElementById('btnFreqCfg').style.display=k==='freq'?'':'none';
|
||||
document.getElementById('segNormal').style.display=k==='apply'?'none':'';
|
||||
document.getElementById('segApply').style.display=k==='apply'?'':'none';
|
||||
document.getElementById('filterDateItem').style.display=k==='apply'?'none':'';
|
||||
groupValue='0';
|
||||
document.querySelectorAll('#segNormal button,#segApply button').forEach(function(b){b.classList.toggle('active',b.getAttribute('data-v')==='0');});
|
||||
renderAll();
|
||||
}
|
||||
function setGroup(btn,v){
|
||||
groupValue=v;
|
||||
var seg=document.getElementById(curTab==='apply'?'segApply':'segNormal');
|
||||
seg.querySelectorAll('button').forEach(function(b){b.classList.toggle('active',b===btn);});
|
||||
renderAll();
|
||||
}
|
||||
function applyGroup(list){
|
||||
if(groupValue==='0')return list;
|
||||
return list.filter(function(t){return String(t.status)===groupValue;});
|
||||
}
|
||||
function empCells(e){
|
||||
return '<td style="font-weight:600;">'+e.name+'</td><td>'+e.code+'</td><td>'+e.sex+'</td><td>'+e.age+'</td>';
|
||||
return '<td style="font-weight:600;">'+e.name+'</td><td>'+e.sex+'</td><td>'+e.age+'</td><td>'+e.tel+'</td><td>'+e.unit+'</td><td>'+e.dept+'</td><td>'+e.point+'</td><td>'+pointUnit[e.point]+'</td>';
|
||||
}
|
||||
function statusCell(t){
|
||||
return '<td><span class="badge '+statusBadge[t.status]+'">'+statusMap[t.status]+'</span></td>';
|
||||
}
|
||||
function renderAll(){
|
||||
document.getElementById('cntOnce').textContent=currentOnce().length;
|
||||
document.getElementById('cntFreq').textContent=currentFreq().length;
|
||||
document.getElementById('cntApply').textContent=currentApply().length;
|
||||
var ol=currentOnce();
|
||||
var ol=applyGroup(currentOnce());
|
||||
document.getElementById('onceBody').innerHTML=ol.length?ol.map(function(t,i){
|
||||
var e=E(t.code);
|
||||
return '<tr><td>'+(i+1)+'</td>'+empCells(e)+'<td>'+e.tel+'</td><td>'+e.unit+'</td><td>'+e.dept+'</td>'
|
||||
+'<td><span class="chip">'+e.group+'</span></td><td>'+e.point+'</td>'
|
||||
+'<td>'+t.plan+'</td><td>'+(t.actual||'—')+'</td>'
|
||||
+'<td><span class="badge '+statusBadge[t.status]+'">'+t.status+'</span></td>'
|
||||
+'<td class="td-actions">'
|
||||
+(t.status==='待随访'||t.status==='已逾期'
|
||||
?'<button class="btn btn-link" onclick="execFollow()">执行随访</button><button class="btn btn-link btn-link--muted" onclick="showToast(\'任务说明:'+(t.note||'无')+'\')">说明</button>'
|
||||
:'<button class="btn btn-link" onclick="showToast(\'该任务已完成,随访结果见「随访管理」\')">查看结果</button>')
|
||||
+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="14" class="td-empty">暂无匹配任务</td></tr>';
|
||||
var fl=currentFreq();
|
||||
var act=actionsHtml(t,'once',e);
|
||||
return '<tr><td>'+(i+1)+'</td>'+empCells(e)+'<td>'+t.plan+'</td><td>'+(t.actual||'—')+'</td>'+statusCell(t)+act+'</tr>';
|
||||
}).join(''):'<tr><td colspan="13" class="td-empty">暂无匹配任务</td></tr>';
|
||||
var fl=applyGroup(currentFreq());
|
||||
document.getElementById('freqBody').innerHTML=fl.length?fl.map(function(t,i){
|
||||
var e=E(t.code);
|
||||
return '<tr><td>'+(i+1)+'</td>'+empCells(e)+'<td>'+e.unit+'</td><td>'+e.dept+'</td>'
|
||||
+'<td><span class="chip">'+e.group+'</span></td><td>'+t.freq+'</td><td>'+e.point+'</td>'
|
||||
+'<td><span class="badge '+statusBadge[t.run]+'">'+t.run+'</span></td>'
|
||||
+'<td class="td-actions">'
|
||||
+(t.run==='启用'
|
||||
?'<button class="btn btn-link" onclick="toggleFreq('+t.id+',\'暂停\')">暂停</button>'
|
||||
:'<button class="btn btn-link" onclick="toggleFreq('+t.id+',\'启用\')">启用</button>')
|
||||
+'<button class="btn btn-link" onclick="genOnce('+t.id+')">立即生成本期</button>'
|
||||
+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="12" class="td-empty">暂无匹配任务</td></tr>';
|
||||
var al=currentApply();
|
||||
var act=actionsHtml(t,'freq',e);
|
||||
return '<tr><td>'+(i+1)+'</td>'+empCells(e)+'<td>'+t.plan+'</td><td>'+(t.actual||'—')+'</td>'+statusCell(t)+act+'</tr>';
|
||||
}).join(''):'<tr><td colspan="13" class="td-empty">暂无匹配任务</td></tr>';
|
||||
var al=applyGroup(currentApply());
|
||||
document.getElementById('applyBody').innerHTML=al.length?al.map(function(t,i){
|
||||
var e=E(t.code);
|
||||
return '<tr><td>'+(i+1)+'</td>'+empCells(e)+'<td>'+e.unit+'</td><td>'+e.dept+'</td><td>'+e.point+'</td>'
|
||||
var act=actionsHtml(t,'apply',e);
|
||||
return '<tr><td>'+(i+1)+'</td>'+empCells(e)
|
||||
+'<td style="text-align:left;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" title="'+t.content+'">'+t.content+'</td>'
|
||||
+'<td>'+t.date+'</td>'
|
||||
+'<td class="td-actions">'
|
||||
+'<button class="btn btn-link" onclick="acceptApply('+t.id+')">接受</button>'
|
||||
+'<button class="btn btn-link btn-link--danger" onclick="rejectApply('+t.id+')">拒绝</button>'
|
||||
+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="11" class="td-empty">暂无待处理申请</td></tr>';
|
||||
+'<td>'+t.date+'</td><td>'+(t.actual||'—')+'</td>'+statusCell(t)+act+'</tr>';
|
||||
}).join(''):'<tr><td colspan="14" class="td-empty">暂无匹配任务</td></tr>';
|
||||
}
|
||||
/* 行操作:新增随访(待/逾期) / 编辑+删除(仅单次未完成) / 随访详情(已完成) */
|
||||
function actionsHtml(t,tab,e){
|
||||
var done=t.status===3;
|
||||
var html='<td class="td-actions">';
|
||||
if(done){
|
||||
html+='<button class="btn btn-link" onclick="viewDetail('+t.id+')">随访详情</button>';
|
||||
}else{
|
||||
html+='<button class="btn btn-link" onclick="addFollow()">新增随访</button>';
|
||||
if(tab==='once'){
|
||||
html+='<button class="btn btn-link" onclick="editTask('+t.id+')">编辑</button>';
|
||||
html+='<button class="btn btn-link btn-link--danger" onclick="askDelete('+t.id+')">删除</button>';
|
||||
}
|
||||
}
|
||||
html+='</td>';
|
||||
return html;
|
||||
}
|
||||
function applyFilter(){renderAll();}
|
||||
function resetFilter(){
|
||||
document.getElementById('filterName').value='';
|
||||
document.getElementById('filterUnit').value='';onFilterUnit();
|
||||
document.getElementById('filterFrom').value='';document.getElementById('filterTo').value='';
|
||||
resetOrg();
|
||||
applyFilter();
|
||||
}
|
||||
|
||||
/* ===== 任务操作 ===== */
|
||||
function execFollow(){
|
||||
/* [交互] 新增随访:跳转随访管理录入本次随访记录 */
|
||||
function addFollow(){
|
||||
showToast('正在跳转「随访管理」录入本次随访结果…');
|
||||
setTimeout(function(){location.href='daily-follow.html';},700);
|
||||
setTimeout(function(){location.href='daily-follow.html?action=new';},500);
|
||||
}
|
||||
function toggleFreq(id,val){
|
||||
var t=freqTasks.find(function(x){return x.id===id;});
|
||||
t.run=val;renderAll();
|
||||
showToast('「'+E(t.code).name+'」频次任务已'+val);
|
||||
/* [交互] 随访详情:跳转随访管理查看随访台账 */
|
||||
function viewDetail(id){
|
||||
showToast('正在跳转「随访管理」查看随访详情…');
|
||||
setTimeout(function(){location.href='daily-follow.html';},500);
|
||||
}
|
||||
function genOnce(id){
|
||||
var t=freqTasks.find(function(x){return x.id===id;});
|
||||
if(t.run==='暂停'){showToast('任务已暂停,请先启用');return;}
|
||||
var plan='2026-09-'+String(8+onceTasks.length%14).padStart(2,'0');
|
||||
onceTasks.push({id:nextId++,code:t.code,plan:plan,actual:'',status:'待随访',note:'由频次任务立即生成本期'});
|
||||
switchTab('once');
|
||||
showToast('已生成单次任务,计划日期 '+plan);
|
||||
var editingId=null,pendingDelId=null;
|
||||
function editTask(id){
|
||||
var t=onceTasks.find(function(x){return x.id===id;});
|
||||
var e=E(t.code);
|
||||
editingId=id;
|
||||
document.getElementById('taskTitle').textContent='编辑';
|
||||
document.getElementById('tEmp').value=e.name;
|
||||
document.getElementById('tEmpBtn').disabled=true;
|
||||
showEmpCard(e);
|
||||
document.getElementById('tDate').value=t.plan;
|
||||
document.getElementById('taskMask').classList.add('open');
|
||||
document.getElementById('taskDrawer').classList.add('open');
|
||||
}
|
||||
function acceptApply(id){
|
||||
var t=applyTasks.find(function(x){return x.id===id;});
|
||||
applyTasks=applyTasks.filter(function(x){return x.id!==id;});
|
||||
onceTasks.push({id:nextId++,code:t.code,plan:'2026-09-12',actual:'',status:'待随访',note:'员工申请:'+t.content});
|
||||
switchTab('once');
|
||||
showToast('已接受申请并转为单次任务(计划 2026-09-12)');
|
||||
function askDelete(id){
|
||||
pendingDelId=id;
|
||||
var t=onceTasks.find(function(x){return x.id===id;});
|
||||
var e=E(t.code);
|
||||
document.getElementById('delText').textContent='是否删除「'+e.name+'」的随访任务';
|
||||
document.getElementById('delMask').classList.add('open');
|
||||
}
|
||||
function rejectApply(id){
|
||||
var t=applyTasks.find(function(x){return x.id===id;});
|
||||
applyTasks=applyTasks.filter(function(x){return x.id!==id;});
|
||||
function confirmDelete(){
|
||||
onceTasks=onceTasks.filter(function(t){return t.id!==pendingDelId;});
|
||||
closeModal('delMask');
|
||||
renderAll();
|
||||
showToast('已拒绝「'+E(t.code).name+'」的随访申请');
|
||||
showToast('随访任务已删除');
|
||||
}
|
||||
|
||||
/* ===== 新建任务 ===== */
|
||||
function fillEmpSel(){
|
||||
var sel=document.getElementById('cEmp');
|
||||
sel.innerHTML='<option value="">请选择员工</option>';
|
||||
empPool.forEach(function(e){
|
||||
var o=document.createElement('option');o.value=e.code;o.textContent=e.name+'('+e.code+' · '+e.point+')';
|
||||
sel.appendChild(o);
|
||||
});
|
||||
}
|
||||
function onTypeRadio(){
|
||||
var v=document.querySelector('input[name="cType"]:checked').value;
|
||||
document.getElementById('boxOnceDate').style.display=v==='once'?'':'none';
|
||||
document.getElementById('boxFreq').style.display=v==='freq'?'':'none';
|
||||
/* ===== 新增/编辑任务抽屉 ===== */
|
||||
var curPickEmp=null;
|
||||
function showEmpCard(e){
|
||||
var card=document.getElementById('tEmpCard');
|
||||
if(!e){card.style.display='none';return;}
|
||||
card.style.display='grid';
|
||||
card.innerHTML='<div>性别<b>'+e.sex+'</b></div><div>年龄<b>'+e.age+'</b></div><div>联系电话<b>'+e.tel+'</b></div><div>身份证<b>'+e.idcard+'</b></div><div>慢病类型<b>'+e.group+'</b></div><div>所属单位<b>'+e.unit+'</b></div><div>所属部门<b>'+e.dept+'</b></div>';
|
||||
}
|
||||
function openCreate(){
|
||||
document.getElementById('cEmp').value='';
|
||||
document.getElementById('cDate').value='2026-09-15';
|
||||
document.getElementById('cNote').value='';
|
||||
document.querySelector('input[name="cType"][value="once"]').checked=true;
|
||||
onTypeRadio();
|
||||
document.getElementById('createMask').classList.add('open');
|
||||
editingId=null;
|
||||
curPickEmp=null;
|
||||
document.getElementById('taskTitle').textContent='新增';
|
||||
document.getElementById('tEmp').value='';
|
||||
document.getElementById('tEmpBtn').disabled=false;
|
||||
showEmpCard(null);
|
||||
document.getElementById('tDate').value='2026-09-15';
|
||||
document.getElementById('taskMask').classList.add('open');
|
||||
document.getElementById('taskDrawer').classList.add('open');
|
||||
}
|
||||
function saveCreate(){
|
||||
var code=document.getElementById('cEmp').value;
|
||||
if(!code){showToast('请选择随访员工');return;}
|
||||
var type=document.querySelector('input[name="cType"]:checked').value;
|
||||
if(type==='once'){
|
||||
var date=document.getElementById('cDate').value;
|
||||
if(!date){showToast('请选择计划随访日期');return;}
|
||||
onceTasks.push({id:nextId++,code:code,plan:date,actual:'',status:'待随访',note:document.getElementById('cNote').value});
|
||||
closeModal('createMask');switchTab('once');
|
||||
showToast('单次任务已创建');
|
||||
function saveTask(){
|
||||
if(!editingId&&!curPickEmp){showToast('请选择随访员工');return;}
|
||||
var date=document.getElementById('tDate').value;
|
||||
if(!date){showToast('请选择随访日期');return;}
|
||||
if(editingId){
|
||||
var t=onceTasks.find(function(x){return x.id===editingId;});
|
||||
t.plan=date;
|
||||
showToast('随访任务已更新');
|
||||
}else{
|
||||
freqTasks.push({id:nextId++,code:code,freq:document.getElementById('cFreq').value,run:'启用'});
|
||||
closeModal('createMask');switchTab('freq');
|
||||
showToast('频次任务已创建并启用');
|
||||
onceTasks.push({id:nextId++,code:curPickEmp.code,plan:date,actual:'',status:1});
|
||||
showToast('随访任务已创建');
|
||||
}
|
||||
closeDrawer('task');
|
||||
switchTab('once');
|
||||
renderAll();
|
||||
}
|
||||
|
||||
/* ===== 选择员工弹窗 ===== */
|
||||
function openEmpPick(){
|
||||
document.getElementById('empQ').value='';
|
||||
renderEmpPick();
|
||||
document.getElementById('empPickMask').classList.add('open');
|
||||
}
|
||||
function renderEmpPick(){
|
||||
var q=document.getElementById('empQ').value.trim();
|
||||
var list=empPool.filter(function(e){return !q||e.name.indexOf(q)!==-1||e.code.toLowerCase().indexOf(q.toLowerCase())!==-1;});
|
||||
document.getElementById('empPickBody').innerHTML=list.length?list.map(function(e){
|
||||
return '<tr><td><input type="radio" name="empSel" value="'+e.code+'"></td>'
|
||||
+'<td style="font-weight:600;">'+e.name+'</td><td>'+e.code+'</td><td>'+e.sex+'</td><td>'+e.age+'</td><td>'+e.unit+'</td><td>'+e.point+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="7" class="td-empty">未找到匹配员工</td></tr>';
|
||||
}
|
||||
function confirmEmpPick(){
|
||||
var r=document.querySelector('input[name="empSel"]:checked');
|
||||
if(!r){showToast('请选择一名员工');return;}
|
||||
curPickEmp=empPool.find(function(x){return x.code===r.value;});
|
||||
document.getElementById('tEmp').value=curPickEmp.name;
|
||||
showEmpCard(curPickEmp);
|
||||
closeModal('empPickMask');
|
||||
}
|
||||
|
||||
/* ===== 频次配置信息弹窗 ===== */
|
||||
function openFreqConfig(){
|
||||
document.getElementById('fcName').value='';
|
||||
document.getElementById('fcUnit').value='';
|
||||
document.getElementById('fcPoint').innerHTML='<option value="">全部医疗点</option>';
|
||||
renderFreqConfig();
|
||||
document.getElementById('freqCfgMask').classList.add('open');
|
||||
}
|
||||
function onFcUnit(){
|
||||
var unit=document.getElementById('fcUnit').value;
|
||||
var sel=document.getElementById('fcPoint');
|
||||
sel.innerHTML='<option value="">全部医疗点</option>';
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
}
|
||||
function renderFreqConfig(){
|
||||
var name=document.getElementById('fcName').value.trim();
|
||||
var unit=document.getElementById('fcUnit').value;
|
||||
var point=document.getElementById('fcPoint').value;
|
||||
var list=freqConfig.filter(function(c){
|
||||
return (!name||c.name.indexOf(name)!==-1)
|
||||
&&(!unit||c.unit===unit)&&(!point||c.point===point);
|
||||
});
|
||||
document.getElementById('fcBody').innerHTML=list.length?list.map(function(c,i){
|
||||
return '<tr><td>'+(i+1)+'</td><td style="font-weight:600;">'+c.name+'</td><td>'+c.code+'</td><td>'+c.sex+'</td><td>'+c.age+'</td><td>'+c.tel+'</td><td>'+c.unit+'</td><td>'+c.point+'</td><td><span class="badge badge--muted">'+c.group+'</span></td><td>'+c.freq+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="10" class="td-empty">暂无频次配置</td></tr>';
|
||||
}
|
||||
function resetFreqConfig(){
|
||||
document.getElementById('fcName').value='';
|
||||
document.getElementById('fcUnit').value='';
|
||||
document.getElementById('fcPoint').innerHTML='<option value="">全部医疗点</option>';
|
||||
renderFreqConfig();
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
@@ -611,8 +811,7 @@ function showToast(msg){
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
|
||||
fillEmpSel();
|
||||
renderAll();
|
||||
switchTab('once');
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -163,13 +163,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item active">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -822,6 +816,11 @@ function showToast(msg){
|
||||
}
|
||||
|
||||
renderTable();
|
||||
/* [交互] 从随访任务页跳转:?action=new 自动打开新增随访抽屉 */
|
||||
(function(){
|
||||
var q=new URLSearchParams(location.search);
|
||||
if(q.get('action')==='new'){ setTimeout(function(){ openForm(); },100); }
|
||||
})();
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -55,6 +55,16 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.org-item{padding:8px 12px;font-size:var(--font-sm);color:var(--text-primary);cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:4px;}
|
||||
.org-item:hover{background:#F0F8FF;color:var(--primary);}
|
||||
.org-item.active{background:var(--primary-light);color:var(--primary);font-weight:500;}
|
||||
.drawer-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:900;}
|
||||
.drawer-mask.open{display:block;}
|
||||
.drawer{position:fixed;top:56px;right:-760px;bottom:0;width:720px;background:#fff;z-index:910;box-shadow:-8px 0 24px rgba(0,0,0,.12);transition:right .25s ease;display:flex;flex-direction:column;}
|
||||
.drawer.open{right:0;}
|
||||
.drawer--narrow{width:640px;right:-680px;}
|
||||
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-lg);font-weight:600;flex-shrink:0;}
|
||||
.drawer__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.drawer__close:hover{color:var(--text-primary);}
|
||||
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
|
||||
.drawer__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.mini-table{width:100%;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;min-width:0;}
|
||||
.mini-table thead th{background:#FAFAFA;position:sticky;top:0;font-size:var(--font-sm);}
|
||||
.mini-table td{white-space:normal;font-size:var(--font-sm);}
|
||||
@@ -62,7 +72,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.action-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;background:#fff;margin-top:16px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.action-bar{display:flex;align-items:center;gap:8px;padding:12px 24px;background:#fff;margin-top:16px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1550px;}
|
||||
@@ -87,28 +97,42 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.page-btn:disabled{opacity:.4;cursor:not-allowed;background:#fff;color:var(--text-placeholder);border-color:var(--border);}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
.drawer-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:900;}
|
||||
.drawer-mask.open{display:block;}
|
||||
.drawer{position:fixed;top:56px;right:-760px;bottom:0;width:720px;background:#fff;z-index:910;box-shadow:-8px 0 24px rgba(0,0,0,.12);transition:right .25s ease;display:flex;flex-direction:column;}
|
||||
.drawer.open{right:0;}
|
||||
.drawer--narrow{width:640px;right:-680px;}
|
||||
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-lg);font-weight:600;flex-shrink:0;}
|
||||
.drawer__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.drawer__close:hover{color:var(--text-primary);}
|
||||
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
|
||||
.drawer__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 12px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid var(--border);}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:110px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:440px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:8px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;}
|
||||
.modal--wide{width:1240px;max-width:96vw;max-height:90vh;display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);}
|
||||
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-base);font-weight:600;flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.modal__close:hover{color:var(--text-primary);}
|
||||
.modal__body{flex:1;overflow-y:auto;padding:20px 24px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
/* 详情弹窗左右两栏 */
|
||||
.report-cols{display:flex;gap:0;height:calc(90vh - 130px);}
|
||||
.report-cols__left{width:50%;overflow-y:auto;padding-right:20px;border-right:1px dashed var(--border);}
|
||||
.report-cols__right{width:50%;overflow-y:auto;padding-left:20px;}
|
||||
.report-title{font-size:var(--font-base);font-weight:700;padding:10px 0 10px 12px;position:relative;margin-top:4px;}
|
||||
.report-title::before{content:'';position:absolute;left:0;top:13px;width:6px;height:18px;background:#E3CB2C;border-radius:2px;}
|
||||
.report-sub{font-size:var(--font-sm);color:var(--text-secondary);line-height:1.7;padding:0 12px 8px;}
|
||||
.report-group{margin-top:16px;}
|
||||
.report-group__name{font-weight:700;font-size:var(--font-base);padding:10px 12px;background:#F6F6F6;border-radius:var(--radius-sm) var(--radius-sm) 0 0;}
|
||||
.report-cat{padding-left:20px;}
|
||||
.report-cat__name{font-size:var(--font-sm);font-weight:700;padding:10px 0 8px 12px;position:relative;}
|
||||
.report-cat__name::before{content:'';position:absolute;left:0;top:12px;width:6px;height:16px;background:#02C2A6;border-radius:2px;}
|
||||
.report-ul{padding:0;margin:0;width:100%;display:flex;}
|
||||
.report-ul li{flex:1;text-align:center;padding:6px 0;font-size:var(--font-sm);border:1px solid #E6E6E6;border-left:none;border-top:none;}
|
||||
.report-ul li:first-child{border-left:1px solid #E6E6E6;}
|
||||
.report-ul.report-ul--head{font-weight:700;}
|
||||
.report-ul.report-ul--head li{background:#F0F2FF;}
|
||||
.report-ul.report-ul--head li:first-child{background:#F0F2FF;}
|
||||
.report-ul:not(.report-ul--head) li:first-child{background:#F6F6F6;}
|
||||
.emp-basic{display:flex;flex-wrap:wrap;gap:4px 0;}
|
||||
.emp-basic div{font-size:var(--font-sm);color:var(--text-secondary);padding:4px 0;}
|
||||
.emp-basic b{color:var(--text-primary);font-weight:600;}
|
||||
.emp-basic .w25{width:25%;}
|
||||
.emp-basic .w50{width:50%;}
|
||||
.emp-basic .w100{width:100%;}
|
||||
.advise-box{background:#F4F4F4;border-radius:var(--radius-sm);padding:10px;font-size:var(--font-sm);line-height:1.7;color:var(--text-primary);min-height:88px;}
|
||||
.sign-box{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:16px;text-align:center;min-height:100px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;}
|
||||
.group-badge{display:inline-block;padding:2px 12px;border-radius:10px;font-size:var(--font-sm);font-weight:600;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -141,13 +165,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -168,8 +186,12 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<!-- [交互] 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>员工姓名/工号</label>
|
||||
<input class="filter-input" id="filterName" placeholder="请输入姓名或工号">
|
||||
<label>员工姓名</label>
|
||||
<input class="filter-input" id="filterName" placeholder="请输入姓名">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>工号</label>
|
||||
<input class="filter-input" id="filterCode" placeholder="请输入工号" style="min-width:110px;">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>员工所属单位</label>
|
||||
@@ -224,8 +246,12 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
|
||||
<!-- [交互] 操作栏 -->
|
||||
<div class="action-bar">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
<button class="btn btn-primary" onclick="doExport()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="openExport()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出记录
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
@@ -234,7 +260,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<table>
|
||||
<thead>
|
||||
<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><th>操作</th>
|
||||
<th>序号</th><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="tableBody"></tbody>
|
||||
@@ -250,29 +276,51 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 解读归档详情抽屉 -->
|
||||
<div class="drawer-mask" id="viewMask" onclick="closeDrawer('view')"></div>
|
||||
<div class="drawer" id="viewDrawer">
|
||||
<div class="drawer__header"><span id="viewTitle">解读归档详情</span><button class="drawer__close" onclick="closeDrawer('view')">×</button></div>
|
||||
<div class="drawer__body" id="viewBody"></div>
|
||||
<div class="drawer__footer">
|
||||
<button class="btn btn-default" onclick="closeDrawer('view')">关闭</button>
|
||||
<button class="btn btn-primary" id="viewSignBtn" onclick="openSign()">查看员工签字</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 员工签字弹窗 -->
|
||||
<div class="modal-mask" id="signMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title">员工确认签字</div>
|
||||
<div id="signHolder" style="border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px;text-align:center;"></div>
|
||||
<!-- [交互] 解读详情弹窗(左右两栏) -->
|
||||
<div class="modal-mask" id="detailMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal__header"><span id="detailTitle">解读详情</span><button class="modal__close" onclick="closeModal('detailMask')">×</button></div>
|
||||
<div class="modal__body" style="padding:0;">
|
||||
<div class="report-cols">
|
||||
<div class="report-cols__left">
|
||||
<div class="report-title">体检结论</div>
|
||||
<div class="report-sub" id="dConclusion"></div>
|
||||
<div class="report-title">体检建议</div>
|
||||
<div class="report-sub" id="dSuggest"></div>
|
||||
<div id="dReport"></div>
|
||||
</div>
|
||||
<div class="report-cols__right">
|
||||
<div class="report-title">员工基本信息</div>
|
||||
<div class="emp-basic" id="dEmp"></div>
|
||||
<div class="report-title">综合解读建议</div>
|
||||
<div class="advise-box" id="dAdvise"></div>
|
||||
<div class="report-title">五类人群重新分布</div>
|
||||
<div style="display:flex;padding:6px 0 10px;gap:16px;">
|
||||
<span id="dGroupBefore" style="font-size:var(--font-sm);color:var(--text-secondary);"></span>
|
||||
<span id="dGroupAfter" style="font-size:var(--font-sm);color:var(--text-secondary);"></span>
|
||||
</div>
|
||||
<div class="report-title">员工确认签字</div>
|
||||
<div id="dSign"></div>
|
||||
<div style="display:flex;width:100%;margin-top:16px;">
|
||||
<div style="width:50%;">
|
||||
<div class="report-title" style="margin-top:0;">解读医生</div>
|
||||
<div style="padding-left:12px;" id="dDoctor"></div>
|
||||
</div>
|
||||
<div style="width:50%;">
|
||||
<div class="report-title" style="margin-top:0;">解读日期</div>
|
||||
<div style="padding-left:12px;" id="dDate"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('signMask')">关闭</button>
|
||||
<button class="btn btn-default" onclick="closeModal('detailMask')">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导出任务抽屉(异步导出任务列表) -->
|
||||
<!-- [交互] 导出任务抽屉 -->
|
||||
<div class="drawer-mask" id="exportMask" onclick="closeDrawer('export')"></div>
|
||||
<div class="drawer drawer--narrow" id="exportDrawer">
|
||||
<div class="drawer__header"><span>导出任务</span><button class="drawer__close" onclick="closeDrawer('export')">×</button></div>
|
||||
@@ -288,32 +336,45 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* ===== 演示数据(脱敏):仅已完成解读的归档记录,与「解读任务」页同源 ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂'};
|
||||
/* ===== 演示数据(脱敏):仅已完成解读的归档记录 ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂','姬塬作业区医疗点':'采油一厂'};
|
||||
var pointMap={
|
||||
'采油一厂':['樊学作业区医疗点','安塞采油队长住点医疗室','姬塬作业区医疗点'],
|
||||
'采油二厂':['姬圪台作业区医疗点','桐园作业区医疗点'],
|
||||
'第四采油厂':['西峰基地医疗点'],
|
||||
'采气一厂':['靖边气田医疗点','乌审旗采气区医疗点']
|
||||
};
|
||||
var groupBadge={'健康人群':'badge--success','亚健康人群':'badge--info','慢性病风险人群':'badge--warning','已确诊慢病人群':'badge--danger','突发风险人群':'badge--danger'};
|
||||
var GROUP_MAP={a:'大病-A类',b:'慢病-B类',c:'异常-C类',d:'风险-D类',e:'健康-E类'};
|
||||
var GROUP_BADGE={a:'#CF1322',b:'#FA8C16',c:'#D48806',d:'#096DD9',e:'#389E0D'};
|
||||
var CHRONIC={'CQ033096':'高血压','CQ010564':'糖尿病','CQ019203':'冠心病','CQ021578':'高血压','CQ027710':'肥胖','CQ036441':'高血压','CQ022317':'肥胖','CQ029905':'无','CQ044871':'无','CQ041822':'无','CQ032144':'无','CQ045130':'无'};
|
||||
var records=[
|
||||
{id:1,code:'CQ033096',name:'赵万福',sex:'男',age:39,unit:'采油二厂',dept:'桐园作业区',point:'桐园作业区医疗点',year:'2026',doctor:'曲志明',date:'2026-09-06',
|
||||
summary:'血压 158/96mmHg;BMI 27.1;血脂轻度异常;心电正常',advise:'高血压2级合并超重,已纳入慢病管理;建议低盐减重、规律服药并每月随访。',group:'已确诊慢病人群'},
|
||||
{id:2,code:'CQ010564',name:'高建军',sex:'男',age:50,unit:'第四采油厂',dept:'基地管理处',point:'西峰基地医疗点',year:'2026',doctor:'闫婷',date:'2026-08-30',
|
||||
summary:'空腹血糖 8.9mmol/L;糖化 7.8%;BMI 27.6;轻度脂肪肝',advise:'2型糖尿病诊断明确,转内分泌专科复核用药方案;双周随访控制血糖。',group:'已确诊慢病人群'},
|
||||
{id:3,code:'CQ032144',name:'李桂芳',sex:'女',age:38,unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',doctor:'李桂芳',date:'2026-09-02',
|
||||
summary:'各项指标基本正常;维生素D偏低',advise:'健康状况良好,补充维生素D并保持运动习惯。',group:'健康人群'},
|
||||
{id:4,code:'CQ045130',name:'杨慧敏',sex:'女',age:33,unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',doctor:'石维国',date:'2026-09-04',
|
||||
summary:'血常规轻度贫血;余正常',advise:'轻度缺铁性贫血,加强营养,三个月复查血常规。',group:'亚健康人群'},
|
||||
{id:5,code:'CQ029905',name:'呼建国',sex:'男',age:36,unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',year:'2025',doctor:'刘玉梅',date:'2025-11-20',
|
||||
summary:'颈椎退变;尿酸 455μmol/L',advise:'颈椎病干预与尿酸管理,控制高嘌呤饮食,年度复查。',group:'慢性病风险人群'},
|
||||
{id:6,code:'CQ019203',name:'曲志明',sex:'男',age:42,unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',year:'2025',doctor:'张秀兰',date:'2025-11-06',
|
||||
summary:'冠心病病史;LDL-C 4.1mmol/L',advise:'冠心病二级预防,强化降脂,随身携带急救药物。',group:'已确诊慢病人群'},
|
||||
{id:7,code:'CQ022317',name:'徐立成',sex:'男',age:44,unit:'采气一厂',dept:'苏里格南作业区',point:'乌审旗采气区医疗点',year:'2025',doctor:'刘玉梅',date:'2025-10-28',
|
||||
summary:'BMI 26.8;尿酸 438μmol/L;血压正常高值',advise:'体重与尿酸共管,清淡饮食,多饮水。',group:'慢性病风险人群'}
|
||||
{id:1,code:'CQ033096',name:'赵万福',sex:'男',age:39,unit:'采油二厂',dept:'桐园作业区',point:'桐园作业区医疗点',year:'2026',doctor:'曲志明',date:'2026-09-06',summary:'血压 158/96mmHg;BMI 27.1;血脂轻度异常;心电正常',advise:'高血压2级合并超重,已纳入慢病管理;建议低盐减重、规律服药并每月随访。',group:'b',beforeGroup:'d'},
|
||||
{id:2,code:'CQ010564',name:'高建军',sex:'男',age:50,unit:'第四采油厂',dept:'基地管理处',point:'西峰基地医疗点',year:'2026',doctor:'闫婷',date:'2026-08-30',summary:'空腹血糖 8.9mmol/L;糖化 7.8%;BMI 27.6;轻度脂肪肝',advise:'2型糖尿病诊断明确,转内分泌专科复核用药方案;双周随访控制血糖。',group:'b',beforeGroup:'c'},
|
||||
{id:3,code:'CQ032144',name:'李桂芳',sex:'女',age:38,unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',doctor:'李桂芳',date:'2026-09-02',summary:'各项指标基本正常;维生素D偏低',advise:'健康状况良好,补充维生素D并保持运动习惯。',group:'e',beforeGroup:'e'},
|
||||
{id:4,code:'CQ045130',name:'杨慧敏',sex:'女',age:33,unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',doctor:'石维国',date:'2026-09-04',summary:'血常规轻度贫血;余正常',advise:'轻度缺铁性贫血,加强营养,三个月复查血常规。',group:'c',beforeGroup:'e'},
|
||||
{id:5,code:'CQ029905',name:'呼建国',sex:'男',age:36,unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',year:'2025',doctor:'刘玉梅',date:'2025-11-20',summary:'颈椎退变;尿酸 455μmol/L',advise:'颈椎病干预与尿酸管理,控制高嘌呤饮食,年度复查。',group:'d',beforeGroup:'d'},
|
||||
{id:6,code:'CQ019203',name:'曲志明',sex:'男',age:42,unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',year:'2025',doctor:'张秀兰',date:'2025-11-06',summary:'冠心病病史;LDL-C 4.1mmol/L',advise:'冠心病二级预防,强化降脂,随身携带急救药物。',group:'b',beforeGroup:'b'},
|
||||
{id:7,code:'CQ022317',name:'徐立成',sex:'男',age:44,unit:'采气一厂',dept:'苏里格南作业区',point:'乌审旗采气区医疗点',year:'2025',doctor:'刘玉梅',date:'2025-10-28',summary:'BMI 26.8;尿酸 438μmol/L;血压正常高值',advise:'体重与尿酸共管,清淡饮食,多饮水。',group:'d',beforeGroup:'d'}
|
||||
];
|
||||
|
||||
/* 体检报告明细模板 */
|
||||
function buildReport(r){
|
||||
return {
|
||||
conclusion: r.summary,
|
||||
suggest: '结合既往史与生活方式,建议定期复查并保持健康管理。',
|
||||
groups: [
|
||||
{analysisName:'一般检查', cats:[
|
||||
{cls:'体格检查', rows:[{name:'血压',result:'128/82',unit:'mmHg',ref:'<140/90'},{name:'心率',result:'74',unit:'次/分',ref:'60-100'}]},
|
||||
{cls:'人体测量', rows:[{name:'身高',result:'172',unit:'cm',ref:''},{name:'体重',result:'78',unit:'kg',ref:''},{name:'BMI',result:'26.4',unit:'',ref:'18.5-23.9'},{name:'腰围',result:'88',unit:'cm',ref:'<85'}]}
|
||||
]},
|
||||
{analysisName:'实验室检查', cats:[
|
||||
{cls:'血常规', rows:[{name:'白细胞',result:'6.1',unit:'×10⁹/L',ref:'3.5-9.5'},{name:'血红蛋白',result:'142',unit:'g/L',ref:'130-175'},{name:'血小板',result:'235',unit:'×10⁹/L',ref:'125-350'}]},
|
||||
{cls:'生化检验', rows:[{name:'空腹血糖',result:'5.8',unit:'mmol/L',ref:'3.9-6.1'},{name:'总胆固醇',result:'5.6',unit:'mmol/L',ref:'<5.2'},{name:'甘油三酯',result:'1.7',unit:'mmol/L',ref:'<1.7'},{name:'尿酸',result:'398',unit:'μmol/L',ref:'208-428'}]}
|
||||
]}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/* ===== 单位部门双列筛选 ===== */
|
||||
var deptMap={
|
||||
'采油一厂':['樊学作业区','采油大队','安全环保科','生产技术部','工会办公室'],
|
||||
@@ -358,6 +419,11 @@ var exportLogs=[
|
||||
{file:'解读归档台账导出_2026-08-25 10:52.xlsx',status:'done',time:'2026-08-25 10:52'},
|
||||
{file:'解读归档台账导出_2026-08-09 16:07.xlsx',status:'fail',time:'2026-08-09 16:07'}
|
||||
];
|
||||
function exportStatusHtml(s){
|
||||
if(s==='done')return '<span class="badge badge--success">已生成</span>';
|
||||
if(s==='fail')return '<span class="badge badge--danger">生成失败</span>';
|
||||
return '<span class="badge badge--warning">生成中</span>';
|
||||
}
|
||||
function renderExportList(){
|
||||
var body=document.getElementById('exportBody');
|
||||
body.innerHTML=exportLogs.map(function(e){
|
||||
@@ -367,23 +433,22 @@ function renderExportList(){
|
||||
return '<tr><td style="text-align:left;">'+e.file+'</td><td>'+exportStatusHtml(e.status)+'</td><td>'+e.time+'</td><td>'+act+'</td></tr>';
|
||||
}).join('')||'<tr><td colspan="4" class="td-empty">暂无导出任务</td></tr>';
|
||||
}
|
||||
function exportStatusHtml(s){
|
||||
if(s==='done')return '<span class="badge badge--success">已生成</span>';
|
||||
if(s==='fail')return '<span class="badge badge--danger">生成失败</span>';
|
||||
return '<span class="badge badge--warning">生成中</span>';
|
||||
}
|
||||
function openExport(){
|
||||
renderExportList();
|
||||
document.getElementById('exportMask').classList.add('open');
|
||||
document.getElementById('exportDrawer').classList.add('open');
|
||||
}
|
||||
function closeDrawer(k){
|
||||
document.getElementById(k+'Mask').classList.remove('open');
|
||||
document.getElementById(k+'Drawer').classList.remove('open');
|
||||
}
|
||||
function nowHM(){
|
||||
var d=new Date(),p=function(n){return (n<10?'0':'')+n;};
|
||||
return '2026-09-07 '+p(d.getHours())+':'+p(d.getMinutes());
|
||||
}
|
||||
function doExport(){
|
||||
exportLogs.unshift({file:'解读归档台账导出_'+nowHM()+'.xlsx',status:'ing',time:'—'});
|
||||
showToast('导出任务已提交,完成后可在「查看导出任务」下载');
|
||||
showToast('导出任务已提交,完成后可在「查看导出记录」下载');
|
||||
if(document.getElementById('exportDrawer').classList.contains('open'))renderExportList();
|
||||
setTimeout(function(){
|
||||
var e=exportLogs[0];
|
||||
@@ -411,14 +476,16 @@ function onFilterUnit(){
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
}
|
||||
function currentData(){
|
||||
var q=document.getElementById('filterName').value.trim();
|
||||
var name=document.getElementById('filterName').value.trim();
|
||||
var code=document.getElementById('filterCode').value.trim();
|
||||
var unit=document.getElementById('filterUnit').value;
|
||||
var point=document.getElementById('filterPoint').value;
|
||||
var year=document.getElementById('filterYear').value;
|
||||
var from=document.getElementById('filterFrom').value;
|
||||
var to=document.getElementById('filterTo').value;
|
||||
return records.filter(function(r){
|
||||
return (!q||r.name.indexOf(q)!==-1||r.code.toLowerCase().indexOf(q.toLowerCase())!==-1)
|
||||
return (!name||r.name.indexOf(name)!==-1)
|
||||
&&(!code||r.code.toLowerCase().indexOf(code.toLowerCase())!==-1)
|
||||
&&(!selUnit||r.unit===selUnit)&&(!selDept||r.dept===selDept)
|
||||
&&(!unit||pointUnit[r.point]===unit)&&(!point||r.point===point)&&(!year||r.year===year)
|
||||
&&(!from||r.date>=from)&&(!to||r.date<=to);
|
||||
@@ -442,8 +509,7 @@ function renderTable(){
|
||||
+'<td>'+r.code+'</td><td>'+r.sex+'</td><td>'+r.age+'</td><td>'+r.unit+'</td><td>'+r.dept+'</td>'
|
||||
+'<td>'+r.point+'</td><td>'+pointUnit[r.point]+'</td><td>'+r.year+'</td><td>'+r.doctor+'</td><td>'+r.date+'</td>'
|
||||
+'<td class="td-actions">'
|
||||
+'<button class="btn btn-link" onclick="openView('+r.id+')">详情</button>'
|
||||
+'<button class="btn btn-link" onclick="openView('+r.id+',true)">签字</button>'
|
||||
+'<button class="btn btn-link" onclick="openDetail('+r.id+')">解读详情</button>'
|
||||
+'</td></tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
@@ -451,6 +517,7 @@ function renderTable(){
|
||||
function applyFilter(){currentPage=1;renderTable();}
|
||||
function resetFilter(){
|
||||
document.getElementById('filterName').value='';
|
||||
document.getElementById('filterCode').value='';
|
||||
document.getElementById('filterUnit').value='';onFilterUnit();
|
||||
document.getElementById('filterYear').value='';
|
||||
document.getElementById('filterFrom').value='';document.getElementById('filterTo').value='';
|
||||
@@ -463,35 +530,51 @@ function turnPage(d){
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ===== 详情抽屉 ===== */
|
||||
var curViewId=null;
|
||||
function openView(id,signFirst){
|
||||
var r=records.find(function(x){return x.id===id;});
|
||||
curViewId=id;
|
||||
document.getElementById('viewTitle').textContent='解读归档详情 · '+r.name;
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v||'—')+'</div></div>';}
|
||||
document.getElementById('viewBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">员工基本信息</div>'
|
||||
+'<div class="detail-grid">'+d('姓名',r.name)+d('员工编号',r.code)+d('性别/年龄',r.sex+' / '+r.age+'岁')+d('单位/部门',r.unit+' / '+r.dept)+d('分配医疗点',r.point)+d('医疗点单位',pointUnit[r.point])+d('体检年份',r.year+'年度体检报告')+d('解读医生',r.doctor)+d('解读日期',r.date)+'</div>'
|
||||
+'<div class="form-section">解读结论</div>'
|
||||
+'<div class="detail-grid">'+d('报告异常摘要',r.summary,true)+d('综合解读建议',r.advise,true)+d('五类人群分类','<span class="badge '+(groupBadge[r.group]||'badge--muted')+'">'+r.group+'</span>',true)+'</div>';
|
||||
document.getElementById('viewMask').classList.add('open');
|
||||
document.getElementById('viewDrawer').classList.add('open');
|
||||
if(signFirst){openSign();}
|
||||
/* ===== 详情弹窗 ===== */
|
||||
function renderReportHtml(report){
|
||||
if(!report.groups||!report.groups.length)return '<div class="td-empty">暂无体检数据</div>';
|
||||
var html='';
|
||||
report.groups.forEach(function(g){
|
||||
html+='<div class="report-group"><div class="report-group__name">'+g.analysisName+'</div>';
|
||||
g.cats.forEach(function(c){
|
||||
html+='<div class="report-cat"><div class="report-cat__name">'+c.cls+'</div>';
|
||||
html+='<ul class="report-ul report-ul--head"><li>名称</li><li>结果</li><li>单位</li><li>参考值</li></ul>';
|
||||
c.rows.forEach(function(row){
|
||||
html+='<ul class="report-ul"><li>'+row.name+'</li><li>'+row.result+'</li><li>'+row.unit+'</li><li>'+row.ref+'</li></ul>';
|
||||
});
|
||||
html+='</div>';
|
||||
});
|
||||
html+='</div>';
|
||||
});
|
||||
return html;
|
||||
}
|
||||
function openSign(){
|
||||
var r=records.find(function(x){return x.id===curViewId;});
|
||||
document.getElementById('signHolder').innerHTML=
|
||||
'<svg width="200" height="64" viewBox="0 0 200 64"><path d="M14 46c16-28 22 18 36-10 10-22 16 26 30-4 9-18 14 16 24-4 8-16 14 12 26 4 12-6 24 8 38 2" stroke="#14213D" stroke-width="2.4" fill="none" stroke-linecap="round"/></svg>'
|
||||
+'<div style="font-size:var(--font-xs);color:var(--text-placeholder);margin-top:8px;">'+r.name+' · '+r.date+' 于 PAD 端确认签字(电子签名哈希存证)</div>';
|
||||
document.getElementById('signMask').classList.add('open');
|
||||
function empBasicHtml(r){
|
||||
return '<div class="w25">姓名<b> '+r.name+'</b></div><div class="w25">性别<b> '+r.sex+'</b></div><div class="w25">年龄<b> '+r.age+'</b></div><div class="w25">工号<b> '+r.code+'</b></div>'
|
||||
+'<div class="w50">所属单位<b> '+r.unit+'</b></div><div class="w50">所属部门<b> '+r.dept+'</b></div>'
|
||||
+'<div class="w100">慢病类型<b> '+(CHRONIC[r.code]||'无')+'</b></div>';
|
||||
}
|
||||
function groupBadgeHtml(v){
|
||||
var color=GROUP_BADGE[v]||'#999';
|
||||
return '<span class="group-badge" style="color:'+color+';background:'+color+'1a;">'+(GROUP_MAP[v]||'健康-E类')+'</span>';
|
||||
}
|
||||
function openDetail(id){
|
||||
var r=records.find(function(x){return x.id===id;});
|
||||
var report=buildReport(r);
|
||||
document.getElementById('detailTitle').textContent='解读详情 · '+r.name;
|
||||
document.getElementById('dConclusion').textContent=report.conclusion;
|
||||
document.getElementById('dSuggest').textContent=report.suggest;
|
||||
document.getElementById('dReport').innerHTML=renderReportHtml(report);
|
||||
document.getElementById('dEmp').innerHTML=empBasicHtml(r);
|
||||
document.getElementById('dAdvise').textContent=r.advise||'—';
|
||||
document.getElementById('dGroupBefore').innerHTML='解读前:'+groupBadgeHtml(r.beforeGroup);
|
||||
document.getElementById('dGroupAfter').innerHTML='解读后:'+groupBadgeHtml(r.group);
|
||||
document.getElementById('dSign').innerHTML='<div class="sign-box" style="min-height:80px;"><svg width="180" height="52" viewBox="0 0 180 52"><path d="M10 38c14-20 20 12 32-6 9-14 14 16 26-2 8-12 12 10 22-2 8-12 14 8 26 2" stroke="#14213D" stroke-width="2.4" fill="none" stroke-linecap="round"/></svg><div style="font-size:var(--font-xs);color:var(--text-placeholder);">'+r.name+' · '+r.date+' 于 PAD 端确认</div></div>';
|
||||
document.getElementById('dDoctor').textContent=r.doctor||'—';
|
||||
document.getElementById('dDate').textContent=r.date||'—';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
function closeDrawer(k){
|
||||
document.getElementById(k+'Mask').classList.remove('open');
|
||||
document.getElementById(k+'Drawer').classList.remove('open');
|
||||
}
|
||||
function closeModal(id){document.getElementById(id).classList.remove('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
|
||||
@@ -72,8 +72,13 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.btn-link--danger{color:var(--danger);}
|
||||
.action-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;background:#fff;margin-top:16px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.action-bar{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 24px;background:#fff;margin-top:16px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.action-bar__left{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
|
||||
.seg{display:inline-flex;border:1px solid var(--primary);border-radius:var(--radius-sm);overflow:hidden;flex-shrink:0;}
|
||||
.seg button{height:32px;padding:0 16px;border:none;background:#fff;color:var(--primary);font-size:var(--font-sm);cursor:pointer;border-right:1px solid var(--primary);transition:all .15s;}
|
||||
.seg button:last-child{border-right:none;}
|
||||
.seg button:hover{background:var(--primary-light);}
|
||||
.seg button.active{background:var(--primary);color:#fff;}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1700px;}
|
||||
@@ -91,6 +96,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.badge--info{background:#E6F7FF;color:#096DD9;border:1px solid #91D5FF;}
|
||||
.badge--danger{background:#FFF1F0;color:#CF1322;border:1px solid #FFCCC7;}
|
||||
.badge--muted{background:#F5F5F5;color:var(--text-secondary);border:1px solid var(--border);}
|
||||
.badge--purple{background:#F9F0FF;color:#722ED1;border:1px solid #D3ADF7;}
|
||||
.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);}
|
||||
.page-btn{min-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;padding:0 6px;transition:all .2s;}
|
||||
@@ -100,28 +106,53 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.toast.show{opacity:1;}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal--wide{width:680px;max-height:84vh;display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);}
|
||||
.modal{width:520px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;max-height:82vh;overflow-y:auto;}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;margin-bottom:16px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:12px;}
|
||||
.modal--wide{width:1240px;max-width:96vw;max-height:90vh;display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);}
|
||||
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-base);font-weight:600;flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.modal__close:hover{color:var(--text-primary);}
|
||||
.modal__body{flex:1;overflow-y:auto;padding:20px 24px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:18px 0 10px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid var(--border);}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:110px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
.form-item{display:flex;flex-direction:column;gap:6px;margin-bottom:14px;}
|
||||
.form-label{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.form-label .req{color:var(--danger);}
|
||||
.form-control{height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);color:var(--text-primary);outline:none;width:100%;}
|
||||
.form-control:focus{border-color:var(--primary);}
|
||||
.form-control[readonly]{background:#FAFAFA;color:var(--text-secondary);}
|
||||
textarea.form-control{height:72px;padding:8px 10px;resize:vertical;line-height:1.5;}
|
||||
textarea.form-control{height:88px;padding:8px 10px;resize:vertical;line-height:1.5;}
|
||||
select.form-control{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;-webkit-appearance:none;padding-right:28px;cursor:pointer;}
|
||||
.upload-box{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:14px;display:flex;align-items:center;gap:10px;color:var(--text-placeholder);font-size:var(--font-sm);background:#FAFAFA;}
|
||||
.section-title{display:flex;align-items:center;gap:8px;font-size:var(--font-base);font-weight:600;color:var(--text-primary);margin:16px 0 10px;}
|
||||
.section-title::before{content:'';width:4px;height:16px;background:var(--primary);border-radius:2px;}
|
||||
/* 解读弹窗左右两栏 */
|
||||
.report-cols{display:flex;gap:0;height:calc(90vh - 130px);}
|
||||
.report-cols__left{width:50%;overflow-y:auto;padding-right:20px;border-right:1px dashed var(--border);}
|
||||
.report-cols__right{width:50%;overflow-y:auto;padding-left:20px;}
|
||||
.report-title{font-size:var(--font-base);font-weight:700;padding:10px 0 10px 12px;position:relative;margin-top:4px;}
|
||||
.report-title::before{content:'';position:absolute;left:0;top:13px;width:6px;height:18px;background:#E3CB2C;border-radius:2px;}
|
||||
.report-sub{font-size:var(--font-sm);color:var(--text-secondary);line-height:1.7;padding:0 12px 8px;}
|
||||
.report-group{margin-top:16px;}
|
||||
.report-group__name{font-weight:700;font-size:var(--font-base);padding:10px 12px;background:#F6F6F6;border-radius:var(--radius-sm) var(--radius-sm) 0 0;}
|
||||
.report-cat{padding-left:20px;}
|
||||
.report-cat__name{font-size:var(--font-sm);font-weight:700;padding:10px 0 8px 12px;position:relative;}
|
||||
.report-cat__name::before{content:'';position:absolute;left:0;top:12px;width:6px;height:16px;background:#02C2A6;border-radius:2px;}
|
||||
.report-ul{padding:0;margin:0;width:100%;display:flex;}
|
||||
.report-ul li{flex:1;text-align:center;padding:6px 0;font-size:var(--font-sm);border:1px solid #E6E6E6;border-left:none;border-top:none;}
|
||||
.report-ul li:first-child{border-left:1px solid #E6E6E6;}
|
||||
.report-ul.report-ul--head{font-weight:700;}
|
||||
.report-ul.report-ul--head li{background:#F0F2FF;}
|
||||
.report-ul.report-ul--head li:first-child{background:#F0F2FF;}
|
||||
.report-ul:not(.report-ul--head) li:first-child{background:#F6F6F6;}
|
||||
.emp-basic{display:flex;flex-wrap:wrap;gap:4px 0;}
|
||||
.emp-basic div{font-size:var(--font-sm);color:var(--text-secondary);padding:4px 0;}
|
||||
.emp-basic b{color:var(--text-primary);font-weight:600;}
|
||||
.emp-basic .w25{width:25%;}
|
||||
.emp-basic .w50{width:50%;}
|
||||
.emp-basic .w100{width:100%;}
|
||||
.advise-box{background:#F4F4F4;border-radius:var(--radius-sm);padding:10px;font-size:var(--font-sm);line-height:1.7;color:var(--text-primary);min-height:88px;}
|
||||
.sign-box{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:16px;text-align:center;min-height:120px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;}
|
||||
.group-badge{display:inline-block;padding:2px 12px;border-radius:10px;font-size:var(--font-sm);font-weight:600;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -154,13 +185,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -181,8 +206,8 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<!-- [交互] 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>员工姓名/工号</label>
|
||||
<input class="filter-input" id="filterName" placeholder="请输入姓名或工号">
|
||||
<label>姓名</label>
|
||||
<input class="filter-input" id="filterName" placeholder="请输入姓名">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>员工所属单位</label>
|
||||
@@ -223,12 +248,6 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<option value="">全部</option><option>2026</option><option>2025</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>任务状态</label>
|
||||
<select class="filter-select" id="filterStatus" style="min-width:100px;">
|
||||
<option value="">全部</option><option>待解读</option><option>已逾期</option><option>已完成</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>解读日期</label>
|
||||
<input class="filter-input" type="date" id="filterFrom" style="min-width:130px;">
|
||||
@@ -243,8 +262,22 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
|
||||
<!-- [交互] 操作栏 -->
|
||||
<div class="action-bar">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
<div class="action-bar__left">
|
||||
<button class="btn btn-primary" onclick="doExport()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="openExport()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出记录
|
||||
</button>
|
||||
<button class="btn btn-primary" onclick="openGenRecord()">生成记录</button>
|
||||
<button class="btn btn-primary" id="btnResetTask" onclick="resetTask()">重新生成解读任务</button>
|
||||
</div>
|
||||
<div class="seg">
|
||||
<button class="active" data-v="0" onclick="setStatusGroup(this,'0')">全部</button>
|
||||
<button data-v="1" onclick="setStatusGroup(this,'1')">待解读</button>
|
||||
<button data-v="2" onclick="setStatusGroup(this,'2')">已逾期</button>
|
||||
<button data-v="3" onclick="setStatusGroup(this,'3')">已完成</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
@@ -253,7 +286,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<table>
|
||||
<thead>
|
||||
<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><th>任务状态</th><th>操作</th>
|
||||
<th>序号</th><th>姓名</th><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="tableBody"></tbody>
|
||||
@@ -269,37 +302,114 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 报告解读弹窗 -->
|
||||
<!-- [交互] 体检报告解读弹窗(可编辑) -->
|
||||
<div class="modal-mask" id="intMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal__header"><span id="intTitle">报告解读</span><button class="modal__close" onclick="closeModal('intMask')">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="form-section" style="margin-top:0;">员工体检摘要</div>
|
||||
<div class="detail-grid" id="intSummary"></div>
|
||||
<div class="form-section">综合解读建议</div>
|
||||
<textarea class="form-control" id="intAdvise" style="height:88px;" placeholder="结合体检指标、既往史与生活方式,给出个体化综合解读与建议"></textarea>
|
||||
<div class="form-section">五类人群重新分类</div>
|
||||
<div style="display:flex;align-items:center;gap:10px;">
|
||||
<select class="form-control" id="intGroup" style="max-width:260px;">
|
||||
<option value="">请选择分类</option>
|
||||
<option>健康人群</option><option>亚健康人群</option><option>慢性病风险人群</option><option>已确诊慢病人群</option><option>突发风险人群</option>
|
||||
</select>
|
||||
<span style="font-size:var(--font-xs);color:var(--text-placeholder);">分类结果将回写健康档案并驱动随访/干预策略</span>
|
||||
</div>
|
||||
<div class="form-section">员工确认签字</div>
|
||||
<div class="upload-box">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 13V4m0 0L6.5 7.5M10 4l3.5 3.5" stroke="#999" stroke-width="1.5" stroke-linecap="round"/><path d="M3 14v2a2 2 0 002 2h10a2 2 0 002-2v-2" stroke="#999" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
签字文件由员工在 PAD 端解读确认时自动回传,无需在此上传
|
||||
<div class="modal__header"><span id="intTitle">体检报告解读</span><button class="modal__close" onclick="closeModal('intMask')">×</button></div>
|
||||
<div class="modal__body" style="padding:0;">
|
||||
<div class="report-cols">
|
||||
<div class="report-cols__left">
|
||||
<div class="report-title">体检结论</div>
|
||||
<div class="report-sub" id="intConclusion"></div>
|
||||
<div class="report-title">体检建议</div>
|
||||
<div class="report-sub" id="intSuggest"></div>
|
||||
<div id="intReport"></div>
|
||||
</div>
|
||||
<div class="report-cols__right">
|
||||
<div class="report-title">员工基本信息</div>
|
||||
<div class="emp-basic" id="intEmp"></div>
|
||||
<div class="report-title">综合解读建议</div>
|
||||
<textarea class="form-control" id="intAdvise" placeholder="结合体检指标、既往史与生活方式,给出个体化综合解读与建议"></textarea>
|
||||
<div class="report-title">五类人群重新分类</div>
|
||||
<select class="form-control" id="intGroup" style="max-width:280px;"></select>
|
||||
<div class="report-title">员工确认签字</div>
|
||||
<div class="sign-box" id="signBox">
|
||||
<div id="signHolder" style="color:var(--text-placeholder);">本人已确认健康随访</div>
|
||||
<button class="btn btn-default" id="signBtn" onclick="doSign()">员工签名</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('intMask')">取消</button>
|
||||
<button class="btn btn-primary" id="intSaveBtn" onclick="saveInterpret()">保存并完成解读</button>
|
||||
<button class="btn btn-primary" id="intSaveBtn" onclick="saveInterpret()">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导出任务抽屉(异步导出任务列表) -->
|
||||
<!-- [交互] 解读详情弹窗(只读) -->
|
||||
<div class="modal-mask" id="detailMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal__header"><span id="detailTitle">解读详情</span><button class="modal__close" onclick="closeModal('detailMask')">×</button></div>
|
||||
<div class="modal__body" style="padding:0;">
|
||||
<div class="report-cols">
|
||||
<div class="report-cols__left">
|
||||
<div class="report-title">体检结论</div>
|
||||
<div class="report-sub" id="dConclusion"></div>
|
||||
<div class="report-title">体检建议</div>
|
||||
<div class="report-sub" id="dSuggest"></div>
|
||||
<div id="dReport"></div>
|
||||
</div>
|
||||
<div class="report-cols__right">
|
||||
<div class="report-title">员工基本信息</div>
|
||||
<div class="emp-basic" id="dEmp"></div>
|
||||
<div class="report-title">综合解读建议</div>
|
||||
<div class="advise-box" id="dAdvise"></div>
|
||||
<div class="report-title">五类人群重新分布</div>
|
||||
<div style="display:flex;padding:6px 0 10px;gap:16px;">
|
||||
<span id="dGroupBefore" style="font-size:var(--font-sm);color:var(--text-secondary);"></span>
|
||||
<span id="dGroupAfter" style="font-size:var(--font-sm);color:var(--text-secondary);"></span>
|
||||
</div>
|
||||
<div class="report-title">员工确认签字</div>
|
||||
<div id="dSign"></div>
|
||||
<div style="display:flex;width:100%;margin-top:16px;">
|
||||
<div style="width:50%;">
|
||||
<div class="report-title" style="margin-top:0;">解读医生</div>
|
||||
<div style="padding-left:12px;" id="dDoctor"></div>
|
||||
</div>
|
||||
<div style="width:50%;">
|
||||
<div class="report-title" style="margin-top:0;">解读日期</div>
|
||||
<div style="padding-left:12px;" id="dDate"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('detailMask')">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 编辑截止日期弹窗 -->
|
||||
<div class="modal-mask" id="editMask">
|
||||
<div class="modal" style="width:440px;">
|
||||
<div class="modal__title">编辑</div>
|
||||
<div class="form-item">
|
||||
<span class="form-label"><span class="req">*</span> 截止日期</span>
|
||||
<input class="form-control" type="date" id="editDeadline">
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeModal('editMask')">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveEdit()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 解读任务生成记录抽屉 -->
|
||||
<div class="drawer-mask" id="genMask" onclick="closeDrawer('gen')"></div>
|
||||
<div class="drawer" id="genDrawer">
|
||||
<div class="drawer__header"><span>解读任务生成记录</span><button class="drawer__close" onclick="closeDrawer('gen')">×</button></div>
|
||||
<div class="drawer__body">
|
||||
<table class="mini-table" style="border-collapse:separate;">
|
||||
<thead><tr><th>序号</th><th>处理进度</th><th>状态</th><th>提示</th><th>创建时间</th><th>开始时间</th><th>结束时间</th><th>操作人</th></tr></thead>
|
||||
<tbody id="genBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="drawer__footer"><button class="btn btn-default" onclick="closeDrawer('gen')">关闭</button></div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导出任务抽屉 -->
|
||||
<div class="drawer-mask" id="exportMask" onclick="closeDrawer('export')"></div>
|
||||
<div class="drawer drawer--narrow" id="exportDrawer">
|
||||
<div class="drawer__header"><span>导出任务</span><button class="drawer__close" onclick="closeDrawer('export')">×</button></div>
|
||||
@@ -315,40 +425,58 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* ===== 演示数据(脱敏):解读任务由2026年度体检报告回传生成,与员工名册/员工查询页体检指标一致 ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂'};
|
||||
/* ===== 演示数据(脱敏):解读任务由年度体检报告回传生成 ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂','姬塬作业区医疗点':'采油一厂'};
|
||||
var pointMap={
|
||||
'采油一厂':['樊学作业区医疗点','安塞采油队长住点医疗室','姬塬作业区医疗点'],
|
||||
'采油二厂':['姬圪台作业区医疗点','桐园作业区医疗点'],
|
||||
'第四采油厂':['西峰基地医疗点'],
|
||||
'采气一厂':['靖边气田医疗点','乌审旗采气区医疗点']
|
||||
};
|
||||
/* summary=摘要 advise=综合建议 group=五类分类 done=完成日期 doctor=解读医生 */
|
||||
/* 五类人群:A大病 B慢病 C异常 D风险 E健康 */
|
||||
var GROUP_MAP={a:'大病-A类',b:'慢病-B类',c:'异常-C类',d:'风险-D类',e:'健康-E类'};
|
||||
var GROUP_BADGE={a:'#CF1322',b:'#FA8C16',c:'#D48806',d:'#096DD9',e:'#389E0D'};
|
||||
var CHRONIC={'CQ033096':'高血压','CQ010564':'糖尿病','CQ019203':'冠心病','CQ021578':'高血压','CQ027710':'肥胖','CQ036441':'高血压','CQ022317':'肥胖','CQ029905':'无','CQ044871':'无','CQ041822':'无','CQ032144':'无','CQ045130':'无'};
|
||||
/* status: 1待解读 2已逾期 3已完成 ; interpretDate 为解读完成日期 */
|
||||
var tasks=[
|
||||
{id:1,code:'CQ033096',name:'赵万福',sex:'男',age:39,tel:'150****6127',unit:'采油二厂',dept:'桐园作业区',point:'桐园作业区医疗点',year:'2026',deadline:'2026-10-31',done:'2026-09-06',doctor:'曲志明',status:'已完成',
|
||||
summary:'血压 158/96mmHg;BMI 27.1;血脂轻度异常;心电正常',advise:'高血压2级合并超重,已纳入慢病管理;建议低盐减重、规律服药并每月随访。',group:'已确诊慢病人群'},
|
||||
{id:2,code:'CQ010564',name:'高建军',sex:'男',age:50,tel:'139****0086',unit:'第四采油厂',dept:'基地管理处',point:'西峰基地医疗点',year:'2026',deadline:'2026-10-31',done:'2026-08-30',doctor:'闫婷',status:'已完成',
|
||||
summary:'空腹血糖 8.9mmol/L;糖化 7.8%;BMI 27.6;轻度脂肪肝',advise:'2型糖尿病诊断明确,转内分泌专科复核用药方案;双周随访控制血糖。',group:'已确诊慢病人群'},
|
||||
{id:3,code:'CQ027710',name:'张秀兰',sex:'女',age:45,tel:'136****2248',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',year:'2026',deadline:'2026-10-31',done:'',doctor:'',status:'待解读',
|
||||
summary:'BMI 25.8;总胆固醇 6.4mmol/L;腰椎退变;余大致正常',advise:'',group:''},
|
||||
{id:4,code:'CQ021578',name:'石维国',sex:'男',age:46,tel:'139****2051',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',deadline:'2026-10-31',done:'',doctor:'',status:'待解读',
|
||||
summary:'血压 138/86mmHg 临界;吸烟指数偏高;余未见明显异常',advise:'',group:''},
|
||||
{id:5,code:'CQ022317',name:'徐立成',sex:'男',age:44,tel:'133****4860',unit:'采气一厂',dept:'苏里格南作业区',point:'乌审旗采气区医疗点',year:'2026',deadline:'2026-10-31',done:'',doctor:'',status:'待解读',
|
||||
summary:'BMI 26.4;尿酸 442μmol/L;夏季中暑史',advise:'',group:''},
|
||||
{id:6,code:'CQ036441',name:'刘玉梅',sex:'女',age:40,tel:'135****7719',unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',year:'2026',deadline:'2026-10-31',done:'',doctor:'',status:'已逾期',
|
||||
summary:'血压 142/88mmHg;甲状腺结节 TI-RADS 3类',advise:'',group:''},
|
||||
{id:7,code:'CQ019203',name:'曲志明',sex:'男',age:42,tel:'137****8890',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',year:'2026',deadline:'2026-10-31',done:'',doctor:'',status:'已逾期',
|
||||
summary:'冠心病病史;LDL-C 3.9mmol/L;心电图 ST-T 改变',advise:'',group:''},
|
||||
{id:8,code:'CQ044871',name:'白瑞',sex:'男',age:31,tel:'155****3316',unit:'采油一厂',dept:'生产技术部',point:'安塞采油队长住点医疗室',year:'2026',deadline:'2026-10-31',done:'',doctor:'',status:'待解读',
|
||||
summary:'轻度脂肪肝;尿酸 468μmol/L;余正常',advise:'',group:''},
|
||||
{id:9,code:'CQ032144',name:'李桂芳',sex:'女',age:38,tel:'138****7742',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',deadline:'2026-10-31',done:'2026-09-02',doctor:'李桂芳',status:'已完成',
|
||||
summary:'各项指标基本正常;维生素D偏低',advise:'健康状况良好,补充维生素D并保持运动习惯。',group:'健康人群'},
|
||||
{id:10,code:'CQ041822',name:'闫婷',sex:'女',age:34,tel:'186****5527',unit:'第四采油厂',dept:'健康管理部',point:'西峰基地医疗点',year:'2026',deadline:'2026-10-31',done:'',doctor:'',status:'待解读',
|
||||
summary:'指标正常;久坐办公,颈肩肌劳损',advise:'',group:''},
|
||||
{id:11,code:'CQ045130',name:'杨慧敏',sex:'女',age:33,tel:'188****7214',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',deadline:'2026-10-31',done:'2026-09-04',doctor:'石维国',status:'已完成',
|
||||
summary:'血常规轻度贫血;余正常',advise:'轻度缺铁性贫血,加强营养,三个月复查血常规。',group:'亚健康人群'}
|
||||
{id:1,code:'CQ033096',name:'赵万福',sex:'男',age:39,tel:'150****6127',unit:'采油二厂',dept:'桐园作业区',point:'桐园作业区医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'2026-09-07',doctor:'曲志明',status:3,advise:'高血压2级合并超重,已纳入慢病管理;建议低盐减重、规律服药并每月随访。',group:'b',beforeGroup:'d'},
|
||||
{id:2,code:'CQ010564',name:'高建军',sex:'男',age:50,tel:'139****0086',unit:'第四采油厂',dept:'基地管理处',point:'西峰基地医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'2026-08-30',doctor:'闫婷',status:3,advise:'2型糖尿病诊断明确,转内分泌专科复核用药方案;双周随访控制血糖。',group:'b',beforeGroup:'c'},
|
||||
{id:3,code:'CQ027710',name:'张秀兰',sex:'女',age:45,tel:'136****2248',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'',doctor:'',status:1,advise:'',group:'',beforeGroup:''},
|
||||
{id:4,code:'CQ021578',name:'石维国',sex:'男',age:46,tel:'139****2051',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'',doctor:'',status:1,advise:'',group:'',beforeGroup:''},
|
||||
{id:5,code:'CQ022317',name:'徐立成',sex:'男',age:44,tel:'133****4860',unit:'采气一厂',dept:'苏里格南作业区',point:'乌审旗采气区医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'',doctor:'',status:1,advise:'',group:'',beforeGroup:''},
|
||||
{id:6,code:'CQ036441',name:'刘玉梅',sex:'女',age:40,tel:'135****7719',unit:'采气一厂',dept:'靖边净化厂',point:'靖边气田医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'',doctor:'',status:2,advise:'',group:'',beforeGroup:''},
|
||||
{id:7,code:'CQ019203',name:'曲志明',sex:'男',age:42,tel:'137****8890',unit:'采油二厂',dept:'姬圪台联合站',point:'姬圪台作业区医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'',doctor:'',status:2,advise:'',group:'',beforeGroup:''},
|
||||
{id:8,code:'CQ044871',name:'白瑞',sex:'男',age:31,tel:'155****3316',unit:'采油一厂',dept:'生产技术部',point:'安塞采油队长住点医疗室',year:'2026',deadline:'2026-10-31',interpretDate:'',doctor:'',status:1,advise:'',group:'',beforeGroup:''},
|
||||
{id:9,code:'CQ032144',name:'李桂芳',sex:'女',age:38,tel:'138****7742',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'2026-09-02',doctor:'李桂芳',status:3,advise:'健康状况良好,补充维生素D并保持运动习惯。',group:'e',beforeGroup:'e'},
|
||||
{id:10,code:'CQ041822',name:'闫婷',sex:'女',age:34,tel:'186****5527',unit:'第四采油厂',dept:'健康管理部',point:'西峰基地医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'',doctor:'',status:1,advise:'',group:'',beforeGroup:''},
|
||||
{id:11,code:'CQ045130',name:'杨慧敏',sex:'女',age:33,tel:'188****7214',unit:'采油一厂',dept:'樊学作业区',point:'樊学作业区医疗点',year:'2026',deadline:'2026-10-31',interpretDate:'2026-09-04',doctor:'石维国',status:3,advise:'轻度缺铁性贫血,加强营养,三个月复查血常规。',group:'c',beforeGroup:'e'}
|
||||
];
|
||||
var nextId=12,curInterpId=null;
|
||||
var nextId=12,curInterpId=null,statusGroup='0',today='2026-09-07';
|
||||
var statusMap={1:'待解读',2:'已逾期',3:'已完成'};
|
||||
var statusBadge={1:'badge--warning',2:'badge--danger',3:'badge--success'};
|
||||
|
||||
/* 体检报告明细模板(嵌套:分析名称→类别→指标行) */
|
||||
function buildReport(t){
|
||||
return {
|
||||
conclusion: t.summary || '各项指标未见明显异常',
|
||||
suggest: '结合既往史与生活方式,建议定期复查并保持健康管理。',
|
||||
groups: [
|
||||
{analysisName:'一般检查', cats:[
|
||||
{cls:'体格检查', rows:[{name:'血压',result:'128/82',unit:'mmHg',ref:'<140/90'},{name:'心率',result:'74',unit:'次/分',ref:'60-100'}]},
|
||||
{cls:'人体测量', rows:[{name:'身高',result:'172',unit:'cm',ref:''},{name:'体重',result:'78',unit:'kg',ref:''},{name:'BMI',result:'26.4',unit:'',ref:'18.5-23.9'},{name:'腰围',result:'88',unit:'cm',ref:'<85'}]}
|
||||
]},
|
||||
{analysisName:'实验室检查', cats:[
|
||||
{cls:'血常规', rows:[{name:'白细胞',result:'6.1',unit:'×10⁹/L',ref:'3.5-9.5'},{name:'血红蛋白',result:'142',unit:'g/L',ref:'130-175'},{name:'血小板',result:'235',unit:'×10⁹/L',ref:'125-350'}]},
|
||||
{cls:'生化检验', rows:[{name:'空腹血糖',result:'5.8',unit:'mmol/L',ref:'3.9-6.1'},{name:'总胆固醇',result:'5.6',unit:'mmol/L',ref:'<5.2'},{name:'甘油三酯',result:'1.7',unit:'mmol/L',ref:'<1.7'},{name:'尿酸',result:'398',unit:'μmol/L',ref:'208-428'}]}
|
||||
]}
|
||||
]
|
||||
};
|
||||
}
|
||||
/* 为已完成任务补充体检摘要 */
|
||||
tasks.forEach(function(t){
|
||||
var summaries={1:'血压 158/96mmHg;BMI 27.1;血脂轻度异常;心电正常',2:'空腹血糖 8.9mmol/L;糖化 7.8%;BMI 27.6;轻度脂肪肝',9:'各项指标基本正常;维生素D偏低',11:'血常规轻度贫血;余正常'};
|
||||
t.summary=summaries[t.id]||'BMI 26.4;尿酸 442μmol/L;余大致正常';
|
||||
});
|
||||
|
||||
/* ===== 单位部门双列筛选 ===== */
|
||||
var deptMap={
|
||||
@@ -419,11 +547,11 @@ function closeDrawer(k){
|
||||
}
|
||||
function nowHM(){
|
||||
var d=new Date(),p=function(n){return (n<10?'0':'')+n;};
|
||||
return '2026-09-07 '+p(d.getHours())+':'+p(d.getMinutes());
|
||||
return today+' '+p(d.getHours())+':'+p(d.getMinutes());
|
||||
}
|
||||
function doExport(){
|
||||
exportLogs.unshift({file:'解读任务导出_'+nowHM()+'.xlsx',status:'ing',time:'—'});
|
||||
showToast('导出任务已提交,完成后可在「查看导出任务」下载');
|
||||
showToast('导出任务已提交,完成后可在「查看导出记录」下载');
|
||||
if(document.getElementById('exportDrawer').classList.contains('open'))renderExportList();
|
||||
setTimeout(function(){
|
||||
var e=exportLogs[0];
|
||||
@@ -455,18 +583,17 @@ function currentData(){
|
||||
var unit=document.getElementById('filterUnit').value;
|
||||
var point=document.getElementById('filterPoint').value;
|
||||
var year=document.getElementById('filterYear').value;
|
||||
var status=document.getElementById('filterStatus').value;
|
||||
var from=document.getElementById('filterFrom').value;
|
||||
var to=document.getElementById('filterTo').value;
|
||||
return tasks.filter(function(t){
|
||||
return (!q||t.name.indexOf(q)!==-1||t.code.toLowerCase().indexOf(q.toLowerCase())!==-1)
|
||||
&&(!selUnit||t.unit===selUnit)&&(!selDept||t.dept===selDept)
|
||||
&&(!unit||pointUnit[t.point]===unit)&&(!point||t.point===point)
|
||||
&&(!year||t.year===year)&&(!status||t.status===status)
|
||||
&&(!from||(t.done&&t.done>=from))&&(!to||(t.done&&t.done<=to));
|
||||
&&(!year||t.year===year)
|
||||
&&(statusGroup==='0'||String(t.status)===statusGroup)
|
||||
&&(!from||(t.interpretDate&&t.interpretDate>=from))&&(!to||(t.interpretDate&&t.interpretDate<=to));
|
||||
});
|
||||
}
|
||||
var statusBadge={'待解读':'badge--warning','已完成':'badge--success','已逾期':'badge--danger'};
|
||||
function renderTable(){
|
||||
var list=currentData();
|
||||
var start=(currentPage-1)*pageSize,pageData=list.slice(start,start+pageSize);
|
||||
@@ -483,21 +610,35 @@ function renderTable(){
|
||||
+'<td>'+(start+i+1)+'</td>'
|
||||
+'<td style="font-weight:600;">'+t.name+'</td>'
|
||||
+'<td>'+t.code+'</td><td>'+t.sex+'</td><td>'+t.age+'</td><td>'+t.tel+'</td><td>'+t.unit+'</td>'
|
||||
+'<td>'+t.point+'</td><td>'+pointUnit[t.point]+'</td><td>'+t.year+'</td><td>'+t.deadline+'</td><td>'+(t.done||'—')+'</td>'
|
||||
+'<td><span class="badge '+statusBadge[t.status]+'">'+t.status+'</span></td>'
|
||||
+'<td class="td-actions">'
|
||||
+(t.status==='已完成'
|
||||
?'<button class="btn btn-link" onclick="openInterpret('+t.id+',true)">查看</button>'
|
||||
:'<button class="btn btn-link" onclick="openInterpret('+t.id+')">解读</button>')
|
||||
+'</td></tr>';
|
||||
+'<td>'+t.point+'</td><td>'+pointUnit[t.point]+'</td><td>'+t.year+'</td><td>'+t.deadline+'</td><td>'+(t.interpretDate||'—')+'</td>'
|
||||
+'<td><span class="badge '+statusBadge[t.status]+'">'+statusMap[t.status]+'</span></td>'
|
||||
+'<td class="td-actions">'+actionHtml(t)+'</td></tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
}
|
||||
/* 行操作:体检报告解读/重新解读/编辑/解读详情 */
|
||||
function canRedo(t){ return t.status===3 && t.interpretDate>=today; }
|
||||
function actionHtml(t){
|
||||
var h='';
|
||||
if(t.status!==3){
|
||||
h+='<button class="btn btn-link" onclick="openInterpret('+t.id+')">体检报告解读</button>';
|
||||
h+='<button class="btn btn-link" onclick="openEdit('+t.id+')">编辑</button>';
|
||||
}else{
|
||||
if(canRedo(t))h+='<button class="btn btn-link" onclick="openInterpret('+t.id+',true)">重新解读</button>';
|
||||
h+='<button class="btn btn-link" onclick="openDetail('+t.id+')">解读详情</button>';
|
||||
}
|
||||
return h;
|
||||
}
|
||||
function setStatusGroup(btn,v){
|
||||
statusGroup=v;
|
||||
btn.parentElement.querySelectorAll('button').forEach(function(b){b.classList.toggle('active',b===btn);});
|
||||
currentPage=1;renderTable();
|
||||
}
|
||||
function applyFilter(){currentPage=1;renderTable();}
|
||||
function resetFilter(){
|
||||
document.getElementById('filterName').value='';
|
||||
document.getElementById('filterUnit').value='';onFilterUnit();
|
||||
document.getElementById('filterYear').value='';document.getElementById('filterStatus').value='';
|
||||
document.getElementById('filterYear').value='';
|
||||
document.getElementById('filterFrom').value='';document.getElementById('filterTo').value='';
|
||||
resetOrg();
|
||||
applyFilter();
|
||||
@@ -508,35 +649,133 @@ function turnPage(d){
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ===== 解读弹窗 ===== */
|
||||
function openInterpret(id,readonly){
|
||||
/* ===== 体检报告渲染 ===== */
|
||||
function renderReportHtml(report){
|
||||
if(!report.groups||!report.groups.length)return '<div class="td-empty">暂无体检数据</div>';
|
||||
var html='';
|
||||
report.groups.forEach(function(g){
|
||||
html+='<div class="report-group"><div class="report-group__name">'+g.analysisName+'</div>';
|
||||
g.cats.forEach(function(c){
|
||||
html+='<div class="report-cat"><div class="report-cat__name">'+c.cls+'</div>';
|
||||
html+='<ul class="report-ul report-ul--head"><li>名称</li><li>结果</li><li>单位</li><li>参考值</li></ul>';
|
||||
c.rows.forEach(function(r){
|
||||
html+='<ul class="report-ul"><li>'+r.name+'</li><li>'+r.result+'</li><li>'+r.unit+'</li><li>'+r.ref+'</li></ul>';
|
||||
});
|
||||
html+='</div>';
|
||||
});
|
||||
html+='</div>';
|
||||
});
|
||||
return html;
|
||||
}
|
||||
function empBasicHtml(t){
|
||||
return '<div class="w25">姓名<b> '+t.name+'</b></div><div class="w25">性别<b> '+t.sex+'</b></div><div class="w25">年龄<b> '+t.age+'</b></div><div class="w25">工号<b> '+t.code+'</b></div>'
|
||||
+'<div class="w50">所属单位<b> '+t.unit+'</b></div><div class="w50">所属部门<b> '+t.dept+'</b></div>'
|
||||
+'<div class="w100">慢病类型<b> '+(CHRONIC[t.code]||'无')+'</b></div>';
|
||||
}
|
||||
function fillGroupSel(val){
|
||||
var sel=document.getElementById('intGroup');
|
||||
sel.innerHTML='<option value="">请选择分类</option>'+Object.keys(GROUP_MAP).map(function(k){
|
||||
return '<option value="'+k+'"'+(k===val?' selected':'')+'>'+GROUP_MAP[k]+'</option>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
/* ===== 体检报告解读弹窗 ===== */
|
||||
function openInterpret(id,redo){
|
||||
var t=tasks.find(function(x){return x.id===id;});
|
||||
curInterpId=id;
|
||||
document.getElementById('intTitle').textContent=(readonly?'解读详情 · ':'报告解读 · ')+t.name+'('+t.year+'年度体检报告)';
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v||'—')+'</div></div>';}
|
||||
document.getElementById('intSummary').innerHTML=
|
||||
d('员工',t.name+' / '+t.code)+d('性别/年龄',t.sex+' / '+t.age+'岁')
|
||||
+d('单位/部门',t.unit+' / '+t.dept)+d('分配医疗点',t.point+'('+pointUnit[t.point]+')')
|
||||
+d('体检年份',t.year)+d('解读截止',t.deadline)
|
||||
+d('报告异常摘要',t.summary,true);
|
||||
document.getElementById('intAdvise').value=t.advise||'';
|
||||
document.getElementById('intGroup').value=t.group||'';
|
||||
document.getElementById('intAdvise').readOnly=!!readonly;
|
||||
document.getElementById('intGroup').disabled=!!readonly;
|
||||
document.getElementById('intSaveBtn').style.display=readonly?'none':'';
|
||||
if(readonly){document.getElementById('intSaveBtn').textContent='保存并完成解读';}
|
||||
var report=buildReport(t);
|
||||
document.getElementById('intTitle').textContent=(redo?'重新解读 · ':'体检报告解读 · ')+t.name+'('+t.year+'年度体检报告)';
|
||||
document.getElementById('intConclusion').textContent=report.conclusion;
|
||||
document.getElementById('intSuggest').textContent=report.suggest;
|
||||
document.getElementById('intReport').innerHTML=renderReportHtml(report);
|
||||
document.getElementById('intEmp').innerHTML=empBasicHtml(t);
|
||||
document.getElementById('intAdvise').value=redo?t.advise:'';
|
||||
fillGroupSel(redo?t.group:'');
|
||||
document.getElementById('signHolder').innerHTML='本人已确认健康随访';
|
||||
document.getElementById('intMask').classList.add('open');
|
||||
}
|
||||
function doSign(){
|
||||
var t=tasks.find(function(x){return x.id===curInterpId;});
|
||||
document.getElementById('signHolder').innerHTML='<svg width="200" height="60" viewBox="0 0 200 60"><path d="M14 42c16-24 22 14 36-8 10-18 16 20 30-2 9-16 14 12 24-2 8-14 14 10 26 4 12-6 24 8 38 2" stroke="#14213D" stroke-width="2.4" fill="none" stroke-linecap="round"/></svg>'
|
||||
+'<div style="font-size:var(--font-xs);color:var(--text-placeholder);margin-top:6px;">'+t.name+' · '+today+' 电子签名存证</div>';
|
||||
}
|
||||
function saveInterpret(){
|
||||
var t=tasks.find(function(x){return x.id===curInterpId;});
|
||||
var advise=document.getElementById('intAdvise').value.trim();
|
||||
var group=document.getElementById('intGroup').value;
|
||||
if(!advise){showToast('请填写综合解读建议');return;}
|
||||
if(!group){showToast('请选择五类人群重新分类');return;}
|
||||
t.advise=advise;t.group=group;t.status='已完成';t.done='2026-09-07';
|
||||
var signed=document.getElementById('signHolder').textContent.indexOf('电子签名')!==-1;
|
||||
t.advise=advise;t.group=group;t.status=3;t.interpretDate=today;
|
||||
t.beforeGroup=t.beforeGroup||'e';
|
||||
t.doctor=t.doctor||'张秀兰';
|
||||
closeModal('intMask');renderTable();
|
||||
showToast('「'+t.name+'」报告解读已完成,结果同步至健康档案');
|
||||
showToast(signed?'「'+t.name+'」报告解读已完成,结果同步至健康档案':'「'+t.name+'」报告解读已完成,员工签字将在 PAD 端确认');
|
||||
}
|
||||
|
||||
/* ===== 解读详情弹窗 ===== */
|
||||
function openDetail(id){
|
||||
var t=tasks.find(function(x){return x.id===id;});
|
||||
var report=buildReport(t);
|
||||
document.getElementById('detailTitle').textContent='解读详情 · '+t.name;
|
||||
document.getElementById('dConclusion').textContent=report.conclusion;
|
||||
document.getElementById('dSuggest').textContent=report.suggest;
|
||||
document.getElementById('dReport').innerHTML=renderReportHtml(report);
|
||||
document.getElementById('dEmp').innerHTML=empBasicHtml(t);
|
||||
document.getElementById('dAdvise').textContent=t.advise||'—';
|
||||
document.getElementById('dGroupBefore').innerHTML='解读前:<span class="group-badge" style="color:'+(GROUP_BADGE[t.beforeGroup]||'#999')+';background:'+(GROUP_BADGE[t.beforeGroup]||'#999')+'1a;">'+(GROUP_MAP[t.beforeGroup]||'健康-E类')+'</span>';
|
||||
document.getElementById('dGroupAfter').innerHTML='解读后:<span class="group-badge" style="color:'+(GROUP_BADGE[t.group]||'#999')+';background:'+(GROUP_BADGE[t.group]||'#999')+'1a;">'+(GROUP_MAP[t.group]||'健康-E类')+'</span>';
|
||||
document.getElementById('dSign').innerHTML='<div class="sign-box" style="min-height:80px;"><svg width="180" height="52" viewBox="0 0 180 52"><path d="M10 38c14-20 20 12 32-6 9-14 14 16 26-2 8-12 12 10 22-2 8-12 14 8 26 2" stroke="#14213D" stroke-width="2.4" fill="none" stroke-linecap="round"/></svg><div style="font-size:var(--font-xs);color:var(--text-placeholder);">'+t.name+' · '+t.interpretDate+' 于 PAD 端确认</div></div>';
|
||||
document.getElementById('dDoctor').textContent=t.doctor||'—';
|
||||
document.getElementById('dDate').textContent=t.interpretDate||'—';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 编辑截止日期 ===== */
|
||||
var editingId=null;
|
||||
function openEdit(id){
|
||||
var t=tasks.find(function(x){return x.id===id;});
|
||||
editingId=id;
|
||||
document.getElementById('editDeadline').value=t.deadline;
|
||||
document.getElementById('editMask').classList.add('open');
|
||||
}
|
||||
function saveEdit(){
|
||||
var t=tasks.find(function(x){return x.id===editingId;});
|
||||
var d=document.getElementById('editDeadline').value;
|
||||
if(!d){showToast('请选择截止日期');return;}
|
||||
t.deadline=d;
|
||||
closeModal('editMask');renderTable();
|
||||
showToast('截止日期已更新');
|
||||
}
|
||||
|
||||
/* ===== 生成记录 / 重新生成 ===== */
|
||||
var genLogs=[
|
||||
{handled:120,pending:135,status:'已完成',prompt:'',create:'2026-09-01 09:00',start:'2026-09-01 09:00',end:'2026-09-01 09:12',operator:'系统'},
|
||||
{handled:0,pending:11,status:'进行中',prompt:'正在生成解读任务…',create:nowHM(),start:nowHM(),end:'',operator:'张秀兰'}
|
||||
];
|
||||
function genStatusHtml(s){
|
||||
if(s==='已完成')return '<span class="badge badge--success">已完成</span>';
|
||||
return '<span class="badge badge--warning">进行中</span>';
|
||||
}
|
||||
function openGenRecord(){
|
||||
renderGenRecord();
|
||||
document.getElementById('genMask').classList.add('open');
|
||||
document.getElementById('genDrawer').classList.add('open');
|
||||
}
|
||||
function renderGenRecord(){
|
||||
document.getElementById('genBody').innerHTML=genLogs.map(function(g,i){
|
||||
return '<tr><td>'+(i+1)+'</td><td>'+(g.pending?g.handled+'/'+g.pending:'—')+'</td><td>'+genStatusHtml(g.status)+'</td><td style="text-align:left;">'+(g.prompt||'—')+'</td><td>'+g.create+'</td><td>'+g.start+'</td><td>'+(g.end||'—')+'</td><td>'+g.operator+'</td></tr>';
|
||||
}).join('')||'<tr><td colspan="8" class="td-empty">暂无生成记录</td></tr>';
|
||||
}
|
||||
function resetTask(){
|
||||
var btn=document.getElementById('btnResetTask');
|
||||
btn.disabled=true;btn.textContent='生成中…';
|
||||
showToast('已提交重新生成解读任务');
|
||||
setTimeout(function(){
|
||||
btn.disabled=false;btn.textContent='重新生成解读任务';
|
||||
genLogs.unshift({handled:0,pending:11,status:'进行中',prompt:'正在生成解读任务…',create:nowHM(),start:nowHM(),end:'',operator:'张秀兰'});
|
||||
showToast('解读任务已重新生成');
|
||||
},1500);
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
|
||||
@@ -1,353 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>入库记录 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.10);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:200px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 14px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;padding-bottom:24px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-select{height:36px;min-width:140px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);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 8px center;cursor:pointer;outline:none;appearance:none;-webkit-appearance:none;}
|
||||
.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;min-width:120px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.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;white-space:nowrap;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.action-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;background:#fff;margin-top:16px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1600px;}
|
||||
thead th{background:#FAFAFA;padding:10px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:12px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
thead tr th:last-child,tbody td:last-child{position:sticky;right:0;z-index:5;background:#fff;box-shadow:-4px 0 8px rgba(0,0,0,0.04);}
|
||||
thead tr th:last-child{z-index:8;background:#FAFAFA;}
|
||||
tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.td-empty{text-align:center;padding:48px 0;color:var(--text-placeholder);}
|
||||
.badge{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.badge--info{background:#E6F7FF;color:#096DD9;border:1px solid #91D5FF;}
|
||||
.badge--warning{background:#FFFBE6;color:#D48806;border:1px solid #FFE58F;}
|
||||
.badge--success{background:#F6FFED;color:#389E0D;border:1px solid #B7EB8F;}
|
||||
.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);}
|
||||
.page-btn{min-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;padding:0 6px;transition:all .2s;}
|
||||
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.page-btn:disabled{opacity:.4;cursor:not-allowed;background:#fff;color:var(--text-placeholder);border-color:var(--border);}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:680px;max-height:82vh;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);display:flex;flex-direction:column;}
|
||||
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-base);font-weight:600;flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.modal__close:hover{color:var(--text-primary);}
|
||||
.modal__body{flex:1;overflow-y:auto;padding:24px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.record-table{width:100%;min-width:0;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
.record-table th{background:#FAFAFA;padding:8px 10px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.record-table td{padding:10px;border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.record-table th:last-child,.record-table td:last-child{position:static;box-shadow:none;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 12px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid var(--border);}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:110px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M14 6.5l7 3.5v4.5c0 4.2-2.9 6.8-7 7.5-4.1-.7-7-3.3-7-7.5V10l7-3.5z" stroke="#fff" stroke-width="1.8" fill="none"/><path d="M11 13.5h6M14 10.5v6" stroke="#fff" stroke-width="1.8" stroke-linecap="round"/></svg> 一线医疗</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-visit-data.html">档案</a>
|
||||
<a href="config-medical-point.html">基础配置</a>
|
||||
<a href="daily-treatment-staff.html" class="active">日常业务</a>
|
||||
<a href="bed-device.html">床头呼叫</a>
|
||||
<a href="stat-clinic-chart.html">数据统计</a>
|
||||
<a href="hut-banner.html">健康小屋</a>
|
||||
<a href="alert-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏(当前一级分组「日常业务」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">日常业务</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>日常诊疗</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-treatment-staff.html" class="sidebar-item">员工就诊</a>
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup open">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item active">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>任务管理</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-follow-task.html" class="sidebar-item">随访任务</a>
|
||||
<a href="daily-interpret.html" class="sidebar-item">解读任务</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-education.html" class="sidebar-item">健康宣教管理</a>
|
||||
<a href="daily-interpret-manage.html" class="sidebar-item">报告解读管理</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
|
||||
<!-- [交互] 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>药品名称</label>
|
||||
<input class="filter-input" id="filterMed" placeholder="请输入药品名称">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>医疗点所属单位</label>
|
||||
<select class="filter-select" id="filterUnit" onchange="onFilterUnit()" style="min-width:120px;">
|
||||
<option value="">全部单位</option>
|
||||
<option>采油一厂</option><option>采油二厂</option><option>第四采油厂</option><option>采气一厂</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>入库医疗点</label>
|
||||
<select class="filter-select" id="filterPoint" style="min-width:160px;">
|
||||
<option value="">全部医疗点</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>入库类型</label>
|
||||
<select class="filter-select" id="filterType" style="min-width:110px;">
|
||||
<option value="">全部类型</option>
|
||||
<option>采购入库</option><option>退药入库</option><option>调拨入库</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>入库日期</label>
|
||||
<input class="filter-input" type="date" id="filterFrom" style="min-width:130px;">
|
||||
<span style="color:var(--text-placeholder);">至</span>
|
||||
<input class="filter-input" type="date" id="filterTo" style="min-width:130px;">
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="applyFilter()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.3"/><path d="M9.5 9.5L13 13" stroke="#fff" stroke-width="1.3" stroke-linecap="round"/></svg>查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="resetFilter()">重置</button>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 操作栏:只读台账,无新增/编辑;导出为异步任务 -->
|
||||
<div class="action-bar">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openExportTasks()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<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><th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<span id="pageInfo"></span>
|
||||
<button class="page-btn" id="prevBtn" onclick="turnPage(-1)">上一页</button>
|
||||
<span id="pageNum" style="min-width:64px;text-align:center;"></span>
|
||||
<button class="page-btn" id="nextBtn" onclick="turnPage(1)">下一页</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 入库单详情弹窗 -->
|
||||
<div class="modal-mask" id="detailMask">
|
||||
<div class="modal">
|
||||
<div class="modal__header"><span id="detailTitle">入库单详情</span><button class="modal__close" onclick="closeModal('detailMask')">×</button></div>
|
||||
<div class="modal__body" id="detailBody"></div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeModal('detailMask')">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导出任务:异步任务列表 -->
|
||||
<div class="modal-mask" id="taskMask">
|
||||
<div class="modal">
|
||||
<div class="modal__header"><span>入库流水导出任务</span><button class="modal__close" onclick="closeModal('taskMask')">×</button></div>
|
||||
<div class="modal__body">
|
||||
<table class="record-table">
|
||||
<thead><tr><th>文件名称</th><th>时间</th><th>状态</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>入库流水-2026年9月.xlsx</td><td>2026-09-06 16:20:11</td><td><span class="badge badge--success">成功</span></td><td><button class="btn btn-link" onclick="showToast('文件下载中…')">下载</button></td></tr>
|
||||
<tr><td>入库流水-2026年8月.xlsx</td><td>2026-08-31 09:05:47</td><td><span class="badge badge--success">成功</span></td><td><button class="btn btn-link" onclick="showToast('文件下载中…')">下载</button></td></tr>
|
||||
<tr><td>入库流水-近7天.xlsx</td><td>2026-09-07 08:41:33</td><td><span class="badge badge--warning">导出中…</span></td><td>—</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeModal('taskMask')">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* ===== 演示数据(脱敏) ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂','姬塬作业区医疗点':'采油一厂'};
|
||||
var pointMap={
|
||||
'采油一厂':['樊学作业区医疗点','安塞采油队长住点医疗室','姬塬作业区医疗点'],
|
||||
'采油二厂':['姬圪台作业区医疗点','桐园作业区医疗点'],
|
||||
'第四采油厂':['西峰基地医疗点'],
|
||||
'采气一厂':['靖边气田医疗点','乌审旗采气区医疗点']
|
||||
};
|
||||
/* 入库流水:供应商均为虚构名称;入库类型为采购/退药/调拨 */
|
||||
var stockIns=[
|
||||
{no:'RK20260905001',m:'阿莫西林胶囊',spec:'0.25g*24粒',unit:'盒',qty:60,type:'采购入库',batch:'AMX-20260612',expire:'2028-05-31',date:'2026-09-05',operator:'李桂芳',point:'樊学作业区医疗点',supplier:'CQ医药配送有限公司',price:18.5,remark:'季度常规补货,验收合格'},
|
||||
{no:'RK20260905002',m:'硝苯地平控释片',spec:'30mg*7片',unit:'盒',qty:30,type:'采购入库',batch:'NIF-20260418',expire:'2028-03-31',date:'2026-09-05',operator:'李桂芳',point:'樊学作业区医疗点',supplier:'CQ医药配送有限公司',price:32.6,remark:'慢病用药加储'},
|
||||
{no:'RK20260903001',m:'蒙脱石散',spec:'3g*10袋',unit:'盒',qty:40,type:'采购入库',batch:'MTX-20260225',expire:'2028-01-31',date:'2026-09-03',operator:'张秀兰',point:'姬圪台作业区医疗点',supplier:'陇原药业仓储中心',price:13.9,remark:'夏秋季肠道用药备货'},
|
||||
{no:'RK20260901001',m:'布洛芬缓释胶囊',spec:'0.3g*20粒',unit:'盒',qty:50,type:'采购入库',batch:'IBU-20260311',expire:'2028-02-28',date:'2026-09-01',operator:'曲志明',point:'姬圪台作业区医疗点',supplier:'陇原药业仓储中心',price:16.0,remark:''},
|
||||
{no:'RK20260828001',m:'藿香正气口服液',spec:'10ml*10支',unit:'盒',qty:35,type:'调拨入库',batch:'HXX-20251120',expire:'2027-10-31',date:'2026-08-28',operator:'刘玉梅',point:'乌审旗采气区医疗点',supplier:'调拨自靖边气田医疗点',price:15.2,remark:'高温季节防暑用药跨点调拨'},
|
||||
{no:'RK20260826001',m:'云南白药气雾剂',spec:'85g+30g',unit:'盒',qty:20,type:'采购入库',batch:'YNB-20260115',expire:'2029-01-14',date:'2026-08-26',operator:'闫婷',point:'西峰基地医疗点',supplier:'金城医药集团(虚构)',price:38.0,remark:'外伤应急用药'},
|
||||
{no:'RK20260825001',m:'复方氯化钠注射液',spec:'500ml',unit:'瓶',qty:30,type:'采购入库',batch:'NS-20260408',expire:'2027-12-31',date:'2026-08-25',operator:'闫婷',point:'西峰基地医疗点',supplier:'金城医药集团(虚构)',price:6.5,remark:'冷链运输,温度记录合格'},
|
||||
{no:'RK20260822001',m:'二甲双胍缓释片',spec:'0.5g*30片',unit:'盒',qty:25,type:'退药入库',batch:'MET-20250906',expire:'2027-08-31',date:'2026-08-22',operator:'高建军',point:'西峰基地医疗点',supplier:'退药人:慢病患者余量退回',price:25.8,remark:'外包装完好,验收后重新入册'},
|
||||
{no:'RK20260818001',m:'阿莫西林胶囊',spec:'0.25g*24粒',unit:'盒',qty:40,type:'采购入库',batch:'AMX-20260612',expire:'2028-05-31',date:'2026-08-18',operator:'白瑞',point:'安塞采油队长住点医疗室',supplier:'CQ医药配送有限公司',price:18.5,remark:''},
|
||||
{no:'RK20260812001',m:'蒙脱石散',spec:'3g*10袋',unit:'盒',qty:30,type:'调拨入库',batch:'MTX-20260225',expire:'2028-01-31',date:'2026-08-12',operator:'呼建国',point:'靖边气田医疗点',supplier:'调拨自桐园作业区医疗点',price:13.9,remark:'支援井站夏秋季备药'}
|
||||
];
|
||||
var typeBadge={'采购入库':'badge--info','退药入库':'badge--warning','调拨入库':'badge--success'};
|
||||
|
||||
/* ===== 列表 ===== */
|
||||
var pageSize=10,currentPage=1;
|
||||
function onFilterUnit(){
|
||||
var unit=document.getElementById('filterUnit').value;
|
||||
var sel=document.getElementById('filterPoint');
|
||||
sel.innerHTML='<option value="">全部医疗点</option>';
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
}
|
||||
function currentData(){
|
||||
var med=document.getElementById('filterMed').value.trim();
|
||||
var unit=document.getElementById('filterUnit').value;
|
||||
var point=document.getElementById('filterPoint').value;
|
||||
var type=document.getElementById('filterType').value;
|
||||
var from=document.getElementById('filterFrom').value;
|
||||
var to=document.getElementById('filterTo').value;
|
||||
return stockIns.filter(function(r){
|
||||
return (!med||r.m.indexOf(med)!==-1)
|
||||
&&(!unit||pointUnit[r.point]===unit)&&(!point||r.point===point)
|
||||
&&(!type||r.type===type)&&(!from||r.date>=from)&&(!to||r.date<=to);
|
||||
});
|
||||
}
|
||||
function renderTable(){
|
||||
var list=currentData();
|
||||
var start=(currentPage-1)*pageSize,pageData=list.slice(start,start+pageSize);
|
||||
var totalPages=Math.ceil(list.length/pageSize)||1;
|
||||
document.getElementById('pageInfo').textContent='共 '+list.length+' 条记录';
|
||||
document.getElementById('pageNum').textContent=currentPage+'/'+totalPages;
|
||||
document.getElementById('prevBtn').disabled=currentPage<=1;
|
||||
document.getElementById('nextBtn').disabled=currentPage>=totalPages;
|
||||
var tbody=document.getElementById('tableBody');
|
||||
if(!pageData.length){tbody.innerHTML='<tr><td colspan="13" class="td-empty">暂无匹配数据</td></tr>';return;}
|
||||
var html='';
|
||||
pageData.forEach(function(r,i){
|
||||
html+='<tr>'
|
||||
+'<td>'+(start+i+1)+'</td>'
|
||||
+'<td>'+r.no+'</td>'
|
||||
+'<td style="font-weight:600;">'+r.m+'</td><td>'+r.spec+'</td><td>'+r.unit+'</td>'
|
||||
+'<td style="color:var(--success);font-weight:600;">+'+r.qty+'</td>'
|
||||
+'<td><span class="badge '+typeBadge[r.type]+'">'+r.type+'</span></td>'
|
||||
+'<td>'+r.batch+'</td><td>'+r.expire+'</td><td>'+r.date+'</td>'
|
||||
+'<td>'+r.operator+'</td><td>'+r.point+'</td>'
|
||||
+'<td class="td-actions"><button class="btn btn-link" onclick="openDetail(\''+r.no+'\')">详情</button></td></tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
}
|
||||
function applyFilter(){currentPage=1;renderTable();}
|
||||
function resetFilter(){
|
||||
['filterMed','filterFrom','filterTo'].forEach(function(k){document.getElementById(k).value='';});
|
||||
document.getElementById('filterUnit').value='';onFilterUnit();
|
||||
document.getElementById('filterType').value='';
|
||||
applyFilter();
|
||||
}
|
||||
function turnPage(d){
|
||||
var totalPages=Math.ceil(currentData().length/pageSize)||1;
|
||||
currentPage=Math.min(Math.max(1,currentPage+d),totalPages);
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ===== 详情弹窗 ===== */
|
||||
function openDetail(no){
|
||||
var r=stockIns.find(function(x){return x.no===no;});
|
||||
document.getElementById('detailTitle').textContent='入库单详情 · '+r.no;
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v||'—')+'</div></div>';}
|
||||
document.getElementById('detailBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">单据信息</div>'
|
||||
+'<div class="detail-grid">'+d('入库单号',r.no)+d('入库类型','<span class="badge '+typeBadge[r.type]+'">'+r.type+'</span>')+d('入库日期',r.date)+d('操作人',r.operator)+d('医疗点所属单位',pointUnit[r.point])+d('入库医疗点',r.point)+d(r.type==='采购入库'?'供应商':'来源',r.supplier,true)+'</div>'
|
||||
+'<div class="form-section">药品明细</div>'
|
||||
+'<div class="detail-grid">'+d('药品名称',r.m)+d('规格',r.spec)+d('单位',r.unit)+d('入库数量','<b style="color:var(--success);">+'+r.qty+'</b> '+r.unit)+d('批次号',r.batch)+d('有效期至',r.expire)+d('进货单价',(r.type==='退药入库'?'—':'¥'+r.price.toFixed(2)+' 元/'+r.unit))+d('入库金额',(r.type==='退药入库'?'—':'¥'+(r.price*r.qty).toFixed(2)+' 元'))+d('备注',r.remark,true)+'</div>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
function closeModal(id){document.getElementById(id).classList.remove('open');}
|
||||
/* ===== 异步导出与导出任务 ===== */
|
||||
function doExport(){showToast('导出任务已提交,完成后可在「查看导出任务」下载');}
|
||||
function openExportTasks(){document.getElementById('taskMask').classList.add('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
|
||||
renderTable();
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,357 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>出库记录 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.10);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:200px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 14px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;padding-bottom:24px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-select{height:36px;min-width:140px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);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 8px center;cursor:pointer;outline:none;appearance:none;-webkit-appearance:none;}
|
||||
.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;min-width:120px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.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;white-space:nowrap;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.action-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;background:#fff;margin-top:16px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.table-card{background:#fff;border-radius:0 0 var(--radius-md) var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0;min-width:1600px;}
|
||||
thead th{background:#FAFAFA;padding:10px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:12px 14px;text-align:center;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
thead tr th:last-child,tbody td:last-child{position:sticky;right:0;z-index:5;background:#fff;box-shadow:-4px 0 8px rgba(0,0,0,0.04);}
|
||||
thead tr th:last-child{z-index:8;background:#FAFAFA;}
|
||||
tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.td-empty{text-align:center;padding:48px 0;color:var(--text-placeholder);}
|
||||
.badge{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.badge--info{background:#E6F7FF;color:#096DD9;border:1px solid #91D5FF;}
|
||||
.badge--danger{background:#FFF1F0;color:#CF1322;border:1px solid #FFCCC7;}
|
||||
.badge--success{background:#F6FFED;color:#389E0D;border:1px solid #B7EB8F;}
|
||||
.badge--warning{background:#FFFBE6;color:#D48806;border:1px solid #FFE58F;}
|
||||
.badge--muted{background:#F5F5F5;color:var(--text-secondary);border:1px solid var(--border);}
|
||||
.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);}
|
||||
.page-btn{min-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;padding:0 6px;transition:all .2s;}
|
||||
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.page-btn:disabled{opacity:.4;cursor:not-allowed;background:#fff;color:var(--text-placeholder);border-color:var(--border);}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:680px;max-height:82vh;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);display:flex;flex-direction:column;}
|
||||
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);font-size:var(--font-base);font-weight:600;flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.modal__close:hover{color:var(--text-primary);}
|
||||
.modal__body{flex:1;overflow-y:auto;padding:24px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.record-table{width:100%;min-width:0;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
.record-table th{background:#FAFAFA;padding:8px 10px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.record-table td{padding:10px;border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.record-table th:last-child,.record-table td:last-child{position:static;box-shadow:none;}
|
||||
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 12px;padding-left:8px;border-left:3px solid var(--primary);}
|
||||
.form-section:first-child{margin-top:0;}
|
||||
.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.detail-item{display:flex;border-bottom:1px solid var(--border);}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:110px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M14 6.5l7 3.5v4.5c0 4.2-2.9 6.8-7 7.5-4.1-.7-7-3.3-7-7.5V10l7-3.5z" stroke="#fff" stroke-width="1.8" fill="none"/><path d="M11 13.5h6M14 10.5v6" stroke="#fff" stroke-width="1.8" stroke-linecap="round"/></svg> 一线医疗</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-visit-data.html">档案</a>
|
||||
<a href="config-medical-point.html">基础配置</a>
|
||||
<a href="daily-treatment-staff.html" class="active">日常业务</a>
|
||||
<a href="bed-device.html">床头呼叫</a>
|
||||
<a href="stat-clinic-chart.html">数据统计</a>
|
||||
<a href="hut-banner.html">健康小屋</a>
|
||||
<a href="alert-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏(当前一级分组「日常业务」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">日常业务</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>日常诊疗</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-treatment-staff.html" class="sidebar-item">员工就诊</a>
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup open">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item active">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>任务管理</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-follow-task.html" class="sidebar-item">随访任务</a>
|
||||
<a href="daily-interpret.html" class="sidebar-item">解读任务</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-education.html" class="sidebar-item">健康宣教管理</a>
|
||||
<a href="daily-interpret-manage.html" class="sidebar-item">报告解读管理</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
|
||||
<!-- [交互] 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>药品名称</label>
|
||||
<input class="filter-input" id="filterMed" placeholder="请输入药品名称">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>医疗点所属单位</label>
|
||||
<select class="filter-select" id="filterUnit" onchange="onFilterUnit()" style="min-width:120px;">
|
||||
<option value="">全部单位</option>
|
||||
<option>采油一厂</option><option>采油二厂</option><option>第四采油厂</option><option>采气一厂</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>出库医疗点</label>
|
||||
<select class="filter-select" id="filterPoint" style="min-width:160px;">
|
||||
<option value="">全部医疗点</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>出库类型</label>
|
||||
<select class="filter-select" id="filterType" style="min-width:110px;">
|
||||
<option value="">全部类型</option>
|
||||
<option>处方出库</option><option>非处方出库</option><option>报损出库</option><option>调拨出库</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>出库日期</label>
|
||||
<input class="filter-input" type="date" id="filterFrom" style="min-width:130px;">
|
||||
<span style="color:var(--text-placeholder);">至</span>
|
||||
<input class="filter-input" type="date" id="filterTo" style="min-width:130px;">
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="applyFilter()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.3"/><path d="M9.5 9.5L13 13" stroke="#fff" stroke-width="1.3" stroke-linecap="round"/></svg>查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="resetFilter()">重置</button>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 操作栏:只读台账,无新增/编辑;导出为异步任务 -->
|
||||
<div class="action-bar">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button>
|
||||
<button class="btn btn-default" onclick="openExportTasks()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<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="tableBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<span id="pageInfo"></span>
|
||||
<button class="page-btn" id="prevBtn" onclick="turnPage(-1)">上一页</button>
|
||||
<span id="pageNum" style="min-width:64px;text-align:center;"></span>
|
||||
<button class="page-btn" id="nextBtn" onclick="turnPage(1)">下一页</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 出库单详情弹窗 -->
|
||||
<div class="modal-mask" id="detailMask">
|
||||
<div class="modal">
|
||||
<div class="modal__header"><span id="detailTitle">出库单详情</span><button class="modal__close" onclick="closeModal('detailMask')">×</button></div>
|
||||
<div class="modal__body" id="detailBody"></div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeModal('detailMask')">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导出任务:异步任务列表 -->
|
||||
<div class="modal-mask" id="taskMask">
|
||||
<div class="modal">
|
||||
<div class="modal__header"><span>出库流水导出任务</span><button class="modal__close" onclick="closeModal('taskMask')">×</button></div>
|
||||
<div class="modal__body">
|
||||
<table class="record-table">
|
||||
<thead><tr><th>文件名称</th><th>时间</th><th>状态</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>出库流水-2026年9月.xlsx</td><td>2026-09-06 16:24:02</td><td><span class="badge badge--success">成功</span></td><td><button class="btn btn-link" onclick="showToast('文件下载中…')">下载</button></td></tr>
|
||||
<tr><td>出库流水-2026年8月.xlsx</td><td>2026-08-31 09:12:56</td><td><span class="badge badge--success">成功</span></td><td><button class="btn btn-link" onclick="showToast('文件下载中…')">下载</button></td></tr>
|
||||
<tr><td>出库流水-近7天.xlsx</td><td>2026-09-07 08:45:19</td><td><span class="badge badge--warning">导出中…</span></td><td>—</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeModal('taskMask')">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* ===== 演示数据(脱敏) ===== */
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂','姬塬作业区医疗点':'采油一厂'};
|
||||
var pointMap={
|
||||
'采油一厂':['樊学作业区医疗点','安塞采油队长住点医疗室','姬塬作业区医疗点'],
|
||||
'采油二厂':['姬圪台作业区医疗点','桐园作业区医疗点'],
|
||||
'第四采油厂':['西峰基地医疗点'],
|
||||
'采气一厂':['靖边气田医疗点','乌审旗采气区医疗点']
|
||||
};
|
||||
/* 出库流水:处方出库与「员工就诊/非员工就诊」记录一一对应 */
|
||||
var stockOuts=[
|
||||
{no:'CK20260906001',m:'阿莫西林胶囊',spec:'0.25g*24粒',unit:'盒',qty:2,type:'处方出库',ref:'员工就诊·呼建国',date:'2026-09-06',operator:'刘玉梅',point:'靖边气田医疗点',link:'呼建国 / 上呼吸道感染 / 2026-09-06 09:30',remark:'就诊开药自动出库'},
|
||||
{no:'CK20260905001',m:'硝苯地平控释片',spec:'30mg*7片',unit:'盒',qty:1,type:'处方出库',ref:'员工就诊·赵万福',date:'2026-09-05',operator:'曲志明',point:'桐园作业区医疗点',link:'赵万福 / 高血压病(2级) / 2026-09-05 15:10',remark:'就诊开药自动出库'},
|
||||
{no:'CK20260905002',m:'硝苯地平控释片',spec:'30mg*7片',unit:'盒',qty:1,type:'处方出库',ref:'非员工就诊·马凤莲',date:'2026-09-05',operator:'李桂芳',point:'樊学作业区医疗点',link:'马凤莲 / 高血压病(2级) / 2026-09-05 10:10',remark:'家属就诊开药'},
|
||||
{no:'CK20260904001',m:'云南白药气雾剂',spec:'85g+30g',unit:'盒',qty:1,type:'处方出库',ref:'员工就诊·杨慧敏',date:'2026-09-04',operator:'石维国',point:'樊学作业区医疗点',link:'杨慧敏 / 踝关节扭伤 / 2026-09-04 11:00',remark:''},
|
||||
{no:'CK20260904002',m:'二甲双胍缓释片',spec:'0.5g*30片',unit:'盒',qty:2,type:'处方出库',ref:'非员工就诊·杨来贵',date:'2026-09-04',operator:'曲志明',point:'姬圪台作业区医疗点',link:'杨来贵 / 2型糖尿病复诊 / 2026-09-04 15:40',remark:''},
|
||||
{no:'CK20260902001',m:'蒙脱石散',spec:'3g*10袋',unit:'盒',qty:1,type:'处方出库',ref:'员工就诊·田震',date:'2026-09-02',operator:'李桂芳',point:'樊学作业区医疗点',link:'田震 / 急性胃肠炎 / 2026-09-02 16:45',remark:'同单另出复方氯化钠1瓶'},
|
||||
{no:'CK20260902002',m:'复方氯化钠注射液',spec:'500ml',unit:'瓶',qty:1,type:'处方出库',ref:'员工就诊·田震',date:'2026-09-02',operator:'李桂芳',point:'樊学作业区医疗点',link:'田震 / 急性胃肠炎 / 2026-09-02 16:45',remark:'静脉补液'},
|
||||
{no:'CK20260830001',m:'藿香正气口服液',spec:'10ml*10支',unit:'盒',qty:3,type:'非处方出库',ref:'井站防暑应急领用',date:'2026-08-30',operator:'刘玉梅',point:'乌审旗采气区医疗点',link:'领取班组:苏里格南巡检二班',remark:'高温季节一线班组应急领用,未走就诊'},
|
||||
{no:'CK20260828001',m:'蒙脱石散',spec:'3g*10袋',unit:'盒',qty:20,type:'调拨出库',ref:'调拨至乌审旗采气区医疗点',date:'2026-08-28',operator:'张秀兰',point:'桐园作业区医疗点',link:'对应入库单:RK20260828001',remark:'防暑止泻用药跨点支援'},
|
||||
{no:'CK20260820001',m:'布洛芬缓释胶囊',spec:'0.3g*20粒',unit:'盒',qty:3,type:'报损出库',ref:'批号IBU-20250120过期',date:'2026-08-20',operator:'高建军',point:'西峰基地医疗点',link:'报损原因:超过有效期,已拍照留证待销毁',remark:'双人复核确认'}
|
||||
];
|
||||
var typeBadge={'处方出库':'badge--info','非处方出库':'badge--muted','报损出库':'badge--danger','调拨出库':'badge--success'};
|
||||
|
||||
/* ===== 列表 ===== */
|
||||
var pageSize=10,currentPage=1;
|
||||
function onFilterUnit(){
|
||||
var unit=document.getElementById('filterUnit').value;
|
||||
var sel=document.getElementById('filterPoint');
|
||||
sel.innerHTML='<option value="">全部医疗点</option>';
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
}
|
||||
function currentData(){
|
||||
var med=document.getElementById('filterMed').value.trim();
|
||||
var unit=document.getElementById('filterUnit').value;
|
||||
var point=document.getElementById('filterPoint').value;
|
||||
var type=document.getElementById('filterType').value;
|
||||
var from=document.getElementById('filterFrom').value;
|
||||
var to=document.getElementById('filterTo').value;
|
||||
return stockOuts.filter(function(r){
|
||||
return (!med||r.m.indexOf(med)!==-1)
|
||||
&&(!unit||pointUnit[r.point]===unit)&&(!point||r.point===point)
|
||||
&&(!type||r.type===type)&&(!from||r.date>=from)&&(!to||r.date<=to);
|
||||
});
|
||||
}
|
||||
function renderTable(){
|
||||
var list=currentData();
|
||||
var start=(currentPage-1)*pageSize,pageData=list.slice(start,start+pageSize);
|
||||
var totalPages=Math.ceil(list.length/pageSize)||1;
|
||||
document.getElementById('pageInfo').textContent='共 '+list.length+' 条记录';
|
||||
document.getElementById('pageNum').textContent=currentPage+'/'+totalPages;
|
||||
document.getElementById('prevBtn').disabled=currentPage<=1;
|
||||
document.getElementById('nextBtn').disabled=currentPage>=totalPages;
|
||||
var tbody=document.getElementById('tableBody');
|
||||
if(!pageData.length){tbody.innerHTML='<tr><td colspan="12" class="td-empty">暂无匹配数据</td></tr>';return;}
|
||||
var html='';
|
||||
pageData.forEach(function(r,i){
|
||||
html+='<tr>'
|
||||
+'<td>'+(start+i+1)+'</td>'
|
||||
+'<td>'+r.no+'</td>'
|
||||
+'<td style="font-weight:600;">'+r.m+'</td><td>'+r.spec+'</td><td>'+r.unit+'</td>'
|
||||
+'<td style="color:var(--danger);font-weight:600;">-'+r.qty+'</td>'
|
||||
+'<td><span class="badge '+typeBadge[r.type]+'">'+r.type+'</span></td>'
|
||||
+'<td style="text-align:left;max-width:180px;overflow:hidden;text-overflow:ellipsis;" title="'+r.ref+'">'+r.ref+'</td>'
|
||||
+'<td>'+r.date+'</td><td>'+r.operator+'</td><td>'+r.point+'</td>'
|
||||
+'<td class="td-actions"><button class="btn btn-link" onclick="openDetail(\''+r.no+'\')">详情</button></td></tr>';
|
||||
});
|
||||
tbody.innerHTML=html;
|
||||
}
|
||||
function applyFilter(){currentPage=1;renderTable();}
|
||||
function resetFilter(){
|
||||
['filterMed','filterFrom','filterTo'].forEach(function(k){document.getElementById(k).value='';});
|
||||
document.getElementById('filterUnit').value='';onFilterUnit();
|
||||
document.getElementById('filterType').value='';
|
||||
applyFilter();
|
||||
}
|
||||
function turnPage(d){
|
||||
var totalPages=Math.ceil(currentData().length/pageSize)||1;
|
||||
currentPage=Math.min(Math.max(1,currentPage+d),totalPages);
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ===== 详情弹窗 ===== */
|
||||
function openDetail(no){
|
||||
var r=stockOuts.find(function(x){return x.no===no;});
|
||||
document.getElementById('detailTitle').textContent='出库单详情 · '+r.no;
|
||||
function d(k,v,full){return '<div class="detail-item'+(full?' detail-item--full':'')+'"><div class="dk">'+k+'</div><div class="dv">'+(v||'—')+'</div></div>';}
|
||||
document.getElementById('detailBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">单据信息</div>'
|
||||
+'<div class="detail-grid">'+d('出库单号',r.no)+d('出库类型','<span class="badge '+typeBadge[r.type]+'">'+r.type+'</span>')+d('出库日期',r.date)+d('操作人',r.operator)+d('医疗点所属单位',pointUnit[r.point])+d('出库医疗点',r.point)+'</div>'
|
||||
+'<div class="form-section">关联信息</div>'
|
||||
+'<div class="detail-grid">'+d('关联单据',r.ref,true)+d(r.type==='处方出库'?'就诊摘要':'说明',r.link,true)+'</div>'
|
||||
+'<div class="form-section">药品明细</div>'
|
||||
+'<div class="detail-grid">'+d('药品名称',r.m)+d('规格',r.spec)+d('单位',r.unit)+d('出库数量','<b style="color:var(--danger);">-'+r.qty+'</b> '+r.unit)+d('备注',r.remark,true)+'</div>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
|
||||
/* ===== 通用 ===== */
|
||||
function closeModal(id){document.getElementById(id).classList.remove('open');}
|
||||
/* ===== 异步导出与导出任务 ===== */
|
||||
function doExport(){showToast('导出任务已提交,完成后可在「查看导出任务」下载');}
|
||||
function openExportTasks(){document.getElementById('taskMask').classList.add('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
|
||||
renderTable();
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -146,13 +146,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item active">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -251,17 +245,10 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 联系电话</span><input class="form-control" id="fPhone" placeholder="手机号"></div>
|
||||
<div class="form-item"><span class="form-label">与员工关系</span><input class="form-control" id="fRel" placeholder="如:家属/协作单位人员"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 就诊时间</span><input class="form-control" type="datetime-local" id="fTime"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 医疗点所属单位</span>
|
||||
<select class="form-control" id="fUnit" onchange="onFormUnit()"><option value="">请选择单位</option><option>采油一厂</option><option>采油二厂</option><option>第四采油厂</option><option>采气一厂</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 就诊医疗点</span>
|
||||
<select class="form-control" id="fPoint"><option value="">请先选择单位</option></select></div>
|
||||
<select class="form-control" id="fPoint"><option value="">请选择医疗点</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 就诊医生</span>
|
||||
<select class="form-control" id="fDoctor"><option value="">请选择医生</option></select></div>
|
||||
<div class="form-item"><span class="form-label">纳入随访</span>
|
||||
<div class="radio-group">
|
||||
<label class="radio"><input type="radio" name="fFollow" value="是">是</label>
|
||||
<label class="radio"><input type="radio" name="fFollow" value="否" checked>否</label>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">诊断信息</div>
|
||||
@@ -357,12 +344,12 @@ var medPool=[
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂','姬塬作业区医疗点':'采油一厂'};
|
||||
/* 非员工就诊:家属/协作单位人员,身份证为虚构号码 */
|
||||
var nonstaffs=[
|
||||
{id:1,user:'马凤莲',sex:'女',age:58,idcard:'622822196803124523',phone:'151****3027',rel:'员工家属',point:'樊学作业区医疗点',disease:'高血压病(2级)',doctor:'李桂芳',time:'2026-09-05 10:10',main:'头晕耳鸣3天',inspect:'血压152/94mmHg',past:'高血压4年',present:'劳累后加重',allergy:'无',revisit:'否',follow:'是',rx:[{m:'硝苯地平控释片',spec:'30mg*7片',num:1,dosage:'一次1片 一日1次'}],advice:'每日监测血压',food:'低盐低脂',sport:'适度散步'},
|
||||
{id:2,user:'杨来贵',sex:'男',age:63,idcard:'620521196307083317',phone:'132****7108',rel:'员工家属',point:'姬圪台作业区医疗点',disease:'2型糖尿病复诊',doctor:'曲志明',time:'2026-09-04 15:40',main:'口渴乏力半月',inspect:'空腹血糖9.2mmol/L',past:'糖尿病8年',present:'血糖控制欠佳',allergy:'无',revisit:'是',follow:'是',rx:[{m:'二甲双胍缓释片',spec:'0.5g*30片',num:2,dosage:'一次1片 一日2次'}],advice:'两周后复查血糖',food:'控制总热量',sport:'餐后快走30分钟'},
|
||||
{id:3,user:'白莲香',sex:'女',age:41,idcard:'612731198502146625',phone:'158****4410',rel:'协作单位人员',point:'桐园作业区医疗点',disease:'急性胃肠炎',doctor:'张秀兰',time:'2026-09-02 11:20',main:'腹痛腹泻1天',inspect:'脐周压痛,肠鸣音活跃',past:'无',present:'进食不洁饭后腹泻',allergy:'无',revisit:'否',follow:'否',rx:[{m:'蒙脱石散',spec:'3g*10袋',num:1,dosage:'一次1袋 一日3次'},{m:'复方氯化钠注射液',spec:'500ml',num:1,dosage:'静脉滴注 1次'}],advice:'补液防脱水',food:'流质饮食',sport:'注意休息'},
|
||||
{id:4,user:'丁胜海',sex:'男',age:52,idcard:'620102197403059116',phone:'139****0213',rel:'员工家属',point:'西峰基地医疗点',disease:'腰肌劳损',doctor:'闫婷',time:'2026-08-30 09:15',main:'腰部酸痛2周',inspect:'腰两侧压痛',past:'久坐工作史',present:'渐进性酸痛',allergy:'磺胺类过敏',revisit:'否',follow:'否',rx:[{m:'布洛芬缓释胶囊',spec:'0.3g*20粒',num:1,dosage:'一次1粒 一日2次'}],advice:'避免久坐,配合理疗',food:'均衡营养',sport:'腰背肌锻炼'},
|
||||
{id:5,user:'周翠兰',sex:'女',age:36,idcard:'610628199001074412',phone:'177****5521',rel:'协作单位人员',point:'乌审旗采气区医疗点',disease:'中暑(先兆)',doctor:'刘玉梅',time:'2026-08-28 14:05',main:'高温作业后头晕出汗',inspect:'体温37.7℃,面色潮红',past:'无',present:'午间露天作业后不适',allergy:'无',revisit:'否',follow:'否',rx:[{m:'藿香正气口服液',spec:'10ml*10支',num:1,dosage:'一次1支 一日2次'}],advice:'阴凉处休息,少量多次饮水',food:'清淡,补充电解质',sport:'避开高温时段'},
|
||||
{id:6,user:'石长有',sex:'男',age:70,idcard:'622801195601021235',phone:'181****6640',rel:'员工家属',point:'安塞采油队长住点医疗室',disease:'冠心病复诊',doctor:'石维国',time:'2026-08-22 10:35',main:'活动后胸闷1月',inspect:'心率78次/分,律齐',past:'冠心病6年',present:'冬季症状加重',allergy:'无',revisit:'是',follow:'是',rx:[],advice:'随身携带急救药物,一月后心内科复诊',food:'低脂高纤维',sport:'避免剧烈运动'}
|
||||
{id:1,user:'马凤莲',sex:'女',age:58,idcard:'622822196803124523',phone:'151****3027',rel:'员工家属',point:'樊学作业区医疗点',disease:'高血压病(2级)',doctor:'李桂芳',time:'2026-09-05 10:10',main:'头晕耳鸣3天',inspect:'血压152/94mmHg',past:'高血压4年',present:'劳累后加重',allergy:'无',revisit:'否',rx:[{m:'硝苯地平控释片',spec:'30mg*7片',num:1,dosage:'一次1片 一日1次'}],advice:'每日监测血压',food:'低盐低脂',sport:'适度散步'},
|
||||
{id:2,user:'杨来贵',sex:'男',age:63,idcard:'620521196307083317',phone:'132****7108',rel:'员工家属',point:'姬圪台作业区医疗点',disease:'2型糖尿病复诊',doctor:'曲志明',time:'2026-09-04 15:40',main:'口渴乏力半月',inspect:'空腹血糖9.2mmol/L',past:'糖尿病8年',present:'血糖控制欠佳',allergy:'无',revisit:'是',rx:[{m:'二甲双胍缓释片',spec:'0.5g*30片',num:2,dosage:'一次1片 一日2次'}],advice:'两周后复查血糖',food:'控制总热量',sport:'餐后快走30分钟'},
|
||||
{id:3,user:'白莲香',sex:'女',age:41,idcard:'612731198502146625',phone:'158****4410',rel:'协作单位人员',point:'桐园作业区医疗点',disease:'急性胃肠炎',doctor:'张秀兰',time:'2026-09-02 11:20',main:'腹痛腹泻1天',inspect:'脐周压痛,肠鸣音活跃',past:'无',present:'进食不洁饭后腹泻',allergy:'无',revisit:'否',rx:[{m:'蒙脱石散',spec:'3g*10袋',num:1,dosage:'一次1袋 一日3次'},{m:'复方氯化钠注射液',spec:'500ml',num:1,dosage:'静脉滴注 1次'}],advice:'补液防脱水',food:'流质饮食',sport:'注意休息'},
|
||||
{id:4,user:'丁胜海',sex:'男',age:52,idcard:'620102197403059116',phone:'139****0213',rel:'员工家属',point:'西峰基地医疗点',disease:'腰肌劳损',doctor:'闫婷',time:'2026-08-30 09:15',main:'腰部酸痛2周',inspect:'腰两侧压痛',past:'久坐工作史',present:'渐进性酸痛',allergy:'磺胺类过敏',revisit:'否',rx:[{m:'布洛芬缓释胶囊',spec:'0.3g*20粒',num:1,dosage:'一次1粒 一日2次'}],advice:'避免久坐,配合理疗',food:'均衡营养',sport:'腰背肌锻炼'},
|
||||
{id:5,user:'周翠兰',sex:'女',age:36,idcard:'610628199001074412',phone:'177****5521',rel:'协作单位人员',point:'乌审旗采气区医疗点',disease:'中暑(先兆)',doctor:'刘玉梅',time:'2026-08-28 14:05',main:'高温作业后头晕出汗',inspect:'体温37.7℃,面色潮红',past:'无',present:'午间露天作业后不适',allergy:'无',revisit:'否',rx:[{m:'藿香正气口服液',spec:'10ml*10支',num:1,dosage:'一次1支 一日2次'}],advice:'阴凉处休息,少量多次饮水',food:'清淡,补充电解质',sport:'避开高温时段'},
|
||||
{id:6,user:'石长有',sex:'男',age:70,idcard:'622801195601021235',phone:'181****6640',rel:'员工家属',point:'安塞采油队长住点医疗室',disease:'冠心病复诊',doctor:'石维国',time:'2026-08-22 10:35',main:'活动后胸闷1月',inspect:'心率78次/分,律齐',past:'冠心病6年',present:'冬季症状加重',allergy:'无',revisit:'是',rx:[],advice:'随身携带急救药物,一月后心内科复诊',food:'低脂高纤维',sport:'避免剧烈运动'}
|
||||
];
|
||||
var nextId=7,editingId=null,curRx=[],pendingDelId=null;
|
||||
|
||||
@@ -462,11 +449,16 @@ function fillDoctorSel(keep){
|
||||
sel.appendChild(o);
|
||||
});
|
||||
}
|
||||
function onFormUnit(){
|
||||
var unit=document.getElementById('fUnit').value;
|
||||
function fillPointSel(keep){
|
||||
var sel=document.getElementById('fPoint');
|
||||
sel.innerHTML='<option value="">请选择医疗点</option>';
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
Object.keys(pointMap).forEach(function(u){
|
||||
(pointMap[u]||[]).forEach(function(p){
|
||||
var o=document.createElement('option');o.textContent=p;
|
||||
if(p===keep)o.selected=true;
|
||||
sel.appendChild(o);
|
||||
});
|
||||
});
|
||||
}
|
||||
function setRadio(name,val){document.querySelectorAll('input[name="'+name+'"]').forEach(function(r){r.checked=(r.value===val);});}
|
||||
function getRadio(name){var r=document.querySelector('input[name="'+name+'"]:checked');return r?r.value:'';}
|
||||
@@ -476,9 +468,8 @@ function openForm(id){
|
||||
document.getElementById('formTitle').textContent=id?('编辑就诊记录 · '+t.user):'新增就诊记录';
|
||||
['fName','fAge','fIdcard','fPhone','fRel','fMain','fInspect','fPast','fPresent','fAllergy','fDisease','fAdvice','fFood','fSport'].forEach(function(k){document.getElementById(k).value='';});
|
||||
document.getElementById('fTime').value=t?t.time.replace(' ','T'):'2026-09-07T09:00';
|
||||
document.getElementById('fUnit').value=t?pointUnit[t.point]:'';
|
||||
onFormUnit();
|
||||
if(t){var ps=document.getElementById('fPoint');[].slice.call(ps.options).forEach(function(o){if(o.text===t.point)o.selected=true;});
|
||||
fillPointSel(t?t.point:'');
|
||||
if(t){
|
||||
document.getElementById('fName').value=t.user;
|
||||
document.getElementById('fAge').value=t.age;
|
||||
document.getElementById('fIdcard').value=t.idcard;
|
||||
@@ -490,7 +481,6 @@ function openForm(id){
|
||||
document.getElementById('fAdvice').value=t.advice;document.getElementById('fFood').value=t.food;document.getElementById('fSport').value=t.sport;
|
||||
}
|
||||
setRadio('fSex',t?t.sex:'');
|
||||
setRadio('fFollow',t?t.follow:'否');
|
||||
setRadio('fRevisit',t?t.revisit:'否');
|
||||
fillDoctorSel(t?t.doctor:'');
|
||||
curRx=t?t.rx.map(function(r){return {m:r.m,spec:r.spec,stock:(medPool.find(function(m){return m.name===r.m;})||{}).stock||0,num:r.num,dosage:r.dosage};}):[];
|
||||
@@ -505,7 +495,6 @@ function saveForm(){
|
||||
var idcard=document.getElementById('fIdcard').value.trim();
|
||||
var phone=document.getElementById('fPhone').value.trim();
|
||||
var time=document.getElementById('fTime').value;
|
||||
var unit=document.getElementById('fUnit').value;
|
||||
var point=document.getElementById('fPoint').value;
|
||||
var doctor=document.getElementById('fDoctor').value;
|
||||
var disease=document.getElementById('fDisease').value.trim();
|
||||
@@ -515,7 +504,7 @@ function saveForm(){
|
||||
if(!/^[1-9]\d{16}[\dXx]$/.test(idcard)){showToast('身份证号需为18位有效号码');return;}
|
||||
if(!/^1[3-9]\d{9}$/.test(phone.replace(/\*/g,'0'))&&!/^1\d{2}\*{4}\d{4}$/.test(phone)){showToast('请填写有效联系电话');return;}
|
||||
if(!time){showToast('请选择就诊时间');return;}
|
||||
if(!unit||!point){showToast('请选择就诊医疗点');return;}
|
||||
if(!point){showToast('请选择就诊医疗点');return;}
|
||||
if(!doctor){showToast('请选择就诊医生');return;}
|
||||
if(!disease){showToast('请填写诊断疾病');return;}
|
||||
var rx=curRx.filter(function(r){return r.m;});
|
||||
@@ -526,14 +515,14 @@ function saveForm(){
|
||||
rel:document.getElementById('fRel').value,point:point,disease:disease,doctor:doctor,time:time.replace('T',' '),
|
||||
main:document.getElementById('fMain').value,inspect:document.getElementById('fInspect').value,
|
||||
past:document.getElementById('fPast').value,present:document.getElementById('fPresent').value,
|
||||
allergy:document.getElementById('fAllergy').value,revisit:getRadio('fRevisit'),follow:getRadio('fFollow'),
|
||||
allergy:document.getElementById('fAllergy').value,revisit:getRadio('fRevisit'),
|
||||
rx:rx,advice:document.getElementById('fAdvice').value,
|
||||
food:document.getElementById('fFood').value,sport:document.getElementById('fSport').value
|
||||
};
|
||||
if(editingId){nonstaffs.splice(nonstaffs.findIndex(function(x){return x.id===editingId;}),1,obj);}
|
||||
else{nonstaffs.push(obj);}
|
||||
closeDrawer('form');renderTable();
|
||||
showToast(editingId?'就诊记录已更新':'就诊记录已登记'+(obj.follow==='是'?',并已生成随访任务':''));
|
||||
showToast(editingId?'就诊记录已更新':'就诊记录已登记');
|
||||
}
|
||||
|
||||
/* ===== 详情抽屉 ===== */
|
||||
@@ -544,7 +533,7 @@ function openView(id){
|
||||
var rxHtml=t.rx.length?'<table class="mini-table"><thead><tr><th>药品名称</th><th>规格</th><th>数量</th><th>用法用量</th></tr></thead><tbody>'+t.rx.map(function(r){return '<tr><td>'+r.m+'</td><td>'+r.spec+'</td><td>'+r.num+'</td><td>'+r.dosage+'</td></tr>';}).join('')+'</tbody></table>':'<span style="color:var(--text-placeholder);font-size:var(--font-sm);">本次就诊未开药</span>';
|
||||
document.getElementById('viewBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">就诊人信息</div>'
|
||||
+'<div class="detail-grid">'+d('就诊人',t.user)+d('性别/年龄',t.sex+' / '+t.age+'岁')+d('身份证号',t.idcard)+d('联系电话',t.phone)+d('与员工关系',t.rel)+d('就诊医疗点',t.point)+d('就诊医生',t.doctor)+d('就诊时间',t.time)+d('是否复诊',t.revisit)+d('纳入随访',t.follow)+'</div>'
|
||||
+'<div class="detail-grid">'+d('就诊人',t.user)+d('性别/年龄',t.sex+' / '+t.age+'岁')+d('身份证号',t.idcard)+d('联系电话',t.phone)+d('与员工关系',t.rel)+d('就诊医疗点',t.point)+d('就诊医生',t.doctor)+d('就诊时间',t.time)+d('是否复诊',t.revisit)+'</div>'
|
||||
+'<div class="form-section">诊断信息</div>'
|
||||
+'<div class="detail-grid">'+d('主诉',t.main,true)+d('查体',t.inspect,true)+d('既往史',t.past)+d('现病史',t.present)+d('过敏史',t.allergy)+d('诊断疾病',t.disease,true)+'</div>'
|
||||
+'<div class="form-section">用药方案</div>'+rxHtml
|
||||
|
||||
@@ -160,13 +160,7 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<a href="daily-treatment-nonstaff.html" class="sidebar-item">非员工就诊</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>用药记录</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="daily-stock-in.html" class="sidebar-item">入库记录</a>
|
||||
<a href="daily-stock-out.html" class="sidebar-item">出库记录</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="daily-ambulance-attendance.html" class="sidebar-item">救护车出勤</a>
|
||||
<a href="daily-follow.html" class="sidebar-item">随访管理</a>
|
||||
<a href="daily-chronic.html" class="sidebar-item">慢病管理</a>
|
||||
<a href="daily-employee-search.html" class="sidebar-item">员工档案</a>
|
||||
@@ -279,19 +273,18 @@ select.form-control{background:#fff url("data:image/svg+xml,%3Csvg xmlns='http:/
|
||||
<input class="form-control" id="fUser" readonly placeholder="点击下方按钮选人" style="flex:1;">
|
||||
<button class="btn btn-default" onclick="openUserPick()">选择员工</button>
|
||||
</div></div>
|
||||
<div class="form-item"><span class="form-label">工号</span><input class="form-control" id="fCode" readonly placeholder="选择员工后自动带出"></div>
|
||||
<div class="form-item"><span class="form-label">性别/年龄</span><input class="form-control" id="fSexAge" readonly placeholder="选择员工后自动带出"></div>
|
||||
<div class="form-item"><span class="form-label">身份证号</span><input class="form-control" id="fIdcard" readonly placeholder="选择员工后自动带出"></div>
|
||||
<div class="form-item"><span class="form-label">联系电话</span><input class="form-control" id="fTel" readonly placeholder="选择员工后自动带出"></div>
|
||||
<div class="form-item"><span class="form-label">所属单位</span><input class="form-control" id="fUUnit" readonly placeholder="选择员工后自动带出"></div>
|
||||
<div class="form-item"><span class="form-label">所属部门</span><input class="form-control" id="fUDept" readonly placeholder="选择员工后自动带出"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 就诊时间</span>
|
||||
<input class="form-control" type="datetime-local" id="fTime"></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 医疗点所属单位</span>
|
||||
<select class="form-control" id="fUnit" onchange="onFormUnit()"><option value="">请选择单位</option><option>采油一厂</option><option>采油二厂</option><option>第四采油厂</option><option>采气一厂</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 就诊医疗点</span>
|
||||
<select class="form-control" id="fPoint"><option value="">请先选择单位</option></select></div>
|
||||
<select class="form-control" id="fPoint"><option value="">请选择医疗点</option></select></div>
|
||||
<div class="form-item"><span class="form-label"><span class="req">*</span> 就诊医生</span>
|
||||
<select class="form-control" id="fDoctor"><option value="">请选择医生</option></select></div>
|
||||
<div class="form-item"><span class="form-label">纳入随访</span>
|
||||
<div class="radio-group">
|
||||
<label class="radio"><input type="radio" name="fFollow" value="是">是</label>
|
||||
<label class="radio"><input type="radio" name="fFollow" value="否" checked>否</label>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">诊断信息</div>
|
||||
@@ -410,27 +403,27 @@ var medPool=[
|
||||
];
|
||||
/* 就诊员工池 */
|
||||
var userPool=[
|
||||
{name:'石维国',code:'CQ021578',sex:'男',age:46,unit:'采油一厂',dept:'樊学作业区',tel:'139****2051'},
|
||||
{name:'李桂芳',code:'CQ032144',sex:'女',age:38,unit:'采油一厂',dept:'樊学作业区',tel:'138****7742'},
|
||||
{name:'白瑞',code:'CQ044871',sex:'男',age:31,unit:'采油一厂',dept:'生产技术部',tel:'155****3316'},
|
||||
{name:'曲志明',code:'CQ019203',sex:'男',age:42,unit:'采油二厂',dept:'姬圪台联合站',tel:'137****8890'},
|
||||
{name:'张秀兰',code:'CQ027710',sex:'女',age:45,unit:'采油二厂',dept:'姬圪台联合站',tel:'136****2248'},
|
||||
{name:'赵万福',code:'CQ033096',sex:'男',age:39,unit:'采油二厂',dept:'桐园作业区',tel:'150****6127'},
|
||||
{name:'高建军',code:'CQ010564',sex:'男',age:50,unit:'第四采油厂',dept:'基地管理处',tel:'139****0086'},
|
||||
{name:'闫婷',code:'CQ041822',sex:'女',age:34,unit:'第四采油厂',dept:'健康管理部',tel:'186****5527'},
|
||||
{name:'刘玉梅',code:'CQ036441',sex:'女',age:40,unit:'采气一厂',dept:'靖边净化厂',tel:'135****7719'},
|
||||
{name:'呼建国',code:'CQ029905',sex:'男',age:36,unit:'采气一厂',dept:'靖边净化厂',tel:'147****9003'}
|
||||
{name:'石维国',code:'CQ021578',sex:'男',age:46,unit:'采油一厂',dept:'樊学作业区',tel:'139****2051',idcard:'610102197804154213'},
|
||||
{name:'李桂芳',code:'CQ032144',sex:'女',age:38,unit:'采油一厂',dept:'樊学作业区',tel:'138****7742',idcard:'610102198603214826'},
|
||||
{name:'白瑞',code:'CQ044871',sex:'男',age:31,unit:'采油一厂',dept:'生产技术部',tel:'155****3316',idcard:'610102199307104517'},
|
||||
{name:'曲志明',code:'CQ019203',sex:'男',age:42,unit:'采油二厂',dept:'姬圪台联合站',tel:'137****8890',idcard:'610102198209285310'},
|
||||
{name:'张秀兰',code:'CQ027710',sex:'女',age:45,unit:'采油二厂',dept:'姬圪台联合站',tel:'136****2248',idcard:'610102197912064629'},
|
||||
{name:'赵万福',code:'CQ033096',sex:'男',age:39,unit:'采油二厂',dept:'桐园作业区',tel:'150****6127',idcard:'610102198511224737'},
|
||||
{name:'高建军',code:'CQ010564',sex:'男',age:50,unit:'第四采油厂',dept:'基地管理处',tel:'139****0086',idcard:'610102197406304419'},
|
||||
{name:'闫婷',code:'CQ041822',sex:'女',age:34,unit:'第四采油厂',dept:'健康管理部',tel:'186****5527',idcard:'610102199001184928'},
|
||||
{name:'刘玉梅',code:'CQ036441',sex:'女',age:40,unit:'采气一厂',dept:'靖边净化厂',tel:'135****7719',idcard:'610102198408214523'},
|
||||
{name:'呼建国',code:'CQ029905',sex:'男',age:36,unit:'采气一厂',dept:'靖边净化厂',tel:'147****9003',idcard:'610102198805174635'}
|
||||
];
|
||||
var pointUnit={'樊学作业区医疗点':'采油一厂','姬圪台作业区医疗点':'采油二厂','西峰基地医疗点':'第四采油厂','靖边气田医疗点':'采气一厂','桐园作业区医疗点':'采油二厂','安塞采油队长住点医疗室':'采油一厂','乌审旗采气区医疗点':'采气一厂'};
|
||||
var treatments=[
|
||||
{id:1,user:'呼建国',code:'CQ029905',sex:'男',age:36,uUnit:'采气一厂',uDept:'靖边净化厂',point:'靖边气田医疗点',disease:'上呼吸道感染',tel:'147****9003',doctor:'刘玉梅',time:'2026-09-06 09:30',main:'发热咽痛2天',inspect:'体温38.2℃,咽部充血',past:'无',present:'受凉后发热',allergy:'无',revisit:'否',follow:'是',rx:[{m:'阿莫西林胶囊',spec:'0.25g*24粒',num:2,dosage:'一次2粒 一日3次'}],advice:'多饮水注意休息,三天后复诊',food:'清淡饮食,忌辛辣',sport:'暂缓运动'},
|
||||
{id:2,user:'赵万福',code:'CQ033096',sex:'男',age:39,uUnit:'采油二厂',uDept:'桐园作业区',point:'桐园作业区医疗点',disease:'高血压病(2级)',tel:'150****6127',doctor:'曲志明',time:'2026-09-05 15:10',main:'头晕1周,血压波动',inspect:'血压158/96mmHg',past:'高血压3年,规律服药',present:'劳累后头晕加重',allergy:'无',revisit:'是',follow:'是',rx:[{m:'硝苯地平控释片',spec:'30mg*7片',num:1,dosage:'一次1片 一日1次'}],advice:'每日晨起测量血压',food:'低盐低脂,每日食盐<5g',sport:'每周150分钟中等强度有氧'},
|
||||
{id:3,user:'杨慧敏',code:'CQ045130',sex:'女',age:33,uUnit:'采油一厂',uDept:'樊学作业区',point:'樊学作业区医疗点',disease:'踝关节扭伤',tel:'188****7214',doctor:'石维国',time:'2026-09-04 11:00',main:'跌倒后右踝肿痛3小时',inspect:'右踝外侧肿胀,活动受限',past:'无',present:'井场巡检时滑倒',allergy:'无',revisit:'否',follow:'否',rx:[{m:'云南白药气雾剂',spec:'85g+30g',num:1,dosage:'外用 一日3次'}],advice:'48小时内冰敷,抬高患肢',food:'均衡饮食',sport:'两周制动,后渐进负重训练'},
|
||||
{id:4,user:'高建军',code:'CQ010564',sex:'男',age:50,uUnit:'第四采油厂',uDept:'基地管理处',point:'西峰基地医疗点',disease:'2型糖尿病复诊',tel:'139****0086',doctor:'闫婷',time:'2026-09-03 10:20',main:'口渴乏力1月',inspect:'空腹血糖8.9mmol/L',past:'糖尿病5年',present:'近1月血糖控制欠佳',allergy:'磺胺类过敏',revisit:'是',follow:'是',rx:[{m:'二甲双胍缓释片',spec:'0.5g*30片',num:2,dosage:'一次1片 一日2次'}],advice:'监测空腹与餐后血糖,两周后复查',food:'控制总热量,主食粗细搭配',sport:'餐后1小时快走30分钟'},
|
||||
{id:5,user:'田震',code:'CQ037744',sex:'男',age:35,uUnit:'采油一厂',uDept:'樊学作业区',point:'樊学作业区医疗点',disease:'急性胃肠炎',tel:'139****5218',doctor:'李桂芳',time:'2026-09-02 16:45',main:'腹痛腹泻1天',inspect:'肠鸣音活跃,脐周压痛',past:'无',present:'进食隔夜饭后腹泻',allergy:'无',revisit:'否',follow:'否',rx:[{m:'蒙脱石散',spec:'3g*10袋',num:1,dosage:'一次1袋 一日3次'},{m:'复方氯化钠注射液',spec:'500ml',num:1,dosage:'静脉滴注 1次'}],advice:'补液防脱水,症状加重随时就诊',food:'流质饮食过渡,忌生冷油腻',sport:'注意休息'},
|
||||
{id:6,user:'徐立成',code:'CQ022317',sex:'男',age:44,uUnit:'采气一厂',uDept:'苏里格南作业区',point:'乌审旗采气区医疗点',disease:'中暑(先兆)',tel:'133****4860',doctor:'刘玉梅',time:'2026-08-28 13:30',main:'高温作业后头晕出汗',inspect:'体温37.8℃,面色潮红',past:'无',present:'午间巡检后不适',allergy:'无',revisit:'否',follow:'否',rx:[{m:'藿香正气口服液',spec:'10ml*10支',num:1,dosage:'一次1支 一日2次'}],advice:'阴凉处休息,少量多次饮水',food:'清淡,适当补充电解质',sport:'避开高温时段作业'},
|
||||
{id:7,user:'张秀兰',code:'CQ027710',sex:'女',age:45,uUnit:'采油二厂',uDept:'姬圪台联合站',point:'姬圪台作业区医疗点',disease:'腰肌劳损',tel:'136****2248',doctor:'曲志明',time:'2026-08-25 09:00',main:'腰部酸痛2周',inspect:'腰两侧压痛,活动受限',past:'久坐工作史',present:'渐进性酸痛',allergy:'无',revisit:'是',follow:'是',rx:[{m:'布洛芬缓释胶囊',spec:'0.3g*20粒',num:1,dosage:'一次1粒 一日2次'}],advice:'避免久坐,配合理疗',food:'均衡营养',sport:'小燕飞等腰背肌锻炼'},
|
||||
{id:8,user:'石维国',code:'CQ021578',sex:'男',age:46,uUnit:'采油一厂',uDept:'樊学作业区',point:'樊学作业区医疗点',disease:'电光性眼炎',tel:'139****2051',doctor:'李桂芳',time:'2026-08-21 18:20',main:'焊接后眼痛流泪6小时',inspect:'睑结膜充血',past:'无',present:'未戴护目镜作业',allergy:'无',revisit:'否',follow:'否',rx:[],advice:'冷敷,避免揉眼,24小时复查',food:'忌辛辣刺激',sport:'减少用眼'}
|
||||
{id:1,user:'呼建国',code:'CQ029905',sex:'男',age:36,uUnit:'采气一厂',uDept:'靖边净化厂',point:'靖边气田医疗点',disease:'上呼吸道感染',tel:'147****9003',doctor:'刘玉梅',time:'2026-09-06 09:30',main:'发热咽痛2天',inspect:'体温38.2℃,咽部充血',past:'无',present:'受凉后发热',allergy:'无',revisit:'否',rx:[{m:'阿莫西林胶囊',spec:'0.25g*24粒',num:2,dosage:'一次2粒 一日3次'}],advice:'多饮水注意休息,三天后复诊',food:'清淡饮食,忌辛辣',sport:'暂缓运动'},
|
||||
{id:2,user:'赵万福',code:'CQ033096',sex:'男',age:39,uUnit:'采油二厂',uDept:'桐园作业区',point:'桐园作业区医疗点',disease:'高血压病(2级)',tel:'150****6127',doctor:'曲志明',time:'2026-09-05 15:10',main:'头晕1周,血压波动',inspect:'血压158/96mmHg',past:'高血压3年,规律服药',present:'劳累后头晕加重',allergy:'无',revisit:'是',rx:[{m:'硝苯地平控释片',spec:'30mg*7片',num:1,dosage:'一次1片 一日1次'}],advice:'每日晨起测量血压',food:'低盐低脂,每日食盐<5g',sport:'每周150分钟中等强度有氧'},
|
||||
{id:3,user:'杨慧敏',code:'CQ045130',sex:'女',age:33,uUnit:'采油一厂',uDept:'樊学作业区',point:'樊学作业区医疗点',disease:'踝关节扭伤',tel:'188****7214',doctor:'石维国',time:'2026-09-04 11:00',main:'跌倒后右踝肿痛3小时',inspect:'右踝外侧肿胀,活动受限',past:'无',present:'井场巡检时滑倒',allergy:'无',revisit:'否',rx:[{m:'云南白药气雾剂',spec:'85g+30g',num:1,dosage:'外用 一日3次'}],advice:'48小时内冰敷,抬高患肢',food:'均衡饮食',sport:'两周制动,后渐进负重训练'},
|
||||
{id:4,user:'高建军',code:'CQ010564',sex:'男',age:50,uUnit:'第四采油厂',uDept:'基地管理处',point:'西峰基地医疗点',disease:'2型糖尿病复诊',tel:'139****0086',doctor:'闫婷',time:'2026-09-03 10:20',main:'口渴乏力1月',inspect:'空腹血糖8.9mmol/L',past:'糖尿病5年',present:'近1月血糖控制欠佳',allergy:'磺胺类过敏',revisit:'是',rx:[{m:'二甲双胍缓释片',spec:'0.5g*30片',num:2,dosage:'一次1片 一日2次'}],advice:'监测空腹与餐后血糖,两周后复查',food:'控制总热量,主食粗细搭配',sport:'餐后1小时快走30分钟'},
|
||||
{id:5,user:'田震',code:'CQ037744',sex:'男',age:35,uUnit:'采油一厂',uDept:'樊学作业区',point:'樊学作业区医疗点',disease:'急性胃肠炎',tel:'139****5218',doctor:'李桂芳',time:'2026-09-02 16:45',main:'腹痛腹泻1天',inspect:'肠鸣音活跃,脐周压痛',past:'无',present:'进食隔夜饭后腹泻',allergy:'无',revisit:'否',rx:[{m:'蒙脱石散',spec:'3g*10袋',num:1,dosage:'一次1袋 一日3次'},{m:'复方氯化钠注射液',spec:'500ml',num:1,dosage:'静脉滴注 1次'}],advice:'补液防脱水,症状加重随时就诊',food:'流质饮食过渡,忌生冷油腻',sport:'注意休息'},
|
||||
{id:6,user:'徐立成',code:'CQ022317',sex:'男',age:44,uUnit:'采气一厂',uDept:'苏里格南作业区',point:'乌审旗采气区医疗点',disease:'中暑(先兆)',tel:'133****4860',doctor:'刘玉梅',time:'2026-08-28 13:30',main:'高温作业后头晕出汗',inspect:'体温37.8℃,面色潮红',past:'无',present:'午间巡检后不适',allergy:'无',revisit:'否',rx:[{m:'藿香正气口服液',spec:'10ml*10支',num:1,dosage:'一次1支 一日2次'}],advice:'阴凉处休息,少量多次饮水',food:'清淡,适当补充电解质',sport:'避开高温时段作业'},
|
||||
{id:7,user:'张秀兰',code:'CQ027710',sex:'女',age:45,uUnit:'采油二厂',uDept:'姬圪台联合站',point:'姬圪台作业区医疗点',disease:'腰肌劳损',tel:'136****2248',doctor:'曲志明',time:'2026-08-25 09:00',main:'腰部酸痛2周',inspect:'腰两侧压痛,活动受限',past:'久坐工作史',present:'渐进性酸痛',allergy:'无',revisit:'是',rx:[{m:'布洛芬缓释胶囊',spec:'0.3g*20粒',num:1,dosage:'一次1粒 一日2次'}],advice:'避免久坐,配合理疗',food:'均衡营养',sport:'小燕飞等腰背肌锻炼'},
|
||||
{id:8,user:'石维国',code:'CQ021578',sex:'男',age:46,uUnit:'采油一厂',uDept:'樊学作业区',point:'樊学作业区医疗点',disease:'电光性眼炎',tel:'139****2051',doctor:'李桂芳',time:'2026-08-21 18:20',main:'焊接后眼痛流泪6小时',inspect:'睑结膜充血',past:'无',present:'未戴护目镜作业',allergy:'无',revisit:'否',rx:[],advice:'冷敷,避免揉眼,24小时复查',food:'忌辛辣刺激',sport:'减少用眼'}
|
||||
];
|
||||
var nextId=9,editingId=null,curRx=[],curUser=null,pendingDelId=null,pendingUser=null;
|
||||
|
||||
@@ -631,11 +624,16 @@ function fillDoctorSel(keep){
|
||||
sel.appendChild(o);
|
||||
});
|
||||
}
|
||||
function onFormUnit(){
|
||||
var unit=document.getElementById('fUnit').value;
|
||||
function fillPointSel(keep){
|
||||
var sel=document.getElementById('fPoint');
|
||||
sel.innerHTML='<option value="">请选择医疗点</option>';
|
||||
if(unit){(pointMap[unit]||[]).forEach(function(p){var o=document.createElement('option');o.textContent=p;sel.appendChild(o);});}
|
||||
Object.keys(pointMap).forEach(function(u){
|
||||
(pointMap[u]||[]).forEach(function(p){
|
||||
var o=document.createElement('option');o.textContent=p;
|
||||
if(p===keep)o.selected=true;
|
||||
sel.appendChild(o);
|
||||
});
|
||||
});
|
||||
}
|
||||
function setRadio(name,val){document.querySelectorAll('input[name="'+name+'"]').forEach(function(r){r.checked=(r.value===val);});}
|
||||
function getRadio(name){var r=document.querySelector('input[name="'+name+'"]:checked');return r?r.value:'';}
|
||||
@@ -645,11 +643,8 @@ function openForm(id){
|
||||
document.getElementById('formTitle').textContent=id?('编辑就诊记录 · '+t.user):'新增就诊记录';
|
||||
document.getElementById('fUser').value=t?t.user:'';
|
||||
document.getElementById('fTime').value=t?t.time.replace(' ','T'):'2026-09-07T09:00';
|
||||
document.getElementById('fUnit').value=t?pointUnit[t.point]:'';
|
||||
onFormUnit();
|
||||
if(t){var ps=document.getElementById('fPoint');[].slice.call(ps.options).forEach(function(o){if(o.text===t.point)o.selected=true;});}
|
||||
fillPointSel(t?t.point:'');
|
||||
fillDoctorSel(t?t.doctor:'');
|
||||
setRadio('fFollow',t?t.follow:'否');
|
||||
setRadio('fRevisit',t?t.revisit:'否');
|
||||
['fMain','fInspect','fPast','fPresent','fAllergy','fDisease','fAdvice','fFood','fSport'].forEach(function(k){document.getElementById(k).value='';});
|
||||
if(t){
|
||||
@@ -659,6 +654,7 @@ function openForm(id){
|
||||
document.getElementById('fAdvice').value=t.advice;document.getElementById('fFood').value=t.food;document.getElementById('fSport').value=t.sport;
|
||||
}
|
||||
curUser=t?userPool.find(function(u){return u.code===t.code;}):null;
|
||||
renderUserInfo(curUser);
|
||||
curRx=t?t.rx.map(function(r){return {m:r.m,spec:r.spec,stock:(medPool.find(function(m){return m.name===r.m;})||{}).stock||0,num:r.num,dosage:r.dosage};}):[];
|
||||
renderRx();
|
||||
document.getElementById('formMask').classList.add('open');
|
||||
@@ -667,32 +663,31 @@ function openForm(id){
|
||||
function saveForm(){
|
||||
var user=document.getElementById('fUser').value;
|
||||
var time=document.getElementById('fTime').value;
|
||||
var unit=document.getElementById('fUnit').value;
|
||||
var point=document.getElementById('fPoint').value;
|
||||
var doctor=document.getElementById('fDoctor').value;
|
||||
var disease=document.getElementById('fDisease').value.trim();
|
||||
if(!user){showToast('请选择就诊人');return;}
|
||||
if(!time){showToast('请选择就诊时间');return;}
|
||||
if(!unit||!point){showToast('请选择就诊医疗点');return;}
|
||||
if(!point){showToast('请选择就诊医疗点');return;}
|
||||
if(!doctor){showToast('请选择就诊医生');return;}
|
||||
if(!disease){showToast('请填写诊断疾病');return;}
|
||||
var rx=curRx.filter(function(r){return r.m;});
|
||||
var bad=rx.find(function(r){return r.num>r.stock;});
|
||||
if(bad){showToast('「'+bad.m+'」库存仅 '+bad.stock+',开药数量超限');return;}
|
||||
var obj={
|
||||
id:editingId||nextId++,user:user,code:curUser?curUser.code:'--',sex:curUser?curUser.sex:'--',age:curUser?curUser.age:'--',
|
||||
id:editingId||nextId++,user:user,code:curUser?curUser.code:'--',idcard:curUser?curUser.idcard:'--',sex:curUser?curUser.sex:'--',age:curUser?curUser.age:'--',
|
||||
uUnit:curUser?curUser.unit:'--',uDept:curUser?curUser.dept:'--',point:point,disease:disease,
|
||||
tel:curUser?curUser.tel:'--',doctor:doctor,time:time.replace('T',' '),
|
||||
main:document.getElementById('fMain').value,inspect:document.getElementById('fInspect').value,
|
||||
past:document.getElementById('fPast').value,present:document.getElementById('fPresent').value,
|
||||
allergy:document.getElementById('fAllergy').value,revisit:getRadio('fRevisit'),follow:getRadio('fFollow'),
|
||||
allergy:document.getElementById('fAllergy').value,revisit:getRadio('fRevisit'),
|
||||
rx:rx,advice:document.getElementById('fAdvice').value,
|
||||
food:document.getElementById('fFood').value,sport:document.getElementById('fSport').value
|
||||
};
|
||||
if(editingId){treatments.splice(treatments.findIndex(function(x){return x.id===editingId;}),1,obj);}
|
||||
else{treatments.push(obj);}
|
||||
closeDrawer('form');renderTable();
|
||||
showToast(editingId?'就诊记录已更新':'就诊记录已登记'+(obj.follow==='是'?',并已生成随访任务':''));
|
||||
showToast(editingId?'就诊记录已更新':'就诊记录已登记');
|
||||
}
|
||||
|
||||
/* ===== 详情抽屉 ===== */
|
||||
@@ -703,7 +698,7 @@ function openView(id){
|
||||
var rxHtml=t.rx.length?'<table class="mini-table"><thead><tr><th>药品名称</th><th>规格</th><th>数量</th><th>用法用量</th></tr></thead><tbody>'+t.rx.map(function(r){return '<tr><td>'+r.m+'</td><td>'+r.spec+'</td><td>'+r.num+'</td><td>'+r.dosage+'</td></tr>';}).join('')+'</tbody></table>':'<span style="color:var(--text-placeholder);font-size:var(--font-sm);">本次就诊未开药</span>';
|
||||
document.getElementById('viewBody').innerHTML=
|
||||
'<div class="form-section" style="margin-top:0;">就诊信息</div>'
|
||||
+'<div class="detail-grid">'+d('就诊人',t.user)+d('工号',t.code)+d('性别/年龄',t.sex+' / '+t.age+'岁')+d('联系电话',t.tel)+d('所属单位',t.uUnit)+d('所属部门',t.uDept)+d('就诊医疗点',t.point)+d('就诊医生',t.doctor)+d('就诊时间',t.time)+d('是否复诊',t.revisit)+d('纳入随访',t.follow)+d('体检报告','<button class="btn btn-link" onclick="showToast(\'体检报告在线预览(演示)\')">查看</button>')+'</div>'
|
||||
+'<div class="detail-grid">'+d('就诊人',t.user)+d('工号',t.code)+d('性别/年龄',t.sex+' / '+t.age+'岁')+d('身份证号',t.idcard)+d('联系电话',t.tel)+d('所属单位',t.uUnit)+d('所属部门',t.uDept)+d('就诊医疗点',t.point)+d('就诊医生',t.doctor)+d('就诊时间',t.time)+d('是否复诊',t.revisit)+d('体检报告','<button class="btn btn-link" onclick="showToast(\'体检报告在线预览(演示)\')">查看</button>')+'</div>'
|
||||
+'<div class="form-section">诊断信息</div>'
|
||||
+'<div class="detail-grid">'+d('主诉',t.main,true)+d('查体',t.inspect,true)+d('既往史',t.past)+d('现病史',t.present)+d('过敏史',t.allergy)+d('诊断疾病',t.disease,true)+'</div>'
|
||||
+'<div class="form-section">用药方案</div>'+rxHtml
|
||||
@@ -727,11 +722,20 @@ function renderUserPick(){
|
||||
+'<td style="font-weight:600;">'+e.name+'</td><td>'+e.code+'</td><td>'+e.unit+'</td><td>'+e.dept+'</td></tr>';
|
||||
}).join(''):'<tr><td colspan="5" class="td-empty">未找到匹配员工</td></tr>';
|
||||
}
|
||||
function renderUserInfo(u){
|
||||
document.getElementById('fCode').value=u?u.code:'';
|
||||
document.getElementById('fSexAge').value=u?(u.sex+' / '+u.age+'岁'):'';
|
||||
document.getElementById('fIdcard').value=u?u.idcard:'';
|
||||
document.getElementById('fTel').value=u?u.tel:'';
|
||||
document.getElementById('fUUnit').value=u?u.unit:'';
|
||||
document.getElementById('fUDept').value=u?u.dept:'';
|
||||
}
|
||||
function confirmUser(){
|
||||
var r=document.querySelector('input[name="userSel"]:checked');
|
||||
if(!r){showToast('请选择一名员工');return;}
|
||||
curUser=userPool.find(function(x){return x.code===r.value;});
|
||||
document.getElementById('fUser').value=curUser.name;
|
||||
renderUserInfo(curUser);
|
||||
closeModal('userMask');
|
||||
}
|
||||
|
||||
|
||||
@@ -132,3 +132,53 @@
|
||||
- `web-admin/frontline-medical/bed-station.html` / `stat-rescue-chart.html` / `stat-rescue-table.html` — 新增 3 页
|
||||
- `web-admin/frontline-medical/*.html` — 45 页侧栏分组/更名/视觉尺寸批量改版
|
||||
- `D:\Work\platform-prototype\index.html` — 站点地图同步
|
||||
|
||||
## [2026-09-08] refactor: 救护车配置收敛 · 侧栏平铺与出勤记录/取消分配移除
|
||||
|
||||
在二线迭代侧栏二级分组基础上,对救护车配置相关功能做收敛简化:
|
||||
|
||||
- **侧栏简化**:基础配置域「救护车」二级子组(含「救护车列表」子项)收敛为顶层平铺单菜单项「救护车配置」,基础配置 8 页侧栏同步调整
|
||||
- **救护车配置页**:移除「数据管理」入口与单车出勤记录台账(出勤登记/编辑/删除、随车医护多选、救助员工选人弹窗、系统生成记录只读标记)
|
||||
- **员工分配页**:移除「取消分配」功能(重新分配保留,已分配员工不再支持取消回落未分配)
|
||||
- **分配统计页**:移除「操作」列,「查看名册」动作并入「已分配员工数量」人数列点击下钻
|
||||
|
||||
**涉及文件:**
|
||||
|
||||
- `web-admin/frontline-medical/config-ambulance.html` — 移除数据管理(出勤记录)功能
|
||||
- `web-admin/frontline-medical/config-allocate.html` — 移除取消分配功能
|
||||
- `web-admin/frontline-medical/config-allocate-stat.html` — 移除操作列、人数列直接下钻名册
|
||||
- `web-admin/frontline-medical/config-medical-point.html` / `config-partner-hospital.html` / `config-medical-staff.html` / `config-medicine.html` / `config-medicine-stock.html` — 侧栏救护车子组平铺
|
||||
|
||||
## [2026-09-09] feat: 日常业务新增救护车出勤 · 移除用药记录
|
||||
|
||||
日常业务域菜单结构调整:删除「用药记录」子分组及其入库/出库两页,新增二级菜单「救护车出勤」,以「所有救护车出勤数据」视角重建(此前单车出勤台账已于 2026-09-08 救护车配置收敛时移除)。
|
||||
|
||||
- **菜单调整**:日常业务侧边栏移除「用药记录」子分组(入库记录/出库记录),在「日常诊疗」后新增顶层二级菜单「救护车出勤」,10 个 daily 页面侧边栏同步
|
||||
- **删除页面**:`daily-stock-in.html`(入库记录)、`daily-stock-out.html`(出库记录)
|
||||
- **新增页面** `daily-ambulance-attendance.html` — 救护车出勤:顶部四统计卡片(当周出勤/当月出勤/年度出勤/累计出勤,按出勤日期统计);医疗点→救护车级联筛选 + 出勤类型/日期区间;列表带所属医疗点/救护车(车牌号)/救护类型等出勤台账列(不展示所属单位);新增/编辑抽屉「医疗点→救护车」级联选车(自动带出救护类型)、出勤司机独立下拉(全部救护车司机,选后带出电话)、出勤日期、出勤类型(病情急救/伤情急救/日常巡诊/应急戒备四类)、随车医护多选弹窗、出勤/到达地点;详情抽屉全字段展示;编辑/删除/异步导出
|
||||
- **`D:\Work\platform-prototype\index.html`** — SITE_MAP 删除入库/出库两行、新增「日常业务 · 救护车出勤」条目
|
||||
|
||||
**涉及文件:**
|
||||
|
||||
- `web-admin/frontline-medical/daily-ambulance-attendance.html` — 新增
|
||||
- `web-admin/frontline-medical/daily-stock-in.html` / `daily-stock-out.html` — 删除
|
||||
- `web-admin/frontline-medical/daily-treatment-staff.html` / `daily-treatment-nonstaff.html` / `daily-follow.html` / `daily-chronic.html` / `daily-chronic-intervention.html` / `daily-employee-search.html` / `daily-follow-task.html` / `daily-interpret.html` / `daily-education.html` / `daily-interpret-manage.html` — 侧边栏移除用药记录、新增救护车出勤
|
||||
- `D:\Work\platform-prototype\index.html` — 站点地图同步
|
||||
|
||||
## [2026-09-09] refactor: 数据统计菜单三级化 · 医疗点/救护车统计报表重做
|
||||
|
||||
数据统计域菜单结构重构:移除「图表视图/报表视图」页内互切,改为三级菜单。
|
||||
|
||||
- **菜单重构**:数据统计下 3 个二级菜单不变;「医疗点统计」「救护车统计」改为可展开子组(复用 sidebar-subgroup 样式),各下挂「统计图表」「统计报表」两个三级菜单;「救助物品统计」删除报表视图,仅保留图表页
|
||||
- **医疗点统计-图表**(stat-clinic-chart.html):移除视图开关;「单个医疗点」Tab 默认选中首个单位+医疗点,进入即有数据
|
||||
- **医疗点统计-报表**(stat-clinic-table.html):完全重做,复刻老项目 medicalPointStatistics —— 本周/本月/本年/自定义时间切换 + 导出/查看导出记录 + 所属单位/时间筛选 + 分组大表(就诊人次/慢病管理/培训宣教/体检报告解读 多级表头)
|
||||
- **救护车统计-报表**(stat-ambulance-table.html):完全重做,复刻老项目救护车数据统计(ambulanceData)—— 本周/本月/本年/自定义时间切换 + 导出/查看导出记录 + 单位→医疗点级联/救护类型/时间筛选 + 分组报表(所属单位/所属医疗点/救护类型/车型/车牌号 + 急诊转运/平诊转运/日常巡诊/应急戒备/其他 各本周·累计出勤次数)
|
||||
- **删除页面**:`stat-rescue-table.html`(救助物品统计-报表)
|
||||
|
||||
**涉及文件:**
|
||||
|
||||
- `web-admin/frontline-medical/stat-clinic-chart.html` / `stat-ambulance-chart.html` / `stat-rescue-chart.html` — 侧栏三级子组化 + 移除视图开关
|
||||
- `web-admin/frontline-medical/stat-clinic-table.html` — 医疗点统计报表重做
|
||||
- `web-admin/frontline-medical/stat-ambulance-table.html` — 救护车统计报表重做
|
||||
- `web-admin/frontline-medical/stat-rescue-table.html` — 删除
|
||||
- `D:\Work\platform-prototype\index.html` — 站点地图同步
|
||||
|
||||
@@ -30,6 +30,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
/* [交互] 二级分组菜单展开/收起:点击分组标题切换 open 类,三级子项默认收起 */
|
||||
.sidebar-group__label{display:flex;align-items:center;justify-content:space-between;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;}
|
||||
.sidebar-group__label:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-group__label svg{transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-group.open .sidebar-group__label svg{transform:rotate(180deg);}
|
||||
.sidebar-group__items{display:none;}
|
||||
.sidebar-group.open .sidebar-group__items{display:block;}
|
||||
.sidebar-item--sub{padding-left:44px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
@@ -108,13 +116,27 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<!-- 侧边栏(当前一级分组「健康小屋」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">健康小屋</div>
|
||||
<a href="hut-banner.html" class="sidebar-item">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item active">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item">大屏数据配置</a>
|
||||
<a href="hut-cabin.html" class="sidebar-item">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item">小屋统计</a>
|
||||
<div class="sidebar-group open" id="grpCollect">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpCollect')">智能采集
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-banner.html" class="sidebar-item sidebar-item--sub">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item sidebar-item--sub">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item sidebar-item--sub active">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item sidebar-item--sub">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item sidebar-item--sub">大屏数据配置</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-group" id="grpInput">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpInput')">基础录入
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-cabin.html" class="sidebar-item sidebar-item--sub">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item sidebar-item--sub">小屋统计</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -312,6 +334,8 @@ function confirmDel(){
|
||||
delCodes.slice().sort(function(a,b){return b-a;}).forEach(function(i){appts.splice(i,1);});
|
||||
closeDel();render();showToast('已删除 '+delCodes.length+' 条预约记录');
|
||||
}
|
||||
/* [交互] 侧栏分组展开/收起 */
|
||||
function toggleGroup(id){document.getElementById(id).classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
|
||||
@@ -30,6 +30,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
/* [交互] 二级分组菜单展开/收起:点击分组标题切换 open 类,三级子项默认收起 */
|
||||
.sidebar-group__label{display:flex;align-items:center;justify-content:space-between;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;}
|
||||
.sidebar-group__label:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-group__label svg{transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-group.open .sidebar-group__label svg{transform:rotate(180deg);}
|
||||
.sidebar-group__items{display:none;}
|
||||
.sidebar-group.open .sidebar-group__items{display:block;}
|
||||
.sidebar-item--sub{padding-left:44px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
@@ -116,13 +124,27 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<!-- 侧边栏(当前一级分组「健康小屋」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">健康小屋</div>
|
||||
<a href="hut-banner.html" class="sidebar-item active">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item">大屏数据配置</a>
|
||||
<a href="hut-cabin.html" class="sidebar-item">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item">小屋统计</a>
|
||||
<div class="sidebar-group open" id="grpCollect">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpCollect')">智能采集
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-banner.html" class="sidebar-item sidebar-item--sub active">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item sidebar-item--sub">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item sidebar-item--sub">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item sidebar-item--sub">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item sidebar-item--sub">大屏数据配置</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-group" id="grpInput">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpInput')">基础录入
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-cabin.html" class="sidebar-item sidebar-item--sub">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item sidebar-item--sub">小屋统计</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -297,6 +319,8 @@ function openDel(i){
|
||||
}
|
||||
function closeDel(){document.getElementById('delMask').classList.remove('open');}
|
||||
function confirmDel(){banners.splice(delIdx,1);closeDel();render();showToast('已删除');}
|
||||
/* [交互] 侧栏分组展开/收起 */
|
||||
function toggleGroup(id){document.getElementById(id).classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
|
||||
@@ -30,6 +30,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
/* [交互] 二级分组菜单展开/收起:点击分组标题切换 open 类,三级子项默认收起 */
|
||||
.sidebar-group__label{display:flex;align-items:center;justify-content:space-between;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;}
|
||||
.sidebar-group__label:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-group__label svg{transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-group.open .sidebar-group__label svg{transform:rotate(180deg);}
|
||||
.sidebar-group__items{display:none;}
|
||||
.sidebar-group.open .sidebar-group__items{display:block;}
|
||||
.sidebar-item--sub{padding-left:44px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
@@ -90,13 +98,27 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<!-- 侧边栏(当前一级分组「健康小屋」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">健康小屋</div>
|
||||
<a href="hut-banner.html" class="sidebar-item">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item">大屏数据配置</a>
|
||||
<a href="hut-cabin.html" class="sidebar-item">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item active">小屋统计</a>
|
||||
<div class="sidebar-group" id="grpCollect">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpCollect')">智能采集
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-banner.html" class="sidebar-item sidebar-item--sub">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item sidebar-item--sub">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item sidebar-item--sub">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item sidebar-item--sub">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item sidebar-item--sub">大屏数据配置</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-group open" id="grpInput">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpInput')">基础录入
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-cabin.html" class="sidebar-item sidebar-item--sub">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item sidebar-item--sub active">小屋统计</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -236,6 +258,8 @@ function render(){
|
||||
+'<td>'+sbp+'</td><td>'+sbg+'</td><td>'+stbp+'</td><td>'+stbg+'</td><td></td></tr>':'';
|
||||
document.getElementById('totalTip').textContent='区间 '+pr.from+' ~ '+pr.to+' · 共 '+rows.length+' 座小屋';
|
||||
}
|
||||
/* [交互] 侧栏分组展开/收起 */
|
||||
function toggleGroup(id){document.getElementById(id).classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
|
||||
@@ -30,6 +30,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
/* [交互] 二级分组菜单展开/收起:点击分组标题切换 open 类,三级子项默认收起 */
|
||||
.sidebar-group__label{display:flex;align-items:center;justify-content:space-between;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;}
|
||||
.sidebar-group__label:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-group__label svg{transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-group.open .sidebar-group__label svg{transform:rotate(180deg);}
|
||||
.sidebar-group__items{display:none;}
|
||||
.sidebar-group.open .sidebar-group__items{display:block;}
|
||||
.sidebar-item--sub{padding-left:44px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
@@ -108,13 +116,27 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<!-- 侧边栏(当前一级分组「健康小屋」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">健康小屋</div>
|
||||
<a href="hut-banner.html" class="sidebar-item">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item">大屏数据配置</a>
|
||||
<a href="hut-cabin.html" class="sidebar-item active">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item">小屋统计</a>
|
||||
<div class="sidebar-group" id="grpCollect">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpCollect')">智能采集
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-banner.html" class="sidebar-item sidebar-item--sub">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item sidebar-item--sub">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item sidebar-item--sub">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item sidebar-item--sub">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item sidebar-item--sub">大屏数据配置</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-group open" id="grpInput">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpInput')">基础录入
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-cabin.html" class="sidebar-item sidebar-item--sub active">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item sidebar-item--sub">小屋统计</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -399,6 +421,8 @@ function openDel(i){
|
||||
}
|
||||
function closeDel(){document.getElementById('delMask').classList.remove('open');}
|
||||
function confirmDel(){cabins.splice(delIdx,1);closeDel();render();showToast('已删除');}
|
||||
/* [交互] 侧栏分组展开/收起 */
|
||||
function toggleGroup(id){document.getElementById(id).classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
|
||||
@@ -30,6 +30,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
/* [交互] 二级分组菜单展开/收起:点击分组标题切换 open 类,三级子项默认收起 */
|
||||
.sidebar-group__label{display:flex;align-items:center;justify-content:space-between;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;}
|
||||
.sidebar-group__label:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-group__label svg{transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-group.open .sidebar-group__label svg{transform:rotate(180deg);}
|
||||
.sidebar-group__items{display:none;}
|
||||
.sidebar-group.open .sidebar-group__items{display:block;}
|
||||
.sidebar-item--sub{padding-left:44px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
@@ -71,17 +79,22 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:440px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal--wide{width:760px;max-height:86vh;display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal--xl{width:1120px;max-width:96vw;max-height:90vh;display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal__header{display:flex;align-items:center;justify-content:space-between;font-size:var(--font-base);font-weight:600;padding-bottom:12px;border-bottom:1px solid var(--border);flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-placeholder);font-size:20px;line-height:1;border:none;background:none;}
|
||||
.modal__close:hover{color:var(--text-primary);}
|
||||
.modal__body{flex:1;overflow-y:auto;padding:16px 2px 4px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;flex-shrink:0;}
|
||||
.form-row{display:flex;align-items:flex-start;gap:12px;margin-bottom:16px;}
|
||||
.form-row__label{width:104px;flex-shrink:0;text-align:right;font-size:var(--font-sm);color:var(--text-secondary);padding-top:7px;}
|
||||
.form-row__label i{color:var(--danger);font-style:normal;margin-right:2px;}
|
||||
.form-row__control{flex:1;display:flex;align-items:center;gap:8px;}
|
||||
.form-row__control{flex:1;display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
|
||||
.form-input{width:100%;height:34px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);outline:none;}
|
||||
.form-input:focus{border-color:var(--primary);}
|
||||
.form-textarea{width:100%;border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 10px;font-size:var(--font-sm);outline:none;resize:vertical;min-height:64px;line-height:1.6;}
|
||||
.form-textarea:focus{border-color:var(--primary);}
|
||||
.time-input{height:34px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 8px;font-size:var(--font-sm);color:var(--text-primary);outline:none;}
|
||||
.time-input:focus{border-color:var(--primary);}
|
||||
.radio-group{display:flex;gap:18px;padding-top:7px;}
|
||||
.radio-group label{display:flex;align-items:center;gap:6px;font-size:var(--font-sm);cursor:pointer;}
|
||||
.radio-group input{accent-color:var(--primary);}
|
||||
@@ -94,9 +107,28 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.detail-item--full{grid-column:1/-1;}
|
||||
.detail-item .dk{width:104px;flex-shrink:0;background:#FAFAFA;padding:9px 12px;font-size:var(--font-sm);color:var(--text-secondary);border-right:1px solid var(--border);}
|
||||
.detail-item .dv{flex:1;padding:9px 12px;font-size:var(--font-sm);color:var(--text-primary);white-space:normal;line-height:1.5;}
|
||||
.inner-table{width:100%;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.inner-table th{background:#FAFAFA;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;padding:7px;border-bottom:1px solid var(--border);}
|
||||
.inner-table td{font-size:var(--font-sm);padding:8px 7px;text-align:center;border-bottom:1px solid #F0F0F0;}
|
||||
.inner-table{width:100%;min-width:0;border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;border-collapse:separate;border-spacing:0;}
|
||||
.inner-table th{background:#FAFAFA;font-size:var(--font-sm);color:var(--text-secondary);font-weight:600;padding:10px 12px;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.inner-table td{font-size:var(--font-sm);padding:10px 12px;text-align:center;border-bottom:1px solid #F0F0F0;color:var(--text-primary);white-space:nowrap;}
|
||||
.inner-table tbody tr:nth-child(even){background:#FAFCFF;}
|
||||
.inner-table tbody tr:hover{background:#F0F7FF;}
|
||||
.inner-table tbody tr:last-child td{border-bottom:none;}
|
||||
.inner-table .mono{font-family:'SFMono-Regular',Consolas,monospace;}
|
||||
.more-wrap{position:relative;display:inline-block;}
|
||||
.more-menu{display:none;position:absolute;right:0;top:calc(100% + 4px);background:#fff;border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-md);min-width:120px;z-index:60;padding:4px 0;text-align:left;}
|
||||
.more-wrap:hover .more-menu{display:block;}
|
||||
.more-menu a{display:block;padding:8px 14px;font-size:var(--font-sm);color:var(--text-primary);cursor:pointer;white-space:nowrap;text-decoration:none;}
|
||||
.more-menu a:hover{background:var(--primary-light);color:var(--primary);}
|
||||
.more-menu a.danger{color:var(--danger);}
|
||||
.more-menu a.danger:hover{background:#FFF1F0;color:var(--danger);}
|
||||
tbody td:last-child:has(.more-wrap:hover){z-index:30;}
|
||||
.toolbar{display:flex;align-items:center;gap:12px;margin-bottom:12px;}
|
||||
.toolbar__label{font-size:var(--font-xs);color:var(--text-secondary);white-space:nowrap;}
|
||||
.toolbar__spacer{flex:1;}
|
||||
.time-row{display:flex;align-items:center;gap:8px;margin-bottom:8px;}
|
||||
.time-row .sep{color:var(--text-placeholder);}
|
||||
.icon-btn{width:34px;height:34px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;color:var(--text-secondary);cursor:pointer;font-size:var(--font-base);line-height:1;}
|
||||
.icon-btn:hover{color:var(--primary);border-color:var(--primary);}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -122,13 +154,27 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<!-- 侧边栏(当前一级分组「健康小屋」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">健康小屋</div>
|
||||
<a href="hut-banner.html" class="sidebar-item">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item active">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item">大屏数据配置</a>
|
||||
<a href="hut-cabin.html" class="sidebar-item">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item">小屋统计</a>
|
||||
<div class="sidebar-group open" id="grpCollect">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpCollect')">智能采集
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-banner.html" class="sidebar-item sidebar-item--sub">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item sidebar-item--sub active">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item sidebar-item--sub">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item sidebar-item--sub">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item sidebar-item--sub">大屏数据配置</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-group" id="grpInput">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpInput')">基础录入
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-cabin.html" class="sidebar-item sidebar-item--sub">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item sidebar-item--sub">小屋统计</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -179,7 +225,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<thead><tr>
|
||||
<th style="width:56px;">序号</th><th style="min-width:150px;">名称</th><th style="min-width:210px;">地点</th>
|
||||
<th style="min-width:90px;">图片</th><th style="min-width:170px;">所属部门</th>
|
||||
<th>启用</th><th>法定排班</th><th>设备数</th><th style="width:210px;">操作</th>
|
||||
<th>启用</th><th>法定排班</th><th>设备数</th><th style="width:280px;">操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
@@ -188,7 +234,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 新增/编辑弹窗 -->
|
||||
<!-- [交互] 新增/编辑健康室弹窗 -->
|
||||
<div class="modal-mask" id="formMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal__header"><span id="formTitle">新增健康室</span><button class="modal__close" onclick="closeForm()">×</button></div>
|
||||
@@ -219,19 +265,23 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
|
||||
<!-- [交互] 设备管理弹窗 -->
|
||||
<div class="modal-mask" id="devMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal--xl">
|
||||
<div class="modal__header"><span id="devTitle">设备管理</span><button class="modal__close" onclick="closeDev()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
|
||||
<label style="font-size:var(--font-xs);color:var(--text-secondary);">设备类型</label>
|
||||
<div class="toolbar">
|
||||
<span class="toolbar__label">设备类型</span>
|
||||
<select class="filter-select" id="devType" onchange="renderDev()" style="min-width:120px;">
|
||||
<option value="">全部</option><option value="1">测量设备</option><option value="2">心理检测</option><option value="3">治疗设备</option><option value="4">监测设备</option>
|
||||
</select>
|
||||
<span style="flex:1;"></span>
|
||||
<button class="btn btn-primary" onclick="showToast('原型示意:设备登记需走设备台账流程')">+ 添加设备</button>
|
||||
<span class="toolbar__spacer"></span>
|
||||
<button class="btn btn-primary" onclick="openDevForm(-1)">+ 添加设备</button>
|
||||
</div>
|
||||
<table class="inner-table">
|
||||
<thead><tr><th>设备编号</th><th>设备名称</th><th>设备类型</th><th>单位预约时间(分钟)</th><th>可预约人数(人)</th><th>设备状态</th></tr></thead>
|
||||
<thead><tr>
|
||||
<th style="min-width:110px;">设备编号</th><th style="min-width:140px;">设备名称</th><th style="min-width:100px;">设备类型</th>
|
||||
<th style="min-width:130px;">单位预约时间(分钟)</th><th style="min-width:110px;">可预约人数(人)</th>
|
||||
<th style="min-width:90px;">设备状态</th><th style="width:150px;">操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="devBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -239,6 +289,164 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 设备新增/编辑弹窗 -->
|
||||
<div class="modal-mask" id="devFormMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal__header"><span id="devFormTitle">新增设备</span><button class="modal__close" onclick="closeDevForm()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>设备编号</div><div class="form-row__control"><input class="form-input" id="dCode" placeholder="如:FX-BP-01"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>设备名称</div><div class="form-row__control"><input class="form-input" id="dName" placeholder="如:血压检测仪"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>设备类型</div><div class="form-row__control">
|
||||
<select class="filter-select" id="dCat" style="width:200px;" onchange="onDevCat()">
|
||||
<option value="">选择类型</option><option value="1">测量设备</option><option value="2">心理检测</option><option value="3">治疗设备</option><option value="4">监测设备</option>
|
||||
</select>
|
||||
</div></div>
|
||||
<div class="form-row" id="devLenRow"><div class="form-row__label">单位预约时间</div><div class="form-row__control">
|
||||
<select class="filter-select" id="dLen" style="width:200px;">
|
||||
<option value="10">10分钟</option><option value="20">20分钟</option><option value="30" selected>30分钟</option><option value="40">40分钟</option><option value="50">50分钟</option><option value="60">60分钟</option>
|
||||
</select>
|
||||
</div></div>
|
||||
<div class="form-row" id="devNumRow"><div class="form-row__label">可预约人数</div><div class="form-row__control"><input class="form-input" id="dNum" placeholder="同一时段可预约人数" style="max-width:200px;"></div></div>
|
||||
<div class="form-row"><div class="form-row__label">设备介绍</div><div class="form-row__control"><textarea class="form-textarea" id="dRemark" placeholder="设备功能与使用说明"></textarea></div></div>
|
||||
<div class="form-row"><div class="form-row__label">预约须知</div><div class="form-row__control"><textarea class="form-textarea" id="dNotice" placeholder="预约前需知事项"></textarea></div></div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeDevForm()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveDevForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 终端管理弹窗 -->
|
||||
<div class="modal-mask" id="termMask">
|
||||
<div class="modal--xl">
|
||||
<div class="modal__header"><span id="termTitle">终端管理</span><button class="modal__close" onclick="closeTerm()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="toolbar">
|
||||
<span class="toolbar__spacer"></span>
|
||||
<button class="btn btn-primary" onclick="openTermForm(-1)">+ 新增终端</button>
|
||||
</div>
|
||||
<table class="inner-table">
|
||||
<thead><tr>
|
||||
<th style="min-width:140px;">终端编号</th><th style="min-width:180px;">终端名称</th>
|
||||
<th style="min-width:100px;">终端状态</th><th style="width:160px;">操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="termBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeTerm()">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 终端新增/编辑弹窗 -->
|
||||
<div class="modal-mask" id="termFormMask">
|
||||
<div class="modal">
|
||||
<div class="modal__header"><span id="termFormTitle">新增终端</span><button class="modal__close" onclick="closeTermForm()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>终端编号</div><div class="form-row__control"><input class="form-input" id="tCode" placeholder="如:FX-T01"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>终端名称</div><div class="form-row__control"><input class="form-input" id="tName" placeholder="如:入口导诊终端"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>是否有效</div><div class="form-row__control">
|
||||
<div class="radio-group"><label><input type="radio" name="tStatus" value="1" checked>有效</label><label><input type="radio" name="tStatus" value="0">无效</label></div>
|
||||
</div></div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeTermForm()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveTermForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 管理员弹窗 -->
|
||||
<div class="modal-mask" id="adminMask">
|
||||
<div class="modal--xl">
|
||||
<div class="modal__header"><span id="adminTitle">管理员</span><button class="modal__close" onclick="closeAdmin()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="toolbar">
|
||||
<span class="toolbar__spacer"></span>
|
||||
<button class="btn btn-primary" onclick="openAdminForm(-1)">+ 新增管理员</button>
|
||||
</div>
|
||||
<table class="inner-table">
|
||||
<thead><tr>
|
||||
<th style="min-width:160px;">账号</th><th style="min-width:140px;">姓名</th><th style="width:200px;">操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="adminBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeAdmin()">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 管理员新增/编辑弹窗 -->
|
||||
<div class="modal-mask" id="adminFormMask">
|
||||
<div class="modal">
|
||||
<div class="modal__header"><span id="adminFormTitle">新增管理员</span><button class="modal__close" onclick="closeAdminForm()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>账号</div><div class="form-row__control"><input class="form-input" id="aUser" placeholder="登录账号"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>姓名</div><div class="form-row__control"><input class="form-input" id="aReal" placeholder="真实姓名"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>密码</div><div class="form-row__control"><input class="form-input" id="aPwd" type="password" placeholder="登录密码"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>确认密码</div><div class="form-row__control"><input class="form-input" id="aPwd2" type="password" placeholder="再次输入密码"></div></div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeAdminForm()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveAdminForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 管理员重置密码弹窗 -->
|
||||
<div class="modal-mask" id="adminPwdMask">
|
||||
<div class="modal">
|
||||
<div class="modal__header"><span id="adminPwdTitle">重置密码</span><button class="modal__close" onclick="closeAdminPwd()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>新密码</div><div class="form-row__control"><input class="form-input" id="apPwd" type="password" placeholder="输入新密码"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>确认密码</div><div class="form-row__control"><input class="form-input" id="apPwd2" type="password" placeholder="再次输入新密码"></div></div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeAdminPwd()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveAdminPwd()">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 自定义排班弹窗 -->
|
||||
<div class="modal-mask" id="selfMask">
|
||||
<div class="modal--xl">
|
||||
<div class="modal__header"><span id="selfTitle">自定义排班</span><button class="modal__close" onclick="closeSelf()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="toolbar">
|
||||
<span class="toolbar__spacer"></span>
|
||||
<button class="btn btn-primary" onclick="openSelfForm(-1)">+ 新增排班</button>
|
||||
</div>
|
||||
<table class="inner-table">
|
||||
<thead><tr>
|
||||
<th style="min-width:140px;">自定义日期</th><th style="min-width:260px;">开放时间</th>
|
||||
<th style="min-width:90px;">启用</th><th style="width:160px;">操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="selfBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeSelf()">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 自定义排班新增/编辑弹窗 -->
|
||||
<div class="modal-mask" id="selfFormMask">
|
||||
<div class="modal--wide">
|
||||
<div class="modal__header"><span id="selfFormTitle">新增排班</span><button class="modal__close" onclick="closeSelfForm()">×</button></div>
|
||||
<div class="modal__body">
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>选择日期</div><div class="form-row__control"><input class="time-input" id="sDate" type="date" style="width:200px;"></div></div>
|
||||
<div class="form-row"><div class="form-row__label"><i>*</i>开放时间</div><div class="form-row__control" style="flex-direction:column;align-items:stretch;"><div id="sTimesBox"></div></div></div>
|
||||
<div class="form-row" id="sStatusRow"><div class="form-row__label"><i>*</i>是否启用</div><div class="form-row__control">
|
||||
<div class="radio-group"><label><input type="radio" name="sStatus" value="是" checked>启用</label><label><input type="radio" name="sStatus" value="否">停用</label></div>
|
||||
</div></div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeSelfForm()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveSelfForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 详情弹窗 -->
|
||||
<div class="modal-mask" id="detailMask">
|
||||
<div class="modal--wide">
|
||||
@@ -265,23 +473,54 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<script>
|
||||
/* 单位→部门共享池(与床头呼叫域一致) */
|
||||
var unitDeparts={'采油一厂':['樊学作业区','麻子山作业区'],'采油二厂':['桐园作业区','姬圪台作业区'],'第四采油厂':['西峰作业区'],'采气一厂':['靖边气田']};
|
||||
/* 健康室数据:与站点/作业区勾稽;devices 内类型 1测量/2心理检测/3治疗设备/4监测设备 */
|
||||
/* 健康室数据:与站点/作业区勾稽;devices 内类型 1测量/2心理检测/3治疗设备/4监测设备;设备 status 1有效/0禁用 */
|
||||
var rooms=[
|
||||
{name:'樊学站点健康小屋',place:'樊学站点基地综合楼一层',unit:'采油一厂',depar:'樊学作业区',use:['樊学作业区'],status:'是',legal:'是',
|
||||
devices:[{code:'FX-BP-01',name:'血压检测仪',cat:1,len:30,num:4},{code:'FX-BG-02',name:'血糖分析仪',cat:1,len:20,num:6},{code:'FX-PSY-03',name:'心理测评系统',cat:2,len:40,num:2},{code:'FX-ECG-04',name:'十二导联心电',cat:4,len:0,num:0}]},
|
||||
devices:[{code:'FX-BP-01',name:'血压检测仪',cat:1,len:30,num:4,status:1,remark:'全自动臂式血压测量,支持数据云端回传。',notice:'测量前静坐 5 分钟,保持安静。'},
|
||||
{code:'FX-BG-02',name:'血糖分析仪',cat:1,len:20,num:6,status:1,remark:'指尖采血快速检测血糖。',notice:'空腹或餐后 2 小时测量。'},
|
||||
{code:'FX-PSY-03',name:'心理测评系统',cat:2,len:40,num:2,status:1,remark:'心理健康量表在线测评。',notice:'请独立完成测评。'},
|
||||
{code:'FX-ECG-04',name:'十二导联心电',cat:4,len:0,num:0,status:1,remark:'十二导联心电采集与判读。',notice:'测量前去除金属饰品。'}],
|
||||
terminals:[{code:'FX-T01',name:'入口导诊终端',status:1},{code:'FX-T02',name:'报告打印终端',status:1}],
|
||||
admins:[{userName:'fxyisheng',realName:'樊学健康师'},{userName:'fxhushi',realName:'樊学护士长'}],
|
||||
selfLayouts:[{date:'2026-09-10',times:[{open:'08:00',close:'12:00'},{open:'14:00',close:'18:00'}],status:'是'},
|
||||
{date:'2026-09-11',times:[{open:'08:00',close:'12:00'}],status:'是'}]},
|
||||
{name:'麻子山站点健康小屋',place:'麻子山站点综合办公楼二层',unit:'采油一厂',depar:'麻子山作业区',use:['麻子山作业区'],status:'是',legal:'是',
|
||||
devices:[{code:'MZ-BP-01',name:'血压检测仪',cat:1,len:30,num:4},{code:'MZ-BG-02',name:'血糖分析仪',cat:1,len:20,num:6},{code:'MZ-BMI-03',name:'体成分分析仪',cat:1,len:20,num:8}]},
|
||||
devices:[{code:'MZ-BP-01',name:'血压检测仪',cat:1,len:30,num:4,status:1,remark:'全自动臂式血压测量。',notice:''},
|
||||
{code:'MZ-BG-02',name:'血糖分析仪',cat:1,len:20,num:6,status:1,remark:'指尖采血快速检测血糖。',notice:''},
|
||||
{code:'MZ-BMI-03',name:'体成分分析仪',cat:1,len:20,num:8,status:1,remark:'体脂率、肌肉量等多指标分析。',notice:'光脚站立测量。'}],
|
||||
terminals:[{code:'MZ-T01',name:'自助签到终端',status:1}],
|
||||
admins:[{userName:'mzjiankangshi',realName:'麻子山健康师'}],
|
||||
selfLayouts:[{date:'2026-09-10',times:[{open:'09:00',close:'17:00'}],status:'是'}]},
|
||||
{name:'桐园站点健康小屋',place:'桐园站点基地服务中心一层',unit:'采油二厂',depar:'桐园作业区',use:['桐园作业区','姬圪台作业区'],status:'是',legal:'是',
|
||||
devices:[{code:'TY-BP-01',name:'血压检测仪',cat:1,len:30,num:4},{code:'TY-BMI-02',name:'体成分分析仪',cat:1,len:20,num:8},{code:'TY-PSY-03',name:'心理测评系统',cat:2,len:40,num:2},{code:'TY-DEC-04',name:'音乐放松舱',cat:3,len:60,num:2}]},
|
||||
devices:[{code:'TY-BP-01',name:'血压检测仪',cat:1,len:30,num:4,status:1,remark:'全自动臂式血压测量。',notice:''},
|
||||
{code:'TY-BMI-02',name:'体成分分析仪',cat:1,len:20,num:8,status:0,remark:'体脂率、肌肉量等多指标分析。',notice:'设备检修中,暂不可预约。'},
|
||||
{code:'TY-PSY-03',name:'心理测评系统',cat:2,len:40,num:2,status:1,remark:'心理健康量表在线测评。',notice:''},
|
||||
{code:'TY-DEC-04',name:'音乐放松舱',cat:3,len:60,num:2,status:1,remark:'音乐放松与生物反馈训练。',notice:'请穿宽松衣物。'}],
|
||||
terminals:[{code:'TY-T01',name:'入口导诊终端',status:1},{code:'TY-T02',name:'报告打印终端',status:1}],
|
||||
admins:[{userName:'tyyisheng',realName:'桐园健康师'},{userName:'tyhushi',realName:'桐园护士长'}],
|
||||
selfLayouts:[{date:'2026-09-10',times:[{open:'08:00',close:'12:00'},{open:'13:30',close:'17:30'}],status:'是'},
|
||||
{date:'2026-09-12',times:[{open:'08:30',close:'11:30'}],status:'否'}]},
|
||||
{name:'西峰基地健康小屋',place:'西峰基地职工服务中心二层',unit:'第四采油厂',depar:'西峰作业区',use:['西峰作业区'],status:'是',legal:'否',
|
||||
devices:[{code:'XF-BP-01',name:'血压检测仪',cat:1,len:30,num:4},{code:'XF-BG-02',name:'血糖分析仪',cat:1,len:20,num:6},{code:'XF-LAS-03',name:'激光治疗仪',cat:3,len:30,num:3},{code:'XF-ECG-04',name:'十二导联心电',cat:4,len:0,num:0},{code:'XF-WCH-05',name:'智能手表充电柜',cat:4,len:0,num:0}]},
|
||||
devices:[{code:'XF-BP-01',name:'血压检测仪',cat:1,len:30,num:4,status:1,remark:'全自动臂式血压测量。',notice:''},
|
||||
{code:'XF-BG-02',name:'血糖分析仪',cat:1,len:20,num:6,status:1,remark:'指尖采血快速检测血糖。',notice:''},
|
||||
{code:'XF-LAS-03',name:'激光治疗仪',cat:3,len:30,num:3,status:1,remark:'低能量激光理疗。',notice:'遵医嘱使用。'},
|
||||
{code:'XF-ECG-04',name:'十二导联心电',cat:4,len:0,num:0,status:1,remark:'十二导联心电采集。',notice:''},
|
||||
{code:'XF-WCH-05',name:'智能手表充电柜',cat:4,len:0,num:0,status:1,remark:'健康手表集中充电与数据同步。',notice:''}],
|
||||
terminals:[{code:'XF-T01',name:'入口导诊终端',status:1},{code:'XF-T02',name:'报告打印终端',status:1}],
|
||||
admins:[{userName:'xfjiankangshi',realName:'西峰健康师'}],
|
||||
selfLayouts:[{date:'2026-09-10',times:[{open:'08:00',close:'18:00'}],status:'是'}]},
|
||||
{name:'靖边气田健康小屋',place:'靖边气田站点营地活动室',unit:'采气一厂',depar:'靖边气田',use:['靖边气田'],status:'否',legal:'是',
|
||||
devices:[{code:'JB-BP-01',name:'血压检测仪',cat:1,len:30,num:4},{code:'JB-BMI-02',name:'体成分分析仪',cat:1,len:20,num:8}]}
|
||||
devices:[{code:'JB-BP-01',name:'血压检测仪',cat:1,len:30,num:4,status:1,remark:'全自动臂式血压测量。',notice:''},
|
||||
{code:'JB-BMI-02',name:'体成分分析仪',cat:1,len:20,num:8,status:1,remark:'体脂率、肌肉量等多指标分析。',notice:''}],
|
||||
terminals:[{code:'JB-T01',name:'入口导诊终端',status:0}],
|
||||
admins:[{userName:'jbjiankangshi',realName:'靖边健康师'}],
|
||||
selfLayouts:[]}
|
||||
];
|
||||
var catName={1:'测量设备',2:'心理检测',3:'治疗设备',4:'监测设备'};
|
||||
var catBadge={1:'badge--info',2:'badge--warning',3:'badge--success',4:'badge--muted'};
|
||||
var gradients=['linear-gradient(135deg,#1890FF,#36CFC9)','linear-gradient(135deg,#722ED1,#1890FF)','linear-gradient(135deg,#FA8C16,#F5222D)','linear-gradient(135deg,#52C41A,#13C2C2)','linear-gradient(135deg,#EB2F96,#722ED1)'];
|
||||
var formIdx=-1,devIdx=-1,delIdx=-1;
|
||||
var devFormIdx=-1,termIdx=-1,termFormIdx=-1,adminIdx=-1,adminFormIdx=-1,adminPwdIdx=-1,selfIdx=-1,selfFormIdx=-1;
|
||||
|
||||
function onFilterUnit(){
|
||||
var u=document.getElementById('filterUnit').value;
|
||||
@@ -302,17 +541,26 @@ function render(){
|
||||
+'<td><span class="badge '+(r.status==='是'?'badge--success':'badge--muted')+'">'+r.status+'</span></td>'
|
||||
+'<td><span class="badge '+(r.legal==='是'?'badge--info':'badge--warning')+'">'+r.legal+'</span></td>'
|
||||
+'<td>'+r.devices.length+' 台</td>'
|
||||
+'<td><button class="btn btn-link" onclick="openDev('+i+')">设备管理</button>'
|
||||
+'<button class="btn btn-link" onclick="openDetail('+i+')">详情</button>'
|
||||
+'<button class="btn btn-link" onclick="openForm('+i+')">编辑</button>'
|
||||
+'<button class="btn btn-link" style="color:var(--danger);" onclick="openDel('+i+')">删除</button></td></tr>';
|
||||
+'<td>'
|
||||
+'<button class="btn btn-link" onclick="openDev('+i+')">设备</button>'
|
||||
+'<button class="btn btn-link" onclick="openTerm('+i+')">终端</button>'
|
||||
+'<button class="btn btn-link" onclick="openAdmin('+i+')">管理员</button>'
|
||||
+'<div class="more-wrap"><button class="btn btn-link">更多 ▾</button>'
|
||||
+'<div class="more-menu">'
|
||||
+'<a onclick="openDetail('+i+')">详情</a>'
|
||||
+'<a onclick="openForm('+i+')">编辑</a>'
|
||||
+'<a onclick="openSelf('+i+')">自定义排班</a>'
|
||||
+'<a class="danger" onclick="openDel('+i+')">删除</a>'
|
||||
+'</div></div>'
|
||||
+'</td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="9">没有符合条件的健康室</td></tr>';
|
||||
var totalDev=rooms.reduce(function(s,r){return s+r.devices.length;},0);
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 间 · 在册 '+rooms.length+' 间(设备合计 '+totalDev+' 台)';
|
||||
var totalTerm=rooms.reduce(function(s,r){return s+r.terminals.length;},0);
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 间 · 在册 '+rooms.length+' 间(设备合计 '+totalDev+' 台 · 终端合计 '+totalTerm+' 个)';
|
||||
}
|
||||
function resetFilter(){['filterUnit','filterDepar','filterName','filterStatus'].forEach(function(id){document.getElementById(id).value='';});document.getElementById('filterDepar').disabled=true;render();}
|
||||
|
||||
/* ---- 新增/编辑 ---- */
|
||||
/* ---- 新增/编辑健康室 ---- */
|
||||
function onFormUnit(){
|
||||
var u=document.getElementById('fUnit').value;
|
||||
var sel=document.getElementById('fDepar');
|
||||
@@ -346,7 +594,7 @@ function saveForm(){
|
||||
var use=Array.prototype.slice.call(document.querySelectorAll('#fUseChips .on')).map(function(c){return c.getAttribute('data-d');});
|
||||
var legal=document.querySelector('input[name=fLegal]:checked').value,status=document.querySelector('input[name=fStatus]:checked').value;
|
||||
if(!name||!place||!u||!d||!use.length){showToast('请完整填写名称/地址/所属与使用部门');return;}
|
||||
if(formIdx<0){rooms.push({name:name,place:place,unit:u,depar:d,use:use,status:status,legal:legal,devices:[]});}
|
||||
if(formIdx<0){rooms.push({name:name,place:place,unit:u,depar:d,use:use,status:status,legal:legal,devices:[],terminals:[],admins:[],selfLayouts:[]});}
|
||||
else{var r=rooms[formIdx];r.name=name;r.place=place;r.unit=u;r.depar=d;r.use=use;r.status=status;r.legal=legal;}
|
||||
closeForm();render();showToast(formIdx<0?'新增成功,可继续为其登记设备':'保存成功');
|
||||
}
|
||||
@@ -357,8 +605,10 @@ function openDetail(i){
|
||||
+di('健康室名称',r.name)+di('地点',r.place)
|
||||
+di('所属部门',r.unit+' / '+r.depar)+di('使用部门',r.use.join('、'))
|
||||
+di('启用状态',r.status)+di('使用法定排班',r.legal)
|
||||
+di('在册设备数',r.devices.length+' 台',true)
|
||||
+di('在册设备数',r.devices.length+' 台')+di('终端数',r.terminals.length+' 个')
|
||||
+di('管理员数',r.admins.length+' 名')+di('自定义排班',r.selfLayouts.length+' 条')
|
||||
+di('设备清单',r.devices.map(function(d){return d.name+'('+d.code+')';}).join('、')||'—',true)
|
||||
+di('终端清单',r.terminals.map(function(t){return t.name+'('+t.code+')';}).join('、')||'—',true)
|
||||
+'</div>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
@@ -375,21 +625,239 @@ function renderDev(){
|
||||
var t=document.getElementById('devType').value;
|
||||
var list=rooms[devIdx].devices.filter(function(d){return !t||String(d.cat)===t;});
|
||||
document.getElementById('devBody').innerHTML=list.map(function(d){
|
||||
return '<tr><td style="font-family:monospace;">'+d.code+'</td><td>'+d.name+'</td>'
|
||||
var j=rooms[devIdx].devices.indexOf(d);
|
||||
return '<tr><td class="mono">'+d.code+'</td><td style="text-align:left;padding-left:12px;font-weight:500;">'+d.name+'</td>'
|
||||
+'<td><span class="badge '+catBadge[d.cat]+'">'+catName[d.cat]+'</span></td>'
|
||||
+'<td>'+(d.cat===4?'—':d.len)+'</td><td>'+(d.cat===4?'—':d.num)+'</td>'
|
||||
+'<td><span class="badge badge--success">有效</span></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="6">该类型下暂无设备</td></tr>';
|
||||
+'<td>'+(d.cat===4?'—':d.len+' 分钟')+'</td><td>'+(d.cat===4?'—':d.num+' 人')+'</td>'
|
||||
+'<td><span class="badge '+(d.status===1?'badge--success':'badge--muted')+'">'+(d.status===1?'有效':'禁用')+'</span></td>'
|
||||
+'<td>'
|
||||
+(d.status===1?'<button class="btn btn-link" style="color:var(--warning);" onclick="toggleDev('+j+',0)">禁用</button>':'<button class="btn btn-link" onclick="toggleDev('+j+',1)">启用</button>')
|
||||
+'<button class="btn btn-link" onclick="openDevForm('+j+')">编辑</button>'
|
||||
+'<button class="btn btn-link" style="color:var(--danger);" onclick="delDev('+j+')">删除</button></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="7">该类型下暂无设备</td></tr>';
|
||||
}
|
||||
function toggleDev(j,st){
|
||||
rooms[devIdx].devices[j].status=st;renderDev();
|
||||
showToast(st===1?'已启用设备':'已禁用设备');
|
||||
}
|
||||
function delDev(j){
|
||||
var d=rooms[devIdx].devices[j];
|
||||
rooms[devIdx].devices.splice(j,1);renderDev();render();
|
||||
showToast('已删除设备 '+d.name);
|
||||
}
|
||||
function onDevCat(){
|
||||
var c=document.getElementById('dCat').value;
|
||||
document.getElementById('devLenRow').style.display=(c==='4'||c==='')?'none':'';
|
||||
document.getElementById('devNumRow').style.display=(c==='4'||c==='')?'none':'';
|
||||
}
|
||||
function openDevForm(j){
|
||||
devFormIdx=j;var d=j>=0?rooms[devIdx].devices[j]:null;
|
||||
document.getElementById('devFormTitle').textContent=j<0?'新增设备':'编辑设备 · '+d.name;
|
||||
document.getElementById('dCode').value=j<0?'':d.code;
|
||||
document.getElementById('dName').value=j<0?'':d.name;
|
||||
document.getElementById('dCat').value=j<0?'':String(d.cat);onDevCat();
|
||||
document.getElementById('dLen').value=j<0?'30':String(d.len);
|
||||
document.getElementById('dNum').value=j<0?'':(d.num||'');
|
||||
document.getElementById('dRemark').value=j<0?'':(d.remark||'');
|
||||
document.getElementById('dNotice').value=j<0?'':(d.notice||'');
|
||||
document.getElementById('devFormMask').classList.add('open');
|
||||
}
|
||||
function closeDevForm(){document.getElementById('devFormMask').classList.remove('open');}
|
||||
function saveDevForm(){
|
||||
var code=document.getElementById('dCode').value.trim(),name=document.getElementById('dName').value.trim();
|
||||
var cat=document.getElementById('dCat').value;
|
||||
if(!code||!name||!cat){showToast('请完整填写编号/名称/类型');return;}
|
||||
var len=cat==='4'?0:Number(document.getElementById('dLen').value);
|
||||
var num=cat==='4'?0:Number(document.getElementById('dNum').value);
|
||||
var remark=document.getElementById('dRemark').value.trim(),notice=document.getElementById('dNotice').value.trim();
|
||||
var obj={code:code,name:name,cat:Number(cat),len:len,num:num,status:1,remark:remark,notice:notice};
|
||||
if(devFormIdx<0){rooms[devIdx].devices.push(obj);}
|
||||
else{var d=rooms[devIdx].devices[devFormIdx];d.code=code;d.name=name;d.cat=Number(cat);d.len=len;d.num=num;d.remark=remark;d.notice=notice;}
|
||||
closeDevForm();renderDev();render();
|
||||
showToast(devFormIdx<0?'设备已添加':'设备已保存');
|
||||
}
|
||||
|
||||
/* ---- 终端管理 ---- */
|
||||
function openTerm(i){
|
||||
termIdx=i;
|
||||
document.getElementById('termTitle').textContent='终端管理 · '+rooms[i].name;
|
||||
renderTerm();document.getElementById('termMask').classList.add('open');
|
||||
}
|
||||
function closeTerm(){document.getElementById('termMask').classList.remove('open');}
|
||||
function renderTerm(){
|
||||
var list=rooms[termIdx].terminals;
|
||||
document.getElementById('termBody').innerHTML=list.map(function(t){
|
||||
var j=rooms[termIdx].terminals.indexOf(t);
|
||||
return '<tr><td class="mono">'+t.code+'</td><td style="text-align:left;padding-left:12px;font-weight:500;">'+t.name+'</td>'
|
||||
+'<td><span class="badge '+(t.status===1?'badge--success':'badge--muted')+'">'+(t.status===1?'有效':'无效')+'</span></td>'
|
||||
+'<td><button class="btn btn-link" onclick="openTermForm('+j+')">编辑</button>'
|
||||
+'<button class="btn btn-link" style="color:var(--danger);" onclick="delTerm('+j+')">删除</button></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="4">暂无终端,点击右上角新增</td></tr>';
|
||||
}
|
||||
function openTermForm(j){
|
||||
termFormIdx=j;var t=j>=0?rooms[termIdx].terminals[j]:null;
|
||||
document.getElementById('termFormTitle').textContent=j<0?'新增终端':'编辑终端 · '+t.name;
|
||||
document.getElementById('tCode').value=j<0?'':t.code;
|
||||
document.getElementById('tName').value=j<0?'':t.name;
|
||||
document.querySelectorAll('input[name=tStatus]')[j>=0&&t.status===0?1:0].checked=true;
|
||||
document.getElementById('termFormMask').classList.add('open');
|
||||
}
|
||||
function closeTermForm(){document.getElementById('termFormMask').classList.remove('open');}
|
||||
function saveTermForm(){
|
||||
var code=document.getElementById('tCode').value.trim(),name=document.getElementById('tName').value.trim();
|
||||
var st=Number(document.querySelector('input[name=tStatus]:checked').value);
|
||||
if(!code||!name){showToast('请完整填写终端编号与名称');return;}
|
||||
var obj={code:code,name:name,status:st};
|
||||
if(termFormIdx<0){rooms[termIdx].terminals.push(obj);}
|
||||
else{var t=rooms[termIdx].terminals[termFormIdx];t.code=code;t.name=name;t.status=st;}
|
||||
closeTermForm();renderTerm();render();
|
||||
showToast(termFormIdx<0?'终端已新增':'终端已保存');
|
||||
}
|
||||
function delTerm(j){
|
||||
var t=rooms[termIdx].terminals[j];
|
||||
rooms[termIdx].terminals.splice(j,1);renderTerm();render();
|
||||
showToast('已删除终端 '+t.name);
|
||||
}
|
||||
|
||||
/* ---- 管理员 ---- */
|
||||
function openAdmin(i){
|
||||
adminIdx=i;
|
||||
document.getElementById('adminTitle').textContent='管理员 · '+rooms[i].name;
|
||||
renderAdmin();document.getElementById('adminMask').classList.add('open');
|
||||
}
|
||||
function closeAdmin(){document.getElementById('adminMask').classList.remove('open');}
|
||||
function renderAdmin(){
|
||||
var list=rooms[adminIdx].admins;
|
||||
document.getElementById('adminBody').innerHTML=list.map(function(a){
|
||||
var j=rooms[adminIdx].admins.indexOf(a);
|
||||
return '<tr><td class="mono">'+a.userName+'</td><td style="text-align:left;padding-left:12px;font-weight:500;">'+a.realName+'</td>'
|
||||
+'<td><button class="btn btn-link" onclick="openAdminPwd('+j+')">重置密码</button>'
|
||||
+'<button class="btn btn-link" onclick="openAdminForm('+j+')">编辑</button>'
|
||||
+'<button class="btn btn-link" style="color:var(--danger);" onclick="delAdmin('+j+')">删除</button></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="3">暂无管理员,点击右上角新增</td></tr>';
|
||||
}
|
||||
function openAdminForm(j){
|
||||
adminFormIdx=j;var a=j>=0?rooms[adminIdx].admins[j]:null;
|
||||
document.getElementById('adminFormTitle').textContent=j<0?'新增管理员':'编辑管理员 · '+a.realName;
|
||||
document.getElementById('aUser').value=j<0?'':a.userName;
|
||||
document.getElementById('aReal').value=j<0?'':a.realName;
|
||||
document.getElementById('aPwd').value='';document.getElementById('aPwd2').value='';
|
||||
document.getElementById('adminFormMask').classList.add('open');
|
||||
}
|
||||
function closeAdminForm(){document.getElementById('adminFormMask').classList.remove('open');}
|
||||
function saveAdminForm(){
|
||||
var user=document.getElementById('aUser').value.trim(),real=document.getElementById('aReal').value.trim();
|
||||
var pwd=document.getElementById('aPwd').value,pwd2=document.getElementById('aPwd2').value;
|
||||
if(!user||!real){showToast('请填写账号与姓名');return;}
|
||||
if(adminFormIdx<0){if(!pwd||pwd!==pwd2){showToast('请设置密码并保持一致');return;}}
|
||||
else if(pwd&&pwd!==pwd2){showToast('两次密码不一致');return;}
|
||||
var obj={userName:user,realName:real};
|
||||
if(adminFormIdx<0){rooms[adminIdx].admins.push(obj);}
|
||||
else{var a=rooms[adminIdx].admins[adminFormIdx];a.userName=user;a.realName=real;}
|
||||
closeAdminForm();renderAdmin();
|
||||
showToast(adminFormIdx<0?'管理员已新增':'管理员已保存');
|
||||
}
|
||||
function delAdmin(j){
|
||||
var a=rooms[adminIdx].admins[j];
|
||||
rooms[adminIdx].admins.splice(j,1);renderAdmin();
|
||||
showToast('已删除管理员 '+a.realName);
|
||||
}
|
||||
function openAdminPwd(j){
|
||||
adminPwdIdx=j;var a=rooms[adminIdx].admins[j];
|
||||
document.getElementById('adminPwdTitle').textContent='重置密码 · '+a.realName;
|
||||
document.getElementById('apPwd').value='';document.getElementById('apPwd2').value='';
|
||||
document.getElementById('adminPwdMask').classList.add('open');
|
||||
}
|
||||
function closeAdminPwd(){document.getElementById('adminPwdMask').classList.remove('open');}
|
||||
function saveAdminPwd(){
|
||||
var pwd=document.getElementById('apPwd').value,pwd2=document.getElementById('apPwd2').value;
|
||||
if(!pwd||pwd!==pwd2){showToast('请设置新密码并保持一致');return;}
|
||||
closeAdminPwd();showToast('密码已重置');
|
||||
}
|
||||
|
||||
/* ---- 自定义排班 ---- */
|
||||
function openSelf(i){
|
||||
selfIdx=i;
|
||||
document.getElementById('selfTitle').textContent='自定义排班 · '+rooms[i].name;
|
||||
renderSelf();document.getElementById('selfMask').classList.add('open');
|
||||
}
|
||||
function closeSelf(){document.getElementById('selfMask').classList.remove('open');}
|
||||
function renderSelf(){
|
||||
var list=rooms[selfIdx].selfLayouts;
|
||||
document.getElementById('selfBody').innerHTML=list.map(function(s){
|
||||
var j=rooms[selfIdx].selfLayouts.indexOf(s);
|
||||
var times=s.times.map(function(t){return t.open+' - '+t.close;}).join('、');
|
||||
return '<tr><td>'+s.date+'</td><td style="text-align:left;padding-left:12px;">'+times+'</td>'
|
||||
+'<td><span class="badge '+(s.status==='是'?'badge--success':'badge--muted')+'">'+s.status+'</span></td>'
|
||||
+'<td><button class="btn btn-link" onclick="openSelfForm('+j+')">编辑</button>'
|
||||
+'<button class="btn btn-link" style="color:var(--danger);" onclick="delSelf('+j+')">删除</button></td></tr>';
|
||||
}).join('')||'<tr><td class="td-empty" colspan="4">暂无自定义排班,点击右上角新增</td></tr>';
|
||||
}
|
||||
function timeRowHtml(t){
|
||||
return '<div class="time-row">'
|
||||
+'<input class="time-input" type="time" value="'+(t?t.open:'08:00')+'" data-k="open">'
|
||||
+'<span class="sep">—</span>'
|
||||
+'<input class="time-input" type="time" value="'+(t?t.close:'12:00')+'" data-k="close">'
|
||||
+'<button class="icon-btn" type="button" onclick="delTimeRow(this)">−</button>'
|
||||
+'</div>';
|
||||
}
|
||||
function renderSelfTimes(times){
|
||||
var box=document.getElementById('sTimesBox');
|
||||
box.innerHTML=(times&×.length?times:[{open:'08:00',close:'12:00'}]).map(timeRowHtml).join('')
|
||||
+'<button class="btn btn-default" type="button" onclick="addTimeRow()">+ 增加时间段</button>';
|
||||
}
|
||||
function addTimeRow(){
|
||||
var box=document.getElementById('sTimesBox');
|
||||
box.insertBefore(htmlToEl(timeRowHtml(null)),box.lastElementChild);
|
||||
}
|
||||
function delTimeRow(btn){
|
||||
var box=document.getElementById('sTimesBox');
|
||||
if(box.querySelectorAll('.time-row').length<=1){showToast('至少保留一个时间段');return;}
|
||||
btn.parentNode.remove();
|
||||
}
|
||||
function htmlToEl(html){var t=document.createElement('template');t.innerHTML=html.trim();return t.content.firstChild;}
|
||||
function openSelfForm(j){
|
||||
selfFormIdx=j;var s=j>=0?rooms[selfIdx].selfLayouts[j]:null;
|
||||
document.getElementById('selfFormTitle').textContent=j<0?'新增排班':'编辑排班 · '+s.date;
|
||||
document.getElementById('sDate').value=j<0?'':s.date;
|
||||
renderSelfTimes(j>=0?s.times:null);
|
||||
document.getElementById('sStatusRow').style.display=j<0?'none':'';
|
||||
if(j>=0){document.querySelectorAll('input[name=sStatus]')[s.status==='否'?1:0].checked=true;}
|
||||
document.getElementById('selfFormMask').classList.add('open');
|
||||
}
|
||||
function closeSelfForm(){document.getElementById('selfFormMask').classList.remove('open');}
|
||||
function saveSelfForm(){
|
||||
var date=document.getElementById('sDate').value;
|
||||
var rows=Array.prototype.slice.call(document.querySelectorAll('#sTimesBox .time-row'));
|
||||
var times=rows.map(function(row){
|
||||
var o=row.querySelector('[data-k=open]').value,c=row.querySelector('[data-k=close]').value;
|
||||
return {open:o||'00:00',close:c||'00:00'};
|
||||
});
|
||||
if(!date){showToast('请选择排班日期');return;}
|
||||
if(!times.length){showToast('请设置开放时间');return;}
|
||||
var status=selfFormIdx>=0?document.querySelector('input[name=sStatus]:checked').value:'是';
|
||||
var obj={date:date,times:times,status:status};
|
||||
if(selfFormIdx<0){rooms[selfIdx].selfLayouts.push(obj);}
|
||||
else{rooms[selfIdx].selfLayouts[selfFormIdx]=obj;}
|
||||
closeSelfForm();renderSelf();
|
||||
showToast(selfFormIdx<0?'排班已新增':'排班已保存');
|
||||
}
|
||||
function delSelf(j){
|
||||
var s=rooms[selfIdx].selfLayouts[j];
|
||||
rooms[selfIdx].selfLayouts.splice(j,1);renderSelf();
|
||||
showToast('已删除 '+s.date+' 的排班');
|
||||
}
|
||||
|
||||
/* ---- 删除 ---- */
|
||||
function openDel(i){
|
||||
delIdx=i;var r=rooms[i];
|
||||
document.getElementById('delBody').innerHTML='确认删除健康室 <b style="color:var(--text-primary);">'+r.name+'</b>?其名下 <b>'+r.devices.length+'</b> 台设备登记与历史预约记录将一并失效,操作不可恢复。';
|
||||
document.getElementById('delBody').innerHTML='确认删除健康室 <b style="color:var(--text-primary);">'+r.name+'</b>?其名下 <b>'+r.devices.length+'</b> 台设备、<b>'+r.terminals.length+'</b> 个终端的登记与历史预约记录将一并失效,操作不可恢复。';
|
||||
document.getElementById('delMask').classList.add('open');
|
||||
}
|
||||
function closeDel(){document.getElementById('delMask').classList.remove('open');}
|
||||
function confirmDel(){rooms.splice(delIdx,1);closeDel();render();showToast('已删除');}
|
||||
/* [交互] 侧栏分组展开/收起 */
|
||||
function toggleGroup(id){document.getElementById(id).classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
|
||||
@@ -30,6 +30,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
/* [交互] 二级分组菜单展开/收起:点击分组标题切换 open 类,三级子项默认收起 */
|
||||
.sidebar-group__label{display:flex;align-items:center;justify-content:space-between;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;}
|
||||
.sidebar-group__label:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-group__label svg{transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-group.open .sidebar-group__label svg{transform:rotate(180deg);}
|
||||
.sidebar-group__items{display:none;}
|
||||
.sidebar-group.open .sidebar-group__items{display:block;}
|
||||
.sidebar-item--sub{padding-left:44px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
@@ -102,13 +110,27 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
<!-- 侧边栏(当前一级分组「健康小屋」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">健康小屋</div>
|
||||
<a href="hut-banner.html" class="sidebar-item">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item active">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item">大屏数据配置</a>
|
||||
<a href="hut-cabin.html" class="sidebar-item">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item">小屋统计</a>
|
||||
<div class="sidebar-group open" id="grpCollect">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpCollect')">智能采集
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-banner.html" class="sidebar-item sidebar-item--sub">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item sidebar-item--sub">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item sidebar-item--sub">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item sidebar-item--sub active">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item sidebar-item--sub">大屏数据配置</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-group" id="grpInput">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpInput')">基础录入
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-cabin.html" class="sidebar-item sidebar-item--sub">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item sidebar-item--sub">小屋统计</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -247,6 +269,8 @@ function openDel(i){
|
||||
}
|
||||
function closeDel(){document.getElementById('delMask').classList.remove('open');}
|
||||
function confirmDel(){schedules.splice(delIdx,1);closeDel();render();showToast('已删除该排班');}
|
||||
/* [交互] 侧栏分组展开/收起 */
|
||||
function toggleGroup(id){document.getElementById(id).classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
|
||||
@@ -30,6 +30,14 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
/* [交互] 二级分组菜单展开/收起:点击分组标题切换 open 类,三级子项默认收起 */
|
||||
.sidebar-group__label{display:flex;align-items:center;justify-content:space-between;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;}
|
||||
.sidebar-group__label:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-group__label svg{transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-group.open .sidebar-group__label svg{transform:rotate(180deg);}
|
||||
.sidebar-group__items{display:none;}
|
||||
.sidebar-group.open .sidebar-group__items{display:block;}
|
||||
.sidebar-item--sub{padding-left:44px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.tab-bar{background:#fff;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);display:flex;flex-wrap:wrap;padding:0 8px;border-bottom:1px solid var(--border);}
|
||||
.tab-item{padding:12px 16px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap;}
|
||||
@@ -79,13 +87,27 @@ td.ro{color:var(--text-placeholder);font-weight:400;}
|
||||
<!-- 侧边栏(当前一级分组「健康小屋」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">健康小屋</div>
|
||||
<a href="hut-banner.html" class="sidebar-item">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item active">大屏数据配置</a>
|
||||
<a href="hut-cabin.html" class="sidebar-item">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item">小屋统计</a>
|
||||
<div class="sidebar-group open" id="grpCollect">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpCollect')">智能采集
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-banner.html" class="sidebar-item sidebar-item--sub">轮播图配置</a>
|
||||
<a href="hut-room.html" class="sidebar-item sidebar-item--sub">健康室管理</a>
|
||||
<a href="hut-appointment.html" class="sidebar-item sidebar-item--sub">预约管理</a>
|
||||
<a href="hut-schedule.html" class="sidebar-item sidebar-item--sub">默认排班</a>
|
||||
<a href="hut-screen.html" class="sidebar-item sidebar-item--sub active">大屏数据配置</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-group" id="grpInput">
|
||||
<div class="sidebar-group__label" onclick="toggleGroup('grpInput')">基础录入
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5L5 6.5l3-3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
</div>
|
||||
<div class="sidebar-group__items">
|
||||
<a href="hut-cabin.html" class="sidebar-item sidebar-item--sub">小屋管理</a>
|
||||
<a href="hut-cabin-stat.html" class="sidebar-item sidebar-item--sub">小屋统计</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
@@ -206,6 +228,8 @@ function cancelEdit(){
|
||||
if(backup){Object.keys(backup).forEach(function(k){t.val[k]=backup[k];});}
|
||||
editing=false;backup=null;renderActions();renderTable();showToast('已取消录入');
|
||||
}
|
||||
/* [交互] 侧栏分组展开/收起 */
|
||||
function toggleGroup(id){document.getElementById(id).classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var el=document.getElementById('toast');el.textContent=msg;el.classList.add('show');
|
||||
clearTimeout(el._timer);el._timer=setTimeout(function(){el.classList.remove('show');},2200);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>救护车统计 | 一线医疗</title>
|
||||
<title>救护车统计 · 统计图表 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
@@ -31,10 +31,13 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.view-switch{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.view-switch a{display:inline-flex;align-items:center;padding:0 14px;height:32px;font-size:var(--font-sm);color:var(--text-secondary);text-decoration:none;background:#fff;}
|
||||
.view-switch a+a{border-left:1px solid var(--border);}
|
||||
.view-switch a.active{background:var(--primary);color:#fff;}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
/* [交互] 所属单位→所属医疗点级联;清空单位回到全局统计(与老系统 allowClear 一致) */
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
@@ -94,22 +97,31 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
<!-- 侧边栏(当前一级分组「数据统计」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">数据统计</div>
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">医疗点统计</a>
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item active">救护车统计</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
医疗点统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-clinic-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup open">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item active">统计图表</a>
|
||||
<a href="stat-ambulance-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="stat-rescue-chart.html" class="sidebar-item">救助物品统计</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<!-- [交互] 图表/报表两种查看形态,数据同源互切 -->
|
||||
<div class="title-line">
|
||||
<span>救护车统计</span>
|
||||
<div class="view-switch" style="margin-left:auto;">
|
||||
<a class="active" href="stat-ambulance-chart.html">图表视图</a>
|
||||
<a href="stat-ambulance-table.html">报表视图</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 单位→医疗点级联筛选,清空单位回全局;统计口径随筛选联动(照搬老系统新版页) -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
@@ -369,6 +381,7 @@ function showToast(msg){
|
||||
document.getElementById('selTopType').innerHTML='<option value="">全部类型</option>'+TYPES.map(function(k){return '<option value="'+k+'">'+TYPE_NAME[k]+'</option>';}).join('');
|
||||
})();
|
||||
renderScope();
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('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>救护车统计 | 一线医疗</title>
|
||||
<title>救护车统计 · 统计报表 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
@@ -30,41 +30,53 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.view-switch{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.view-switch a{display:inline-flex;align-items:center;padding:0 14px;height:32px;font-size:var(--font-sm);color:var(--text-secondary);text-decoration:none;background:#fff;}
|
||||
.view-switch a+a{border-left:1px solid var(--border);}
|
||||
.view-switch a.active{background:var(--primary);color:#fff;}
|
||||
.toolbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;}
|
||||
.date-switch{display:inline-flex;height:32px;line-height:32px;border:1px solid var(--primary);border-radius:var(--radius-sm);overflow:hidden;font-size:var(--font-sm);}
|
||||
.date-switch span{padding:0 16px;cursor:pointer;color:var(--primary);background:#fff;border-right:1px solid var(--primary);white-space:nowrap;}
|
||||
.date-switch span:last-child{border-right:none;}
|
||||
.date-switch span.on{background:var(--primary);color:#fff;}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-select{height:36px;min-width:140px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);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 8px center;cursor:pointer;outline:none;appearance:none;-webkit-appearance:none;}
|
||||
.filter-select:disabled{background-color:#F5F5F5;color:var(--text-placeholder);cursor:not-allowed;}
|
||||
.num-row{display:flex;gap:16px;margin-top:16px;align-items:stretch;}
|
||||
.stat-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:16px 20px;}
|
||||
.stat-card__title{font-weight:600;color:var(--text-primary);margin-bottom:12px;font-size:var(--font-base);}
|
||||
.stat-card__grid{display:flex;justify-content:space-around;background:#F8F8FA;border-radius:10px;padding:14px 8px;}
|
||||
.stat-cell{text-align:center;}
|
||||
.stat-cell__val{font-size:22px;font-weight:600;color:var(--text-primary);}
|
||||
.stat-cell__val small{font-size:var(--font-xs);font-weight:400;color:var(--text-placeholder);margin-left:2px;}
|
||||
.stat-cell__name{font-size:var(--font-sm);color:var(--text-secondary);margin-top:4px;}
|
||||
.num-card--l{width:32%;}.num-card--r{width:68%;}
|
||||
.title-line{display:flex;align-items:center;margin-bottom:16px;}
|
||||
.title-line span{font-size:var(--font-base);font-weight:600;}
|
||||
.tbl-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:18px 22px;margin-top:16px;}
|
||||
.tbl-card__title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin-bottom:12px;}
|
||||
.tbl-scroll{overflow-x:auto;}
|
||||
table.rpt{width:100%;border-collapse:separate;border-spacing:0;min-width:1100px;}
|
||||
.rpt th,.rpt td{border:1px solid #F0F0F0;padding:10px 12px;font-size:var(--font-sm);text-align:center;white-space:nowrap;}
|
||||
.rpt thead th{background:#FAFAFA;color:var(--text-secondary);font-weight:500;font-size:var(--font-sm);}
|
||||
.rpt thead tr:first-child th{background:#F0F5FF;color:var(--text-primary);font-weight:600;font-size:var(--font-sm);}
|
||||
.rpt tbody tr:hover{background:#F8FBFF;}
|
||||
.rpt .num{font-variant-numeric:tabular-nums;}
|
||||
.rpt .hl{color:#1684FC;font-weight:600;}
|
||||
.rpt tfoot td{background:#FAFAFA;font-weight:600;font-size:var(--font-sm);}
|
||||
.rpt--sm{min-width:0;}
|
||||
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
|
||||
.td-empty{text-align:center;padding:32px 0;color:var(--text-placeholder);font-size:var(--font-sm);border:1px solid #F0F0F0;}
|
||||
.filter-date{height:36px;min-width:150px;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;}
|
||||
.filter-date:focus{border-color:var(--primary);}
|
||||
.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;white-space:nowrap;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);margin-top:16px;}
|
||||
.table-card__content{overflow-x:auto;}
|
||||
table{width:100%;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
thead th{background:#FAFAFA;color:var(--text-secondary);font-weight:600;padding:10px 14px;border-bottom:1px solid var(--border);white-space:nowrap;text-align:center;font-size:var(--font-sm);}
|
||||
thead tr.grp th{background:#F0F5FF;color:var(--text-primary);border-right:1px solid var(--border);font-size:var(--font-sm);}
|
||||
tbody td{padding:12px 14px;border-bottom:1px solid #F0F0F0;text-align:center;white-space:nowrap;font-size:var(--font-sm);}
|
||||
tbody tr:hover td{background:#F8FBFF;}
|
||||
.td-empty{text-align:center;padding:48px 0;color:var(--text-placeholder);}
|
||||
.num-cur{color:var(--primary);font-weight:600;}
|
||||
.num-total{color:var(--text-secondary);}
|
||||
.badge{display:inline-block;padding:1px 8px;border-radius:10px;font-size:var(--font-xs);line-height:18px;}
|
||||
.badge--danger{background:#FFF1F0;color:#FF4D4F;border:1px solid #FFA39E;}
|
||||
.badge--info{background:#E6F7FF;color:#1890FF;border:1px solid #91D5FF;}
|
||||
.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);}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:560px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:8px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;}
|
||||
.record-table{width:100%;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
.record-table th{background:#FAFAFA;padding:8px 10px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.record-table td{padding:10px;border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
</style>
|
||||
@@ -89,219 +101,222 @@ table.rpt{width:100%;border-collapse:separate;border-spacing:0;min-width:1100px;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏(当前一级分组「数据统计」的二级菜单) -->
|
||||
<!-- 侧边栏(当前一级分组「数据统计」,救护车统计子组展开) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">数据统计</div>
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">医疗点统计</a>
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item active">救护车统计</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
医疗点统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-clinic-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup open">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-ambulance-table.html" class="sidebar-item active">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="stat-rescue-chart.html" class="sidebar-item">救助物品统计</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<!-- [交互] 图表/报表两种查看形态,数据同源互切 -->
|
||||
<div class="title-line">
|
||||
<span>救护车统计</span>
|
||||
<div class="view-switch" style="margin-left:auto;">
|
||||
<a href="stat-ambulance-chart.html">图表视图</a>
|
||||
<a class="active" href="stat-ambulance-table.html">报表视图</a>
|
||||
<!-- 时间切换 + 导出操作(照搬老系统 DateButtonSelector + 导出按钮) -->
|
||||
<div class="toolbar">
|
||||
<div class="date-switch" id="dateSwitch">
|
||||
<span class="on" data-type="week" onclick="switchDateType('week')">本周</span>
|
||||
<span data-type="month" onclick="switchDateType('month')">本月</span>
|
||||
<span data-type="year" onclick="switchDateType('year')">本年</span>
|
||||
<span data-type="picker" onclick="switchDateType('picker')">自定义</span>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 9V2M4.5 4.5L7 2l2.5 2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出</button>
|
||||
<button class="btn btn-default" onclick="openExportLog()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6.5" cy="6.5" r="4.5" stroke="currentColor" stroke-width="1.4"/><path d="M10 10l3 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>查看导出记录</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 与图表视图共用同一单位→医疗点级联筛选,报表口径随筛选联动 -->
|
||||
<!-- 筛选栏:单位→医疗点级联 + 救护类型 + 时间 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>所属单位</label>
|
||||
<label>单位名称</label>
|
||||
<select class="filter-select" id="selUnit" onchange="onUnitChange()" style="min-width:160px;">
|
||||
<option value="">全部单位</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>所属医疗点</label>
|
||||
<select class="filter-select" id="selPoint" onchange="renderScope()" style="min-width:220px;" disabled>
|
||||
<option value="">请先选择所属单位</option>
|
||||
<select class="filter-select" id="selPoint" onchange="renderTable()" style="min-width:200px;" disabled>
|
||||
<option value="">请先选择单位</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡片与图表视图同源(出勤次数为累计口径) -->
|
||||
<div class="num-row">
|
||||
<div class="stat-card num-card--l">
|
||||
<div class="stat-card__title">基本数据</div>
|
||||
<div class="stat-card__grid" id="cardBase"></div>
|
||||
<div class="filter-item">
|
||||
<label>救护类型</label>
|
||||
<select class="filter-select" id="selType" onchange="renderTable()" style="min-width:120px;">
|
||||
<option value="">全部</option>
|
||||
<option>急救型</option>
|
||||
<option>转运型</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="stat-card num-card--r">
|
||||
<div class="stat-card__title">出勤次数</div>
|
||||
<div class="stat-card__grid" id="cardDispatch"></div>
|
||||
<div class="filter-item" id="dateSingle">
|
||||
<label>时间</label>
|
||||
<input type="date" class="filter-date" id="dateSingleInput" value="2026-09-07">
|
||||
</div>
|
||||
<div class="filter-item" id="dateRange" style="display:none;">
|
||||
<label>时间</label>
|
||||
<input type="date" class="filter-date" id="dateStart" value="2026-09-01">
|
||||
<span style="color:var(--text-placeholder);">至</span>
|
||||
<input type="date" class="filter-date" id="dateEnd" value="2026-09-07">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 占比类指标以报表呈现:类型占比 / 出勤次数占比(本周+累计并列) -->
|
||||
<div class="two-col">
|
||||
<div class="tbl-card" style="margin-top:16px;">
|
||||
<div class="tbl-card__title">救护车类型占比</div>
|
||||
<table class="rpt rpt--sm" id="tblType"></table>
|
||||
<!-- 分组报表:基础信息 + 五类出勤次数(本周/累计) -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="grp">
|
||||
<th rowspan="2" style="min-width:110px;">所属单位</th>
|
||||
<th rowspan="2" style="min-width:170px;">所属医疗点</th>
|
||||
<th rowspan="2" style="min-width:90px;">救护类型</th>
|
||||
<th rowspan="2" style="min-width:170px;">车型</th>
|
||||
<th rowspan="2" style="min-width:100px;">车牌号</th>
|
||||
<th colspan="2">急诊转运</th>
|
||||
<th colspan="2">平诊转运</th>
|
||||
<th colspan="2">日常巡诊</th>
|
||||
<th colspan="2">应急戒备</th>
|
||||
<th colspan="2">其他</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="period-text">本周</span>出勤次数</th>
|
||||
<th>累计出勤次数</th>
|
||||
<th><span class="period-text">本周</span>出勤次数</th>
|
||||
<th>累计出勤次数</th>
|
||||
<th><span class="period-text">本周</span>出勤次数</th>
|
||||
<th>累计出勤次数</th>
|
||||
<th><span class="period-text">本周</span>出勤次数</th>
|
||||
<th>累计出勤次数</th>
|
||||
<th><span class="period-text">本周</span>出勤次数</th>
|
||||
<th>累计出勤次数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="tbl-card" style="margin-top:16px;">
|
||||
<div class="tbl-card__title">出勤次数占比</div>
|
||||
<table class="rpt rpt--sm" id="tblDisp"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 医护人员出勤排名:五类×(本周/累计)分组表头,替代 TOP5 条形图的全量口径 -->
|
||||
<div class="tbl-card">
|
||||
<div class="tbl-card__title">医护人员出勤次数排名</div>
|
||||
<div class="tbl-scroll"><table class="rpt" id="tblStaff"></table></div>
|
||||
</div>
|
||||
|
||||
<!-- 本周逐日出勤趋势:表格形态(5 类 + 合计,含周合计行) -->
|
||||
<div class="tbl-card">
|
||||
<div class="tbl-card__title">本周出勤次数变化趋势</div>
|
||||
<div class="tbl-scroll"><table class="rpt rpt--sm" id="tblWeek"></table></div>
|
||||
<div class="pagination"><span id="totalTip"></span></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 导出记录弹窗 -->
|
||||
<div class="modal-mask" id="exportMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title">救护车统计导出记录</div>
|
||||
<table class="record-table">
|
||||
<thead><tr><th>文件名称</th><th>时间</th><th>结果</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>救护车统计-2026年9月.xlsx</td><td>2026-09-05 15:41:36</td><td style="color:#389E0D;">成功</td><td><button class="btn btn-link" onclick="showToast('导出明细下载中…')">下载</button></td></tr>
|
||||
<tr><td>救护车统计-2026年8月.xlsx</td><td>2026-08-28 11:09:52</td><td style="color:#389E0D;">成功</td><td><button class="btn btn-link" onclick="showToast('导出明细下载中…')">下载</button></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeExportLog()">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* 数据源与「救护车统计-图表」完全一致(与救护车配置页勾稽),此处略注释,两页共享同构数据 */
|
||||
var TYPES=['jz','pz','rc','yj','qt'];
|
||||
var TYPE_NAME={jz:'急救转运',pz:'平诊转运',rc:'日常巡诊',yj:'应急戒备',qt:'其他出勤'};
|
||||
var pts=[
|
||||
{unit:'采油一厂',name:'樊学作业区医疗点',total:1,jj:1,zy:0,rad:860,
|
||||
w:{jz:3,pz:2,rc:5,yj:1,qt:1},t:{jz:42,pz:28,rc:76,yj:15,qt:9},
|
||||
staff:[{name:'李桂芳',w:{jz:2,pz:1,rc:3,yj:1,qt:1},t:{jz:24,pz:16,rc:41,yj:8,qt:5}},
|
||||
{name:'石维国',w:{jz:1,pz:1,rc:2,yj:0,qt:0},t:{jz:18,pz:12,rc:35,yj:7,qt:4}}]},
|
||||
{unit:'采油一厂',name:'安塞采油队长住点医疗室',total:1,jj:0,zy:1,rad:540,
|
||||
w:{jz:0,pz:3,rc:2,yj:0,qt:1},t:{jz:9,pz:41,rc:33,yj:6,qt:10},
|
||||
staff:[{name:'周娟',w:{jz:0,pz:3,rc:2,yj:0,qt:1},t:{jz:9,pz:41,rc:33,yj:6,qt:10}}]},
|
||||
{unit:'采油一厂',name:'姬塬作业区医疗点',total:0,jj:0,zy:0,rad:0,
|
||||
w:{jz:0,pz:0,rc:0,yj:0,qt:0},t:{jz:0,pz:0,rc:0,yj:0,qt:0},staff:[]},
|
||||
{unit:'采油二厂',name:'姬圪台作业区医疗点',total:1,jj:1,zy:0,rad:1240,
|
||||
w:{jz:2,pz:1,rc:4,yj:2,qt:0},t:{jz:35,pz:22,rc:61,yj:18,qt:7},
|
||||
staff:[{name:'曲志明',w:{jz:1,pz:1,rc:2,yj:1,qt:0},t:{jz:19,pz:13,rc:34,yj:10,qt:4}},
|
||||
{name:'张秀兰',w:{jz:1,pz:0,rc:2,yj:1,qt:0},t:{jz:16,pz:9,rc:27,yj:8,qt:3}}]},
|
||||
{unit:'采油二厂',name:'桐园作业区医疗点',total:0,jj:0,zy:0,rad:0,
|
||||
w:{jz:0,pz:0,rc:0,yj:0,qt:0},t:{jz:0,pz:0,rc:0,yj:0,qt:0},staff:[]},
|
||||
{unit:'第四采油厂',name:'西峰基地医疗点',total:1,jj:0,zy:1,rad:2100,
|
||||
w:{jz:1,pz:6,rc:7,yj:3,qt:2},t:{jz:18,pz:88,rc:97,yj:26,qt:14},
|
||||
staff:[{name:'高建军',w:{jz:1,pz:3,rc:3,yj:2,qt:1},t:{jz:10,pz:45,rc:49,yj:14,qt:8}},
|
||||
{name:'闫婷',w:{jz:0,pz:3,rc:4,yj:1,qt:1},t:{jz:8,pz:43,rc:48,yj:12,qt:6}}]},
|
||||
{unit:'采气一厂',name:'靖边气田医疗点',total:1,jj:1,zy:0,rad:760,
|
||||
w:{jz:2,pz:1,rc:3,yj:1,qt:1},t:{jz:27,pz:19,rc:48,yj:12,qt:6},
|
||||
staff:[{name:'刘玉梅',w:{jz:2,pz:1,rc:2,yj:1,qt:0},t:{jz:16,pz:11,rc:29,yj:7,qt:3}},
|
||||
{name:'呼建国',w:{jz:0,pz:0,rc:1,yj:0,qt:1},t:{jz:11,pz:8,rc:19,yj:5,qt:3}}]},
|
||||
{unit:'采气一厂',name:'乌审旗采气区医疗点',total:1,jj:1,zy:0,rad:680,
|
||||
w:{jz:1,pz:1,rc:3,yj:2,qt:0},t:{jz:22,pz:14,rc:40,yj:16,qt:5},
|
||||
staff:[{name:'徐立成',w:{jz:1,pz:0,rc:2,yj:1,qt:0},t:{jz:13,pz:8,rc:24,yj:10,qt:3}},
|
||||
{name:'马丽华',w:{jz:0,pz:1,rc:1,yj:1,qt:0},t:{jz:9,pz:6,rc:16,yj:6,qt:2}}]}
|
||||
/* 数据源:6 辆救护车(与「救护车配置」页车牌/车型/救护类型勾稽,与「救护车统计-图表」五类出勤口径同源);
|
||||
出勤五类:急诊转运/平诊转运/日常巡诊/应急戒备/其他,各分 本周/累计 出勤次数 */
|
||||
var cars=[
|
||||
{unit:'采油一厂',point:'樊学作业区医疗点',type:'急救型',model:'江铃轻型监护型救护车',plate:'CQ·0712A',
|
||||
w:{jz:3,pz:2,rc:5,yj:1,qt:1},t:{jz:42,pz:28,rc:76,yj:15,qt:9}},
|
||||
{unit:'采油二厂',point:'姬圪台作业区医疗点',type:'急救型',model:'福田图雅诺监护型救护车',plate:'CQ·1366B',
|
||||
w:{jz:2,pz:1,rc:4,yj:2,qt:0},t:{jz:35,pz:22,rc:61,yj:18,qt:7}},
|
||||
{unit:'第四采油厂',point:'西峰基地医疗点',type:'转运型',model:'福特全顺转运型救护车',plate:'CQ·0208C',
|
||||
w:{jz:1,pz:6,rc:7,yj:3,qt:2},t:{jz:18,pz:88,rc:97,yj:26,qt:14}},
|
||||
{unit:'采气一厂',point:'靖边气田医疗点',type:'急救型',model:'东风轻型救护车',plate:'CQ·1533D',
|
||||
w:{jz:2,pz:1,rc:3,yj:1,qt:1},t:{jz:27,pz:19,rc:48,yj:12,qt:6}},
|
||||
{unit:'采油一厂',point:'安塞采油队长住点医疗室',type:'转运型',model:'江淮瑞风转运型救护车',plate:'CQ·0917E',
|
||||
w:{jz:0,pz:3,rc:2,yj:0,qt:1},t:{jz:9,pz:41,rc:33,yj:6,qt:10}},
|
||||
{unit:'采气一厂',point:'乌审旗采气区医疗点',type:'急救型',model:'红旗轻型监护型救护车',plate:'CQ·2201F',
|
||||
w:{jz:1,pz:1,rc:3,yj:2,qt:0},t:{jz:22,pz:14,rc:40,yj:16,qt:5}}
|
||||
];
|
||||
var TYPES=['jz','pz','rc','yj','qt'];
|
||||
var dateType='week';
|
||||
var PERIOD_TEXT={week:'本周',month:'本月',year:'本年',picker:'时段内'};
|
||||
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<');}
|
||||
function scope(){
|
||||
var u=document.getElementById('selUnit').value,p=document.getElementById('selPoint').value;
|
||||
if(p)return pts.filter(function(x){return x.name===p;});
|
||||
if(u)return pts.filter(function(x){return x.unit===u;});
|
||||
return pts;
|
||||
}
|
||||
function sumField(list,period,key){var s=0;list.forEach(function(p){s+=p[period][key];});return s;}
|
||||
function sumV(obj){return TYPES.reduce(function(s,k){return s+obj[k];},0);}
|
||||
function renderCards(){
|
||||
var sc=scope(),total=0,jj=0,zy=0,rad=0;
|
||||
sc.forEach(function(p){total+=p.total;jj+=p.jj;zy+=p.zy;rad+=p.rad;});
|
||||
document.getElementById('cardBase').innerHTML=cell(total,'辆','总数量')+cell(jj,'辆','急救型数量')+cell(zy,'辆','转运型数量')+cell(rad,'人','辐射人数');
|
||||
document.getElementById('cardDispatch').innerHTML=TYPES.map(function(k){return cell(sumField(sc,'t',k),'次',TYPE_NAME[k]);}).join('');
|
||||
}
|
||||
function cell(v,u,n){return '<div class="stat-cell"><div class="stat-cell__val">'+v+'<small>'+u+'</small></div><div class="stat-cell__name">'+n+'</div></div>';}
|
||||
/* 类型占比表 */
|
||||
function renderTblType(){
|
||||
var sc=scope(),jj=0,zy=0;
|
||||
sc.forEach(function(p){jj+=p.jj;zy+=p.zy;});
|
||||
var tot=jj+zy||1;
|
||||
document.getElementById('tblType').innerHTML=
|
||||
'<thead><tr><th>救护类型</th><th>数量(辆)</th><th>占比</th></tr></thead><tbody>'
|
||||
+'<tr><td>急救型</td><td class="num hl">'+jj+'</td><td class="num">'+(jj/tot*100).toFixed(1)+'%</td></tr>'
|
||||
+'<tr><td>转运型</td><td class="num hl">'+zy+'</td><td class="num">'+(zy/tot*100).toFixed(1)+'%</td></tr>'
|
||||
+'</tbody><tfoot><tr><td>合计</td><td class="num">'+(jj+zy)+'</td><td class="num">100%</td></tr></tfoot>';
|
||||
}
|
||||
/* 出勤次数占比表:本周/累计并列 + 累计占比 */
|
||||
function renderTblDisp(){
|
||||
var sc=scope(),tTot=TYPES.reduce(function(s,k){return s+sumField(sc,'t',k);},0)||1;
|
||||
var html='<thead><tr><th>出勤类型</th><th>本周(次)</th><th>累计(次)</th><th>累计占比</th></tr></thead><tbody>';
|
||||
TYPES.forEach(function(k){
|
||||
var w=sumField(sc,'w',k),t=sumField(sc,'t',k);
|
||||
html+='<tr><td>'+TYPE_NAME[k]+'</td><td class="num">'+w+'</td><td class="num hl">'+t+'</td><td class="num">'+(t/tTot*100).toFixed(1)+'%</td></tr>';
|
||||
var u=document.getElementById('selUnit').value;
|
||||
var p=document.getElementById('selPoint').value;
|
||||
var t=document.getElementById('selType').value;
|
||||
return cars.filter(function(c){
|
||||
if(u&&c.unit!==u)return false;
|
||||
if(p&&c.point!==p)return false;
|
||||
if(t&&c.type!==t)return false;
|
||||
return true;
|
||||
});
|
||||
html+='</tbody><tfoot><tr><td>合计</td><td class="num">'+TYPES.reduce(function(s,k){return s+sumField(sc,'w',k);},0)+'</td><td class="num">'+TYPES.reduce(function(s,k){return s+sumField(sc,'t',k);},0)+'</td><td class="num">100%</td></tr></tfoot>';
|
||||
document.getElementById('tblDisp').innerHTML=html;
|
||||
}
|
||||
/* 医护出勤排名:分组表头 5类×本周/累计+合计;未选点时带单位/医疗点归属列 */
|
||||
function staffRows(sc){
|
||||
var map={},order=[];
|
||||
sc.forEach(function(p){p.staff.forEach(function(s){
|
||||
if(!map[s.name]){map[s.name]={name:s.name,unit:p.unit,point:p.name,w:{},t:{}};TYPES.forEach(function(k){map[s.name].w[k]=0;map[s.name].t[k]=0;});order.push(s.name);}
|
||||
TYPES.forEach(function(k){map[s.name].w[k]+=s.w[k];map[s.name].t[k]+=s.t[k];});
|
||||
});});
|
||||
return order.map(function(n){return map[n];});
|
||||
/* 时间切换:更新分组表头前缀 + 时间控件形态 */
|
||||
function switchDateType(type){
|
||||
dateType=type;
|
||||
document.querySelectorAll('#dateSwitch span').forEach(function(s){s.classList.toggle('on',s.dataset.type===type);});
|
||||
document.querySelectorAll('.period-text').forEach(function(e){e.textContent=PERIOD_TEXT[type];});
|
||||
document.getElementById('dateSingle').style.display=(type==='picker')?'none':'';
|
||||
document.getElementById('dateRange').style.display=(type==='picker')?'':'none';
|
||||
}
|
||||
function renderTblStaff(){
|
||||
var showOwner=!document.getElementById('selPoint').value;
|
||||
var rows=staffRows(scope()).filter(function(s){return sumV(s.t)>0||sumV(s.w)>0;})
|
||||
.sort(function(a,b){return sumV(b.t)-sumV(a.t);});
|
||||
var h='<thead><tr><th rowspan="2">排名</th><th rowspan="2">医护人员</th>'
|
||||
+(showOwner?'<th rowspan="2">所属单位</th><th rowspan="2">所属医疗点</th>':'')
|
||||
+TYPES.map(function(k){return '<th colspan="2">'+TYPE_NAME[k]+'</th>';}).join('')
|
||||
+'<th colspan="2">合计</th></tr><tr>'
|
||||
+TYPES.map(function(){return '<th>本周</th><th>累计</th>';}).join('')
|
||||
+'<th>本周</th><th>累计</th></tr></thead>';
|
||||
if(!rows.length){document.getElementById('tblStaff').innerHTML=h+'<tbody><tr><td colspan="'+(showOwner?15:13)+'" class="td-empty" style="border-top:none;">当前范围内暂无医护人员出勤记录</td></tr></tbody>';return;}
|
||||
h+='<tbody>'+rows.map(function(s,i){
|
||||
return '<tr><td class="num">'+(i+1)+'</td><td style="font-weight:600;">'+esc(s.name)+'</td>'
|
||||
+(showOwner?'<td>'+esc(s.unit)+'</td><td>'+esc(s.point)+'</td>':'')
|
||||
+TYPES.map(function(k){return '<td class="num">'+s.w[k]+'</td><td class="num">'+s.t[k]+'</td>';}).join('')
|
||||
+'<td class="num hl">'+sumV(s.w)+'</td><td class="num hl">'+sumV(s.t)+'</td></tr>';
|
||||
}).join('')+'</tbody>';
|
||||
document.getElementById('tblStaff').innerHTML=h;
|
||||
}
|
||||
/* 本周趋势表:逐日×5类+合计,含总计行(与图表页堆积柱同源拆分) */
|
||||
var DAYS=['周一','周二','周三','周四','周五','周六','周日'];
|
||||
var WT=[2,1,2,1,3,2,1];
|
||||
function splitWeek(v){
|
||||
var S=WT.reduce(function(a,b){return a+b;},0),out=WT.map(function(x){return Math.floor(v*x/S);});
|
||||
var rem=v-out.reduce(function(a,b){return a+b;},0),i=0;
|
||||
while(rem>0){out[i%7]++;rem--;i++;}
|
||||
return out;
|
||||
}
|
||||
function renderTblWeek(){
|
||||
var sc=scope(),cols=TYPES.map(function(k){return splitWeek(sumField(sc,'w',k));});
|
||||
var h='<thead><tr><th>星期</th>'+TYPES.map(function(k){return '<th>'+TYPE_NAME[k]+'(次)</th>';}).join('')+'<th>当日合计</th></tr></thead><tbody>';
|
||||
DAYS.forEach(function(d,i){
|
||||
var dayTot=0;TYPES.forEach(function(k,j){dayTot+=cols[j][i];});
|
||||
h+='<tr><td>'+d+'</td>'+TYPES.map(function(k,j){return '<td class="num">'+cols[j][i]+'</td>';}).join('')+'<td class="num hl">'+dayTot+'</td></tr>';
|
||||
});
|
||||
h+='</tbody><tfoot><tr><td>本周合计</td>'+TYPES.map(function(k,j){return '<td class="num">'+cols[j].reduce(function(a,b){return a+b;},0)+'</td>';}).join('')
|
||||
+'<td class="num">'+TYPES.reduce(function(s,k,j){return s+cols[j].reduce(function(a,b){return a+b;},0);},0)+'</td></tr></tfoot>';
|
||||
document.getElementById('tblWeek').innerHTML=h;
|
||||
function renderTable(){
|
||||
var list=scope();
|
||||
if(!list.length){
|
||||
document.getElementById('tbody').innerHTML='<tr><td class="td-empty" colspan="15">暂无数据</td></tr>';
|
||||
}else{
|
||||
document.getElementById('tbody').innerHTML=list.map(function(c){
|
||||
var typeBadge=c.type==='急救型'?'<span class="badge badge--danger">急救型</span>':'<span class="badge badge--info">转运型</span>';
|
||||
return '<tr>'
|
||||
+'<td>'+esc(c.unit)+'</td>'
|
||||
+'<td style="text-align:left;font-weight:600;">'+esc(c.point)+'</td>'
|
||||
+'<td>'+typeBadge+'</td>'
|
||||
+'<td style="text-align:left;">'+esc(c.model)+'</td>'
|
||||
+'<td>'+esc(c.plate)+'</td>'
|
||||
+TYPES.map(function(k){return '<td class="num-cur">'+c.w[k]+'</td><td class="num-total">'+c.t[k]+'</td>';}).join('')
|
||||
+'</tr>';
|
||||
}).join('');
|
||||
}
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 辆救护车';
|
||||
}
|
||||
/* 单位→医疗点级联 */
|
||||
function onUnitChange(){
|
||||
var u=document.getElementById('selUnit').value,sel=document.getElementById('selPoint');
|
||||
if(!u){sel.innerHTML='<option value="">请先选择所属单位</option>';sel.disabled=true;}
|
||||
else{
|
||||
if(!u){
|
||||
sel.innerHTML='<option value="">请先选择单位</option>';sel.disabled=true;
|
||||
}else{
|
||||
sel.disabled=false;
|
||||
var list=pts.filter(function(p){return p.unit===u;});
|
||||
sel.innerHTML='<option value="">全部医疗点(该单位)</option>'+list.map(function(p){return '<option>'+esc(p.name)+'</option>';}).join('');
|
||||
var list=cars.filter(function(c){return c.unit===u;});
|
||||
sel.innerHTML='<option value="">全部医疗点(该单位)</option>'+list.map(function(c){return '<option>'+esc(c.point)+'</option>';}).join('');
|
||||
}
|
||||
renderScope();
|
||||
renderTable();
|
||||
}
|
||||
function renderScope(){renderCards();renderTblType();renderTblDisp();renderTblStaff();renderTblWeek();}
|
||||
function doExport(){showToast('导出任务已提交,完成后将推送站内通知');}
|
||||
function openExportLog(){document.getElementById('exportMask').classList.add('open');}
|
||||
function closeExportLog(){document.getElementById('exportMask').classList.remove('open');}
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
/* 初始化:单位下拉 + 首屏渲染 */
|
||||
(function(){
|
||||
var us=[];pts.forEach(function(p){if(us.indexOf(p.unit)<0)us.push(p.unit);});
|
||||
var us=[];cars.forEach(function(c){if(us.indexOf(c.unit)<0)us.push(c.unit);});
|
||||
document.getElementById('selUnit').innerHTML='<option value="">全部单位</option>'+us.map(function(u){return '<option>'+esc(u)+'</option>';}).join('');
|
||||
})();
|
||||
renderScope();
|
||||
document.getElementById('exportMask').addEventListener('click',function(e){if(e.target===this)closeExportLog();});
|
||||
renderTable();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>医疗点统计 | 一线医疗</title>
|
||||
<title>医疗点统计 · 统计图表 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
@@ -31,10 +31,13 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.view-switch{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.view-switch a{display:inline-flex;align-items:center;padding:0 14px;height:32px;font-size:var(--font-sm);color:var(--text-secondary);text-decoration:none;background:#fff;}
|
||||
.view-switch a+a{border-left:1px solid var(--border);}
|
||||
.view-switch a.active{background:var(--primary);color:#fff;}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
/* [交互] 一级Tab:全部医疗点 / 单个医疗点,与老系统页内Tab一致 */
|
||||
.tabs{display:flex;gap:4px;background:#fff;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);padding:0 16px;margin-bottom:16px;}
|
||||
.tab{padding:14px 18px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;}
|
||||
@@ -104,22 +107,31 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
<!-- 侧边栏(当前一级分组「数据统计」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">数据统计</div>
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item active">医疗点统计</a>
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">救护车统计</a>
|
||||
<div class="sidebar-subgroup open">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
医疗点统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item active">统计图表</a>
|
||||
<a href="stat-clinic-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-ambulance-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="stat-rescue-chart.html" class="sidebar-item">救助物品统计</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<!-- [交互] 图表/报表两种查看形态,数据同源互切 -->
|
||||
<div style="display:flex;align-items:center;margin-bottom:16px;">
|
||||
<span style="font-size:var(--font-base);font-weight:600;">医疗点统计</span>
|
||||
<div class="view-switch" style="margin-left:auto;">
|
||||
<a class="active" href="stat-clinic-chart.html">图表视图</a>
|
||||
<a href="stat-clinic-table.html">报表视图</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
<div class="tab active" onclick="switchTab(0,this)">全部医疗点</div>
|
||||
<div class="tab" onclick="switchTab(1,this)">单个医疗点</div>
|
||||
@@ -353,6 +365,10 @@ function showToast(msg){
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
initUnitSel();renderKpi();renderAllCharts();
|
||||
/* 单个医疗点 Tab 默认选中首个单位并联动出首个医疗点,避免首次进入无数据 */
|
||||
document.getElementById('selUnit').value=points[0].unit;
|
||||
onUnitChange();
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('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>医疗点统计 | 一线医疗</title>
|
||||
<title>医疗点统计 · 统计报表 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
@@ -30,35 +30,31 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.view-switch{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.view-switch a{display:inline-flex;align-items:center;padding:0 14px;height:32px;font-size:var(--font-sm);color:var(--text-secondary);text-decoration:none;background:#fff;}
|
||||
.view-switch a+a{border-left:1px solid var(--border);}
|
||||
.view-switch a.active{background:var(--primary);color:#fff;}
|
||||
.tabs{display:flex;gap:4px;background:#fff;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);padding:0 16px;margin-bottom:16px;}
|
||||
.tab{padding:14px 18px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;}
|
||||
.tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
|
||||
.tab-pane{display:none;}
|
||||
.tab-pane.active{display:block;}
|
||||
.kpi-row{display:flex;gap:16px;}
|
||||
.kpi{flex:1;height:96px;border-radius:10px;color:#fff;display:flex;align-items:center;justify-content:space-around;padding:0 12px;}
|
||||
.kpi--c1{background:linear-gradient(90deg,#0093FF 0%,#57B8FF 100%);}
|
||||
.kpi--c2{background:linear-gradient(90deg,#48D147 0%,#88D187 100%);}
|
||||
.kpi--c3{background:linear-gradient(90deg,#FFA440 0%,#FFC17C 100%);}
|
||||
.kpi--c4{background:linear-gradient(90deg,#FF5640 0%,#FF8A7B 100%);}
|
||||
.kpi--c5{background:linear-gradient(90deg,#8167F5 0%,#A897F5 100%);}
|
||||
.kpi__mid{text-align:center;}
|
||||
.kpi__val{font-size:28px;font-weight:700;}
|
||||
.kpi__val small{font-size:var(--font-sm);font-weight:400;margin-left:3px;}
|
||||
.kpi__name{font-size:var(--font-sm);margin-top:4px;}
|
||||
.kpi__ico{width:34px;height:34px;opacity:.9;}
|
||||
/* 工具栏:时间切换 + 导出操作 */
|
||||
.toolbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;}
|
||||
.date-switch{display:inline-flex;height:32px;line-height:32px;border:1px solid var(--primary);border-radius:var(--radius-sm);overflow:hidden;font-size:var(--font-sm);}
|
||||
.date-switch span{padding:0 16px;cursor:pointer;color:var(--primary);background:#fff;border-right:1px solid var(--primary);white-space:nowrap;}
|
||||
.date-switch span:last-child{border-right:none;}
|
||||
.date-switch span.on{background:var(--primary);color:#fff;}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-select{height:36px;min-width:140px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);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 8px center;cursor:pointer;outline:none;appearance:none;-webkit-appearance:none;}
|
||||
.filter-date{height:36px;min-width:150px;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;}
|
||||
.filter-date:focus{border-color:var(--primary);}
|
||||
.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;white-space:nowrap;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
/* 分组表头:与图表页同源的「本周/累计」双列结构 */
|
||||
/* 分组表头报表 */
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);margin-top:16px;}
|
||||
.table-card__content{overflow-x:auto;}
|
||||
table{width:100%;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
@@ -71,9 +67,16 @@ tbody tr:hover td{background:#F8FBFF;}
|
||||
.num-total{color:var(--text-secondary);}
|
||||
.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);}
|
||||
.stat-name{text-align:left;font-weight:600;color:var(--text-primary);background:#FAFAFA;}
|
||||
.grp-cell{text-align:left;font-weight:600;color:var(--primary);background:#F0F5FF;vertical-align:middle;}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--font-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
/* 导出记录弹窗 */
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:560px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:8px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;}
|
||||
.record-table{width:100%;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
.record-table th{background:#FAFAFA;padding:8px 10px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.record-table td{padding:10px;border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
</style>
|
||||
</head>
|
||||
@@ -97,187 +100,212 @@ tbody tr:hover td{background:#F8FBFF;}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏(当前一级分组「数据统计」的二级菜单) -->
|
||||
<!-- 侧边栏(当前一级分组「数据统计」,医疗点统计子组展开) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">数据统计</div>
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item active">医疗点统计</a>
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">救护车统计</a>
|
||||
<div class="sidebar-subgroup open">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
医疗点统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-clinic-table.html" class="sidebar-item active">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-ambulance-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="stat-rescue-chart.html" class="sidebar-item">救助物品统计</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<!-- [交互] 图表/报表两种查看形态,数据同源互切 -->
|
||||
<div style="display:flex;align-items:center;margin-bottom:16px;">
|
||||
<span style="font-size:var(--font-base);font-weight:600;">医疗点统计</span>
|
||||
<div class="view-switch" style="margin-left:auto;">
|
||||
<a href="stat-clinic-chart.html">图表视图</a>
|
||||
<a class="active" href="stat-clinic-table.html">报表视图</a>
|
||||
<!-- 时间切换 + 导出操作(照搬老系统 DateButtonSelector + 导出按钮) -->
|
||||
<div class="toolbar">
|
||||
<div class="date-switch" id="dateSwitch">
|
||||
<span class="on" data-type="week" onclick="switchDateType('week')">本周</span>
|
||||
<span data-type="month" onclick="switchDateType('month')">本月</span>
|
||||
<span data-type="year" onclick="switchDateType('year')">本年</span>
|
||||
<span data-type="picker" onclick="switchDateType('picker')">自定义</span>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-primary" onclick="doExport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 9V2M4.5 4.5L7 2l2.5 2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出</button>
|
||||
<button class="btn btn-default" onclick="openExportLog()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6.5" cy="6.5" r="4.5" stroke="currentColor" stroke-width="1.4"/><path d="M10 10l3 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>查看导出记录</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
<div class="tab active" onclick="switchTab(0,this)">全部医疗点</div>
|
||||
<div class="tab" onclick="switchTab(1,this)">单个医疗点</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ Tab1 全部医疗点:KPI + 逐点报表 ============ -->
|
||||
<div class="tab-pane active" id="paneAll">
|
||||
<div class="kpi-row" id="kpiRow"></div>
|
||||
|
||||
<!-- [交互] 与图表页 TOP5 同源:每点 4 组指标,均分 本周/累计 两列 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="grp">
|
||||
<th rowspan="2" style="min-width:110px;">所属单位</th>
|
||||
<th rowspan="2" style="min-width:170px;">医疗点名称</th>
|
||||
<th colspan="4">基本数据</th>
|
||||
<th colspan="2">就诊服务人数</th>
|
||||
<th colspan="2">慢病服务人数</th>
|
||||
<th colspan="2">急救培训场次</th>
|
||||
<th colspan="2">急救培训人次</th>
|
||||
<th colspan="2">健康宣教场次</th>
|
||||
<th colspan="2">健康宣教人次</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>
|
||||
<th>本周</th><th>累计</th>
|
||||
<th>本周</th><th>累计</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbodyAll"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination"><span id="totalTip"></span></div>
|
||||
<!-- 筛选栏:所属单位 + 时间 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>所属单位</label>
|
||||
<select class="filter-select" id="selUnit" onchange="renderTable()" style="min-width:160px;">
|
||||
<option value="">全部单位</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item" id="dateSingle">
|
||||
<label>时间</label>
|
||||
<input type="date" class="filter-date" id="dateSingleInput" value="2026-09-07">
|
||||
</div>
|
||||
<div class="filter-item" id="dateRange" style="display:none;">
|
||||
<label>时间</label>
|
||||
<input type="date" class="filter-date" id="dateStart" value="2026-09-01">
|
||||
<span style="color:var(--text-placeholder);">至</span>
|
||||
<input type="date" class="filter-date" id="dateEnd" value="2026-09-07">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ Tab2 单个医疗点:级联筛选 + 指标报表 ============ -->
|
||||
<div class="tab-pane" id="paneOne">
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>所属单位</label>
|
||||
<select class="filter-select" id="selUnit" onchange="onUnitChange()" style="min-width:160px;">
|
||||
<option value="">请选择所属单位</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>所属医疗点</label>
|
||||
<select class="filter-select" id="selPoint" onchange="renderOne()" style="min-width:220px;">
|
||||
<option value="">请先选择所属单位</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th style="width:160px;text-align:left;padding-left:16px;">指标分组</th><th style="text-align:left;padding-left:16px;">指标名称</th><th style="width:160px;">本周</th><th style="width:160px;">累计</th></tr>
|
||||
</thead>
|
||||
<tbody id="tbodyOne"><tr><td class="td-empty" colspan="4">请先选择单位与医疗点</td></tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination"><span id="oneTip"></span></div>
|
||||
<!-- 分组大表:就诊人次 / 慢病管理 / 培训宣教 / 体检报告解读 多级表头 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="grp">
|
||||
<th rowspan="3" style="min-width:110px;">所属单位</th>
|
||||
<th rowspan="3" style="min-width:180px;">医疗点名称</th>
|
||||
<th rowspan="3" style="min-width:100px;">建立时间</th>
|
||||
<th rowspan="3" style="min-width:150px;">合作医院</th>
|
||||
<th rowspan="3" style="min-width:80px;">医生人数</th>
|
||||
<th rowspan="3" style="min-width:80px;">护士人数</th>
|
||||
<th rowspan="3" style="min-width:130px;">已分配员工数量</th>
|
||||
<th colspan="2">就诊人次</th>
|
||||
<th colspan="4">慢病管理</th>
|
||||
<th colspan="8">培训宣教</th>
|
||||
<th colspan="2">体检报告解读</th>
|
||||
</tr>
|
||||
<tr class="grp">
|
||||
<th rowspan="2"><span class="period-text">本周</span>就诊人次</th>
|
||||
<th rowspan="2">累计就诊人次</th>
|
||||
<th rowspan="2">慢病人数</th>
|
||||
<th rowspan="2">当前应服务人数</th>
|
||||
<th rowspan="2">当前已服务人数</th>
|
||||
<th rowspan="2">累计服务人数</th>
|
||||
<th colspan="4">急救培训</th>
|
||||
<th colspan="4">健康宣教</th>
|
||||
<th rowspan="2">一对一</th>
|
||||
<th rowspan="2">群体</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="period-text">本周</span>场次</th>
|
||||
<th>累计场次</th>
|
||||
<th><span class="period-text">本周</span>人次</th>
|
||||
<th>累计人次</th>
|
||||
<th><span class="period-text">本周</span>场次</th>
|
||||
<th>累计场次</th>
|
||||
<th><span class="period-text">本周</span>人次</th>
|
||||
<th>累计人次</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination"><span id="totalTip"></span></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 导出记录弹窗 -->
|
||||
<div class="modal-mask" id="exportMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title">医疗点统计导出记录</div>
|
||||
<table class="record-table">
|
||||
<thead><tr><th>文件名称</th><th>时间</th><th>结果</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>医疗点统计-2026年9月.xlsx</td><td>2026-09-05 15:41:36</td><td style="color:#389E0D;">成功</td><td><button class="btn btn-link" onclick="showToast('导出明细下载中…')">下载</button></td></tr>
|
||||
<tr><td>医疗点统计-2026年8月.xlsx</td><td>2026-08-28 11:09:52</td><td style="color:#389E0D;">成功</td><td><button class="btn btn-link" onclick="showToast('导出明细下载中…')">下载</button></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeExportLog()">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* 与「医疗点统计-图表」完全同源的数据,报表形态呈现 */
|
||||
/* 数据源:8 个医疗点,口径与老系统 resourceStatistics 一致;
|
||||
就诊按人次、慢病按 慢病人数/应服务/已服务/累计服务、培训宣教按 场次+人次、体检解读按 一对一/群体 */
|
||||
var points=[
|
||||
{unit:'采油一厂',name:'樊学作业区医疗点',short:'樊学',staff:7,doc:3,nurse:4,rad:2860,visitW:186,visitT:4120,chrW:15,chrT:326,trainSW:1,trainST:9,trainPW:45,trainPT:620,eduSW:2,eduST:14,eduPW:160,eduPT:1180},
|
||||
{unit:'采油一厂',name:'安塞采油队长住点医疗室',short:'安塞',staff:3,doc:1,nurse:2,rad:960,visitW:32,visitT:780,chrW:4,chrT:74,trainSW:0,trainST:3,trainPW:0,trainPT:120,eduSW:0,eduST:4,eduPW:0,eduPT:180},
|
||||
{unit:'采油一厂',name:'姬塬作业区医疗点',short:'姬塬',staff:5,doc:2,nurse:3,rad:1730,visitW:118,visitT:860,chrW:6,chrT:63,trainSW:1,trainST:2,trainPW:60,trainPT:140,eduSW:1,eduST:3,eduPW:90,eduPT:210},
|
||||
{unit:'采油二厂',name:'姬圪台作业区医疗点',short:'姬圪台',staff:5,doc:2,nurse:3,rad:2140,visitW:142,visitT:3310,chrW:20,chrT:415,trainSW:1,trainST:7,trainPW:38,trainPT:480,eduSW:1,eduST:11,eduPW:95,eduPT:860},
|
||||
{unit:'采油二厂',name:'桐园作业区医疗点',short:'桐园',staff:4,doc:2,nurse:2,rad:1420,visitW:88,visitT:1960,chrW:10,chrT:158,trainSW:0,trainST:5,trainPW:0,trainPT:260,eduSW:1,eduST:8,eduPW:70,eduPT:520},
|
||||
{unit:'第四采油厂',name:'西峰基地医疗点',short:'西峰',staff:11,doc:5,nurse:6,rad:4350,visitW:268,visitT:6420,chrW:31,chrT:728,trainSW:2,trainST:12,trainPW:96,trainPT:1350,eduSW:3,eduST:18,eduPW:240,eduPT:1760},
|
||||
{unit:'采气一厂',name:'靖边气田医疗点',short:'靖边',staff:4,doc:2,nurse:2,rad:1680,visitW:96,visitT:2240,chrW:12,chrT:196,trainSW:1,trainST:6,trainPW:42,trainPT:350,eduSW:1,eduST:9,eduPW:88,eduPT:640},
|
||||
{unit:'采气一厂',name:'乌审旗采气区医疗点',short:'乌审旗',staff:5,doc:2,nurse:3,rad:1550,visitW:104,visitT:2480,chrW:9,chrT:210,trainSW:1,trainST:5,trainPW:36,trainPT:280,eduSW:1,eduST:8,eduPW:75,eduPT:590}
|
||||
{unit:'采油一厂',name:'樊学作业区医疗点',create:'2020-03',hosp:'CQ油田总医院',doc:3,nurse:4,rad:2860,
|
||||
visitW:186,visitT:4120,chrNum:120,chrShould:18,chrDone:15,chrTotal:326,
|
||||
trainSW:1,trainST:9,trainPW:45,trainPT:620,eduSW:2,eduST:14,eduPW:160,eduPT:1180,one:96,group:18},
|
||||
{unit:'采油一厂',name:'安塞采油队长住点医疗室',create:'2022-06',hosp:'吴起油田医院',doc:1,nurse:2,rad:960,
|
||||
visitW:32,visitT:780,chrNum:38,chrShould:6,chrDone:4,chrTotal:74,
|
||||
trainSW:0,trainST:3,trainPW:0,trainPT:120,eduSW:0,eduST:4,eduPW:0,eduPT:180,one:22,group:6},
|
||||
{unit:'采油一厂',name:'姬塬作业区医疗点',create:'2021-09',hosp:'CQ油田总医院',doc:2,nurse:3,rad:1730,
|
||||
visitW:118,visitT:860,chrNum:52,chrShould:8,chrDone:6,chrTotal:63,
|
||||
trainSW:1,trainST:2,trainPW:60,trainPT:140,eduSW:1,eduST:3,eduPW:90,eduPT:210,one:30,group:8},
|
||||
{unit:'采油二厂',name:'姬圪台作业区医疗点',create:'2019-11',hosp:'CQ油田总医院',doc:2,nurse:3,rad:2140,
|
||||
visitW:142,visitT:3310,chrNum:168,chrShould:24,chrDone:20,chrTotal:415,
|
||||
trainSW:1,trainST:7,trainPW:38,trainPT:480,eduSW:1,eduST:11,eduPW:95,eduPT:860,one:88,group:16},
|
||||
{unit:'采油二厂',name:'桐园作业区医疗点',create:'2021-04',hosp:'庆阳市人民医院',doc:2,nurse:2,rad:1420,
|
||||
visitW:88,visitT:1960,chrNum:64,chrShould:12,chrDone:10,chrTotal:158,
|
||||
trainSW:0,trainST:5,trainPW:0,trainPT:260,eduSW:1,eduST:8,eduPW:70,eduPT:520,one:36,group:9},
|
||||
{unit:'第四采油厂',name:'西峰基地医疗点',create:'2018-05',hosp:'第四采油厂总医院',doc:5,nurse:6,rad:4350,
|
||||
visitW:268,visitT:6420,chrNum:286,chrShould:36,chrDone:31,chrTotal:728,
|
||||
trainSW:2,trainST:12,trainPW:96,trainPT:1350,eduSW:3,eduST:18,eduPW:240,eduPT:1760,one:142,group:25},
|
||||
{unit:'采气一厂',name:'靖边气田医疗点',create:'2020-08',hosp:'CQ油田总医院',doc:2,nurse:2,rad:1680,
|
||||
visitW:96,visitT:2240,chrNum:82,chrShould:14,chrDone:12,chrTotal:196,
|
||||
trainSW:1,trainST:6,trainPW:42,trainPT:350,eduSW:1,eduST:9,eduPW:88,eduPT:640,one:44,group:11},
|
||||
{unit:'采气一厂',name:'乌审旗采气区医疗点',create:'2022-02',hosp:'庆阳市人民医院',doc:2,nurse:3,rad:1550,
|
||||
visitW:104,visitT:2480,chrNum:90,chrShould:12,chrDone:9,chrTotal:210,
|
||||
trainSW:1,trainST:5,trainPW:36,trainPT:280,eduSW:1,eduST:8,eduPW:75,eduPT:590,one:40,group:10}
|
||||
];
|
||||
var dateType='week';
|
||||
var PERIOD_TEXT={week:'本周',month:'本月',year:'本年',picker:'当前'};
|
||||
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<');}
|
||||
function pair(a,b){return '<td class="num-cur">'+a+'</td><td class="num-total">'+b+'</td>';}
|
||||
function switchTab(i,el){
|
||||
document.querySelectorAll('.tab').forEach(function(t,k){t.classList.toggle('active',k===i);});
|
||||
document.getElementById('paneAll').classList.toggle('active',i===0);
|
||||
document.getElementById('paneOne').classList.toggle('active',i===1);
|
||||
function scope(){
|
||||
var u=document.getElementById('selUnit').value;
|
||||
return u?points.filter(function(p){return p.unit===u;}):points;
|
||||
}
|
||||
function renderKpi(){
|
||||
var staff=0,doc=0,nurse=0,rad=0;
|
||||
points.forEach(function(p){staff+=p.staff;doc+=p.doc;nurse+=p.nurse;rad+=p.rad;});
|
||||
var items=[
|
||||
{v:points.length,u:'个',n:'医疗点总数量',c:'c1',ico:'M4 24h4V12H4v12zm7 0h4V4h-4v20zm7 0h4V16h-4v8z'},
|
||||
{v:staff,u:'人',n:'医务人员总数量',c:'c2',ico:'M16 4a5 5 0 1 1-5 5 5 5 0 0 1 5-5zm0 12c-6 0-10 3-10 6v2h20v-2c0-3-4-6-10-6z'},
|
||||
{v:doc,u:'人',n:'医生总数量',c:'c3',ico:'M16 4a5 5 0 1 1-5 5 5 5 0 0 1 5-5zm0 12c-6 0-10 3-10 6v2h20v-2c0-3-4-6-10-6z'},
|
||||
{v:nurse,u:'人',n:'护士总数量',c:'c4',ico:'M16 4a5 5 0 1 1-5 5 5 5 0 0 1 5-5zm0 12c-6 0-10 3-10 6v2h20v-2c0-3-4-6-10-6z'},
|
||||
{v:rad,u:'人',n:'辐射员工总数量',c:'c5',ico:'M16 12a4 4 0 1 1-4 4 4 4 0 0 1 4-4zm0-9a2 2 0 1 1-2 2 2 2 0 0 1 2-2zm0 26a2 2 0 1 1-2 2 2 2 0 0 1 2-2zm-9-11a2 2 0 1 1-2 2 2 2 0 0 1 2-2zm18 0a2 2 0 1 1-2 2 2 2 0 0 1 2-2z'}
|
||||
];
|
||||
document.getElementById('kpiRow').innerHTML=items.map(function(it){
|
||||
return '<div class="kpi kpi--'+it.c+'">'
|
||||
+'<svg class="kpi__ico" viewBox="0 0 32 32" fill="#fff" style="opacity:.85;"><path d="'+it.ico+'"/></svg>'
|
||||
+'<div class="kpi__mid"><div class="kpi__val">'+it.v+'<small>'+it.u+'</small></div><div class="kpi__name">'+it.n+'</div></div>'
|
||||
+'<span style="width:34px;"></span></div>';
|
||||
}).join('');
|
||||
/* 时间切换:更新分组表头前缀 + 时间控件形态 */
|
||||
function switchDateType(type){
|
||||
dateType=type;
|
||||
document.querySelectorAll('#dateSwitch span').forEach(function(s){s.classList.toggle('on',s.dataset.type===type);});
|
||||
document.querySelectorAll('.period-text').forEach(function(e){e.textContent=PERIOD_TEXT[type];});
|
||||
document.getElementById('dateSingle').style.display=(type==='picker')?'none':'';
|
||||
document.getElementById('dateRange').style.display=(type==='picker')?'':'none';
|
||||
}
|
||||
function renderAll(){
|
||||
/* 与图表 TOP5 同口径:按累计就诊人数降序排行 */
|
||||
var list=points.slice().sort(function(a,b){return b.visitT-a.visitT;});
|
||||
document.getElementById('tbodyAll').innerHTML=list.map(function(p){
|
||||
return '<tr><td>'+esc(p.unit)+'</td><td style="text-align:left;font-weight:600;">'+esc(p.name)+'</td>'
|
||||
+'<td>'+p.staff+'</td><td>'+p.doc+'</td><td>'+p.nurse+'</td><td>'+p.rad+'</td>'
|
||||
+pair(p.visitW,p.visitT)+pair(p.chrW,p.chrT)
|
||||
+pair(p.trainSW,p.trainST)+pair(p.trainPW,p.trainPT)
|
||||
+pair(p.eduSW,p.eduST)+pair(p.eduPW,p.eduPT)
|
||||
function renderTable(){
|
||||
var list=scope();
|
||||
document.getElementById('tbody').innerHTML=list.map(function(p){
|
||||
return '<tr>'
|
||||
+'<td>'+esc(p.unit)+'</td>'
|
||||
+'<td style="text-align:left;font-weight:600;">'+esc(p.name)+'</td>'
|
||||
+'<td>'+esc(p.create)+'</td>'
|
||||
+'<td>'+esc(p.hosp)+'</td>'
|
||||
+'<td>'+p.doc+'</td>'
|
||||
+'<td>'+p.nurse+'</td>'
|
||||
+'<td>'+p.rad+'</td>'
|
||||
+'<td class="num-cur">'+p.visitW+'</td><td class="num-total">'+p.visitT+'</td>'
|
||||
+'<td>'+p.chrNum+'</td><td>'+p.chrShould+'</td><td class="num-cur">'+p.chrDone+'</td><td class="num-total">'+p.chrTotal+'</td>'
|
||||
+'<td>'+p.trainSW+'</td><td>'+p.trainST+'</td><td>'+p.trainPW+'</td><td>'+p.trainPT+'</td>'
|
||||
+'<td>'+p.eduSW+'</td><td>'+p.eduST+'</td><td>'+p.eduPW+'</td><td>'+p.eduPT+'</td>'
|
||||
+'<td>'+p.one+'</td><td>'+p.group+'</td>'
|
||||
+'</tr>';
|
||||
}).join('');
|
||||
document.getElementById('totalTip').textContent='共 '+list.length+' 个医疗点';
|
||||
}
|
||||
/* ===== 单个医疗点报表 ===== */
|
||||
function initUnitSel(){
|
||||
var us=[];points.forEach(function(p){if(us.indexOf(p.unit)<0)us.push(p.unit);});
|
||||
document.getElementById('selUnit').innerHTML='<option value="">请选择单位</option>'+us.map(function(u){return '<option>'+esc(u)+'</option>';}).join('');
|
||||
}
|
||||
function onUnitChange(){
|
||||
var u=document.getElementById('selUnit').value,sel=document.getElementById('selPoint');
|
||||
if(!u){sel.innerHTML='<option value="">请先选择所属单位</option>';sel.disabled=true;clearOne();return;}
|
||||
sel.disabled=false;
|
||||
sel.innerHTML=points.filter(function(p){return p.unit===u;}).map(function(p){return '<option value="'+p.name+'">'+esc(p.name)+'</option>';}).join('');
|
||||
renderOne();
|
||||
}
|
||||
function clearOne(){
|
||||
document.getElementById('tbodyOne').innerHTML='<tr><td class="td-empty" colspan="4">请先选择单位与医疗点</td></tr>';
|
||||
document.getElementById('oneTip').textContent='';
|
||||
}
|
||||
function row(groupSpan,name,w,t){return '<tr>'+groupSpan+'<td style="text-align:left;padding-left:16px;">'+esc(name)+'</td><td class="num-cur">'+w+'</td><td class="num-total">'+t+'</td></tr>';}
|
||||
function renderOne(){
|
||||
var n=document.getElementById('selPoint').value;
|
||||
var p=points.filter(function(x){return x.name===n;})[0];
|
||||
if(!p){clearOne();return;}
|
||||
var g=function(rows,title){
|
||||
return rows.map(function(r,i){
|
||||
var span=i===0?'<td class="grp-cell" rowspan="'+rows.length+'" style="text-align:left;padding-left:16px;">'+title+'</td>':'';
|
||||
return row(span,r[0],r[1],r[2]);
|
||||
}).join('');
|
||||
};
|
||||
var html='';
|
||||
html+=g([['医务人员总数',p.staff,'—'],['医生人数',p.doc,'—'],['护士人数',p.nurse,'—'],['辐射员工人数',p.rad,'—']],'基本数据');
|
||||
html+=g([['就诊服务人数',p.visitW,p.visitT],['慢病服务人数',p.chrW,p.chrT]],'服务人数');
|
||||
html+=g([['培训场次',p.trainSW,p.trainST],['培训人次',p.trainPW,p.trainPT],['宣教场次',p.eduSW,p.eduST],['宣教人次',p.eduPW,p.eduPT]],'培训宣教');
|
||||
document.getElementById('tbodyOne').innerHTML=html;
|
||||
document.getElementById('oneTip').textContent='医疗点:'+p.name;
|
||||
}
|
||||
function doExport(){showToast('导出任务已提交,完成后将推送站内通知');}
|
||||
function openExportLog(){document.getElementById('exportMask').classList.add('open');}
|
||||
function closeExportLog(){document.getElementById('exportMask').classList.remove('open');}
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
initUnitSel();renderKpi();renderAll();
|
||||
/* 初始化:单位下拉 + 首屏渲染 */
|
||||
(function(){
|
||||
var us=[];points.forEach(function(p){if(us.indexOf(p.unit)<0)us.push(p.unit);});
|
||||
document.getElementById('selUnit').innerHTML='<option value="">全部单位</option>'+us.map(function(u){return '<option>'+esc(u)+'</option>';}).join('');
|
||||
})();
|
||||
document.getElementById('exportMask').addEventListener('click',function(e){if(e.target===this)closeExportLog();});
|
||||
renderTable();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -31,10 +31,13 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.view-switch{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.view-switch a{display:inline-flex;align-items:center;padding:0 14px;height:32px;font-size:var(--font-sm);color:var(--text-secondary);text-decoration:none;background:#fff;}
|
||||
.view-switch a+a{border-left:1px solid var(--border);}
|
||||
.view-switch a.active{background:var(--primary);color:#fff;}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:9px 24px;font-size:var(--font-sm);color:rgba(255,255,255,0.45);cursor:pointer;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;stroke:currentColor;transition:transform .2s;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;}
|
||||
.sidebar-subgroup.open .sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:40px;}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
@@ -98,22 +101,31 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
<!-- 侧边栏(当前一级分组「数据统计」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">数据统计</div>
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">医疗点统计</a>
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">救护车统计</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
医疗点统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-clinic-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 10 10" fill="none"><path d="M3 1l4 4-4 4" stroke-width="1.5"/></svg>
|
||||
救护车统计
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">统计图表</a>
|
||||
<a href="stat-ambulance-table.html" class="sidebar-item">统计报表</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="stat-rescue-chart.html" class="sidebar-item active">救助物品统计</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<!-- [交互] 图表/报表两种查看形态,数据同源互切 -->
|
||||
<div class="title-line">
|
||||
<span>救助物品统计</span>
|
||||
<div class="view-switch" style="margin-left:auto;">
|
||||
<a class="active" href="stat-rescue-chart.html">图表视图</a>
|
||||
<a href="stat-rescue-table.html">报表视图</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 单下拉「全部+各医疗点」(老系统此页无单位级联);数据导入与模板下载为启用功能 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
@@ -290,6 +302,7 @@ document.getElementById('importMask').addEventListener('click',function(e){if(e.
|
||||
document.getElementById('taskMask').addEventListener('click',function(e){if(e.target===this)closeTask();});
|
||||
document.getElementById('selPoint').innerHTML='<option value="">全部</option>'+sites.map(function(s){return '<option>'+esc(s.name)+'</option>';}).join('');
|
||||
renderScope();
|
||||
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>救助物品统计 | 一线医疗</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;font-size:var(--font-sm);background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.10);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:200px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 14px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;padding-bottom:24px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:9px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.view-switch{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
|
||||
.view-switch a{display:inline-flex;align-items:center;padding:0 14px;height:32px;font-size:var(--font-sm);color:var(--text-secondary);text-decoration:none;background:#fff;}
|
||||
.view-switch a+a{border-left:1px solid var(--border);}
|
||||
.view-switch a.active{background:var(--primary);color:#fff;}
|
||||
.filter-bar{background:#fff;padding:16px 24px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-select{height:36px;min-width:140px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);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 8px center;cursor:pointer;outline:none;appearance:none;-webkit-appearance:none;}
|
||||
.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;white-space:nowrap;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-link{background:none;color:var(--primary);padding:0 4px;height:auto;}.btn-link:hover{color:#40a9ff;}
|
||||
.title-line{display:flex;align-items:center;margin-bottom:16px;}
|
||||
.title-line span{font-size:var(--font-base);font-weight:600;}
|
||||
.item-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:16px 20px;margin-top:16px;}
|
||||
.item-card__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);margin-bottom:12px;}
|
||||
.item-card__grid{display:flex;justify-content:space-around;background:#F8F8FA;border-radius:10px;padding:16px 8px;}
|
||||
.item-cell{text-align:center;}
|
||||
.item-cell__ico{width:36px;height:36px;margin:0 auto;border-radius:50%;display:flex;align-items:center;justify-content:center;}
|
||||
.item-cell__val{font-size:24px;font-weight:600;color:var(--text-primary);margin-top:6px;}
|
||||
.item-cell__val small{font-size:var(--font-xs);font-weight:400;color:var(--text-placeholder);margin-left:2px;}
|
||||
.item-cell__name{font-size:var(--font-sm);color:var(--text-secondary);margin-top:4px;}
|
||||
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
|
||||
.tbl-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:18px 22px;margin-top:16px;}
|
||||
.tbl-card__title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin-bottom:12px;}
|
||||
.tbl-scroll{overflow-x:auto;}
|
||||
table.rpt{width:100%;border-collapse:separate;border-spacing:0;min-width:1200px;}
|
||||
.rpt th,.rpt td{border:1px solid #F0F0F0;padding:10px 12px;font-size:var(--font-sm);text-align:center;white-space:nowrap;}
|
||||
.rpt thead th{background:#FAFAFA;color:var(--text-secondary);font-weight:500;font-size:var(--font-sm);}
|
||||
.rpt thead tr:first-child th{background:#F0F5FF;color:var(--text-primary);font-weight:600;font-size:var(--font-sm);}
|
||||
.rpt tbody tr:hover{background:#F8FBFF;}
|
||||
.rpt .num{font-variant-numeric:tabular-nums;}
|
||||
.rpt .hl{color:#1684FC;font-weight:600;}
|
||||
.rpt tfoot td{background:#FAFAFA;font-weight:600;font-size:var(--font-sm);}
|
||||
.rpt--sm{min-width:0;}
|
||||
.td-empty{text-align:center;padding:32px 0;color:var(--text-placeholder);font-size:var(--font-sm);}
|
||||
/* 导入弹窗(页内实现) */
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:950;align-items:center;justify-content:center;}
|
||||
.modal-mask.open{display:flex;}
|
||||
.modal{width:440px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:24px;}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:8px;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;}
|
||||
.modal--wide{width:640px;}
|
||||
.record-table{width:100%;border-collapse:collapse;font-size:var(--font-sm);}
|
||||
.record-table th{background:#FAFAFA;padding:8px 10px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
.record-table td{padding:10px;border-bottom:1px solid #F0F0F0;white-space:nowrap;}
|
||||
.drop-zone{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:16px;text-align:center;color:var(--text-placeholder);font-size:var(--font-sm);cursor:pointer;line-height:1.8;}
|
||||
.drop-zone:hover{border-color:var(--primary);color:var(--primary);background:#F8FBFF;}
|
||||
.toast{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 24px;border-radius:var(--radius-sm);font-size:var(--font-sm);z-index:9999;opacity:0;transition:opacity .2s;pointer-events:none;}
|
||||
.toast.show{opacity:1;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M14 6.5l7 3.5v4.5c0 4.2-2.9 6.8-7 7.5-4.1-.7-7-3.3-7-7.5V10l7-3.5z" stroke="#fff" stroke-width="1.8" fill="none"/><path d="M11 13.5h6M14 10.5v6" stroke="#fff" stroke-width="1.8" stroke-linecap="round"/></svg> 一线医疗</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-visit-data.html">档案</a>
|
||||
<a href="config-medical-point.html">基础配置</a>
|
||||
<a href="daily-treatment-staff.html">日常业务</a>
|
||||
<a href="bed-device.html">床头呼叫</a>
|
||||
<a href="stat-clinic-chart.html" class="active">数据统计</a>
|
||||
<a href="hut-banner.html">健康小屋</a>
|
||||
<a href="alert-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏(当前一级分组「数据统计」的二级菜单) -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">数据统计</div>
|
||||
<a href="stat-clinic-chart.html" class="sidebar-item">医疗点统计</a>
|
||||
<a href="stat-ambulance-chart.html" class="sidebar-item">救护车统计</a>
|
||||
<a href="stat-rescue-chart.html" class="sidebar-item active">救助物品统计</a>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<!-- [交互] 图表/报表两种查看形态,数据同源互切 -->
|
||||
<div class="title-line">
|
||||
<span>救助物品统计</span>
|
||||
<div class="view-switch" style="margin-left:auto;">
|
||||
<a href="stat-rescue-chart.html">图表视图</a>
|
||||
<a class="active" href="stat-rescue-table.html">报表视图</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 与图表视图共用同一医疗点下拉(含「全部」)与导入/模板功能 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>所属医疗点</label>
|
||||
<select class="filter-select" id="selPoint" onchange="renderScope()" style="min-width:220px;">
|
||||
<option value="">全部</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="openImport()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 9V2M4.5 4.5L7 2l2.5 2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>批量导入数据</button>
|
||||
<button class="btn btn-default" onclick="openImportTasks()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导入任务</button>
|
||||
<button class="btn btn-default" onclick="showToast('救助物品模板下载功能演示')">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v7M4.5 6.5L7 9l2.5-2.5M2 12h10" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>救助物品模板下载
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 物品卡与图表视图同源 -->
|
||||
<div class="item-card">
|
||||
<div class="item-card__title">小药棒</div>
|
||||
<div class="item-card__grid" id="cardStick"></div>
|
||||
</div>
|
||||
<div class="two-col">
|
||||
<div class="item-card" style="margin-top:0;">
|
||||
<div class="item-card__title">药品箱</div>
|
||||
<div class="item-card__grid" id="cardBox"></div>
|
||||
</div>
|
||||
<div class="item-card" style="margin-top:0;">
|
||||
<div class="item-card__title">急救包</div>
|
||||
<div class="item-card__grid" id="cardAid"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 三张占比饼图的报表形态:物品类别 × 三项指标与占比 -->
|
||||
<div class="tbl-card">
|
||||
<div class="tbl-card__title">救助物品占比统计</div>
|
||||
<div class="tbl-scroll"><table class="rpt rpt--sm" id="tblRatio"></table></div>
|
||||
</div>
|
||||
|
||||
<!-- 明细报表:逐医疗点全量指标(分组表头),对应图表页的全局/单点视角 -->
|
||||
<div class="tbl-card">
|
||||
<div class="tbl-card__title" id="tblDetailTitle">各医疗点救助物品明细</div>
|
||||
<div class="tbl-scroll"><table class="rpt" id="tblDetail"></table></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- [交互] 数据导入弹窗(页内实现,与图表视图一致) -->
|
||||
<div class="modal-mask" id="importMask">
|
||||
<div class="modal">
|
||||
<div class="modal__title"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 14V3M6.5 6.5L10 3l3.5 3.5M3 16h14" stroke="#1890FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg> 导入救助物品数据</div>
|
||||
<div style="margin-top:14px;">
|
||||
<div class="drop-zone" onclick="showToast('演示环境请选择本地文件(仅支持.xlsx)')">点击选择或拖拽文件到此处上传<br>救助物品模板.xlsx</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeImport()">取消</button>
|
||||
<button class="btn btn-primary" onclick="doImport()">开始导入</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 导入任务:异步任务列表 -->
|
||||
<div class="modal-mask" id="taskMask">
|
||||
<div class="modal modal--wide">
|
||||
<div class="modal__title">救助物品导入任务</div>
|
||||
<table class="record-table">
|
||||
<thead><tr><th>文件名称</th><th>时间</th><th>结果</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>救助物品数据-2026年9月.xlsx</td><td>2026-09-05 15:41:36</td><td style="color:#389E0D;">成功:新增 96 条领用记录</td><td><button class="btn btn-link" onclick="showToast('导入明细下载中…')">下载明细</button></td></tr>
|
||||
<tr><td>救助物品数据-2026年8月.xlsx</td><td>2026-08-28 11:09:52</td><td style="color:#D48806;">部分成功:新增 88 条、失败 4 条</td><td><button class="btn btn-link" onclick="showToast('导入明细下载中…')">下载明细</button></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="modal__footer"><button class="btn btn-default" onclick="closeTask()">关闭</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* 数据源与「救助物品统计-图表」完全一致 */
|
||||
var sites=[
|
||||
{name:'樊学作业区医疗点',bzxpsl:26,xybxpsl:96,ljpbsl:1280,bzxprs:22,ljpzrs:940,bzghyp:360,xybzfy:42600,ypxljsl:6,ypxxpsl:2,ypxzfy:18000,jjbljsl:4,jjbxpsl:1,jjbzfy:6400},
|
||||
{name:'安塞采油队长住点医疗室',bzxpsl:8,xybxpsl:34,ljpbsl:420,bzxprs:6,ljpzrs:310,bzghyp:120,xybzfy:13800,ypxljsl:2,ypxxpsl:1,ypxzfy:5600,jjbljsl:1,jjbxpsl:0,jjbzfy:1600},
|
||||
{name:'姬塬作业区医疗点',bzxpsl:12,xybxpsl:47,ljpbsl:560,bzxprs:9,ljpzrs:402,bzghyp:150,xybzfy:18600,ypxljsl:3,ypxxpsl:1,ypxzfy:8200,jjbljsl:2,jjbxpsl:0,jjbzfy:3100},
|
||||
{name:'姬圪台作业区医疗点',bzxpsl:18,xybxpsl:68,ljpbsl:890,bzxprs:15,ljpzrs:660,bzghyp:240,xybzfy:29800,ypxljsl:4,ypxxpsl:1,ypxzfy:12000,jjbljsl:3,jjbxpsl:1,jjbzfy:4800},
|
||||
{name:'桐园作业区医疗点',bzxpsl:10,xybxpsl:41,ljpbsl:470,bzxprs:8,ljpzrs:350,bzghyp:130,xybzfy:15200,ypxljsl:3,ypxxpsl:1,ypxzfy:8400,jjbljsl:2,jjbxpsl:1,jjbzfy:3200},
|
||||
{name:'西峰基地医疗点',bzxpsl:32,xybxpsl:118,ljpbsl:1520,bzxprs:28,ljpzrs:1180,bzghyp:410,xybzfy:51200,ypxljsl:8,ypxxpsl:2,ypxzfy:23600,jjbljsl:5,jjbxpsl:2,jjbzfy:8600},
|
||||
{name:'靖边气田医疗点',bzxpsl:14,xybxpsl:52,ljpbsl:620,bzxprs:11,ljpzrs:450,bzghyp:170,xybzfy:20400,ypxljsl:3,ypxxpsl:1,ypxzfy:9200,jjbljsl:2,jjbxpsl:1,jjbzfy:3500},
|
||||
{name:'乌审旗采气区医疗点',bzxpsl:12,xybxpsl:45,ljpbsl:540,bzxprs:9,ljpzrs:388,bzghyp:140,xybzfy:17900,ypxljsl:3,ypxxpsl:1,ypxzfy:8800,jjbljsl:2,jjbxpsl:1,jjbzfy:3300}
|
||||
];
|
||||
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<');}
|
||||
function scope(){
|
||||
var p=document.getElementById('selPoint').value;
|
||||
return p?sites.filter(function(x){return x.name===p;}):sites;
|
||||
}
|
||||
function sumField(list,f){return list.reduce(function(s,x){return s+x[f];},0);}
|
||||
function cellFor(v,unit,name,bg,svg){
|
||||
return '<div class="item-cell"><div class="item-cell__ico" style="background:'+bg+';"><svg width="20" height="20" viewBox="0 0 20 20" fill="none">'+svg+'</svg></div>'
|
||||
+'<div class="item-cell__val">'+v+(unit?'<small>'+unit+'</small>':'')+'</div><div class="item-cell__name">'+name+'</div></div>';
|
||||
}
|
||||
var ICO={
|
||||
pill:'<rect x="6" y="3" width="8" height="14" rx="4" stroke="#fff" stroke-width="1.6"/><path d="M6 10h8" stroke="#fff" stroke-width="1.6"/>',
|
||||
num:'<path d="M4 16h12M6 12l3-6 3 4 2-3" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>',
|
||||
people:'<circle cx="10" cy="6.5" r="3" stroke="#fff" stroke-width="1.6"/><path d="M4.5 16c0-3 2.5-4.5 5.5-4.5S15.5 13 15.5 16" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/>',
|
||||
cost:'<circle cx="10" cy="10" r="6.5" stroke="#fff" stroke-width="1.6"/><path d="M7.5 7l2.5 3 2.5-3M10 10v4M7.5 12h5" stroke="#fff" stroke-width="1.4" stroke-linecap="round"/>'
|
||||
};
|
||||
function renderCards(){
|
||||
var sc=scope();
|
||||
document.getElementById('cardStick').innerHTML=
|
||||
cellFor(sumField(sc,'bzxpsl'),'个','本周新配数量','#1E92FF',ICO.pill)
|
||||
+cellFor(sumField(sc,'ljpbsl'),'个','累计配备数量','#48D147',ICO.num)
|
||||
+cellFor(sumField(sc,'bzxprs'),'人','本周新配人数','#FFAE53',ICO.people)
|
||||
+cellFor(sumField(sc,'ljpzrs'),'人','累计配备人数','#8168F5',ICO.people)
|
||||
+cellFor(sumField(sc,'bzghyp'),'片','本周更换药品(片)','#FF5641',ICO.pill)
|
||||
+cellFor(sumField(sc,'xybzfy').toLocaleString(),'元','总费用','#57B8FF',ICO.cost);
|
||||
document.getElementById('cardBox').innerHTML=
|
||||
cellFor(sumField(sc,'ypxljsl'),'个','数量','#1E92FF',ICO.num)
|
||||
+cellFor(sumField(sc,'ypxxpsl'),'个','今年新配数量','#48D147',ICO.num)
|
||||
+cellFor(sumField(sc,'ypxzfy').toLocaleString(),'元','总费用','#FFAE53',ICO.cost);
|
||||
document.getElementById('cardAid').innerHTML=
|
||||
cellFor(sumField(sc,'jjbljsl'),'个','数量','#1E92FF',ICO.num)
|
||||
+cellFor(sumField(sc,'jjbxpsl'),'个','今年新配数量','#48D147',ICO.num)
|
||||
+cellFor(sumField(sc,'jjbzfy').toLocaleString(),'元','总费用','#FFAE53',ICO.cost);
|
||||
}
|
||||
/* 占比统计表:三张饼图(总数量/今年新增/总费用)的行式表达 */
|
||||
function renderRatio(){
|
||||
var sc=scope();
|
||||
var qty=[sumField(sc,'ljpbsl'),sumField(sc,'ypxljsl'),sumField(sc,'jjbljsl')];
|
||||
var nw=[sumField(sc,'xybxpsl'),sumField(sc,'ypxxpsl'),sumField(sc,'jjbxpsl')];
|
||||
var cf=[sumField(sc,'xybzfy'),sumField(sc,'ypxzfy'),sumField(sc,'jjbzfy')];
|
||||
var tq=qty[0]+qty[1]+qty[2]||1,tn=nw[0]+nw[1]+nw[2]||1,tc=cf[0]+cf[1]+cf[2]||1;
|
||||
var names=['小药棒','药品箱','急救包'];
|
||||
var h='<thead><tr><th>物品类别</th><th>总数量</th><th>数量占比</th><th>今年新增数量</th><th>新增占比</th><th>总费用(元)</th><th>费用占比</th></tr></thead><tbody>';
|
||||
names.forEach(function(n,i){
|
||||
h+='<tr><td style="font-weight:600;">'+n+'</td><td class="num hl">'+qty[i].toLocaleString()+'</td><td class="num">'+(qty[i]/tq*100).toFixed(1)+'%</td>'
|
||||
+'<td class="num hl">'+nw[i].toLocaleString()+'</td><td class="num">'+(nw[i]/tn*100).toFixed(1)+'%</td>'
|
||||
+'<td class="num hl">'+cf[i].toLocaleString()+'</td><td class="num">'+(cf[i]/tc*100).toFixed(1)+'%</td></tr>';
|
||||
});
|
||||
h+='</tbody><tfoot><tr><td>合计</td><td class="num">'+(qty[0]+qty[1]+qty[2]).toLocaleString()+'</td><td class="num">100%</td>'
|
||||
+'<td class="num">'+(nw[0]+nw[1]+nw[2]).toLocaleString()+'</td><td class="num">100%</td>'
|
||||
+'<td class="num">'+(cf[0]+cf[1]+cf[2]).toLocaleString()+'</td><td class="num">100%</td></tr></tfoot>';
|
||||
document.getElementById('tblRatio').innerHTML=h;
|
||||
}
|
||||
/* 明细报表:分组表头 小药棒(7)/药品箱(3)/急救包(3),按累计配备数量降序 */
|
||||
function renderDetail(){
|
||||
var sc=scope().slice().sort(function(a,b){return b.ljpbsl-a.ljpbsl;});
|
||||
document.getElementById('tblDetailTitle').textContent=document.getElementById('selPoint').value?('救助物品明细 · '+document.getElementById('selPoint').value):'各医疗点救助物品明细';
|
||||
var h='<thead><tr><th rowspan="2">所属医疗点</th><th colspan="7">小药棒</th><th colspan="3">药品箱</th><th colspan="3">急救包</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><th>总费用(元)</th></tr></thead>';
|
||||
if(!sc.length){h+='<tbody><tr><td colspan="14" class="td-empty">暂无数据</td></tr></tbody>';document.getElementById('tblDetail').innerHTML=h;return;}
|
||||
h+='<tbody>'+sc.map(function(s){
|
||||
return '<tr><td style="font-weight:600;">'+esc(s.name)+'</td>'
|
||||
+'<td class="num">'+s.bzxpsl+'</td><td class="num">'+s.xybxpsl+'</td><td class="num hl">'+s.ljpbsl+'</td><td class="num">'+s.bzxprs+'</td><td class="num">'+s.ljpzrs+'</td><td class="num">'+s.bzghyp+'</td><td class="num">'+s.xybzfy.toLocaleString()+'</td>'
|
||||
+'<td class="num">'+s.ypxljsl+'</td><td class="num">'+s.ypxxpsl+'</td><td class="num">'+s.ypxzfy.toLocaleString()+'</td>'
|
||||
+'<td class="num">'+s.jjbljsl+'</td><td class="num">'+s.jjbxpsl+'</td><td class="num">'+s.jjbzfy.toLocaleString()+'</td></tr>';
|
||||
}).join('')+'</tbody>';
|
||||
var T={};
|
||||
['bzxpsl','xybxpsl','ljpbsl','bzxprs','ljpzrs','bzghyp','xybzfy','ypxljsl','ypxxpsl','ypxzfy','jjbljsl','jjbxpsl','jjbzfy'].forEach(function(f){T[f]=sumField(sc,f);});
|
||||
h+='<tfoot><tr><td>合计</td><td class="num">'+T.bzxpsl+'</td><td class="num">'+T.xybxpsl+'</td><td class="num">'+T.ljpbsl+'</td><td class="num">'+T.bzxprs+'</td><td class="num">'+T.ljpzrs+'</td><td class="num">'+T.bzghyp+'</td><td class="num">'+T.xybzfy.toLocaleString()+'</td>'
|
||||
+'<td class="num">'+T.ypxljsl+'</td><td class="num">'+T.ypxxpsl+'</td><td class="num">'+T.ypxzfy.toLocaleString()+'</td>'
|
||||
+'<td class="num">'+T.jjbljsl+'</td><td class="num">'+T.jjbxpsl+'</td><td class="num">'+T.jjbzfy.toLocaleString()+'</td></tr></tfoot>';
|
||||
document.getElementById('tblDetail').innerHTML=h;
|
||||
}
|
||||
function renderScope(){renderCards();renderRatio();renderDetail();}
|
||||
function openImport(){document.getElementById('importMask').classList.add('open');}
|
||||
function closeImport(){document.getElementById('importMask').classList.remove('open');}
|
||||
function doImport(){closeImport();showToast('导入任务已提交,完成后将推送站内通知');}
|
||||
/* [交互] 查看导入任务(异步任务演示) */
|
||||
function openImportTasks(){document.getElementById('taskMask').classList.add('open');}
|
||||
function closeTask(){document.getElementById('taskMask').classList.remove('open');}
|
||||
function showToast(msg){
|
||||
var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
|
||||
clearTimeout(t._timer);t._timer=setTimeout(function(){t.classList.remove('show');},2200);
|
||||
}
|
||||
document.getElementById('importMask').addEventListener('click',function(e){if(e.target===this)closeImport();});
|
||||
document.getElementById('taskMask').addEventListener('click',function(e){if(e.target===this)closeTask();});
|
||||
document.getElementById('selPoint').innerHTML='<option value="">全部</option>'+sites.map(function(s){return '<option>'+esc(s.name)+'</option>';}).join('');
|
||||
renderScope();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user