This commit is contained in:
fengpu
2026-09-09 15:16:25 +08:00
47 changed files with 18991 additions and 16730 deletions
@@ -172,9 +172,24 @@
.project-card__meta {
display: flex; align-items: center; gap: 6px;
}
/* AI 推荐标签分三档,字号阶梯放大 + 深色实底强化等级对比:
强烈推荐 12px 红橙实底 > 建议加做 11px 紫蓝实底 > 可选参考 10px 浅蓝描边 */
.project-card__badge--ai {
background: linear-gradient(135deg, #7c5cfc 0%, #4f8ef7 100%);
color: #fff; cursor: pointer; box-shadow: 0 2px 6px rgba(124, 92, 252, 0.3);
color: #fff; cursor: pointer; font-weight: 700;
}
.project-card__badge--ai-high {
height: 26px; padding: 0 12px; border-radius: 13px; font-size: 12px;
background: linear-gradient(135deg, #cf1322 0%, #f5222d 55%, #ff7a45 100%);
box-shadow: 0 3px 8px rgba(207, 19, 34, 0.35);
}
.project-card__badge--ai-mid {
height: 24px; padding: 0 11px; border-radius: 12px; font-size: 11px;
background: linear-gradient(135deg, #531dab 0%, #722ed1 50%, #1677ff 100%);
box-shadow: 0 2px 6px rgba(83, 29, 171, 0.35);
}
.project-card__badge--ai-low {
height: 20px; padding: 0 8px; border-radius: 10px; font-size: 10px; font-weight: 600;
background: #f0f5ff; color: #597ef7; border: 1px solid #d6e4ff;
}
.project-card__arrow {
flex-shrink: 0; color: #d0d0d0; font-size: 16px; cursor: pointer;
@@ -235,7 +250,15 @@
/* AI 推荐理由弹窗 */
.ai-modal { padding: 24px 20px 18px; }
.ai-modal__project {
font-size: 15px; font-weight: 700; color: #7c5cfc; text-align: center; margin-bottom: 12px;
font-size: 15px; font-weight: 700; color: #7c5cfc; text-align: center; margin-bottom: 10px;
}
.ai-modal__level {
display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 12px;
}
.ai-modal__level-cap { font-size: 12px; color: var(--text-muted); }
.ai-modal__level-desc {
font-size: 12px; line-height: 1.6; color: var(--text-secondary); text-align: center;
margin: -4px 0 12px;
}
.ai-modal__reason {
background: #f7f9fb; border-radius: 14px; padding: 14px 16px; margin-bottom: 18px;
@@ -351,6 +374,11 @@
<div class="confirm-modal ai-modal">
<div class="confirm-modal__title">✨ 智能推荐</div>
<div class="ai-modal__project" id="aiModalProject"></div>
<div class="ai-modal__level">
<span class="ai-modal__level-cap">推荐等级</span>
<span class="project-card__badge" id="aiModalLevel"></span>
</div>
<div class="ai-modal__level-desc" id="aiModalLevelDesc"></div>
<div class="ai-modal__reason" id="aiModalReason"></div>
<button class="confirm-modal__btn confirm-modal__btn--primary ai-modal__close" onclick="closeAiReason()">知道了</button>
</div>
@@ -359,6 +387,12 @@
<script>
// 年度体检总额度(可用额度 = 总额度 − 已选项目费用,原型模拟数据)
const annualLimit = 1600;
// AI 推荐等级:3 强烈推荐(既往异常直接相关)> 2 建议加做(存在风险因素)> 1 可选参考(一般性补充筛查)
const AI_LEVELS = {
3: { label: '强烈推荐', cls: 'high', icon: '🔥', desc: '与您的既往异常发现直接相关,建议本年度务必完成。' },
2: { label: '建议加做', cls: 'mid', icon: '✨', desc: '健康画像显示存在相关风险因素,建议在本年度体检中加做。' },
1: { label: '可选参考', cls: 'low', icon: '✨', desc: '按年龄段与常见风险的一般性补充筛查,可结合剩余额度自行选择。' }
};
const projects = [
{ id: 'general', name: '一般检查', desc: '身高、体重、血压、视力', price: 120, type: 'required', level: 'normal' },
{ id: 'blood', name: '血常规', desc: '血红蛋白、白细胞、血小板等', price: 80, type: 'required', level: 'normal' },
@@ -369,11 +403,11 @@
{ id: 'glucose', name: '空腹血糖', desc: '空腹静脉血糖检测', price: 40, type: 'required', level: 'normal' },
{ id: 'ecg', name: '心电图', desc: '十二导联心电图检查', price: 75, type: 'required', level: 'key' },
{ id: 'xray', name: '胸部X光', desc: '胸部正位X线摄影', price: 140, type: 'optional', level: 'normal' },
{ id: 'ultrasound', name: '腹部B超', desc: '肝胆脾胰肾超声检查', price: 180, type: 'optional', level: 'key', aiRecommend: true, aiReason: '健康画像显示 BMI 26.8(超重),且近年血脂偏高,建议加做腹部超声重点筛查脂肪肝与胆囊病变。预计费用 ¥180,在本年度体检额度内。' },
{ id: 'thyroid', name: '甲状腺彩超', desc: '甲状腺结构与结节筛查', price: 160, type: 'optional', level: 'key', aiRecommend: true, aiReason: '既往史显示 2024 年体检发现甲状腺结节(TI-RADS 2 类),建议每年做一次超声随访复查,观察结节变化。预计费用 ¥160,在本年度体检额度内。' },
{ id: 'tumor', name: '肿瘤标志物', desc: '基础肿瘤风险筛查', price: 220, type: 'optional', level: 'key', aiRecommend: true, aiReason: '家族史提示直系亲属有肿瘤病史,结合您所处年龄段(45 岁以上),建议今年纳入基础肿瘤标志物筛查,做到早发现早干预。预计费用 ¥220,在本年度体检额度内。' },
{ id: 'echo', name: '心脏彩超', desc: '心脏结构与瓣膜功能超声', price: 360, type: 'optional', level: 'key' },
{ id: 'gastro', name: '胃幽门螺杆菌检测', desc: 'C13 呼气试验,筛查胃部风险', price: 480, type: 'optional', level: 'normal' }
{ id: 'ultrasound', name: '腹部B超', desc: '肝胆脾胰肾超声检查', price: 180, type: 'optional', level: 'key', aiLevel: 3, aiReason: '健康画像显示 BMI 26.8(超重),且近年血脂持续偏高,属于脂肪肝与胆囊病变的高风险人群,建议本年度务必完成腹部超声重点筛查。预计费用 ¥180,在本年度体检额度内。' },
{ id: 'thyroid', name: '甲状腺彩超', desc: '甲状腺结构与结节筛查', price: 160, type: 'optional', level: 'key', aiLevel: 2, aiReason: '既往史显示 2024 年体检发现甲状腺结节(TI-RADS 2 类),建议每年做一次超声随访复查,观察结节变化。预计费用 ¥160,在本年度体检额度内。' },
{ id: 'tumor', name: '肿瘤标志物', desc: '基础肿瘤风险筛查', price: 220, type: 'optional', level: 'key', aiLevel: 2, aiReason: '家族史提示直系亲属有肿瘤病史,结合您所处年龄段(45 岁以上),建议今年纳入基础肿瘤标志物筛查,做到早发现早干预。预计费用 ¥220,在本年度体检额度内。' },
{ id: 'echo', name: '心脏彩超', desc: '心脏结构与瓣膜功能超声', price: 360, type: 'optional', level: 'key', aiLevel: 1, aiReason: '近两次体检血压处于正常高值,可完成一次心脏彩超,建立心脏结构与瓣膜功能的基线资料,便于日后对比随访。预计费用 ¥360,请注意控制项目总额。' },
{ id: 'gastro', name: '胃幽门螺杆菌检测', desc: 'C13 呼气试验,筛查胃部风险', price: 480, type: 'optional', level: 'normal', aiLevel: 1, aiReason: '幽门螺杆菌是胃癌明确的危险因素,国内感染率较高。如从未检测过,建议先做一次 C13 呼气试验筛查,阳性可规范四联根除治疗。预计费用 ¥480,可结合剩余额度自行选择。' }
];
let activeTab = 'optional';
@@ -397,9 +431,11 @@
}
function getOptionalProjects() {
// [交互] AI 推荐项目排在列表前面
const optional = projects.filter(project => project.type === 'optional');
return [...optional.filter(project => project.aiRecommend), ...optional.filter(project => !project.aiRecommend)];
// [交互] AI 推荐项目按推荐等级从高到低排在列表前面,未推荐项目保持原顺序
return projects
.filter(project => project.type === 'optional')
.slice()
.sort((a, b) => (b.aiLevel || 0) - (a.aiLevel || 0));
}
function getRequiredFee() {
@@ -443,6 +479,7 @@
const isReadonly = project.type === 'required';
const isSelected = selectedOptionalIds.has(project.id);
const projectLevelText = project.level === 'key' ? '重点项目' : '一般项目';
const aiLevel = AI_LEVELS[project.aiLevel];
card.className = `project-card${isReadonly ? ' project-card--readonly' : ''}${isSelected ? ' selected' : ''}`;
card.innerHTML = `
<div class="project-card__check${isReadonly ? ' project-card__check--hidden' : ''}"></div>
@@ -455,7 +492,7 @@
<span class="project-card__price">${formatPrice(project.price)}</span>
<div class="project-card__meta">
<span class="project-card__badge${project.level === 'key' ? ' project-card__badge--key' : ''}">${projectLevelText}</span>
${project.aiRecommend ? '<span class="project-card__badge project-card__badge--ai">✨ 推荐</span>' : ''}
${aiLevel ? `<span class="project-card__badge project-card__badge--ai project-card__badge--ai-${aiLevel.cls}">${aiLevel.icon} ${aiLevel.label}</span>` : ''}
</div>
</div>
<span class="project-card__arrow" data-detail="${project.id}">&#8250;</span>
@@ -523,7 +560,12 @@
window.location.href = 'booking-hospital.html';
}
function openAiReason(project) {
const level = AI_LEVELS[project.aiLevel];
document.getElementById('aiModalProject').textContent = project.name;
const levelEl = document.getElementById('aiModalLevel');
levelEl.textContent = level.icon + ' ' + level.label;
levelEl.className = 'project-card__badge project-card__badge--ai project-card__badge--ai-' + level.cls;
document.getElementById('aiModalLevelDesc').textContent = level.desc;
document.getElementById('aiModalReason').textContent = project.aiReason;
document.getElementById('aiModal').classList.remove('hidden');
}
@@ -130,6 +130,9 @@
.type-card__icon--gastro {
background: linear-gradient(135deg, #fff7e6 0%, #ffe7ba 100%);
}
.type-card__icon--cta {
background: linear-gradient(135deg, #fff1f0 0%, #ffccc7 100%);
}
.type-card__main { flex: 1; min-width: 0; }
.type-card__name {
font-size: 16px;
@@ -318,6 +321,34 @@
</div>
</div>
</div>
<div class="type-card" onclick="selectType(this, 'cta')">
<div class="type-card__header">
<div class="type-card__icon type-card__icon--cta">🫀</div>
<div class="type-card__main">
<div class="type-card__name">冠脉CTA体检</div>
<div class="type-card__badges">
<span class="status-badge status-badge--ongoing">进行中</span>
<span class="status-badge status-badge--appt-open">已开启预约</span>
</div>
</div>
<div class="radio-dot"></div>
</div>
<div class="type-card__info">
<div class="info-row">
<span class="info-row__label">体检时间</span>
<span class="info-row__value">2026-06-23 至 2026-08-31</span>
</div>
<div class="info-row">
<span class="info-row__label">预约时间</span>
<span class="info-row__value">2026-06-01 至 2026-08-20</span>
</div>
<div class="info-row">
<span class="info-row__label">所属人群</span>
<span class="info-row__value">35岁及以下-女</span>
</div>
</div>
</div>
</div>
</div>
@@ -337,6 +368,8 @@
function goNext() {
if (selectedType === 'gastro') {
window.location.href = 'gastro-hospital.html?from=booking-type';
} else if (selectedType === 'cta') {
window.location.href = 'cta-hospital.html?from=booking-type';
} else {
window.location.href = 'booking-hospital.html?from=booking-type';
}
@@ -0,0 +1,409 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>冠脉CTA预约 - 预约完成</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary: #13c2c2; --primary-dark: #0f9b9b; --primary-light: #e6fffb;
--danger: #ff4d4f; --danger-light: #fff1f0;
--text-primary: #1a1a1a; --text-secondary: #666666; --text-muted: #8c8c8c;
--bg-page: #f0f2f5; --bg-content: #f7f9fb;
--shadow: 0 10px 30px rgba(19, 194, 194, 0.08);
}
body {
background: var(--bg-page); display: flex; justify-content: center; align-items: flex-start;
min-height: 100vh; padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
color: var(--text-primary);
}
.phone-shell {
width: 390px; min-height: 844px; background: var(--bg-content);
border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
overflow: hidden; position: relative; display: flex; flex-direction: column;
}
.phone-status-bar {
height: 44px; background: #fff; display: flex; align-items: center;
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
.nav-bar {
height: 44px; display: flex; align-items: center; padding: 0 16px;
background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative;
}
.nav-back { font-size: 18px; color: var(--text-primary); cursor: pointer; line-height: 1; text-decoration: none; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; }
.scroll-content {
flex: 1; overflow-y: auto;
background: linear-gradient(180deg, #effbfb 0%, #f7f9fb 180px, #f7f9fb 100%);
padding-bottom: 100px;
}
.scroll-content::-webkit-scrollbar { display: none; }
.page-body { padding: 16px; }
.stepper { display: flex; align-items: center; justify-content: center; margin-bottom: 18px; padding: 16px 0; }
.stepper__item { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; text-decoration: none; }
.stepper__dot {
width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; background: #e8e8e8; color: #bfbfbf; transition: all 0.25s;
}
.stepper__item--done .stepper__dot { background: var(--primary); color: #fff; }
.stepper__item--done { pointer-events: none; }
.stepper__label { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.stepper__item--done .stepper__label { color: var(--primary-dark); }
.stepper__line { width: 44px; height: 3px; background: #e8e8e8; margin: 0 8px; margin-bottom: 22px; border-radius: 2px; }
.stepper__line--done { background: var(--primary); }
.section-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; }
.info-card {
background: #fff; border-radius: 20px; padding: 18px 16px; margin-bottom: 14px;
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
}
.info-card__row {
display: flex; justify-content: space-between; align-items: center;
padding: 12px 0; border-bottom: 1px solid #f0f0f0;
}
.info-card__row:first-child { padding-top: 0; }
.info-card__row:last-child { border-bottom: none; padding-bottom: 0; }
.info-card__label { font-size: 13px; color: var(--text-muted); }
.info-card__value { font-size: 14px; font-weight: 600; color: var(--text-primary); text-align: right; }
.info-card__value--highlight { color: var(--primary-dark); }
.tips-card {
background: #fff; border-radius: 20px; padding: 16px; margin-bottom: 14px;
border: 1px solid #eef5f5; box-shadow: 0 8px 24px rgba(0,0,0,0.04);
}
.tips-card__title { font-size: 15px; font-weight: 700; margin-bottom: 10px; }
.tips-card__item {
display: flex; gap: 8px; font-size: 13px; line-height: 1.7;
color: var(--text-secondary); margin-bottom: 8px;
}
.tips-card__item:last-child { margin-bottom: 0; }
.tips-card__dot {
width: 6px; height: 6px; border-radius: 50%; background: var(--primary);
margin-top: 8px; flex-shrink: 0;
}
.bottom-actions {
position: absolute; left: 16px; right: 16px; bottom: 18px;
display: flex; gap: 12px; padding-bottom: 16px;
}
.bottom-actions__btn {
flex: 1; height: 48px; border-radius: 24px; font-size: 15px; font-weight: 600; border: none; cursor: pointer;
}
.bottom-actions__btn--ghost {
background: var(--danger-light); color: var(--danger); border: 1px solid rgba(255,77,79,0.2);
}
.bottom-actions__btn--primary {
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
color: #fff; box-shadow: 0 10px 20px rgba(19,194,194,0.22);
}
.toast {
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(0.9);
background: rgba(0,0,0,0.75); color: #fff; padding: 14px 22px; border-radius: 12px;
font-size: 13px; line-height: 1.6; text-align: center; z-index: 200;
opacity: 0; pointer-events: none; transition: all 0.25s ease; max-width: 280px;
}
.toast.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
/* 原型演示状态下拉框(导航栏右上角) */
.demo-select {
margin-left: auto; flex-shrink: 0; font-family: inherit;
font-size: 11px; font-weight: 600; color: var(--text-secondary);
border: 1px solid #e8e8e8; border-radius: 12px; padding: 3px 6px;
background: #f5f5f5; cursor: pointer; outline: none;
}
/* 预约结果横幅 */
.result-banner {
display: flex; align-items: flex-start; gap: 12px;
border-radius: 20px; padding: 16px; margin-bottom: 14px;
}
.result-banner--success { background: linear-gradient(135deg, #f6ffed 0%, #ffffff 100%); border: 1px solid #b7eb8f; }
.result-banner--fail { background: linear-gradient(135deg, #fff1f0 0%, #ffffff 100%); border: 1px solid #ffccc7; }
.result-banner__icon {
width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
}
.result-banner--success .result-banner__icon { background: #52c41a; }
.result-banner--fail .result-banner__icon { background: #ff4d4f; }
.result-banner--success .icon-cross { display: none; }
.result-banner--fail .icon-check { display: none; }
.result-banner__title { font-size: 18px; font-weight: 800; margin-bottom: 4px; }
.result-banner--success .result-banner__title { color: #389e0d; }
.result-banner--fail .result-banner__title { color: #cf1322; }
.result-banner__sub { font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.result-banner__reason {
display: none; align-items: center; gap: 6px; margin-top: 6px;
font-size: 13px; color: var(--text-secondary);
}
.result-banner--fail .result-banner__reason { display: flex; }
.reason-help {
width: 16px; height: 16px; border-radius: 50%; border: 1px solid #ff4d4f; color: #ff4d4f;
display: inline-flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 700; cursor: pointer; flex-shrink: 0; transition: all 0.2s;
}
.reason-help:hover { background: #ff4d4f; color: #fff; }
/* 失败原因详情弹窗 */
.reason-modal {
width: 100%; background: #fff; border-radius: 24px; padding: 22px 20px 18px;
box-shadow: 0 20px 50px rgba(0,0,0,0.16);
}
.reason-modal__title { font-size: 17px; font-weight: 700; text-align: center; margin-bottom: 16px; }
.reason-modal__item { margin-bottom: 14px; }
.reason-modal__label { font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
.reason-modal__text { font-size: 14px; font-weight: 600; color: var(--text-primary); line-height: 1.6; }
.reason-modal__text--danger { color: #cf1322; }
.reason-modal__btn {
width: 100%; height: 44px; border-radius: 22px; border: none; cursor: pointer;
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff;
font-size: 15px; font-weight: 600; margin-top: 4px;
}
/* 取消预约确认弹窗 */
.modal-overlay {
position: absolute; inset: 0; background: rgba(0,0,0,0.42); z-index: 120;
display: flex; align-items: center; justify-content: center; padding: 24px;
}
.modal-overlay.hidden { display: none; }
.cancel-modal {
width: 100%; background: #fff; border-radius: 24px; padding: 22px 20px 18px;
box-shadow: 0 20px 50px rgba(0,0,0,0.16);
}
.cancel-modal__title { font-size: 17px; font-weight: 700; text-align: center; margin-bottom: 6px; }
.cancel-modal__desc { font-size: 12px; color: var(--text-muted); text-align: center; line-height: 1.6; margin-bottom: 14px; }
.cancel-modal__order {
background: #f7f9fb; border-radius: 12px; padding: 10px 14px; margin-bottom: 16px;
font-size: 13px; font-weight: 600; color: var(--text-secondary); text-align: center;
}
.cancel-modal__label { font-size: 13px; font-weight: 600; margin-bottom: 10px; }
.cancel-modal__label em { color: var(--danger); font-style: normal; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.chip {
padding: 7px 14px; border-radius: 16px; border: 1px solid #e8e8e8; background: #fafafa;
font-size: 13px; color: var(--text-secondary); cursor: pointer; transition: all 0.2s; user-select: none;
}
.chip.selected { background: var(--primary-light); border-color: var(--primary); color: var(--primary-dark); font-weight: 600; }
.other-input {
display: none; width: 100%; border: 1px solid #e8e8e8; border-radius: 12px;
padding: 10px 12px; font-size: 13px; font-family: inherit; line-height: 1.6;
resize: none; outline: none; margin-bottom: 6px; color: var(--text-primary);
}
.other-input.show { display: block; }
.other-input:focus { border-color: var(--primary); }
.cancel-modal__err { display: none; font-size: 12px; color: var(--danger); margin-bottom: 6px; }
.cancel-modal__err.show { display: block; }
.cancel-modal__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px; }
.cancel-modal__btn { height: 44px; border-radius: 22px; font-size: 15px; font-weight: 600; border: none; cursor: pointer; }
.cancel-modal__btn--ghost { background: #f5f5f5; color: var(--text-secondary); }
.cancel-modal__btn--danger { background: var(--danger); color: #fff; box-shadow: 0 6px 16px rgba(255,77,79,0.28); }
</style>
</head>
<body>
<div class="phone-shell">
<div class="phone-status-bar">
<span class="time">12:00</span>
<div class="icons">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
</div>
</div>
<div class="nav-bar">
<a class="nav-back" href="index.html">&#8249;</a>
<span class="nav-title">冠脉CTA预约</span>
<!-- [交互] 原型演示:切换预约成功/失败两态 -->
<select class="demo-select" id="demoSelect" title="原型演示:切换预约结果状态" onchange="setResult(this.value)">
<option value="success">预约成功</option>
<option value="fail">预约失败</option>
</select>
</div>
<div class="scroll-content">
<div class="page-body">
<!-- 步骤条:全部完成(冠脉CTA免问卷,仅两步) -->
<div class="stepper">
<div class="stepper__item stepper__item--done" onclick="showToast()"><div class="stepper__dot">&#10003;</div><div class="stepper__label">选择医院</div></div>
<div class="stepper__line stepper__line--done"></div>
<div class="stepper__item stepper__item--done" onclick="showToast()"><div class="stepper__dot">&#10003;</div><div class="stepper__label">预约日期</div></div>
</div>
<!-- [交互] 预约结果横幅:成功/失败两态,由右上角演示切换器控制 -->
<div class="result-banner result-banner--success" id="resultBanner">
<div class="result-banner__icon">
<svg class="icon-check" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>
<svg class="icon-cross" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
</div>
<div>
<div class="result-banner__title" id="resultTitle">预约成功</div>
<div class="result-banner__sub" id="resultSub">已为您锁定冠脉CTA检查名额,请按预约日期准时到检</div>
<div class="result-banner__reason">
<span>失败原因:所选日期号源已约满</span>
<span class="reason-help" onclick="openReasonModal()">?</span>
</div>
</div>
</div>
<!-- 预约信息 -->
<div class="info-card">
<div class="section-title">预约信息</div>
<div class="info-card__row">
<span class="info-card__label">体检医院</span>
<span class="info-card__value">宁夏宝石花医院</span>
</div>
<div class="info-card__row">
<span class="info-card__label">体检员工</span>
<span class="info-card__value">刘韵琴</span>
</div>
<div class="info-card__row">
<span class="info-card__label">体检地址</span>
<span class="info-card__value">银川市西夏区怀远路148号</span>
</div>
<div class="info-card__row">
<span class="info-card__label">体检日期</span>
<span class="info-card__value info-card__value--highlight">2026年3月23日</span>
</div>
<div class="info-card__row">
<span class="info-card__label">体检项目</span>
<span class="info-card__value info-card__value--highlight">冠脉CTA体检</span>
</div>
</div>
<!-- [交互] 体检须知:仅预约成功态显示,失败态隐藏 -->
<div class="tips-card" id="tipsCard">
<div class="tips-card__title">体检须知</div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查前24小时请避免剧烈运动,检查当天避免吸烟,勿饮用咖啡、浓茶等刺激性饮品。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>心率过快或心律不齐者,请遵医嘱在检查前服用控制心率药物(如β受体阻滞剂)。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查需屏气配合,请提前练习平静状态下屏气10~15秒。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>对碘对比剂过敏、甲状腺功能异常、肾功能不全或妊娠期,请提前告知医生。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>请携带本人身份证件按时前往医院。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>若需取消预约,请至少提前一天操作。</span></div>
</div>
</div>
</div>
<!-- [交互] 预约成功态底部按钮 -->
<div class="bottom-actions" id="actionsSuccess">
<!-- [交互] 取消预约改为二次确认弹窗,需选择或填写取消原因 -->
<button class="bottom-actions__btn bottom-actions__btn--ghost" onclick="openCancelModal()">取消预约</button>
<button class="bottom-actions__btn bottom-actions__btn--primary" onclick="window.location.href='my-appointments-all.html?type=cta'">查看预约详情</button>
</div>
<!-- [交互] 预约失败态底部按钮:重新预约,跳回冠脉CTA预约日期页 -->
<div class="bottom-actions" id="actionsFail" style="display: none;">
<button class="bottom-actions__btn bottom-actions__btn--primary" onclick="window.location.href='cta-date.html'">重新预约</button>
</div>
<div class="toast" id="stepToast">当前已预约冠脉CTA检查,无法重新选择,请先取消预约</div>
<!-- [交互] 点击失败原因旁的小问号,弹窗查看具体失败原因 -->
<div class="modal-overlay hidden" id="reasonModal">
<div class="reason-modal">
<div class="reason-modal__title">失败原因详情</div>
<div class="reason-modal__item">
<div class="reason-modal__label">失败原因</div>
<div class="reason-modal__text reason-modal__text--danger">号源争抢失败:宁夏宝石花医院 2026年3月23日 冠脉CTA检查号源已被其他员工约满</div>
</div>
<div class="reason-modal__item">
<div class="reason-modal__label">发生时间</div>
<div class="reason-modal__text">2026-03-16 12:00:35</div>
</div>
<div class="reason-modal__item">
<div class="reason-modal__label">处理建议</div>
<div class="reason-modal__text">请点击「重新预约」选择其他可约日期;冠脉CTA检查仅可预约 7~30 天内的号源,若长期无可用号源,可联系健康管理专员协调加号。</div>
</div>
<button class="reason-modal__btn" onclick="closeReasonModal()">知道了</button>
</div>
</div>
<!-- [交互] 取消预约二次确认:单选原因chips,选「其他」时填写具体原因 -->
<div class="modal-overlay hidden" id="cancelModal">
<div class="cancel-modal">
<div class="cancel-modal__title">确认取消预约</div>
<div class="cancel-modal__desc">取消后名额将释放,如仍需检查请重新预约</div>
<div class="cancel-modal__order">宁夏宝石花医院 · 2026年3月23日</div>
<div class="cancel-modal__label">请选择取消原因 <em>*</em></div>
<div class="chips" id="cancelChips">
<span class="chip" data-reason="时间冲突" onclick="selectChip(this)">时间冲突</span>
<span class="chip" data-reason="医院选择不当" onclick="selectChip(this)">医院选择不当</span>
<span class="chip" data-reason="日期选择不当" onclick="selectChip(this)">日期选择不当</span>
<span class="chip" data-reason="个人健康原因" onclick="selectChip(this)">个人健康原因</span>
<span class="chip" data-reason="other" onclick="selectChip(this)">其他</span>
</div>
<textarea class="other-input" id="otherInput" rows="2" maxlength="100" placeholder="请填写取消原因(必填)"></textarea>
<div class="cancel-modal__err" id="cancelErr">请选择或填写取消原因</div>
<div class="cancel-modal__actions">
<button class="cancel-modal__btn cancel-modal__btn--ghost" onclick="closeCancelModal()">再想想</button>
<button class="cancel-modal__btn cancel-modal__btn--danger" onclick="confirmCancel()">确认取消</button>
</div>
</div>
</div>
</div>
<script>
var toastTimer = null;
function showToast() {
var toast = document.getElementById('stepToast');
toast.classList.add('show');
clearTimeout(toastTimer);
toastTimer = setTimeout(function() { toast.classList.remove('show'); }, 2200);
}
// [交互] 原型演示:切换预约成功/失败两态(横幅、底部按钮、体检须知联动)
function setResult(state) {
var fail = state === 'fail';
var banner = document.getElementById('resultBanner');
banner.classList.toggle('result-banner--fail', fail);
banner.classList.toggle('result-banner--success', !fail);
document.getElementById('resultTitle').textContent = fail ? '预约失败' : '预约成功';
document.getElementById('resultSub').style.display = fail ? 'none' : '';
document.getElementById('actionsSuccess').style.display = fail ? 'none' : 'flex';
document.getElementById('actionsFail').style.display = fail ? 'flex' : 'none';
// 预约失败时隐藏体检须知(未成功到检,须知无意义)
document.getElementById('tipsCard').style.display = fail ? 'none' : '';
document.getElementById('stepToast').textContent = fail
? '预约未成功,请点击下方「重新预约」按钮重新预约'
: '当前已预约冠脉CTA检查,无法重新选择,请先取消预约';
}
function openReasonModal() {
document.getElementById('reasonModal').classList.remove('hidden');
}
function closeReasonModal() {
document.getElementById('reasonModal').classList.add('hidden');
}
// [交互] 取消预约二次确认:原因单选 + 其他原因填写 + 校验 + 确认后返回预约日期页重新选择
var cancelReason = null;
function selectChip(el) {
var chips = document.querySelectorAll('#cancelChips .chip');
for (var i = 0; i < chips.length; i++) chips[i].classList.remove('selected');
el.classList.add('selected');
cancelReason = el.dataset.reason;
document.getElementById('otherInput').classList.toggle('show', cancelReason === 'other');
hideCancelErr();
}
function hideCancelErr() {
document.getElementById('cancelErr').classList.remove('show');
}
function openCancelModal() {
cancelReason = null;
var chips = document.querySelectorAll('#cancelChips .chip');
for (var i = 0; i < chips.length; i++) chips[i].classList.remove('selected');
var input = document.getElementById('otherInput');
input.value = '';
input.classList.remove('show');
hideCancelErr();
document.getElementById('cancelModal').classList.remove('hidden');
}
function closeCancelModal() {
document.getElementById('cancelModal').classList.add('hidden');
}
function confirmCancel() {
var input = document.getElementById('otherInput');
if (!cancelReason || (cancelReason === 'other' && !input.value.trim())) {
document.getElementById('cancelErr').classList.add('show');
return;
}
closeCancelModal();
var toast = document.getElementById('stepToast');
toast.textContent = '预约已取消';
showToast();
setTimeout(function() {
window.location.href = 'cta-date.html';
}, 1200);
}
</script>
</body>
</html>
+350
View File
@@ -0,0 +1,350 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>冠脉CTA预约 - 预约日期</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary: #13c2c2;
--primary-dark: #0f9b9b;
--primary-light: #e6fffb;
--text-primary: #1a1a1a;
--text-secondary: #666666;
--text-muted: #8c8c8c;
--border: #e8f3f3;
--bg-page: #f0f2f5;
--bg-content: #f7f9fb;
--shadow: 0 10px 30px rgba(19, 194, 194, 0.08);
}
body {
background: var(--bg-page); display: flex; justify-content: center;
align-items: flex-start; min-height: 100vh; padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
color: var(--text-primary);
}
.phone-shell {
width: 390px; min-height: 844px; background: var(--bg-content);
border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
overflow: hidden; position: relative; display: flex; flex-direction: column;
}
.phone-status-bar {
height: 44px; background: #fff; display: flex; align-items: center;
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
.nav-bar {
height: 44px; display: flex; align-items: center; padding: 0 16px;
background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative;
}
.nav-back { font-size: 18px; color: var(--text-primary); cursor: pointer; line-height: 1; text-decoration: none; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: var(--text-primary); }
.scroll-content { flex: 1; overflow-y: auto; background: linear-gradient(180deg, #effbfb 0%, #f7f9fb 180px, #f7f9fb 100%); padding-bottom: 120px; }
.scroll-content::-webkit-scrollbar { display: none; }
.page-body { padding: 16px; }
.stepper { display: flex; align-items: center; justify-content: center; margin-bottom: 18px; padding: 16px 0; }
.stepper__item { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; text-decoration: none; }
.stepper__item--future { cursor: default; pointer-events: none; opacity: 0.45; }
.stepper__dot {
width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; background: #e8e8e8; color: #bfbfbf; transition: all 0.25s;
}
.stepper__item--done .stepper__dot { background: var(--primary); color: #fff; }
.stepper__item--active { cursor: default; pointer-events: none; }
.stepper__item--active .stepper__dot {
width: 34px; height: 34px; font-size: 14px;
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff;
box-shadow: 0 0 0 6px rgba(19,194,194,0.2);
}
.stepper__label { font-size: 12px; color: var(--text-muted); white-space: nowrap; transition: all 0.2s; }
.stepper__item--done .stepper__label { color: var(--primary-dark); }
.stepper__item--active .stepper__label {
color: var(--primary-dark); font-weight: 700; font-size: 13px;
background: var(--primary-light); padding: 2px 10px; border-radius: 10px;
}
.stepper__item--done:hover .stepper__dot { transform: scale(1.12); box-shadow: 0 0 0 4px rgba(19,194,194,0.15); }
.stepper__item--done:hover .stepper__label { text-decoration: underline; text-underline-offset: 3px; }
.stepper__line { width: 44px; height: 3px; background: #e8e8e8; margin: 0 8px; margin-bottom: 22px; border-radius: 2px; }
.stepper__line--done { background: var(--primary); }
.section-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; margin-top: 6px; }
.summary-card {
background: #fff; border-radius: 20px; padding: 18px 16px; margin-bottom: 14px;
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
}
.summary-list { display: flex; flex-direction: column; gap: 14px; }
.summary-item { display: flex; justify-content: space-between; gap: 12px; }
.summary-item__label { font-size: 13px; color: var(--text-muted); flex-shrink: 0; }
.summary-item__value { font-size: 14px; font-weight: 600; text-align: right; line-height: 1.6; }
/* 预约状态条 */
.status-card {
background: #fff; border-radius: 20px; padding: 14px 16px; margin-bottom: 14px;
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
}
.status-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.status-badge {
display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700;
padding: 4px 12px; border-radius: 12px; flex-shrink: 0;
}
.status-badge--open { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
.status-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: #52c41a; }
.status-range { font-size: 12px; color: var(--text-secondary); font-weight: 600; }
.status-tip {
display: flex; align-items: center; gap: 6px; margin-top: 10px; padding-top: 10px;
border-top: 1px dashed #f0f0f0; font-size: 12px; color: var(--text-muted); line-height: 1.5;
}
.status-tip svg { flex-shrink: 0; }
.date-card {
background: #fff; border-radius: 20px; padding: 18px 16px;
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
}
.calendar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
.calendar-header__month { font-size: 17px; font-weight: 700; color: var(--text-primary); }
.calendar-header__nav { display: flex; gap: 8px; }
.calendar-header__btn {
width: 32px; height: 32px; border-radius: 10px; border: 1px solid #e8e8e8;
background: #fff; display: flex; align-items: center; justify-content: center;
cursor: pointer; font-size: 14px; color: var(--text-secondary); transition: all 0.2s;
}
.calendar-header__btn:hover { border-color: var(--primary); color: var(--primary); }
.calendar-header__btn:disabled { opacity: 0.3; pointer-events: none; }
.calendar-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; margin-bottom: 8px; }
.calendar-weekday { text-align: center; font-size: 12px; font-weight: 600; color: var(--text-muted); padding: 6px 0; }
.calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.calendar-cell {
display: flex; flex-direction: column; align-items: center; justify-content: center;
height: 52px; border-radius: 12px; cursor: pointer; transition: all 0.2s;
border: 2px solid transparent; background: #f9fbfb; position: relative;
}
.calendar-cell:hover { border-color: var(--primary); }
.calendar-cell.selected { background: var(--primary); border-color: var(--primary); }
.calendar-cell.selected .calendar-cell__day,
.calendar-cell.selected .calendar-cell__slots { color: #fff; }
.calendar-cell.disabled { opacity: 0.3; pointer-events: none; background: #f5f5f5; }
.calendar-cell.empty { background: transparent; pointer-events: none; }
.calendar-cell__day { font-size: 15px; font-weight: 700; color: var(--text-primary); line-height: 1; }
.calendar-cell__slots { font-size: 10px; color: var(--primary-dark); font-weight: 600; margin-top: 2px; }
.calendar-cell__full { font-size: 10px; color: var(--text-muted); font-weight: 600; margin-top: 2px; }
.calendar-cell.today .calendar-cell__day { color: var(--primary-dark); }
.calendar-cell.today { border-color: rgba(19,194,194,0.3); }
.bottom-actions {
position: absolute; left: 16px; right: 16px; bottom: 18px;
display: flex; gap: 12px; padding-bottom: 16px;
}
.bottom-actions__btn { flex: 1; height: 48px; border-radius: 24px; font-size: 15px; font-weight: 600; border: none; cursor: pointer; }
.bottom-actions__btn--ghost { background: #fff; color: var(--primary-dark); border: 2px solid #d0eded; }
.bottom-actions__btn--primary {
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
color: #fff; box-shadow: 0 10px 20px rgba(19,194,194,0.22);
}
.modal-overlay {
position: absolute; inset: 0; background: rgba(0,0,0,0.42); z-index: 120;
display: flex; align-items: center; justify-content: center; padding: 24px;
}
.modal-overlay.hidden { display: none; }
.confirm-modal { width: 100%; background: #fff; border-radius: 24px; padding: 22px 20px 18px; box-shadow: 0 20px 50px rgba(0,0,0,0.16); }
.confirm-modal__title { font-size: 18px; font-weight: 700; text-align: center; margin-bottom: 8px; }
.confirm-modal__desc { font-size: 13px; color: var(--text-muted); text-align: center; line-height: 1.6; margin-bottom: 18px; }
.confirm-modal__info { background: #f7f9fb; border-radius: 16px; padding: 14px 16px; margin-bottom: 18px; }
.confirm-modal__row { display: flex; justify-content: space-between; align-items: center; font-size: 14px; color: var(--text-secondary); margin-bottom: 12px; }
.confirm-modal__row:last-child { margin-bottom: 0; }
.confirm-modal__value { font-size: 15px; font-weight: 700; color: var(--text-primary); }
.confirm-modal__value--highlight { color: var(--primary-dark); }
.confirm-modal__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.confirm-modal__btn { height: 44px; border-radius: 22px; font-size: 15px; font-weight: 600; border: none; cursor: pointer; }
.confirm-modal__btn--ghost { background: #f5f5f5; color: var(--text-secondary); }
.confirm-modal__btn--primary { background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff; }
.toast {
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(0.9);
background: rgba(0,0,0,0.75); color: #fff; padding: 14px 22px; border-radius: 12px;
font-size: 13px; line-height: 1.6; text-align: center; z-index: 200;
opacity: 0; pointer-events: none; transition: all 0.25s ease; max-width: 280px;
}
.toast.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
</style>
</head>
<body>
<div class="phone-shell">
<div class="phone-status-bar">
<span class="time">12:00</span>
<div class="icons">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
</div>
</div>
<div class="nav-bar">
<a class="nav-back" href="cta-hospital.html">&#8249;</a>
<span class="nav-title">冠脉CTA预约</span>
</div>
<div class="scroll-content">
<div class="page-body">
<div class="stepper">
<a class="stepper__item stepper__item--done" href="cta-hospital.html"><div class="stepper__dot">&#10003;</div><div class="stepper__label">选择医院</div></a>
<div class="stepper__line stepper__line--done"></div>
<div class="stepper__item stepper__item--active"><div class="stepper__dot">2</div><div class="stepper__label">预约日期</div></div>
</div>
<div class="summary-card">
<div class="section-title">预约信息</div>
<div class="summary-list">
<div class="summary-item"><div class="summary-item__label">体检类型</div><div class="summary-item__value">冠脉CTA体检</div></div>
<div class="summary-item"><div class="summary-item__label">体检医院</div><div class="summary-item__value">宁夏宝石花医院</div></div>
</div>
</div>
<!-- [交互] 预约状态与可预约日期范围,日期范围由脚本按「最早7天后」规则动态生成 -->
<div class="status-card">
<div class="status-row">
<span class="status-badge status-badge--open"><span class="status-badge__dot"></span>可预约</span>
<span class="status-range" id="rangeText"></span>
</div>
<div class="status-tip">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8c8c8c" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
<span>冠脉CTA检查需提前预约,最早仅可预约7天后的日期,超出范围日期不可选择</span>
</div>
</div>
<div class="date-card">
<div class="calendar-header">
<span class="calendar-header__month" id="calendarMonth"></span>
<div class="calendar-header__nav">
<button class="calendar-header__btn" id="prevMonth">&#8249;</button>
<button class="calendar-header__btn" id="nextMonth">&#8250;</button>
</div>
</div>
<div class="calendar-weekdays">
<span class="calendar-weekday"></span><span class="calendar-weekday"></span>
<span class="calendar-weekday"></span><span class="calendar-weekday"></span>
<span class="calendar-weekday"></span><span class="calendar-weekday"></span>
<span class="calendar-weekday"></span>
</div>
<div class="calendar-grid" id="calendarGrid"></div>
</div>
</div>
</div>
<div class="bottom-actions">
<button class="bottom-actions__btn bottom-actions__btn--ghost" onclick="location.href='cta-hospital.html'">上一步</button>
<button class="bottom-actions__btn bottom-actions__btn--primary" onclick="openConfirm()">确定预约</button>
</div>
<div class="modal-overlay hidden" id="confirmModal">
<div class="confirm-modal">
<div class="confirm-modal__title">确认预约信息</div>
<div class="confirm-modal__desc">请确认以下冠脉CTA预约信息无误</div>
<div class="confirm-modal__info">
<div class="confirm-modal__row"><span>体检类型</span><span class="confirm-modal__value">冠脉CTA体检</span></div>
<div class="confirm-modal__row"><span>体检医院</span><span class="confirm-modal__value">宁夏宝石花医院</span></div>
<div class="confirm-modal__row"><span>预约日期</span><span class="confirm-modal__value confirm-modal__value--highlight" id="confirmDate">--</span></div>
</div>
<div class="confirm-modal__actions">
<button class="confirm-modal__btn confirm-modal__btn--ghost" onclick="closeConfirm()">取消</button>
<button class="confirm-modal__btn confirm-modal__btn--primary" onclick="showSuccessToast()">确认预约</button>
</div>
</div>
</div>
<div class="toast" id="successToast">预约成功!请按时前往医院进行冠脉CTA检查</div>
</div>
<script>
var today = new Date(2026, 2, 16);
// 冠脉CTA预约窗口:最早7天后,最晚30天后
var minBookDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
var maxBookDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
function fmtDate(d) {
var m = d.getMonth() + 1; var day = d.getDate();
return d.getFullYear() + '-' + (m < 10 ? '0' + m : m) + '-' + (day < 10 ? '0' + day : day);
}
document.getElementById('rangeText').textContent =
'可预约日期:' + fmtDate(minBookDate) + ' 至 ' + fmtDate(maxBookDate);
var currentYear = today.getFullYear();
var currentMonth = today.getMonth();
var selectedDate = null;
var grid = document.getElementById('calendarGrid');
var monthLabel = document.getElementById('calendarMonth');
var prevBtn = document.getElementById('prevMonth');
var nextBtn = document.getElementById('nextMonth');
var toastTimer = null;
function getSlots(year, month, day) {
var d = new Date(year, month, day);
var dow = d.getDay();
// 早于7天后或超出30天窗口均不可约
if (d < minBookDate) return -1;
if (d > maxBookDate) return -1;
if (dow === 0 || dow === 6) return 0;
var seed = (day * 7 + month * 13) % 20;
if (seed < 3) return 0;
return seed + 2;
}
function renderCalendar() {
grid.innerHTML = '';
monthLabel.textContent = currentYear + '年' + (currentMonth + 1) + '月';
prevBtn.disabled = (currentYear === minBookDate.getFullYear() && currentMonth <= minBookDate.getMonth());
nextBtn.disabled = (currentYear > maxBookDate.getFullYear()) ||
(currentYear === maxBookDate.getFullYear() && currentMonth >= maxBookDate.getMonth());
var firstDay = new Date(currentYear, currentMonth, 1);
var startDow = firstDay.getDay();
startDow = startDow === 0 ? 6 : startDow - 1;
var daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
for (var i = 0; i < startDow; i++) {
var empty = document.createElement('div');
empty.className = 'calendar-cell empty';
grid.appendChild(empty);
}
for (var day = 1; day <= daysInMonth; day++) {
(function(d) {
var cell = document.createElement('div');
var slots = getSlots(currentYear, currentMonth, d);
var isToday = (currentYear === today.getFullYear() && currentMonth === today.getMonth() && d === today.getDate());
var isDisabled = slots <= 0;
var isFull = slots === 0;
var isPast = slots === -1;
var cls = 'calendar-cell';
if (isToday) cls += ' today';
if (isDisabled) cls += ' disabled';
if (selectedDate && selectedDate.y === currentYear && selectedDate.m === currentMonth && selectedDate.d === d) cls += ' selected';
cell.className = cls;
var slotsHtml = '';
if (isPast) slotsHtml = '';
else if (isFull) slotsHtml = '<span class="calendar-cell__full">不可约</span>';
else if (slots > 0) slotsHtml = '<span class="calendar-cell__slots">余' + slots + '</span>';
cell.innerHTML = '<span class="calendar-cell__day">' + d + '</span>' + slotsHtml;
if (!isDisabled) {
cell.addEventListener('click', function() {
selectedDate = { y: currentYear, m: currentMonth, d: d };
renderCalendar();
});
}
grid.appendChild(cell);
})(day);
}
}
prevBtn.addEventListener('click', function() {
currentMonth--;
if (currentMonth < 0) { currentMonth = 11; currentYear--; }
renderCalendar();
});
nextBtn.addEventListener('click', function() {
currentMonth++;
if (currentMonth > 11) { currentMonth = 0; currentYear++; }
renderCalendar();
});
// 默认选中最早可预约日期(7天后)
selectedDate = { y: minBookDate.getFullYear(), m: minBookDate.getMonth(), d: minBookDate.getDate() };
renderCalendar();
function openConfirm() {
if (!selectedDate) return;
document.getElementById('confirmDate').textContent = selectedDate.y + '年' + (selectedDate.m + 1) + '月' + selectedDate.d + '日';
document.getElementById('confirmModal').classList.remove('hidden');
}
function closeConfirm() { document.getElementById('confirmModal').classList.add('hidden'); }
function showSuccessToast() {
closeConfirm();
window.location.href = 'cta-date-selected.html';
}
</script>
</body>
</html>
@@ -0,0 +1,220 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>冠脉CTA预约</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary: #13c2c2;
--primary-dark: #0f9b9b;
--primary-light: #e6fffb;
--text-primary: #1a1a1a;
--text-secondary: #666666;
--text-muted: #8c8c8c;
--border: #e8f3f3;
--bg-page: #f0f2f5;
--bg-content: #f7f9fb;
--shadow: 0 10px 30px rgba(19, 194, 194, 0.08);
}
body {
background: var(--bg-page);
display: flex;
justify-content: center;
align-items: flex-start;
min-height: 100vh;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
color: var(--text-primary);
}
.phone-shell {
width: 390px; min-height: 844px; background: var(--bg-content);
border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
overflow: hidden; position: relative; display: flex; flex-direction: column;
}
.phone-status-bar {
height: 44px; background: #fff; display: flex; align-items: center;
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
.nav-bar {
height: 44px; display: flex; align-items: center; padding: 0 16px;
background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative;
}
.nav-back { font-size: 18px; color: var(--text-primary); cursor: pointer; line-height: 1; text-decoration: none; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: var(--text-primary); }
.nav-right {
position: absolute; right: 16px; font-size: 13px; color: var(--primary);
font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 4px;
}
.scroll-content { flex: 1; overflow-y: auto; background: linear-gradient(180deg, #effbfb 0%, #f7f9fb 180px, #f7f9fb 100%); padding-bottom: 120px; }
.scroll-content::-webkit-scrollbar { display: none; }
.page-body { padding: 16px; }
.stepper { display: flex; align-items: center; justify-content: center; margin-bottom: 18px; padding: 16px 0; }
.stepper__item { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; text-decoration: none; }
.stepper__item--future { cursor: default; pointer-events: none; opacity: 0.45; }
.stepper__dot {
width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; background: #e8e8e8; color: #bfbfbf; transition: all 0.25s;
}
.stepper__item--done .stepper__dot { background: var(--primary); color: #fff; }
.stepper__item--active { cursor: default; pointer-events: none; }
.stepper__item--active .stepper__dot {
width: 34px; height: 34px; font-size: 14px;
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff;
box-shadow: 0 0 0 6px rgba(19,194,194,0.2);
}
.stepper__label { font-size: 12px; color: var(--text-muted); white-space: nowrap; transition: all 0.2s; }
.stepper__item--done .stepper__label { color: var(--primary-dark); }
.stepper__item--active .stepper__label {
color: var(--primary-dark); font-weight: 700; font-size: 13px;
background: var(--primary-light); padding: 2px 10px; border-radius: 10px;
}
.stepper__line { width: 44px; height: 3px; background: #e8e8e8; margin: 0 8px; margin-bottom: 22px; border-radius: 2px; }
.stepper__line--done { background: var(--primary); }
.section-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; margin-top: 6px; }
.hospital-card {
background: #fff; border-radius: 18px; padding: 16px; margin-bottom: 12px;
border: 2px solid transparent; box-shadow: var(--shadow); cursor: pointer;
display: flex; align-items: center; justify-content: space-between; transition: all 0.25s ease;
}
.hospital-card.active { border-color: var(--primary); background: var(--primary-light); }
.hospital-card__info { display: flex; align-items: center; gap: 12px; }
.hospital-card__icon {
width: 42px; height: 42px; border-radius: 14px;
background: linear-gradient(135deg, #e6fffb 0%, #b5f5ec 100%);
display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0;
}
.hospital-card__name { font-size: 15px; font-weight: 600; color: var(--text-primary); margin-bottom: 2px; }
.hospital-card__addr { font-size: 12px; color: var(--text-muted); }
.radio-dot {
width: 22px; height: 22px; border-radius: 50%; border: 2px solid #d9d9d9;
display: flex; align-items: center; justify-content: center; transition: all 0.25s ease; flex-shrink: 0;
}
.hospital-card.active .radio-dot { border-color: var(--primary); background: var(--primary); }
.radio-dot::after { content: ''; width: 8px; height: 8px; border-radius: 50%; background: #fff; opacity: 0; transition: opacity 0.25s ease; }
.hospital-card.active .radio-dot::after { opacity: 1; }
.bottom-actions { position: absolute; left: 16px; right: 16px; bottom: 18px; padding-bottom: 16px; }
.bottom-actions__btn {
width: 100%; height: 48px; border-radius: 24px; font-size: 15px; font-weight: 600;
border: none; cursor: pointer; background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
color: #fff; box-shadow: 0 10px 20px rgba(19, 194, 194, 0.22);
}
.modal-overlay {
position: absolute; inset: 0; background: rgba(0,0,0,0.45); z-index: 100;
display: flex; align-items: center; justify-content: center;
}
.modal-overlay.hidden { display: none; }
.modal-card { width: 340px; background: #fff; border-radius: 24px; padding: 24px 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.18); }
.modal-card__title { font-size: 18px; font-weight: 700; text-align: center; margin-bottom: 6px; }
.modal-card__sub { font-size: 13px; color: var(--text-muted); text-align: center; margin-bottom: 20px; }
.modal-field { display: flex; justify-content: space-between; align-items: center; padding: 14px 0; border-bottom: 1px solid #f0f0f0; }
.modal-field:last-of-type { border-bottom: none; }
.modal-field__label { font-size: 14px; color: var(--text-muted); }
.modal-field__value { font-size: 14px; color: var(--text-primary); font-weight: 600; }
.modal-confirm-btn {
margin-top: 20px; width: 100%; height: 44px; border-radius: 22px; font-size: 15px; font-weight: 600;
border: none; cursor: pointer; background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
color: #fff; box-shadow: 0 8px 20px rgba(19, 194, 194, 0.2);
}
</style>
</head>
<body>
<div class="phone-shell">
<div class="phone-status-bar">
<span class="time">12:00</span>
<div class="icons">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
</div>
</div>
<div class="nav-bar">
<a class="nav-back" href="booking-type.html">&#8249;</a>
<span class="nav-title">冠脉CTA预约</span>
<span class="nav-right" onclick="openModal()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
个人信息
</span>
</div>
<div class="scroll-content">
<div class="page-body">
<!-- 冠脉CTA免问卷:仅「选择医院 → 预约日期」两步 -->
<div class="stepper">
<a class="stepper__item stepper__item--active" href="cta-hospital.html"><div class="stepper__dot">1</div><div class="stepper__label">选择医院</div></a>
<div class="stepper__line"></div>
<div class="stepper__item stepper__item--future"><div class="stepper__dot">2</div><div class="stepper__label">预约日期</div></div>
</div>
<div class="section-title">选择医院</div>
<div class="hospital-card active" onclick="selectHospital(this)">
<div class="hospital-card__info">
<div class="hospital-card__icon">🏥</div>
<div>
<div class="hospital-card__name">宁夏宝石花医院</div>
<div class="hospital-card__addr">宁夏银川市</div>
</div>
</div>
<div class="radio-dot"></div>
</div>
<div class="hospital-card" onclick="selectHospital(this)">
<div class="hospital-card__info">
<div class="hospital-card__icon">🏥</div>
<div>
<div class="hospital-card__name">CQ星龙园医院</div>
<div class="hospital-card__addr">陕西西安市</div>
</div>
</div>
<div class="radio-dot"></div>
</div>
<div class="hospital-card" onclick="selectHospital(this)">
<div class="hospital-card__info">
<div class="hospital-card__icon">🏥</div>
<div>
<div class="hospital-card__name">唐都医院</div>
<div class="hospital-card__addr">陕西西安市</div>
</div>
</div>
<div class="radio-dot"></div>
</div>
</div>
</div>
<div class="bottom-actions">
<button class="bottom-actions__btn" onclick="goNext()">下一步</button>
</div>
<div class="modal-overlay hidden" id="personModal">
<div class="modal-card">
<div class="modal-card__title">确认个人信息</div>
<div class="modal-card__sub">请核对以下信息,确认无误后继续预约</div>
<div class="modal-field"><span class="modal-field__label">姓名</span><span class="modal-field__value">刘韵琴</span></div>
<div class="modal-field"><span class="modal-field__label">单位</span><span class="modal-field__value">CQ能源第一采油厂</span></div>
<div class="modal-field"><span class="modal-field__label">身份证号</span><span class="modal-field__value">6101021994********</span></div>
<div class="modal-field"><span class="modal-field__label">性别</span><span class="modal-field__value"></span></div>
<div class="modal-field"><span class="modal-field__label">年龄</span><span class="modal-field__value">32</span></div>
<button class="modal-confirm-btn" onclick="closeModal()">确认</button>
</div>
</div>
</div>
<script>
if (new URLSearchParams(window.location.search).get('from') === 'booking-type') {
document.getElementById('personModal').classList.remove('hidden');
}
function selectHospital(el) {
document.querySelectorAll('.hospital-card').forEach(c => c.classList.remove('active'));
el.classList.add('active');
}
// [交互] 冠脉CTA无问卷环节,选择医院后直接进入预约日期
function goNext() {
location.href = 'cta-date.html';
}
function openModal() { document.getElementById('personModal').classList.remove('hidden'); }
function closeModal() { document.getElementById('personModal').classList.add('hidden'); }
</script>
</body>
</html>
+27 -4
View File
@@ -100,7 +100,7 @@
}
.scroll-content::-webkit-scrollbar { display: none; }
.page-body { padding: 16px; }
/* 年度体检计划 Banner 轮播:常规体检 / 胃肠镜体检 / 未开启计划占位,共张滑动切换 */
/* 年度体检计划 Banner 轮播:常规体检 / 胃肠镜体检 / 冠脉CTA体检 / 未开启计划占位,共张滑动切换 */
.banner {
position: relative;
border-radius: 20px;
@@ -127,6 +127,8 @@
}
.banner-slide--routine { background: linear-gradient(135deg, #0eb5b0 0%, #35d6c5 100%); }
.banner-slide--gastro { background: linear-gradient(135deg, #12a5c4 0%, #3cc3dc 100%); }
/* 冠脉CTA体检:暖红渐变,呼应心脏/冠脉意象,与青绿的常规、蓝青的胃肠镜区分 */
.banner-slide--cta { background: linear-gradient(135deg, #e8544f 0%, #ff8a65 100%); }
.banner-slide--waiting { background: linear-gradient(135deg, #93a1b3 0%, #c3ccd8 100%); }
/* 右侧大号水印图标 + 圆环装饰,营造 banner 图氛围 */
.banner-slide__deco {
@@ -454,7 +456,7 @@
<div class="scroll-content">
<div class="page-body">
<!-- [交互] 左右滑动切换张计划 Banner,点击圆点跳转到对应张 -->
<!-- [交互] 左右滑动切换张计划 Banner,点击圆点跳转到对应张 -->
<div class="banner">
<div class="banner__track" id="bannerTrack">
<!-- 第一张:常规体检 | [交互] 点击进入: reports.html(已体检,查看报告) -->
@@ -492,7 +494,23 @@
</div>
</div>
<!-- 第三张:未开启年度体检计划占位图 -->
<!-- 第三张:冠脉CTA体检 | [交互] 点击进入: my-appointments-all.html?type=cta(已预约,查看预约) -->
<div class="banner-slide banner-slide--cta" onclick="location.href='my-appointments-all.html?type=cta'">
<span class="banner-slide__ring"></span>
<span class="banner-slide__deco">🫀</span>
<div class="banner-slide__title">单位已拟定2026年度冠脉CTA体检计划</div>
<div class="banner-slide__date">🗓 体检日期:2026-10-08 至 2026-12-20</div>
<!-- 圆圈进度(右下角):已预约 = 60%(已选项目20%→已预约60%→体检中80%→已体检100%),dashoffset = 131.9 × 40% ≈ 52.8 -->
<div class="banner-progress">
<svg width="52" height="52" viewBox="0 0 52 52" fill="none">
<circle cx="26" cy="26" r="21" stroke="rgba(255,255,255,0.35)" stroke-width="4"/>
<circle cx="26" cy="26" r="21" stroke="#ffffff" stroke-width="4" stroke-linecap="round" stroke-dasharray="131.9" stroke-dashoffset="52.8" transform="rotate(-90 26 26)"/>
</svg>
<span class="banner-progress__text">已预约</span>
</div>
</div>
<!-- 第四张:未开启年度体检计划占位图 -->
<div class="banner-slide banner-slide--waiting">
<span class="banner-slide__deco">🌱</span>
<div class="banner-waiting__icon">🌱</div>
@@ -505,6 +523,7 @@
<span class="banner__dot is-active"></span>
<span class="banner__dot"></span>
<span class="banner__dot"></span>
<span class="banner__dot"></span>
</div>
<!-- [交互] 胃肠镜医院预选通知条:仅管理员开启预选计划期间展示;
@@ -601,11 +620,15 @@
(function () {
var track = document.getElementById('bannerTrack');
var dots = document.querySelectorAll('#bannerDots .banner__dot');
// 各张计划对应的圆点主色(常规青绿/胃肠镜蓝青/冠脉CTA暖红/占位灰)
var DOT_COLORS = ['#13c2c2', '#12a5c4', '#e8544f', '#93a1b3'];
// 滚动时按滚动位置判定当前展示张数,同步高亮圆点
track.addEventListener('scroll', function () {
var index = Math.round(track.scrollLeft / track.clientWidth);
dots.forEach(function (dot, i) {
dot.classList.toggle('is-active', i === index);
var active = i === index;
dot.classList.toggle('is-active', active);
dot.style.background = active ? DOT_COLORS[index] : '';
});
});
// 点击圆点平滑滚动到对应张
@@ -119,6 +119,29 @@
}
.hero-card__title { font-size: 14px; font-weight: 700; color: #0d7878; }
.hero-card__range { margin-left: auto; font-size: 10px; color: var(--text-muted); }
/* 年份区间选择器:开始/结束两个下拉,选项互相联动保证区间合法 */
.year-picker__sep { font-size: 10px; color: var(--text-muted); }
.year-select {
border: 1px solid var(--border); background: #fff; border-radius: 8px;
font-size: 11px; font-weight: 700; color: var(--primary-dark);
padding: 2px 18px 2px 6px; font-family: inherit; cursor: pointer; outline: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%238c8c8c'/%3E%3C/svg%3E");
background-repeat: no-repeat; background-position: right 5px center;
}
.year-select:focus { border-color: var(--primary); }
/* 顶部年份选择条 */
.year-bar {
display: flex;
align-items: center;
gap: 8px;
background: #fff;
border: 1px solid var(--border);
border-radius: 14px;
padding: 10px 14px;
box-shadow: var(--paper-shadow);
}
.year-bar__label { font-size: 12px; font-weight: 700; color: var(--text-secondary); }
.hero-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
@@ -317,36 +340,46 @@
</div>
<div class="scroll-content">
<div class="page-body">
<!--AI 纵向总结卡 -->
<!--年份选择(置于最顶部,选择区间后整页重渲染) -->
<div class="year-bar">
<span class="year-bar__label">体检年份</span>
<select class="year-select" id="yearFrom" aria-label="开始年份"></select>
<span class="year-picker__sep">-</span>
<select class="year-select" id="yearTo" aria-label="结束年份"></select>
</div>
<!-- ② AI 纵向总结卡 -->
<div class="hero-card">
<div class="hero-card__head">
<span class="hero-card__ai-badge">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.9 5.6L19.5 10l-5.6 1.9L12 17.5l-1.9-5.6L4.5 10l5.6-1.9z"/></svg>
AI
</span>
<span class="hero-card__title">五年纵向对比总结</span>
<span class="hero-card__range">2021 - 2025</span>
<span class="hero-card__title" id="heroTitle">五年纵向对比总结</span>
</div>
<div class="hero-card__range" id="heroRangeMeta" style="margin-left:0;padding:8px 14px 0;"></div>
<div class="hero-stats">
<div class="hero-stat hero-stat--danger">
<div class="hero-stat__value">5</div>
<div class="hero-stat__label">今年异常</div>
<div class="hero-stat__value" id="statAbn">5</div>
<div class="hero-stat__label">期末异常</div>
</div>
<div class="hero-stat hero-stat--warn">
<div class="hero-stat__value">3</div>
<div class="hero-stat__label">化趋势</div>
<div class="hero-stat__value" id="statWorse">3</div>
<div class="hero-stat__label">化趋势</div>
</div>
<div class="hero-stat hero-stat--danger">
<div class="hero-stat__value">1</div>
<div class="hero-stat__value" id="statNew">1</div>
<div class="hero-stat__label">新增异常</div>
</div>
<div class="hero-stat hero-stat--success">
<div class="hero-stat__value">2</div>
<div class="hero-stat__value" id="statBetter">2</div>
<div class="hero-stat__label">转好恢复</div>
</div>
</div>
<!-- [交互] 总结文案随所选年份区间由脚本按区间数据重新生成 -->
<div class="hero-card__text">
近五年您的心脑血管代谢相关指标呈持续上行趋势:总胆固醇、甘油三酯、BMI 连续三年上升,低密度脂蛋白今年首次越限,尿酸已连续四年高于正常范围;颈部影像提示生理曲度变直已持续两年。好消息是去年轻度偏高的转氨酶(ALT/AST)今年均回归正常。建议将血脂与体重管理列为本年度健康干预的第一优先级。
<p id="heroLead"></p>
<p id="heroNotes"></p>
</div>
<div class="hero-card__ai-note">内容由 AI 基于历年体检数据生成,仅供参考,不构成诊断依据</div>
</div>
@@ -356,7 +389,6 @@
<div class="filter-row">
<button class="filter-chip is-active" data-f="all" type="button" onclick="applyFilter(this)">全部</button>
<button class="filter-chip" data-f="abn" type="button" onclick="applyFilter(this)">异常</button>
<button class="filter-chip" data-f="worse" type="button" onclick="applyFilter(this)">恶化趋势</button>
<button class="filter-chip" data-f="normal" type="button" onclick="applyFilter(this)">正常</button>
</div>
@@ -390,11 +422,11 @@
{ name: '血常规', keys: ['hgb', 'wbc', 'plt'] }
];
var NUM = {
bmi: { name: 'BMI', unit: 'kg/m²', ref: [18.5, 23.9], v: [23.1, 23.8, 24.5, 25.2, 25.8], badge: ['化趋势', 'worse'] },
bmi: { name: 'BMI', unit: 'kg/m²', ref: [18.5, 23.9], v: [23.1, 23.8, 24.5, 25.2, 25.8], badge: ['化趋势', 'worse'] },
sbp: { name: '收缩压', unit: 'mmHg', ref: [90, 139], v: [112, 115, 118, 116, 120], badge: ['平稳', 'stable'] },
dbp: { name: '舒张压', unit: 'mmHg', ref: [60, 89], v: [72, 74, 73, 76, 78], badge: ['平稳', 'stable'] },
tc: { name: '总胆固醇 TC', unit: 'mmol/L', ref: [3.1, 5.7], v: [4.62, 4.95, 5.36, 5.78, 6.10], badge: ['化趋势', 'worse'] },
tg: { name: '甘油三酯 TG', unit: 'mmol/L', ref: [0.4, 1.7], v: [1.20, 1.35, 1.55, 1.72, 2.08], badge: ['化趋势', 'worse'] },
tc: { name: '总胆固醇 TC', unit: 'mmol/L', ref: [3.1, 5.7], v: [4.62, 4.95, 5.36, 5.78, 6.10], badge: ['化趋势', 'worse'] },
tg: { name: '甘油三酯 TG', unit: 'mmol/L', ref: [0.4, 1.7], v: [1.20, 1.35, 1.55, 1.72, 2.08], badge: ['化趋势', 'worse'] },
hdl: { name: '高密度脂蛋白 HDL-C', unit: 'mmol/L', ref: [1.04, 1.55], v: [1.35, 1.30, 1.26, 1.22, 1.18], badge: ['平稳', 'stable'] },
ldl: { name: '低密度脂蛋白 LDL-C', unit: 'mmol/L', ref: [0, 3.4], v: [2.80, 3.00, 3.10, 3.35, 3.92], badge: ['新增异常', 'new'] },
glu: { name: '空腹血糖 GLU', unit: 'mmol/L', ref: [3.9, 6.1], v: [5.0, 5.1, 4.9, 5.3, 5.2], badge: ['平稳', 'stable'] },
@@ -419,59 +451,99 @@
];
function isAbn(item, vi) { return item.v[vi] < item.ref[0] || item.v[vi] > item.ref[1]; }
// 组内排序权重:异常在前,恶化 > 新增 > 连续异常 > 转好 > 平稳
// ===== 所选年份区间(原型仅有 2021-2025 五年体检数据,可选范围以此为准)=====
var sel = { from: YEARS[0], to: YEARS[YEARS.length - 1] };
function range() {
var a = YEARS.indexOf(sel.from), b = YEARS.indexOf(sel.to);
return { a: a, b: b, n: b - a + 1, ys: YEARS.slice(a, b + 1) };
}
// 取指标在当前区间内的数值序列
function vals(it) { var r = range(); return it.v.slice(r.a, r.b + 1); }
// 区间内是否呈不利走向(端点对比方向性变化),随所选区间动态计算
function deltaWorse(key) {
var it = NUM[key], vv = vals(it);
if (vv.length < 2) return false;
var first = vv[0], last = vv[vv.length - 1];
var hi = it.ref[1], lo = it.ref[0];
if (hi < Infinity && last > hi) return last > first;
return last < lo ? last < first : false;
}
// 组内排序权重:期末异常在前;区间内不利走向 > 期末新增 > 区间内全程异常 > 区间内转好 > 静态分级兜底
function weight(key) {
var it = NUM[key], b = it.badge[1];
var abn = isAbn(it, 4) ? 0 : 1;
var order = { worse: 0, new: 1, keep: 2, better: 3, stable: 4 }[b];
var it = NUM[key], r = range(), e = r.b, s = r.a;
var lastAbn = isAbn(it, e), firstAbn = isAbn(it, s);
var abn = lastAbn ? 0 : 1;
var order;
if (deltaWorse(key)) order = 0;
else if (lastAbn && !firstAbn) order = 1;
else if (lastAbn) order = 2;
else if (!lastAbn && firstAbn) order = 3;
else order = 4 + ({ worse: 0, new: 1, keep: 2, better: 3, stable: 4 }[it.badge[1]] || 4);
return abn * 10 + order;
}
// 缩略趋势线(纯内联 SVG,异常点标红)
// 缩略趋势线(纯内联 SVG按所选区间取点,异常点标红)
function sparkline(item) {
var w = 96, h = 34, pad = 5;
var min = Math.min.apply(null, item.v), max = Math.max.apply(null, item.v);
var vs = vals(item);
var min = Math.min.apply(null, vs), max = Math.max.apply(null, vs);
if (max === min) max = min + 1;
var step = (w - pad * 2) / 4;
var pts = item.v.map(function (v, i) {
return (pad + i * step).toFixed(1) + ',' + (h - pad - (v - min) / (max - min) * (h - pad * 2)).toFixed(1);
});
var dots = item.v.map(function (v, i) {
var cx = pad + i * step, cy = h - pad - (v - min) / (max - min) * (h - pad * 2);
return '<circle cx="' + cx.toFixed(1) + '" cy="' + cy.toFixed(1) + '" r="2.6" fill="' + ((v < item.ref[0] || v > item.ref[1]) ? '#ff4d4f' : '#13c2c2') + '"/>';
var step = vs.length > 1 ? (w - pad * 2) / (vs.length - 1) : 0;
function X(i) { return pad + i * step; }
function Y(v) { return h - pad - (v - min) / (max - min) * (h - pad * 2); }
var pts = vs.map(function (v, i) { return X(i).toFixed(1) + ',' + Y(v).toFixed(1); });
var dots = vs.map(function (v, i) {
return '<circle cx="' + X(i).toFixed(1) + '" cy="' + Y(v).toFixed(1) + '" r="2.6" fill="' + ((v < item.ref[0] || v > item.ref[1]) ? '#ff4d4f' : '#13c2c2') + '"/>';
}).join('');
return '<svg width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '"><polyline points="' + pts.join(' ') + '" fill="none" stroke="#13c2c2" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>' + dots + '</svg>';
}
function fmtV(v) { return v >= 100 ? String(Math.round(v)) : String(v); }
// 区间端点对比:返回 {last, delta, worse, newAbn, keepAbn, better, n}
function endCompare(it) {
var r = range(), vv = vals(it);
var first = vv[0], last = vv[vv.length - 1];
var hi = it.ref[1], lo = it.ref[0];
var lastAbn = last < lo || last > hi, firstAbn = first < lo || first > hi;
var worse = (hi < Infinity && last > hi) ? last > first : (last < lo ? last < first : false);
var allAbn = vv.every(function (v) { return v < lo || v > hi; });
return { r: r, last: last, delta: last - first, worse: worse, newAbn: lastAbn && !firstAbn, keepAbn: lastAbn && firstAbn && allAbn, better: !lastAbn && firstAbn };
}
function fmtDelta(it, d) {
var dec = it.v[0] >= 100 || Math.abs(d) >= 10 ? 0 : (Math.abs(d) >= 1 ? 1 : 2);
return (d > 0 ? '+' : '') + d.toFixed(dec);
}
// ===== 渲染数值指标分组(大类折叠卡,默认收起;筛选时自动展开有匹配项的大类=====
// ===== 渲染数值指标分组(大类折叠卡,默认全部展开;点击大类头可收起=====
var filter = 'all';
function renderGroups() {
var e = range().b;
var html = '';
CATS.forEach(function (cat) {
var keys = cat.keys.slice().sort(function (a, b) { return weight(a) - weight(b); });
var abnCount = cat.keys.filter(function (k) { return isAbn(NUM[k], 4); }).length;
var abnCount = cat.keys.filter(function (k) { return isAbn(NUM[k], e); }).length;
var cards = '';
var shown = 0;
keys.forEach(function (key) {
var it = NUM[key];
var abn = isAbn(it, 4);
var show = filter === 'all' || (filter === 'abn' && abn) || (filter === 'worse' && it.badge[1] === 'worse') || (filter === 'normal' && !abn);
var last = it.v[e];
var abn = isAbn(it, e);
var show = filter === 'all' || (filter === 'abn' && abn) || (filter === 'normal' && !abn);
if (!show) return;
var arrow = abn ? (it.v[4] > it.ref[1] ? ' ↑' : ' ↓') : '';
shown++;
var arrow = abn ? (last > it.ref[1] ? ' ↑' : ' ↓') : '';
cards += '<div class="metric-card" data-key="' + key + '" onclick="goDetail(\'' + key + '\')">'
+ '<div class="metric-card__top"><span class="metric-card__name">' + it.name + '</span>'
+ '<span class="badge badge--' + it.badge[1] + '">' + it.badge[0] + '</span></div>'
+ '<div class="metric-card__bottom"><div>'
+ '<div class="metric-card__value' + (abn ? ' is-abn' : '') + '">' + fmtV(it.v[4]) + arrow + '<span class="metric-card__unit">' + it.unit + '</span></div>'
+ '<div class="metric-card__value' + (abn ? ' is-abn' : '') + '">' + fmtV(last) + arrow + '<span class="metric-card__unit">' + it.unit + '</span></div>'
+ '<div class="metric-card__ref">参考 ' + it.ref[0] + '-' + it.ref[1] + '</div></div>'
+ '<div class="metric-card__spark">' + sparkline(it) + '</div>'
+ '</div></div>';
});
if (!cards) return;
var collapsed = filter === 'all' ? ' is-collapsed' : '';
html += '<div class="cat-group' + collapsed + '">'
html += '<div class="cat-group">'
+ '<div class="cat-group__head" onclick="toggleCat(this)">' + cat.name
+ '<small>' + cat.keys.length + ' 项</small>'
+ (abnCount ? '<span class="cat-group__abn">异常 ' + abnCount + '</span>' : '')
+ '<small>' + shown + ' 项</small>'
+ (filter !== 'normal' && abnCount ? '<span class="cat-group__abn">异常 ' + abnCount + '</span>' : '')
+ '<span class="cat-group__arrow">▾</span></div>'
+ '<div class="cat-group__body">' + cards + '</div></div>';
});
@@ -485,25 +557,133 @@
btn.classList.add('is-active');
filter = btn.getAttribute('data-f');
renderGroups();
renderQual();
}
// [交互] 点击指标卡进入详情页,携带当前区间(详情页同步按区间渲染)
function goDetail(item) {
location.href = 'indicator-compare-detail.html?item=' + encodeURIComponent(item) + '&from=' + sel.from + '&to=' + sel.to;
}
// [交互] 点击指标卡进入详情页(与报告页行级入口同一目标页)
function goDetail(item) { location.href = 'indicator-compare-detail.html?item=' + encodeURIComponent(item); }
// ===== 渲染定性项目区 =====
// ===== 渲染定性项目区(圆点与结论均随区间变化)=====
function renderQual() {
var r = range();
var html = '';
QUAL.forEach(function (q) {
var dots = q.st.map(function (s) { return '<i class="is-' + s + '"></i>'; }).join('');
var st = q.st.slice(r.a, r.b + 1);
// 按当前筛选过滤定性项目:以区间末年的状态判断是否有异常
var curAbn = st[st.length - 1] === 'a';
if (!(filter === 'all' || (filter === 'abn' && curAbn) || (filter === 'normal' && !curAbn))) return;
var dots = st.map(function (s) { return '<i class="is-' + s + '"></i>'; }).join('');
// 区间内结论按圆点序列动态生成
var n = st.length, tail = 0, head = -1;
for (var i = n - 1; i >= 0 && st[i] === 'a'; i--) tail++;
for (var j = 0; j < n; j++) { if (st[j] === 'a') { head = j; break; } }
var desc;
var preAbn = q.st.slice(0, r.a).indexOf('a') !== -1;
if (!tail) {
desc = head !== -1
? r.ys[head] + ' 年曾异常,' + r.ys[n - 1] + ' 年已恢复正常'
: (preAbn ? '所选区间未见异常' : '历年未见异常');
} else if (tail === n) {
desc = n === 1 ? '该年度存在异常' : (preAbn && head === 0 ? '异常持续 ' + (n + r.a) + ' 年(区间起点前已检出)' : '持续 ' + n + ' 年');
} else {
desc = r.ys[head] + ' 年检出,至 ' + r.ys[n - 1 - tail] + ' 年恢复';
}
html += '<div class="qual-card" onclick="goDetail(\'' + q.key + '\')">'
+ '<div class="qual-card__main"><div class="qual-card__name">' + q.name + '</div>'
+ '<div class="qual-card__desc' + (q.warn ? ' is-warn' : '') + '">' + q.desc + '</div></div>'
+ '<div class="qual-card__desc' + (tail ? ' is-warn' : '') + '">' + desc + '</div></div>'
+ '<div class="qual-dots">' + dots + '</div>'
+ '<div class="qual-years">21-25</div></div>';
+ '<div class="qual-years">' + r.ys[0].slice(2) + '-' + r.ys[n - 1].slice(2) + '</div></div>';
});
document.getElementById('qualBody').innerHTML = html;
document.getElementById('qualBody').innerHTML = html || '<div class="metric-card__ref" style="text-align:center;padding:16px 0">该筛选条件下暂无定性项目</div>';
}
renderGroups();
renderQual();
// ===== AI 总结文案(按所选区间数据生成,模拟端点对比口径)=====
function buildSummary() {
var r = range();
var nums = Object.keys(NUM).map(function (k) {
var it = NUM[k];
return { key: k, it: it, cmp: endCompare(it) };
});
var abnNums = nums.filter(function (x) { var l = x.cmp.last; return l < x.it.ref[0] || l > x.it.ref[1]; });
var lead;
if (r.n === 1) {
// 单年度:只报当年结果,不做趋势对比
lead = r.ys[0] + ' 年度体检共 ' + abnNums.length + ' 项指标处于参考范围之外' +
(abnNums.length ? '' + abnNums.map(function (x) { return x.it.name; }).join('、') + '。' : '。');
} else {
lead = '在 ' + r.ys[0] + '' + r.ys[r.n - 1] + ' 共 ' + r.n + ' 次体检中,您的多项指标呈持续上行趋势:' +
nums.filter(function (x) { return x.cmp.worse; }).map(function (x) { return x.it.name; }).join('、') +
' 较 ' + r.ys[0] + ' 年分别升高 ' +
nums.filter(function (x) { return x.cmp.worse; }).map(function (x) { return fmtDelta(x.it, x.cmp.delta); }).join(' / ') +
';期末共 ' + abnNums.length + ' 项指标处于参考范围之外。';
}
var notes = r.n > 1 ? nums.filter(function (x) { return x.cmp.newAbn || x.cmp.keepAbn || x.cmp.better; }).map(function (x) {
var y = r.n + ' 年间';
if (x.cmp.newAbn) return x.it.name + y + '首次越限';
if (x.cmp.keepAbn) return x.it.name + y + '持续高于正常范围';
return x.it.name + y + '回归正常范围';
}) : [];
var qualNotes = QUAL.map(function (q) {
var st = q.st.slice(r.a, r.b + 1);
var n = st.length, tail = 0, head = -1;
for (var i = n - 1; i >= 0 && st[i] === 'a'; i--) tail++;
for (var j = 0; j < n; j++) { if (st[j] === 'a') { head = j; break; } }
if (tail === n && n > 1) return q.name + '异常持续 ' + n + ' 年';
if (tail && head > 0 && n > 1) return q.name + '自 ' + r.ys[head] + ' 年起异常';
return '';
}).filter(Boolean);
var all = notes.concat(qualNotes);
var fallback = r.n === 1 ? '当年各指标与检查结论详见下方明细。' : '区间内各指标与检查结论未见明显异常波动。';
return { lead: lead, notes: all.length ? all.join('') + '。' : fallback };
}
// ===== 区间应用:联动下拉选项、整页重渲染 =====
function fillYearSelect(selEl, list) {
selEl.innerHTML = list.map(function (y) { return '<option value="' + y + '">' + y + '</option>'; }).join('');
}
function applyRange() {
var r = range();
document.getElementById('heroTitle').textContent = r.n + ' 年纵向对比总结';
document.getElementById('heroRangeMeta').textContent =
r.ys[0] + ' - ' + r.ys[r.n - 1] + ' · 覆盖 ' + r.n + ' 次体检';
var nums = Object.keys(NUM).map(function (k) { return { it: NUM[k], cmp: endCompare(NUM[k]) }; });
document.getElementById('statAbn').textContent = nums.filter(function (x) {
return x.cmp.last < x.it.ref[0] || x.cmp.last > x.it.ref[1];
}).length;
document.getElementById('statWorse').textContent = nums.filter(function (x) { return x.cmp.worse; }).length;
document.getElementById('statNew').textContent = nums.filter(function (x) { return x.cmp.newAbn; }).length;
document.getElementById('statBetter').textContent = nums.filter(function (x) { return x.cmp.better; }).length;
var sum = buildSummary();
document.getElementById('heroLead').textContent = sum.lead;
document.getElementById('heroNotes').textContent = sum.notes;
renderGroups();
renderQual();
}
(function initYearPicker() {
var fromSel = document.getElementById('yearFrom');
var toSel = document.getElementById('yearTo');
fromSel.addEventListener('change', function () {
sel.from = fromSel.value;
// 开始年不得晚于结束年:自动顶到结束年,并反向刷新选项
if (Number(sel.from) > Number(sel.to)) { sel.to = sel.from; toSel.value = sel.to; }
fillYearSelect(toSel, YEARS.filter(function (y) { return Number(y) >= Number(sel.from); }));
toSel.value = sel.to;
applyRange();
});
toSel.addEventListener('change', function () {
sel.to = toSel.value;
if (Number(sel.to) < Number(sel.from)) { sel.from = sel.to; fromSel.value = sel.from; }
fillYearSelect(fromSel, YEARS.filter(function (y) { return Number(y) <= Number(sel.to); }));
fromSel.value = sel.from;
applyRange();
});
fillYearSelect(fromSel, YEARS);
fillYearSelect(toSel, YEARS);
fromSel.value = sel.from;
toSel.value = sel.to;
})();
applyRange();
</script>
</body>
</html>
@@ -139,7 +139,7 @@
/* 顶部体检类型 Tab */
.type-tabs {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
gap: 8px;
padding: 5px;
background: rgba(255,255,255,0.92);
@@ -384,10 +384,11 @@
</div>
<div class="scroll-content">
<!-- [交互] 点击切换 常规体检/胃肠镜体检 详情 -->
<!-- [交互] 点击切换 常规体检/胃肠镜体检/冠脉CTA体检 详情 -->
<div class="type-tabs">
<button class="type-tabs__btn type-tabs__btn--active" type="button" id="tabRoutine" onclick="setType('routine')">常规体检</button>
<button class="type-tabs__btn" type="button" id="tabGastro" onclick="setType('gastro')">胃肠镜体检</button>
<button class="type-tabs__btn" type="button" id="tabCta" onclick="setType('cta')">冠脉CTA体检</button>
</div>
<!-- ======================= 常规体检 · 待体检 ======================= -->
@@ -554,6 +555,72 @@
<button class="rebook-btn" style="width:auto;padding:0 40px;" type="button" onclick="location.href='gastro-hospital.html'">立即预约</button>
</div>
</div>
<!-- ======================= 冠脉CTA体检 · 待体检 ======================= -->
<div class="panel hidden" data-type="cta" data-status="pending">
<div class="summary-card">
<div class="section-title">冠脉CTA体检</div>
<div class="summary-list">
<div class="summary-item"><div class="summary-item__label">体检医院</div><div class="summary-item__value">宁夏宝石花医院</div></div>
<div class="summary-item"><div class="summary-item__label">体检员工</div><div class="summary-item__value">刘韵琴</div></div>
<div class="summary-item"><div class="summary-item__label">体检地址</div><div class="summary-item__value">银川市西夏区怀远路148号</div></div>
<div class="summary-item"><div class="summary-item__label">体检日期</div><div class="summary-item__value">2026年3月23日</div></div>
<div class="summary-item"><div class="summary-item__label">体检项目</div><div class="summary-item__value">冠脉CTA体检</div></div>
<div class="summary-item"><div class="summary-item__label">状态</div><div class="summary-item__value" style="color:#fa8c16;">待体检</div></div>
</div>
</div>
<div class="tips-card">
<div class="tips-card__title">体检须知</div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查前24小时请避免剧烈运动,检查当天避免吸烟,勿饮用咖啡、浓茶等刺激性饮品。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>心率过快或心律不齐者,请遵医嘱在检查前服用控制心率药物(如β受体阻滞剂)。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查需屏气配合,请提前练习平静状态下屏气10~15秒。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>对碘对比剂过敏、甲状腺功能异常、肾功能不全或妊娠期,请提前告知医生。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>请携带本人身份证件按时前往医院。</span></div>
<div class="tips-card__item"><span class="tips-card__dot"></span><span>若需取消预约,请至少提前一天操作。</span></div>
</div>
<div class="progress-card">
<div class="section-title">项目列表</div>
<div class="project-list">
<div class="project-item"><div class="project-item__icon project-item__icon--pending">&#9679;</div><div class="project-item__name">冠脉钙化积分扫描</div><div class="project-item__status project-item__status--pending">未检</div></div>
<div class="project-item"><div class="project-item__icon project-item__icon--pending">&#9679;</div><div class="project-item__name">冠脉CTA成像</div><div class="project-item__status project-item__status--pending">未检</div></div>
</div>
</div>
</div>
<!-- ======================= 冠脉CTA体检 · 已完成 ======================= -->
<div class="panel hidden" data-type="cta" data-status="done">
<div class="summary-card">
<div class="section-title">冠脉CTA体检</div>
<div class="summary-list">
<div class="summary-item"><div class="summary-item__label">体检医院</div><div class="summary-item__value">宁夏宝石花医院</div></div>
<div class="summary-item"><div class="summary-item__label">体检员工</div><div class="summary-item__value">刘韵琴</div></div>
<div class="summary-item"><div class="summary-item__label">体检地址</div><div class="summary-item__value">银川市西夏区怀远路148号</div></div>
<div class="summary-item"><div class="summary-item__label">体检日期</div><div class="summary-item__value">2026年3月23日</div></div>
<div class="summary-item"><div class="summary-item__label">体检项目</div><div class="summary-item__value">冠脉CTA体检</div></div>
<div class="summary-item"><div class="summary-item__label">状态</div><div class="summary-item__value" style="color:#52c41a;">已体检</div></div>
</div>
</div>
<div class="progress-card">
<div class="section-title">项目列表</div>
<div class="project-list">
<div class="project-item"><div class="project-item__icon project-item__icon--done">&#10003;</div><div class="project-item__name">冠脉钙化积分扫描</div><div class="project-item__status project-item__status--done">已体检</div></div>
<div class="project-item"><div class="project-item__icon project-item__icon--done">&#10003;</div><div class="project-item__name">冠脉CTA成像</div><div class="project-item__status project-item__status--done">已体检</div></div>
</div>
</div>
</div>
<!-- ======================= 冠脉CTA体检 · 无预约信息 ======================= -->
<div class="panel hidden" data-type="cta" data-status="none">
<div class="empty">
<div class="empty__icon">
<svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="#bfbfbf" stroke-width="1.6"><rect x="3" y="4" width="18" height="17" rx="3"/><path d="M3 9h18"/><path d="M8 2v4M16 2v4"/><path d="M9 15l2.2 2.2L15 13.5"/></svg>
</div>
<div class="empty__title">暂无冠脉CTA体检预约</div>
<div class="empty__desc">您还没有预约冠脉CTA体检,预约成功后可在此查看预约详情、体检须知与检查项目。</div>
<!-- [交互] 点击跳转至: cta-hospital.html(进入冠脉CTA预约流程) -->
<button class="rebook-btn" style="width:auto;padding:0 40px;" type="button" onclick="location.href='cta-hospital.html'">立即预约</button>
</div>
</div>
</div>
</div>
@@ -604,6 +671,7 @@
currentType = type;
document.getElementById('tabRoutine').classList.toggle('type-tabs__btn--active', type === 'routine');
document.getElementById('tabGastro').classList.toggle('type-tabs__btn--active', type === 'gastro');
document.getElementById('tabCta').classList.toggle('type-tabs__btn--active', type === 'cta');
applyView();
}
@@ -689,13 +757,13 @@
fillProgress('r', ROUTINE_PROJECTS, 5); // 常规·待体检 5/26
fillProgress('rd', ROUTINE_PROJECTS, 26); // 常规·已完成 26/26
// [交互] URL 参数直达:?type=routine|gastro&status=pending|done|none
// [交互] URL 参数直达:?type=routine|gastro|cta&status=pending|done|none
(function initFromUrl() {
if (!window.URLSearchParams) { return; }
var params = new URLSearchParams(window.location.search);
var pType = params.get('type');
var pStatus = params.get('status');
if (pType === 'routine' || pType === 'gastro') { setType(pType); }
if (pType === 'routine' || pType === 'gastro' || pType === 'cta') { setType(pType); }
if (pStatus === 'pending' || pStatus === 'done' || pStatus === 'none') {
setDemoStatus(pStatus);
}
+508
View File
@@ -0,0 +1,508 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>冠脉CTA体检报告</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary: #20c7c7;
--primary-dark: #119b9b;
--primary-light: #e8fbfb;
--border: #cfeeee;
--line: #dff3f3;
--bg-page: #f0f2f5;
--bg-content: #f6fbfb;
--text-primary: #1a1a1a;
--text-secondary: #666;
--text-muted: #8c8c8c;
--success: #52c41a;
--paper-shadow: 0 8px 24px rgba(17, 155, 155, 0.08);
}
body {
background: var(--bg-page);
display: flex;
justify-content: center;
align-items: flex-start;
min-height: 100vh;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
color: var(--text-primary);
}
.phone-shell {
width: 390px;
min-height: 844px;
background: var(--bg-content);
border-radius: 44px;
box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
overflow: hidden;
position: relative;
display: flex;
flex-direction: column;
}
.phone-status-bar {
height: 44px;
background: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
font-size: 12px;
font-weight: 600;
flex-shrink: 0;
}
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
.nav-bar {
height: 44px;
display: flex;
align-items: center;
padding: 0 16px;
background: #fff;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
position: relative;
}
.nav-back {
font-size: 18px;
color: var(--text-primary);
cursor: pointer;
line-height: 1;
text-decoration: none;
}
.nav-title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 17px;
font-weight: 600;
color: var(--text-primary);
}
.nav-action {
margin-left: auto;
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 12px;
color: var(--primary-dark);
text-decoration: none;
font-weight: 600;
}
.scroll-content {
flex: 1;
overflow-y: auto;
background: linear-gradient(180deg, #ecfbfb 0%, #f7fbfb 160px, #f7fbfb 100%);
}
.scroll-content::-webkit-scrollbar { display: none; }
.page-body { padding: 14px; }
/* 报告卡片 */
.report-paper {
background: #fff;
border-radius: 20px;
box-shadow: var(--paper-shadow);
border: 1px solid rgba(32, 199, 199, 0.08);
overflow: hidden;
}
.report-header {
padding: 18px 16px 14px;
background: linear-gradient(180deg, #fbffff 0%, #f4ffff 100%);
border-bottom: 1px solid var(--line);
}
.report-header__top {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 12px;
}
.report-header__title {
font-size: 20px;
font-weight: 700;
letter-spacing: 1px;
color: #0f7d7d;
margin-bottom: 6px;
}
.report-header__sub {
font-size: 12px;
color: var(--text-muted);
line-height: 1.6;
}
.report-tag--cta {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 62px;
height: 28px;
padding: 0 10px;
border-radius: 14px;
background: #e6fffb;
color: #08979c;
border: 1px solid #87e8de;
font-size: 12px;
font-weight: 700;
flex-shrink: 0;
}
/* 章节 */
.report-section {
padding: 14px 16px 0;
}
.report-section__title {
height: 30px;
display: flex;
align-items: center;
padding: 0 12px;
margin: 0 -16px 12px;
background: linear-gradient(90deg, #78e3e3 0%, #a4eded 100%);
color: #0c7070;
font-size: 13px;
font-weight: 700;
letter-spacing: 0.5px;
}
.report-section__title--score {
background: linear-gradient(90deg, #ffd591 0%, #ffe7ba 100%);
color: #ad6800;
}
.report-section__title--vessel {
background: linear-gradient(90deg, #b5f5ec 0%, #d9f9f4 100%);
color: #006d75;
}
/* 检查字段 */
.field-list {
display: flex;
flex-direction: column;
gap: 10px;
padding-bottom: 14px;
}
.field-item {
display: flex;
flex-direction: column;
gap: 4px;
}
.field-item__label {
font-size: 12px;
color: var(--text-muted);
font-weight: 600;
}
.field-item__value-wrap {
position: relative;
}
.field-item__value {
font-size: 13px;
line-height: 1.7;
color: var(--text-primary);
background: #f9fffe;
border: 1px solid var(--border);
border-radius: 10px;
padding: 10px 12px;
min-height: 40px;
max-height: 76px;
overflow: hidden;
transition: max-height 0.3s ease;
}
.field-item.is-expanded .field-item__value {
max-height: 600px;
}
.field-item__fade {
position: absolute;
left: 1px;
right: 1px;
bottom: 1px;
height: 32px;
background: linear-gradient(180deg, rgba(249,255,254,0) 0%, rgba(249,255,254,0.96) 60%);
pointer-events: none;
border-radius: 0 0 10px 10px;
}
.field-item.is-expanded .field-item__fade {
display: none;
}
.field-item__toggle {
display: none;
align-items: center;
gap: 4px;
position: absolute;
right: 12px;
bottom: 8px;
border: none;
background: #f9fffe;
color: var(--primary-dark);
font-size: 12px;
font-weight: 600;
cursor: pointer;
padding: 2px 6px;
border-radius: 4px;
z-index: 1;
}
.field-item__toggle.is-visible {
display: inline-flex;
}
/* 冠脉病变分段列表 */
.vessel-list {
display: flex;
flex-direction: column;
gap: 8px;
padding-bottom: 14px;
}
.vessel-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
border-radius: 12px;
background: #f9fffe;
border: 1px solid var(--border);
}
.vessel-item__name { font-size: 13px; font-weight: 700; color: var(--text-primary); width: 128px; flex-shrink: 0; }
.vessel-item__desc { flex: 1; font-size: 12px; color: var(--text-secondary); line-height: 1.6; }
.vessel-item__grade {
font-size: 11px;
font-weight: 700;
padding: 2px 8px;
border-radius: 10px;
flex-shrink: 0;
}
.vessel-item__grade--ok { background: #f6ffed; color: #52c41a; border: 1px solid #b7eb8f; }
.vessel-item__grade--warn { background: #fff7e6; color: #fa8c16; border: 1px solid #ffd591; }
/* 影像报告 */
.image-section__label {
font-size: 12px;
color: var(--text-muted);
font-weight: 600;
margin-bottom: 8px;
}
.image-view-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 14px;
border: 1px solid var(--border);
border-radius: 10px;
background: #f9fffe;
color: var(--primary-dark);
font-size: 13px;
font-weight: 600;
cursor: pointer;
margin-bottom: 14px;
transition: border-color 0.2s, background 0.2s;
}
.image-view-link:hover { border-color: var(--primary); background: var(--primary-light); }
/* 分割线 */
.divider {
height: 1px;
background: var(--line);
margin: 0 16px;
}
/* 返回按钮 */
.back-btn-wrap {
padding: 10px 16px 18px;
}
.back-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
width: 100%;
height: 46px;
border: none;
border-radius: 23px;
background: linear-gradient(135deg, #13c2c2, #36cfc9);
color: #fff;
font-size: 15px;
font-weight: 600;
cursor: pointer;
box-shadow: 0 8px 20px rgba(19, 194, 194, 0.22);
}
.bottom-spacer { height: 20px; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="phone-status-bar">
<span class="time">12:00</span>
<div class="icons">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
</div>
</div>
<div class="nav-bar">
<!-- [交互] 返回按钮:返回体检报告列表 -->
<span class="nav-back" onclick="location.href='reports.html'"></span>
<span class="nav-title">冠脉CTA报告</span>
<!-- [交互] 下载按钮:下载冠脉CTA报告 -->
<a class="nav-action" href="javascript:void(0)">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
下载
</a>
</div>
<div class="scroll-content">
<div class="page-body">
<div class="report-paper">
<!-- 报告头部 -->
<div class="report-header">
<div class="report-header__top">
<div>
<div class="report-header__title">2025年冠脉CTA报告</div>
<div class="report-header__sub">姓名:张旭
<br>性别:男
<br>年龄:32
<br>身份证号:430626198503250024
<br>体检日期:2025-03-21
<br>体检医院:CQ星龙园医院
</div>
</div>
<span class="report-tag--cta">冠脉CTA体检</span>
</div>
</div>
<!-- ========== 检查所见 ========== -->
<div class="report-section">
<div class="report-section__title">检查所见</div>
<div class="field-list">
<div class="field-item" id="field-technique">
<div class="field-item__label">扫描技术与图像质量</div>
<div class="field-item__value-wrap">
<div class="field-item__value">回顾性心电门控冠脉CTA扫描,扫描范围自气管分叉至心尖部。扫描时心率68次/分,屏气良好,图像质量满足诊断要求。冠脉分布:右侧型。</div>
<div class="field-item__fade"></div>
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
</div>
</div>
<div class="field-item" id="field-cardiac">
<div class="field-item__label">心脏及心外所见</div>
<div class="field-item__value-wrap">
<div class="field-item__value">各心腔大小未见扩大,左心耳未见血栓,主动脉及瓣膜未见明显钙化,心包少量积液。双肺下叶少许条索影。</div>
<div class="field-item__fade"></div>
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
</div>
</div>
</div>
</div>
<div class="divider"></div>
<!-- ========== 钙化积分 ========== -->
<div class="report-section">
<div class="report-section__title report-section__title--score">冠状动脉钙化积分</div>
<div class="field-list">
<div class="field-item" id="field-agatston">
<div class="field-item__label">Agatston 总积分</div>
<div class="field-item__value-wrap">
<div class="field-item__value">Agatston 总积分约 86 分(轻度钙化)。其中LAD约52分,RCA约28分,LCX约6分,LM未见明显钙化。</div>
<div class="field-item__fade"></div>
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
</div>
</div>
</div>
</div>
<div class="divider"></div>
<!-- ========== 冠脉病变 ========== -->
<div class="report-section">
<div class="report-section__title report-section__title--vessel">冠脉病变</div>
<div class="vessel-list">
<div class="vessel-item"><div class="vessel-item__name">左主干 LM</div><div class="vessel-item__desc">未见斑块及狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
<div class="vessel-item"><div class="vessel-item__name">左前降支 LAD 近段</div><div class="vessel-item__desc">混合斑块,管腔狭窄约30%</div><span class="vessel-item__grade vessel-item__grade--warn">轻度狭窄</span></div>
<div class="vessel-item"><div class="vessel-item__name">左前降支 LAD 中段</div><div class="vessel-item__desc">管壁光滑,未见狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
<div class="vessel-item"><div class="vessel-item__name">第一对角支 D1</div><div class="vessel-item__desc">钙化斑块,管腔狭窄&lt;25%</div><span class="vessel-item__grade vessel-item__grade--ok">未见明显狭窄</span></div>
<div class="vessel-item"><div class="vessel-item__name">左回旋支 LCX 近段</div><div class="vessel-item__desc">管壁光滑,未见狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
<div class="vessel-item"><div class="vessel-item__name">左回旋支 LCX 远段</div><div class="vessel-item__desc">少量钙化斑块,管腔未见明显狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见明显狭窄</span></div>
<div class="vessel-item"><div class="vessel-item__name">右冠状动脉 RCA 近段</div><div class="vessel-item__desc">钙化斑块,管腔狭窄约40%</div><span class="vessel-item__grade vessel-item__grade--warn">轻度狭窄</span></div>
<div class="vessel-item"><div class="vessel-item__name">右冠状动脉 RCA 中远段</div><div class="vessel-item__desc">管壁光滑,未见狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
</div>
</div>
<div class="divider"></div>
<!-- ========== 诊断结论 ========== -->
<div class="report-section">
<div class="report-section__title">诊断结论</div>
<div class="field-list">
<div class="field-item" id="field-conclusion">
<div class="field-item__label">影像诊断</div>
<div class="field-item__value-wrap">
<div class="field-item__value">1. 冠状动脉粥样硬化表现;2. LAD近段混合斑块伴管腔约30%狭窄,RCA近段钙化斑块伴约40%狭窄,余所见冠脉未见明显狭窄;3. 冠状动脉轻度钙化(Agatston 总积分约86分);4. CAD-RADS 2。</div>
<div class="field-item__fade"></div>
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
</div>
</div>
<div class="field-item" id="field-advice">
<div class="field-item__label">健康建议</div>
<div class="field-item__value-wrap">
<div class="field-item__value">建议低盐低脂饮食,规律有氧运动,控制血压、血脂、血糖;他汀类用药及随访方案请心内科门诊评估,结合危险因素决定下一步功能学检查。</div>
<div class="field-item__fade"></div>
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
</div>
</div>
</div>
</div>
<div class="divider"></div>
<!-- ========== 影像报告 ========== -->
<div class="report-section">
<div class="report-section__title">影像报告</div>
<div class="image-section__label">冠脉CTA原始图像</div>
<div class="image-view-link">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
查看
</div>
<div class="image-section__label">三维重建图像</div>
<div class="image-view-link">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
查看
</div>
<div class="image-section__label">钙化积分报告</div>
<div class="image-view-link">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
查看
</div>
</div>
<!-- 返回按钮 -->
<div class="back-btn-wrap">
<!-- [交互] 返回报告列表按钮 -->
<button class="back-btn" onclick="location.href='reports.html'">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>
返回报告列表
</button>
</div>
</div>
<div class="bottom-spacer"></div>
</div>
</div>
</div>
<script>
// [交互] 展开/收起字段内容
function toggleField(btn) {
var item = btn.closest('.field-item');
var fade = item.querySelector('.field-item__fade');
var isExpanded = item.classList.toggle('is-expanded');
btn.innerHTML = isExpanded
? '收起 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>'
: '展开 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>';
if (fade) fade.style.display = isExpanded ? 'none' : '';
}
// 页面加载后,检测哪些字段内容超过3行,仅对超出的显示展开按钮
document.addEventListener('DOMContentLoaded', function() {
var items = document.querySelectorAll('.field-item');
items.forEach(function(item) {
var value = item.querySelector('.field-item__value');
var btn = item.querySelector('.field-item__toggle');
if (!value || !btn) return;
// scrollHeight 为完整内容高度,clientHeight 为可见高度
if (value.scrollHeight > value.clientHeight + 2) {
btn.classList.add('is-visible');
}
});
});
</script>
</body>
</html>
+16 -1
View File
@@ -104,6 +104,7 @@
border-radius: 11px; font-size: 11px; font-weight: 600; white-space: nowrap; flex-shrink: 0;
}
.report-tag--gastro { background: #e6fffb; color: #08979c; border: 1px solid #87e8de; }
.report-tag--cta { background: #fff1f0; color: #cf1322; border: 1px solid #ffa39e; }
.report-tag--regular { background: #e6f7ff; color: #096dd9; border: 1px solid #91d5ff; }
.report-item__arrow { font-size: 18px; color: #c6c6c6; flex-shrink: 0; }
.bottom-spacer { height: 28px; }
@@ -134,7 +135,7 @@
<div class="sum-card__divider"></div>
<div class="sum-card__meta">
<div><span class="k">起始年份</span><span class="v">2012</span></div>
<div><span class="k">报告总数</span><span class="v">11</span></div>
<div><span class="k">报告总数</span><span class="v">12</span></div>
</div>
<svg class="sum-card__timeline" width="96" height="36" viewBox="0 0 96 36">
<line x1="8" y1="11" x2="88" y2="11" stroke="rgba(255,255,255,0.4)" stroke-width="2" stroke-linecap="round"/>
@@ -179,6 +180,20 @@
</div>
<span class="report-item__arrow"></span>
</div>
<!-- [交互] 点击跳转至: report-cta.html(冠脉CTA报告) -->
<div class="report-item" onclick="location.href='report-cta.html'">
<div class="report-item__icon" style="background:#fff1f0;color:#cf1322;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/><path d="M3.2 12h5.3l1.5-3 2.5 6 1.5-3h5.3"/></svg>
</div>
<div class="report-item__content">
<div class="report-item__header">
<span class="report-item__title">2025年度体检报告</span>
<span class="report-tag report-tag--cta">冠脉CTA体检</span>
</div>
<div class="report-item__meta">CQ星龙园医院</div>
</div>
<span class="report-item__arrow"></span>
</div>
<!-- [交互] 点击跳转至: report-query.html(常规体检) -->
<div class="report-item" onclick="location.href='report-query.html'">
<div class="report-item__icon" style="background:#e6f7ff;color:#096dd9;">
+2 -1
View File
@@ -204,7 +204,7 @@ const SITE_MAP = [
{ file:'pre-plan.html', label:'单位体检计划管理' },
{ file:'pre-quota-group.html', label:'群体额度配置' },
{ file:'pre-quota-personal.html', label:'员工额度配置' },
{ file:'pre-item-hospital-fee.html', label:'医院体检项目费用' },
{ file:'pre-item-hospital-fee.html', label:'医院体检项目' },
{ file:'pre-item-unit-fee.html', label:'单位体检项目费用' },
{ file:'pre-item-combo-template.html', label:'体检项目组合模板' },
{ file:'pre-item-exception.html', label:'组合模板例外配置' },
@@ -659,6 +659,7 @@ const SITE_MAP = [
{ file:'indicator-compare.html', label:'指标纵向对比总览' },
{ file:'indicator-compare-detail.html', label:'指标纵向对比详情' },
{ file:'report-gastro.html', label:'胃肠镜报告详情' },
{ file:'report-cta.html', label:'冠脉CTA报告详情' },
{ file:'messages.html', label:'消息列表' },
{ file:'message-detail.html', label:'消息详情' },
{ file:'project-detail.html', label:'体检项目详情' }
@@ -1,138 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1280, initial-scale=1.0">
<title>五类人群信息登记 | 医疗点PAD端</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif; background: #05080f; min-height: 840px; min-width: 1320px; display: grid; place-items: center; padding: 20px; }
.device-frame { width: 1280px; height: 800px; background: #eef1f6; border-radius: 24px; overflow: hidden; box-shadow: 0 24px 64px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.04); position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.drawer__head { height: 56px; background: #fff; display: flex; align-items: center; padding: 0 20px; gap: 12px; flex-shrink: 0; box-shadow: 0 2px 6px rgba(74,90,127,.06); }
.drawer__back { color: #1890ff; font-size: 14px; cursor: pointer; text-decoration: none; }
.drawer__title { font-size: 16px; font-weight: 600; color: #333; }
.drawer__body { flex: 1; overflow-y: auto; padding: 16px 24px; scrollbar-width: none; }
.drawer__body::-webkit-scrollbar { display: none; }
.drawer__foot { height: 60px; background: #fff; display: flex; align-items: center; justify-content: center; gap: 14px; flex-shrink: 0; box-shadow: 0 -2px 6px rgba(74,90,127,.06); }
.btn { height: 32px; padding: 0 18px; border-radius: 6px; border: 1px solid #d9dee8; background: #fff; color: #4a5a7f; font-size: 13px; cursor: pointer; }
.btn--primary { background: #1890ff; border-color: #1890ff; color: #fff; }
/* 顶部只读员工信息 */
.emp-bar { background: #fff; border-radius: 12px; padding: 12px 18px; display: flex; gap: 34px; font-size: 13px; color: #4a5a7f; box-shadow: 0 2px 8px rgba(74,90,127,.05); }
.emp-bar b { color: #333; font-weight: 500; }
/* 分类单选 */
.cls-row { background: #fff; border-radius: 12px; padding: 14px 18px; margin-top: 12px; box-shadow: 0 2px 8px rgba(74,90,127,.05); display: flex; align-items: center; gap: 22px; font-size: 13px; color: #333; }
.cls-row label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.cls-row input { accent-color: #1890ff; width: 15px; height: 15px; }
.sec { background: #fff; border-radius: 12px; padding: 14px 18px; margin-top: 12px; box-shadow: 0 2px 8px rgba(74,90,127,.05); }
.sec__head { display: flex; align-items: center; margin-bottom: 10px; }
.sec__title { font-size: 14px; font-weight: 600; color: #333; border-left: 3px solid #1890ff; padding-left: 8px; flex: 1; }
.table { width: 100%; border-collapse: collapse; font-size: 12px; }
.table th { background: #f6f8fc; color: #4a5a7f; font-weight: 500; padding: 8px 10px; text-align: left; }
.table td { padding: 7px 10px; border-bottom: 1px solid #f0f2f5; }
.table input, .table select { width: 100%; height: 30px; border: 1px solid #d9dee8; border-radius: 6px; padding: 0 8px; font-size: 12px; outline: none; box-sizing: border-box; }
.op-del { color: #f5222d; cursor: pointer; font-size: 12px; }
.link-add { color: #1890ff; font-size: 12px; cursor: pointer; text-decoration: none; }
</style>
</head>
<body>
<div class="device-frame">
<div class="drawer__head">
<a class="drawer__back" href="javascript:history.back()">&#x2039; 返回</a>
<span class="drawer__title">五类人群信息登记</span>
</div>
<div class="drawer__body">
<div class="emp-bar">
<span>单位:<b>CQ能源采油三大队</b></span>
<span>部门:<b>采油三队</b></span>
<span>姓名:<b>石维国</b></span>
<span>身份证号:<b>612427********3417</b></span>
</div>
<div class="sec">
<div class="sec__head"><span class="sec__title">人群分类</span></div>
<div class="cls-row" style="padding:0;box-shadow:none;border-radius:0">
<label><input type="radio" name="cls">a-大病人群A</label>
<label><input type="radio" name="cls" checked onclick="showCls('b')">b-慢病人群B</label>
<label><input type="radio" name="cls" onclick="showCls('c')">c-异常人群C</label>
<label><input type="radio" name="cls" onclick="showCls('d')">d-风险人群D</label>
<label><input type="radio" name="cls" onclick="showCls('e')">e-健康人群E</label>
</div>
</div>
<!-- B 慢病人群 -->
<div class="sec" id="secB">
<div class="sec__head">
<span class="sec__title">慢病信息</span>
<!-- [交互] 添加一行慢病记录 -->
<button class="btn btn--primary" style="height:28px;padding:0 12px">添 加</button>
</div>
<table class="table">
<tr><th style="width:26%">慢病名称</th><th style="width:16%">确诊年份</th><th style="width:26%">确诊医院</th><th>治疗情况</th><th style="width:50px">操作</th></tr>
<tr><td><input value="原发性高血压3级"></td><td><input value="2019"></td><td><input value="定边县人民医院"></td><td><input value="口服降压药,血压控制一般"></td><td><span class="op-del">删除</span></td></tr>
<tr><td><input value="2型糖尿病"></td><td><input value="2022"></td><td><input value="CQ能源职工医院"></td><td><input value="二甲双胍治疗,定期监测"></td><td><span class="op-del">删除</span></td></tr>
</table>
</div>
<!-- C 异常人群 -->
<div class="sec" id="secC" style="display:none">
<div class="sec__head">
<span class="sec__title">异常指标信息</span>
<!-- [交互] 添加时打开「体检报告」指标多选弹窗(旧系统 chooseModal),勾选指标回填本表 -->
<a class="link-add" href="javascript:void(0)"> 从体检报告添加</a>
</div>
<table class="table">
<tr><th>指标名称</th><th>指标值</th><th>参考范围</th><th style="width:12%">确诊年份</th><th style="width:22%">确诊医院</th><th style="width:50px">操作</th></tr>
<tr><td>空腹血糖</td><td><input value="7.8"></td><td>3.9~6.1</td><td><input value="2025"></td><td><input value="定边县人民医院"></td><td><span class="op-del">删除</span></td></tr>
<tr><td>血清总胆固醇</td><td><input value="6.12"></td><td>0~5.2</td><td><input value="2025"></td><td><input value="定边县人民医院"></td><td><span class="op-del">删除</span></td></tr>
</table>
</div>
<!-- D 风险人群 -->
<div class="sec" id="secD" style="display:none">
<div class="sec__head">
<span class="sec__title">风险疾病信息</span>
<!-- [交互] 添加时打开「评估结果」多选弹窗 -->
<a class="link-add" href="javascript:void(0)"> 从评估结果添加</a>
</div>
<table class="table">
<tr><th>疾病名称</th><th style="width:24%">风险等级</th><th style="width:20%">评估年份</th><th style="width:50px">操作</th></tr>
<tr><td>心脑血管疾病风险</td><td><select><option>中风险</option><option selected>高风险</option></select></td><td><input value="2025"></td><td><span class="op-del">删除</span></td></tr>
</table>
</div>
<!-- A 大病人群 -->
<div class="sec" id="secA" style="display:none">
<div class="sec__head">
<span class="sec__title">大病信息</span>
<button class="btn btn--primary" style="height:28px;padding:0 12px">添 加</button>
</div>
<table class="table">
<tr><th>大病名称</th><th style="width:12%">确诊年份</th><th style="width:20%">确诊医院</th><th style="width:16%">大病状态</th><th>治疗情况</th><th style="width:50px">操作</th></tr>
<tr><td><input value="—"></td><td><input></td><td><input></td><td><select><option>治疗期</option><option>康复期</option></select></td><td><input></td><td><span class="op-del">删除</span></td></tr>
</table>
</div>
<!-- E 健康人群 -->
<div class="sec" id="secE" style="display:none">
<div style="font-size:13px;color:#969eb0;text-align:center;padding:16px 0">健康人群无需登记附加信息</div>
</div>
</div>
<div class="drawer__foot">
<button class="btn" onclick="history.back()">取 消</button>
<!-- [交互] 确认保存五类人群登记信息,返回解读抽屉 -->
<button class="btn btn--primary" onclick="history.back()">确 认</button>
</div>
</div>
<script>
// 按人群分类切换信息表显隐
function showCls(k) {
['A', 'B', 'C', 'D', 'E'].forEach(function (c) {
document.getElementById('sec' + c).style.display = c === k.toUpperCase() ? 'block' : 'none';
});
}
</script>
</body>
</html>
+118 -68
View File
@@ -45,6 +45,8 @@
.tag--ht { background: rgba(24,144,255,.12); color: #1890ff; }
.tag--dm { background: rgba(42,193,139,.12); color: #2ac18b; }
.tag--chd { background: rgba(0,195,195,.12); color: #00c3c3; }
.tag--ob { background: rgba(252,163,24,.12); color: #fca318; }
.tag--oth { background: rgba(104,98,214,.12); color: #6862d6; }
/* 医药信息 */
.med-card { background: #f2f6ff; border-radius: 10px; padding: 10px 14px; font-size: 12px; color: #4a5a7f; line-height: 1.9; position: relative; }
.med-card b { color: #333; font-size: 13px; }
@@ -57,6 +59,7 @@
.task-opt input { accent-color: #1890ff; width: 15px; height: 15px; }
.task-opt--on { background: #dae3f3; }
.pill { display: inline-block; padding: 1px 10px; border-radius: 12px; font-size: 11px; background: rgba(252,163,24,.12); color: #fca318; }
.pill--over { background: rgba(253,33,33,.08); color: #fd2121; }
/* 签名块 */
.sign-box { flex: 1; height: 110px; border: 1px dashed #b7c3d6; border-radius: 8px; background: #f7f9fc; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; color: #969eb0; font-size: 13px; cursor: pointer; }
.sign-box svg { width: 22px; height: 22px; stroke: #969eb0; fill: none; stroke-width: 2; }
@@ -99,8 +102,8 @@
<body>
<div class="device-frame">
<div class="drawer__head">
<!-- [交互] 返回随访管理列表: follow-records.html -->
<a class="drawer__back" href="follow-records.html">&#x2039; 返回</a>
<!-- [交互] 点击返回来源页面(来源记录为空时回退到浏览器历史) -->
<a class="drawer__back" href="follow-records.html" onclick="goBack(); return false;">&#x2039; 返回</a>
<span class="drawer__title">新增随访</span>
</div>
@@ -123,14 +126,14 @@
</div>
</div>
<div class="form-grid" style="margin-top:14px">
<div class="fld"><span class="fld__label">姓名</span><input value="岳春生" readonly></div>
<div class="fld"><span class="fld__label">性别</span><input value="男" readonly></div>
<div class="fld"><span class="fld__label">年龄</span><input value="54" readonly></div>
<div class="fld"><span class="fld__label">工号</span><input value="1035678" readonly></div>
<div class="fld"><span class="fld__label">联系电话</span><input value="139****2214" readonly></div>
<div class="fld"><span class="fld__label">单位/部门</span><input value="陕E作业区 / 管理四中心" readonly></div>
<div class="fld"><span class="fld__label">姓名</span><input id="empName" value="岳春生" readonly></div>
<div class="fld"><span class="fld__label">性别</span><input id="empGender" value="男" readonly></div>
<div class="fld"><span class="fld__label">年龄</span><input id="empAge" value="54" readonly></div>
<div class="fld"><span class="fld__label">工号</span><input id="empNo" value="1035678" readonly></div>
<div class="fld"><span class="fld__label">联系电话</span><input value="13956282214" readonly></div>
<div class="fld"><span class="fld__label">单位/部门</span><input id="empUnitDept" value="陕E作业区 / 管理四中心" readonly></div>
<!-- 慢病标签由员工慢病档案自动回显,不可手工修改 -->
<div class="fld fld--full"><span class="fld__label">慢病</span><span style="line-height:26px"><span class="tag tag--ht">高血压</span><span class="tag tag--dm">糖尿病</span></span></div>
<div class="fld fld--full"><span class="fld__label">慢病</span><span id="empTags" style="line-height:26px"><span class="tag tag--ht">高血压</span><span class="tag tag--dm">糖尿病</span></span></div>
</div>
</div>
@@ -139,7 +142,6 @@
<div class="form-grid">
<div class="fld"><span class="fld__label">随访医生</span><input value="石维国(当前登录)" readonly></div>
<div class="fld"><span class="fld__label">随访日期</span><input value="2026-09-04" readonly></div>
<div class="fld"><span class="fld__label"><span class="fld__req">*</span>下次随访</span><input value="2026-10-04"></div>
<div class="fld fld--full"><span class="fld__label"><span class="fld__req">*</span>随访形式</span>
<span class="radio">
<label><input type="radio" name="form" checked>门诊随访</label>
@@ -149,9 +151,6 @@
</span>
</div>
<div class="fld fld--full"><span class="fld__label"><span class="fld__req">*</span>症状</span><textarea placeholder="请输入目前症状与主诉">偶有头晕,血压波动,无胸闷心悸。</textarea></div>
<div class="fld"><span class="fld__label"><span class="fld__req">*</span>效果评价</span>
<select><option>良好</option><option selected>一般</option><option>不良</option></select>
</div>
</div>
</div>
@@ -184,7 +183,11 @@
<span class="radio"><label><input type="radio" name="salt"></label><label><input type="radio" name="salt"></label><label><input type="radio" name="salt" checked></label></span>
</div>
<div class="fld"><span class="fld__label">心理调整</span>
<select><option selected>良好</option><option>一般</option><option></option></select>
<span class="radio">
<label><input type="radio" name="psych" checked>良好</label>
<label><input type="radio" name="psych">一般</label>
<label><input type="radio" name="psych"></label>
</span>
</div>
<div class="fld fld--full"><span class="fld__label">遵医行为</span>
<span class="radio"><label><input type="radio" name="comp" >良好</label><label><input type="radio" name="comp" checked>一般</label><label><input type="radio" name="comp"></label></span>
@@ -195,8 +198,8 @@
<div class="sec">
<div class="sec__title">用药情况</div>
<div class="med-grid">
<div class="med-card"><b>苯磺酸氨氯地平片</b>5mg×7片 · 23.80元)<br>数量:2盒 用法用量:口服,一日1次,一次1片<div class="med-card__ops"><span class="op-del">删除</span></div></div>
<div class="med-card"><b>二甲双胍缓释片</b>0.5g×30片 · 32.40元)<br>数量:1盒 用法用量:口服,一日2次,一次1片<div class="med-card__ops"><span class="op-del">删除</span></div></div>
<div class="med-card"><b>苯磺酸氨氯地平片</b><br>用法用量:口服,一日1次,一次1片<div class="med-card__ops"><span class="op-del" onclick="this.parentNode.parentNode.remove()">删除</span></div></div>
<div class="med-card"><b>二甲双胍缓释片</b><br>用法用量:口服,一日2次,一次1片<div class="med-card__ops"><span class="op-del" onclick="this.parentNode.parentNode.remove()">删除</span></div></div>
</div>
<!-- [交互] 点击打开页内「新增用药」弹窗 -->
<button class="add-med-btn" onclick="openModal('medModal')"> 新增用药</button>
@@ -232,19 +235,51 @@
<!-- [交互] 员工存在待随访的巡诊任务时在此显示,勾选后随本次随访一并处理;选中态底色加深 -->
<label class="task-opt task-opt--on" onclick="this.classList.toggle('task-opt--on')">
<input type="checkbox" checked>
<span style="flex:1">2026年第三季度高血压随访任务<br><span style="color:#969eb0">任务来源:慢病干预计划 随访时限2026-09-06 前</span></span>
<span class="pill">待随访 · 还剩2</span>
<span style="flex:1"><b style="color:#333">频次巡诊</b><br><span style="color:#969eb0">计划随访日期2026-09-04</span></span>
<span class="pill pill--over">已逾期 · 逾期4</span>
</label>
<label class="task-opt" style="margin-top:10px" onclick="this.classList.toggle('task-opt--on')">
<input type="checkbox">
<span style="flex:1"><b style="color:#333">单次巡诊</b><br><span style="color:#969eb0">计划随访日期:2026-09-12</span></span>
<span class="pill">待随访 · 还剩4天</span>
</label>
<label class="task-opt" style="margin-top:10px" onclick="this.classList.toggle('task-opt--on')">
<input type="checkbox">
<span style="flex:1"><b style="color:#333">申请随诊</b><br><span style="color:#969eb0">计划随访日期:2026-09-15</span></span>
<span class="pill">待随访 · 还剩7天</span>
</label>
</div>
<div class="sec">
<div class="sec__title">员工签字</div>
<div class="fld fld--full" style="align-items:flex-start">
<div class="form-grid">
<div class="fld"><span class="fld__label"><span class="fld__req">*</span>下次随访</span><input value="2026-10-04"></div>
<div class="fld"><span class="fld__label"><span class="fld__req">*</span>随访效果</span>
<span class="radio">
<label><input type="radio" name="effect">良好</label>
<label><input type="radio" name="effect" checked>一般</label>
<label><input type="radio" name="effect">不良</label>
</span>
</div>
</div>
<div class="fld fld--full" style="align-items:flex-start;margin-top:14px">
<span class="fld__label" style="padding-top:8px"><span class="fld__req">*</span>签字</span>
<!-- [交互] 点击打开页内手写签名弹窗 -->
<div class="sign-box" onclick="openSign()">
<svg viewBox="0 0 24 24"><path d="M17 3a2.8 2.8 0 014 4L7.5 20.5 2 22l1.5-5.5z"/></svg>
点击签名
<div style="flex:1">
<div class="radio" style="margin-bottom:10px">
<label><input type="radio" name="signType" checked onclick="switchSignType('hand')">手写签名</label>
<label><input type="radio" name="signType" onclick="switchSignType('img')">签字图片</label>
</div>
<!-- [交互] 手写签名:点击打开页内手写签名弹窗 -->
<div class="sign-box" id="signHandBox" onclick="openSign()">
<svg viewBox="0 0 24 24"><path d="M17 3a2.8 2.8 0 014 4L7.5 20.5 2 22l1.5-5.5z"/></svg>
点击签名
</div>
<!-- [交互] 签字图片:点击上传图片,与手写签名两者选其一即可 -->
<div class="sign-box" id="signImgBox" style="display:none" onclick="document.getElementById('signImgInput').click()">
<svg viewBox="0 0 24 24"><path d="M12 16V4M7 9l5-5 5 5"/><path d="M4 20h16"/></svg>
上传签字图片
</div>
<input type="file" id="signImgInput" accept="image/*" style="display:none" onchange="onSignImg(this)">
</div>
</div>
</div>
@@ -261,36 +296,13 @@
<div class="modal">
<div class="modal__head"><span class="modal__title">新增用药</span><button class="modal__close" onclick="closeModal('medModal')">&#x2715;</button></div>
<div class="modal__body">
<div class="search-line">
<input placeholder="请输入药品名称查询" value="氨氯地平">
<button class="btn btn--primary">查 询</button>
<div class="drug-list">
<table>
<tr><th>名称</th><th>规格</th><th>单位</th><th>售价(元)</th><th>库存</th></tr>
<tr onclick="pickDrug(this)"><td>苯磺酸氨氯地平片</td><td>5mg×7片</td><td></td><td>23.80</td><td>86</td></tr>
<tr onclick="pickDrug(this)"><td>苯磺酸左氨氯地平片</td><td>2.5mg×14片</td><td></td><td>28.50</td><td>40</td></tr>
<tr onclick="pickDrug(this)"><td>氨氯地平贝那普利片</td><td>5mg×7片</td><td></td><td>45.00</td><td>12</td></tr>
</table>
</div>
</div>
<div class="ro-row" style="margin-top:210px">
<div class="ro-box">规格<b>5mg×7片</b></div>
<div class="ro-box">单位<b></b></div>
<div class="ro-box">售价<b>23.80 元</b></div>
<div class="ro-box">库存<b>86</b></div>
</div>
<div class="fld" style="margin-bottom:14px"><span class="fld__label" style="width:88px"><span class="fld__req">*</span>数量</span>
<span class="stepper">
<button onclick="step(-1)"></button><input id="qty" value="2"><button onclick="step(1)"></button>
</span>
<span style="font-size:12px;color:#969eb0;margin-left:8px">不可超过库存 86</span>
</div>
<div class="fld"><span class="fld__label" style="width:88px"><span class="fld__req">*</span>用法用量</span><input value="口服,一日1次,一次1片"></div>
<div class="fld" style="margin-bottom:14px"><span class="fld__label" style="width:88px"><span class="fld__req">*</span>药物名称</span><input id="medName" placeholder="请输入药物名称"></div>
<div class="fld"><span class="fld__label" style="width:88px"><span class="fld__req">*</span>用法用量</span><input id="medUsage" placeholder="如:口服,一日1次,一次1片"></div>
</div>
<div class="modal__foot">
<button class="btn" onclick="closeModal('medModal')">取 消</button>
<!-- [交互] 确认后生成一张用药卡片加入用药情况 -->
<button class="btn btn--primary" onclick="closeModal('medModal')">确 认</button>
<!-- [交互] 确认后生成一张用药卡片加入用药情况,可多次新增 -->
<button class="btn btn--primary" onclick="addMed()">确 认</button>
</div>
</div>
</div>
@@ -319,31 +331,69 @@
</div>
<script>
// 返回来源页面:优先取 referrer,取不到则回退浏览器历史
function goBack() {
if (document.referrer) { location.href = document.referrer; }
else { history.back(); }
}
// 从 URL 参数回填员工信息(由任务中心「进行随访」带入)
(function () {
var p = new URLSearchParams(location.search);
if (!p.get('name')) return;
// 带入了员工信息(来自任务中心)时隐藏姓名搜索行;无参数(来自随访管理)则保留搜索
document.querySelector('.inquiry').style.display = 'none';
document.getElementById('empName').value = p.get('name');
document.getElementById('empGender').value = p.get('gender') || '';
document.getElementById('empAge').value = p.get('age') || '';
document.getElementById('empNo').value = p.get('empno') || '';
var unit = p.get('unit') || '', dept = p.get('dept') || '';
document.getElementById('empUnitDept').value = dept ? (unit + ' / ' + dept) : unit;
var tagClass = { '高血压': 'tag--ht', '糖尿病': 'tag--dm', '冠心病': 'tag--chd', '肥胖': 'tag--ob', '其他': 'tag--oth' };
var tags = (p.get('tags') || '').split(',').filter(Boolean);
document.getElementById('empTags').innerHTML = tags.map(function (t) {
return '<span class="tag ' + (tagClass[t] || 'tag--oth') + '">' + t + '</span>';
}).join('');
})();
function openModal(id) { document.getElementById(id).classList.add('open'); }
function closeModal(id) { document.getElementById(id).classList.remove('open'); }
// 搜索结果回填:收起浮层
function pickEmp() { document.getElementById('iqResult').style.display = 'none'; }
// 药品选中:隐藏结果浮层并回填只读区
function pickDrug(tr) {
document.querySelector('.drug-list').style.display = 'none';
var tds = tr.querySelectorAll('td');
var boxes = document.querySelectorAll('.ro-box b');
boxes[0].textContent = tds[1].textContent;
boxes[1].textContent = tds[2].textContent;
boxes[2].textContent = tds[3].textContent + ' 元';
boxes[3].textContent = tds[4].textContent;
}
// 数量步进(上限为库存)
function step(d) {
var el = document.getElementById('qty');
var v = parseInt(el.value || '1', 10) + d;
if (v < 1) v = 1;
if (v > 86) v = 86;
el.value = v;
// 新增用药:手动录入药物名称与用法用量,生成用药卡片(可多次新增)
function addMed() {
var name = document.getElementById('medName').value.trim();
var usage = document.getElementById('medUsage').value.trim();
if (!name) { alert('请输入药物名称'); return; }
if (!usage) { alert('请输入用法用量'); return; }
var card = document.createElement('div');
card.className = 'med-card';
card.innerHTML = '<b>' + name + '</b><br>用法用量:' + usage +
'<div class="med-card__ops"><span class="op-del" onclick="this.parentNode.parentNode.remove()">删除</span></div>';
document.querySelector('.med-grid').appendChild(card);
document.getElementById('medName').value = '';
document.getElementById('medUsage').value = '';
closeModal('medModal');
}
// 手写签名(页内弹窗)
function openSign() { document.getElementById('signModal').classList.add('open'); }
function closeSign() { document.getElementById('signModal').classList.remove('open'); }
// 签字方式切换:手写签名 / 签字图片(两者选其一)
function switchSignType(type) {
var isHand = type === 'hand';
document.getElementById('signHandBox').style.display = isHand ? 'flex' : 'none';
document.getElementById('signImgBox').style.display = isHand ? 'none' : 'flex';
}
// 签字图片:读取上传图片并预览
function onSignImg(input) {
var file = input.files && input.files[0];
if (!file) return;
var reader = new FileReader();
reader.onload = function (e) {
var box = document.getElementById('signImgBox');
box.innerHTML = '<img src="' + e.target.result + '" style="max-width:100%;max-height:92px;object-fit:contain">' +
'<span style="font-size:11px;color:#969eb0">已上传 · 点击可重新上传</span>';
};
reader.readAsDataURL(file);
}
var canvas = document.getElementById('signCanvas');
var ctx = canvas.getContext('2d');
var drawing = false, hasInk = false;
@@ -366,7 +416,7 @@
}
function confirmSign() {
if (!hasInk) { alert('您还没有进行签字!'); return; }
var box = document.querySelector('.sign-box');
var box = document.getElementById('signHandBox');
box.innerHTML = '<span style="font-size:26px;font-family:KaiTi,serif;color:#333">岳春生</span><span style="font-size:11px">已签名 · 点击可重签</span>';
closeSign();
}
+39 -13
View File
@@ -44,6 +44,8 @@
/* 签名块 */
.sign-box { flex: 1; height: 130px; border: 1px dashed #b7c3d6; border-radius: 8px; background: #f7f9fc; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; color: #969eb0; font-size: 13px; cursor: pointer; }
.sign-box svg { width: 22px; height: 22px; stroke: #969eb0; fill: none; stroke-width: 2; }
.radio { display: flex; gap: 16px; align-items: center; font-size: 13px; color: #333; }
.radio input { accent-color: #1890ff; width: 14px; height: 14px; }
.drawer__foot { height: 60px; background: #fff; display: flex; align-items: center; justify-content: center; gap: 14px; flex-shrink: 0; box-shadow: 0 -2px 6px rgba(74,90,127,.06); }
/* 页内弹窗:手写签名 */
.overlay { position: absolute; inset: 0; background: rgba(15,23,42,.45); z-index: 60; display: none; align-items: center; justify-content: center; }
@@ -120,9 +122,8 @@
<div class="fld"><span class="fld__label"><span class="fld__req">*</span>综合解读建议</span>
<textarea placeholder="请输入综合解读建议">血压、血糖控制欠佳,建议调整降压方案并内分泌科评估降糖治疗;加强生活方式干预,2 周后门诊复查。</textarea>
</div>
<div class="fld"><span class="fld__label">重新分类</span>
<div class="fld"><span class="fld__label">五类人群分类</span>
<select>
<!-- [交互] 选择 A/B/C/D 类时需完成五类人群信息登记,打开五类人群抽屉: five-class-drawer.html -->
<option>请选择五类人群分类</option>
<option>a-大病人群A</option>
<option selected>b-慢病人群B</option>
@@ -131,23 +132,30 @@
<option>e-健康人群E</option>
</select>
</div>
<button class="btn" style="width:100%" onclick="location.href='five-class-drawer.html'">登记五类人群信息</button>
</div>
<div class="form-card">
<div class="form-card__title">员工确认签字</div>
<div style="font-size:12px;color:#969eb0;margin-bottom:8px">本人已确认健康随访</div>
<div class="fld"><span class="fld__label">签名</span>
<!-- [交互] 点击打开页内手写签名弹窗 -->
<div class="sign-box" onclick="openSign()" style="flex:1">
<svg viewBox="0 0 24 24"><path d="M17 3a2.8 2.8 0 014 4L7.5 20.5 2 22l1.5-5.5z"/></svg>
点击签名
<div class="fld"><span class="fld__label"><span class="fld__req">*</span>签字</span>
<div style="flex:1">
<div class="radio" style="margin-bottom:10px">
<label><input type="radio" name="signType" checked onclick="switchSignType('hand')">手写签名</label>
<label><input type="radio" name="signType" onclick="switchSignType('img')">签字图片</label>
</div>
<!-- [交互] 手写签名:点击打开页内手写签名弹窗 -->
<div class="sign-box" id="signHandBox" onclick="openSign()">
<svg viewBox="0 0 24 24"><path d="M17 3a2.8 2.8 0 014 4L7.5 20.5 2 22l1.5-5.5z"/></svg>
点击签名
</div>
<!-- [交互] 签字图片:点击上传图片,与手写签名两者选其一即可 -->
<div class="sign-box" id="signImgBox" style="display:none" onclick="document.getElementById('signImgInput').click()">
<svg viewBox="0 0 24 24"><path d="M12 16V4M7 9l5-5 5 5"/><path d="M4 20h16"/></svg>
上传签字图片
</div>
<input type="file" id="signImgInput" accept="image/*" style="display:none" onchange="onSignImg(this)">
</div>
</div>
<div class="fld"><span class="fld__label">签字图片</span>
<!-- [交互] 上传签字图片(仅 png/jpg),旧系统调起相册/拍照 -->
<select style="height:32px;padding:6px 10px"><option>上传文件(png/jpg)…</option></select>
</div>
</div>
</div>
</div>
@@ -185,6 +193,24 @@
// 手写签名(页内弹窗)
function openSign() { document.getElementById('signModal').classList.add('open'); }
function closeSign() { document.getElementById('signModal').classList.remove('open'); }
// 签字方式切换:手写签名 / 签字图片(两者选其一)
function switchSignType(type) {
var isHand = type === 'hand';
document.getElementById('signHandBox').style.display = isHand ? 'flex' : 'none';
document.getElementById('signImgBox').style.display = isHand ? 'none' : 'flex';
}
// 签字图片:读取上传图片并预览
function onSignImg(input) {
var file = input.files && input.files[0];
if (!file) return;
var reader = new FileReader();
reader.onload = function (e) {
var box = document.getElementById('signImgBox');
box.innerHTML = '<img src="' + e.target.result + '" style="max-width:100%;max-height:100px;object-fit:contain">' +
'<span style="font-size:11px;color:#969eb0">已上传 · 点击可重新上传</span>';
};
reader.readAsDataURL(file);
}
var canvas = document.getElementById('signCanvas');
var ctx = canvas.getContext('2d');
var drawing = false, hasInk = false;
@@ -207,7 +233,7 @@
}
function confirmSign() {
if (!hasInk) { alert('您还没有进行签字!'); return; }
var box = document.querySelector('.sign-box');
var box = document.getElementById('signHandBox');
box.innerHTML = '<span style="font-size:26px;font-family:KaiTi,serif;color:#333">石维国</span><span style="font-size:11px">已签名 · 点击可重签</span>';
closeSign();
}
+3 -12
View File
@@ -205,7 +205,7 @@
</div>
</div>
<div class="login-form__item">
<!-- [交互] 点击登录,校验通过后跳转至任务中心(主页): ./task.html -->
<!-- [交互] 点击登录,直接跳转至任务中心(主页): ./task.html -->
<button class="login-form__submit" onclick="doLogin()">登 录</button>
</div>
</div>
@@ -220,18 +220,9 @@
captchaIdx = (captchaIdx + 1) % captchaList.length;
document.getElementById('captchaText').textContent = captchaList[captchaIdx];
}
// 登录校验与跳转(原型不做真实鉴权)
// 登录跳转(原型不做鉴权校验,直接进入系统
function doLogin() {
var toast = document.getElementById('toast');
function showToast(msg) {
toast.textContent = msg;
toast.style.display = 'block';
setTimeout(function () { toast.style.display = 'none'; }, 1600);
}
if (!document.getElementById('username').value) { showToast('请输入账号!'); return; }
if (!document.getElementById('password').value) { showToast('请输入密码!'); return; }
showToast('登录成功,正在进入系统…');
setTimeout(function () { location.href = './task.html'; }, 800);
location.href = './task.html';
}
</script>
+25 -20
View File
@@ -161,39 +161,39 @@
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待随访 2 次</span><span class="pill pill--wait">待随访</span></div>
<div class="tcard__dates">计划随访:2026-09-08 截止日期:2026-09-15</div>
<div class="info-block"><b>岳春生</b> 男 · 54岁 · 1035678<br><span class="tag tag--ht">高血压</span><span class="tag tag--dm">糖尿病</span><br>陕E作业区管理四中心</div>
<!-- [交互] 点击打开新增随访抽屉: follow-drawer.html -->
<button class="tcard__btn" onclick="location.href='follow-drawer.html'">进行随访</button>
<div class="info-block"><b>岳春生</b> 男 · 54岁 · 1035678<br><span class="tag tag--ht">高血压</span><span class="tag tag--dm">糖尿病</span><br>采油一厂-信息部</div>
<!-- [交互] 点击打开新增随访抽屉并带入员工信息: follow-drawer.html -->
<button class="tcard__btn" onclick="goFollow('岳春生','男','54','1035678','采油一厂','信息部','高血压,糖尿病')">进行随访</button>
</div>
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待随访 1 次</span><span class="pill pill--over">已逾期</span></div>
<div class="tcard__dates">计划随访:2026-08-25 截止日期:2026-09-01</div>
<div class="info-block"><b>田淑珍</b> 女 · 61岁 · 1042237<br><span class="tag tag--chd">冠心病</span><br>陕E作业区转运站</div>
<button class="tcard__btn" onclick="location.href='follow-drawer.html'">进行随访</button>
<div class="info-block"><b>田淑珍</b> 女 · 61岁 · 1042237<br><span class="tag tag--chd">冠心病</span><br>采油一厂-转运站</div>
<button class="tcard__btn" onclick="goFollow('田淑珍','女','61','1042237','采油一厂','转运站','冠心病')">进行随访</button>
</div>
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待随访 3 次</span><span class="pill pill--wait">待随访</span></div>
<div class="tcard__dates">计划随访:2026-09-12 截止日期:2026-09-19</div>
<div class="info-block"><b>尹立春</b> 男 · 47岁 · 1028945<br><span class="tag tag--ob">肥胖</span><span class="tag tag--oth">其他</span><br>陕E作业区注水大队</div>
<button class="tcard__btn" onclick="location.href='follow-drawer.html'">进行随访</button>
<div class="info-block"><b>尹立春</b> 男 · 47岁 · 1028945<br><span class="tag tag--ob">肥胖</span><span class="tag tag--oth">其他</span><br>采油一厂-注水大队</div>
<button class="tcard__btn" onclick="goFollow('尹立春','男','47','1028945','采油一厂','注水大队','肥胖,其他')">进行随访</button>
</div>
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待随访 1 次</span><span class="pill pill--wait">待随访</span></div>
<div class="tcard__dates">计划随访:2026-09-10 截止日期:2026-09-17</div>
<div class="info-block"><b>戴文广</b> 男 · 58岁 · 1031002<br><span class="tag tag--ht">高血压</span><br>采油一大队</div>
<button class="tcard__btn" onclick="location.href='follow-drawer.html'">进行随访</button>
<div class="info-block"><b>戴文广</b> 男 · 58岁 · 1031002<br><span class="tag tag--ht">高血压</span><br>采油一厂-作业一大队</div>
<button class="tcard__btn" onclick="goFollow('戴文广','男','58','1031002','采油一厂','作业一大队','高血压')">进行随访</button>
</div>
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待随访 2 次</span><span class="pill pill--wait">待随访</span></div>
<div class="tcard__dates">计划随访:2026-09-14 截止日期:2026-09-21</div>
<div class="info-block"><b>付桂荣</b> 女 · 52岁 · 1044518<br><span class="tag tag--dm">糖尿病</span><br>采油二大队</div>
<button class="tcard__btn" onclick="location.href='follow-drawer.html'">进行随访</button>
<div class="info-block"><b>付桂荣</b> 女 · 52岁 · 1044518<br><span class="tag tag--dm">糖尿病</span><br>采油二厂-作业二大队</div>
<button class="tcard__btn" onclick="goFollow('付桂荣','女','52','1044518','采油二厂','作业二大队','糖尿病')">进行随访</button>
</div>
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待随访 1 次</span><span class="pill pill--wait">待随访</span></div>
<div class="tcard__dates">计划随访:2026-09-16 截止日期:2026-09-23</div>
<div class="info-block"><b>曲志明</b> 男 · 45岁 · 1037781<br><span class="tag tag--chd">冠心病</span><span class="tag tag--ht">高血压</span><br>输气作业区</div>
<button class="tcard__btn" onclick="location.href='follow-drawer.html'">进行随访</button>
<div class="info-block"><b>曲志明</b> 男 · 45岁 · 1037781<br><span class="tag tag--chd">冠心病</span><span class="tag tag--ht">高血压</span><br>输气厂-输气作业区</div>
<button class="tcard__btn" onclick="goFollow('曲志明','男','45','1037781','输气厂','输气作业区','冠心病,高血压')">进行随访</button>
</div>
</div>
@@ -203,7 +203,7 @@
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待解读 1 次<span class="tcard__edit" onclick="openModal('deadlineModal')">编辑</span></span><span class="pill pill--wait">待解读</span></div>
<div class="tcard__dates">截止日期:2026-09-12</div>
<div class="info-block"><b>石维国</b> 男 · 50岁 · 1029334<br><span class="tag tag--ht">高血压</span><br>采油三大队</div>
<div class="info-block"><b>石维国</b> 男 · 50岁 · 1029334<br><span class="tag tag--ht">高血压</span><br>采油三厂-作业三大队</div>
<!-- [交互] 点击打开解读报告抽屉: interpret-drawer.html -->
<button class="tcard__btn" onclick="location.href='interpret-drawer.html'">进行解读</button>
</div>
@@ -211,20 +211,20 @@
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待解读 2 次<span class="tcard__edit" onclick="openModal('deadlineModal')">编辑</span></span><span class="pill pill--wait">待解读</span></div>
<div class="tcard__dates">截止日期:2026-09-18<br>截止日期:2026-09-20</div>
<div class="info-block"><b>赵春霞</b> 女 · 46岁 · 1045690<br><span class="tag tag--dm">糖尿病</span><span class="tag tag--ob">肥胖</span><br>采油一大队</div>
<div class="info-block"><b>赵春霞</b> 女 · 46岁 · 1045690<br><span class="tag tag--dm">糖尿病</span><span class="tag tag--ob">肥胖</span><br>采油一厂-作业一大队</div>
<!-- [交互] 多条待解读,点击先打开「选择解读任务」页内弹窗 -->
<button class="tcard__btn" onclick="openModal('selectModal')">进行解读</button>
</div>
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待解读 1 次<span class="tcard__edit" onclick="openModal('deadlineModal')">编辑</span></span><span class="pill pill--over">已逾期</span></div>
<div class="tcard__dates">截止日期:2026-08-30</div>
<div class="info-block"><b>马福成</b> 男 · 63岁 · 1026011<br><span class="tag tag--chd">冠心病</span><br>运输大队</div>
<div class="info-block"><b>马福成</b> 男 · 63岁 · 1026011<br><span class="tag tag--chd">冠心病</span><br>运输公司-运输大队</div>
<button class="tcard__btn" onclick="location.href='interpret-drawer.html'">进行解读</button>
</div>
<div class="tcard">
<div class="tcard__head"><span class="tcard__times">待解读 1 次<span class="tcard__edit" onclick="openModal('deadlineModal')">编辑</span></span><span class="pill pill--wait">待解读</span></div>
<div class="tcard__dates">截止日期:2026-09-25</div>
<div class="info-block"><b>杨海燕</b> 女 · 49岁 · 1043358<br><span class="tag tag--oth">其他</span><br>供电服务班</div>
<div class="info-block"><b>杨海燕</b> 女 · 49岁 · 1043358<br><span class="tag tag--oth">其他</span><br>供电公司-供电服务班</div>
<button class="tcard__btn" onclick="location.href='interpret-drawer.html'">进行解读</button>
</div>
</div>
@@ -259,7 +259,7 @@
<div class="modal__body">
<div class="emp-card">
<div><b>赵春霞</b> 女 · 46岁 · 工号 1045690</div>
<div>所属单位:CQ能源采油一大队 <span class="tag tag--dm">糖尿病</span><span class="tag tag--ob">肥胖</span></div>
<div>所属单位:CQ能源采油一厂-作业一大队 <span class="tag tag--dm">糖尿病</span><span class="tag tag--ob">肥胖</span></div>
</div>
<div class="section-label">该员工有 2 条待解读任务,请选择一条进入解读:</div>
<!-- [交互] 点击任务行进入解读报告抽屉: interpret-drawer.html -->
@@ -267,13 +267,11 @@
<span class="task-row__name">2025年体检报告</span>
<span class="pill pill--wait">待解读</span>
<span class="task-row__date">截止日期:2026-09-18</span>
<span style="color:#969eb0">高血压、糖尿病</span>
</div>
<div class="task-row" onclick="location.href='interpret-drawer.html'">
<span class="task-row__name">2024年体检报告</span>
<span class="pill pill--wait">待解读</span>
<span class="task-row__date">截止日期:2026-09-20</span>
<span style="color:#969eb0">糖尿病</span>
</div>
</div>
<div class="modal__foot"><button class="btn" onclick="closeModal('selectModal')">取 消</button></div>
@@ -282,6 +280,13 @@
</div>
<script>
// 携带员工信息跳转至新增随访抽屉
function goFollow(name, gender, age, empno, unit, dept, tags) {
var p = new URLSearchParams();
p.set('name', name); p.set('gender', gender); p.set('age', age);
p.set('empno', empno); p.set('unit', unit); p.set('dept', dept); p.set('tags', tags);
location.href = 'follow-drawer.html?' + p.toString();
}
// 随访/解读 Tab 切换(切换时重置表单)
function switchTab(name) {
var isFollow = name === 'follow';
+235 -8
View File
@@ -80,6 +80,10 @@
.col1{left:56px;width:110px;min-width:110px;max-width:110px;}
.col2{left:166px;width:120px;min-width:120px;max-width:120px;}
.th-base.col0,.th-base.col1,.th-base.col2{z-index:5;}
/* 右侧冻结操作列 */
.th-op{position:sticky;right:0;background:#FAFAFA;z-index:5;}
.td-op{position:sticky;right:0;background:#fff;z-index:2;text-align:center;}
tbody tr:hover .td-op{background:#F8FBFF;}
.res-abn{color:var(--danger);font-weight:600;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
@@ -93,6 +97,28 @@
.toast{position:fixed;top:76px;left:50%;transform:translateX(-50%) translateY(-16px);background:#fff;box-shadow:var(--shadow-md);border-radius:var(--radius-sm);padding:10px 20px;font-size:var(--font-sm);color:var(--text-primary);opacity:0;pointer-events:none;transition:all .25s;z-index:1000;display:flex;align-items:center;gap:8px;}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0);}
.toast svg{flex-shrink:0;}
.btn-danger{background:#fff;color:var(--danger);border:1px solid var(--danger);}.btn-danger:hover{background:#fff1f0;}
/* 弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:999;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:640px;max-height:85vh;display:flex;flex-direction:column;}
.modal--wide{width:960px;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--border);flex-shrink:0;}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{flex:1;overflow-y:auto;padding:24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);flex-shrink:0;}
/* 报告内容 */
.report-note{border-radius:var(--radius-sm);padding:12px 16px;font-size:var(--font-sm);line-height:1.9;margin-bottom:16px;}
.report-note--conclusion{border:1px solid #FFD591;background:#FFF7E6;color:#873800;}
.report-note--advice{border:1px solid #B7EB8F;background:#F6FFED;color:#389E0D;}
.report-section{margin-bottom:24px;}
.report-section:last-child{margin-bottom:0;}
.report-section__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);padding-left:10px;border-left:3px solid var(--primary);margin-bottom:12px;line-height:1.4;}
.report-sub__title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:14px 0 8px;}
.report-sub:first-of-type .report-sub__title{margin-top:0;}
.result-abnormal{color:var(--danger);font-weight:600;}
</style>
</head>
<body>
@@ -146,18 +172,26 @@
</div>
<div class="filter-item">
<label>姓名:</label>
<input class="filter-input" type="text" placeholder="请输入" style="width:130px;min-width:unset;">
<input class="filter-input" type="text" id="fName" placeholder="请输入" style="width:130px;min-width:unset;">
</div>
<div class="filter-item">
<label>员工编号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="width:130px;min-width:unset;">
<input class="filter-input" type="text" id="fEmpNo" placeholder="请输入" style="width:130px;min-width:unset;">
</div>
<div class="filter-item">
<label>身份证号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="width:160px;min-width:unset;">
<input class="filter-input" type="text" id="fIdCard" placeholder="请输入" style="width:160px;min-width:unset;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
<div class="filter-item">
<label>异常员工:</label>
<select class="filter-select" style="min-width:100px;" id="abnormalFilter">
<option value="">全部</option>
<option value="abnormal"></option>
<option value="normal"></option>
</select>
</div>
<button class="btn btn-primary" onclick="applyFilter()">查询</button>
<button class="btn btn-default" onclick="resetFilter()">重置</button>
</div>
<!-- 操作栏 -->
@@ -183,6 +217,154 @@
<button class="page-btn active">1</button>
</div>
</div>
<!-- 查看体检报告弹窗(参考常规体检报告页) -->
<div class="modal-overlay" id="report-modal" onclick="if(event.target===this)closeReport()">
<div class="modal modal--wide">
<div class="modal__header">
<div class="modal__title" id="report-title">体检报告</div>
<button class="modal__close" onclick="closeReport()"></button>
</div>
<div class="modal__body">
<!-- 体检结论 -->
<div class="report-section">
<div class="report-section__title">体检结论</div>
<div class="report-note report-note--conclusion">1. 血脂异常:甘油三酯轻度偏高;<br>2. 视力疲劳:双眼裸眼视力下降;<br>3. 其余各项体检指标未见明显异常。</div>
</div>
<!-- 体检建议 -->
<div class="report-section">
<div class="report-section__title">体检建议</div>
<div class="report-note report-note--advice">1. 建议低脂清淡饮食,少油少糖,规律运动,3个月后复查血脂;<br>2. 注意用眼卫生,避免长时间使用电子屏幕,必要时眼科随诊;<br>3. 建议每年进行一次健康体检,动态关注各项指标变化。</div>
</div>
<!-- 物理检查 -->
<div class="report-section">
<div class="report-section__title">物理检查</div>
<div class="report-sub">
<div class="report-sub__title">一般检查</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>身高</td><td>175</td><td>cm</td><td>-</td></tr>
<tr><td>体重</td><td>70.5</td><td>kg</td><td>-</td></tr>
<tr><td>体质指数(BMI)</td><td>23.0</td><td>kg/m²</td><td>18.5~23.9</td></tr>
<tr><td>收缩压</td><td>122</td><td>mmHg</td><td>90~139</td></tr>
<tr><td>舒张压</td><td>78</td><td>mmHg</td><td>60~89</td></tr>
</tbody>
</table>
</div>
<div class="report-sub">
<div class="report-sub__title">视力</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>裸眼视力(右)</td><td class="result-abnormal">0.8 ↓</td><td>-</td><td>≥1.0</td></tr>
<tr><td>裸眼视力(左)</td><td>1.0</td><td>-</td><td>≥1.0</td></tr>
</tbody>
</table>
</div>
</div>
<!-- 内科 -->
<div class="report-section">
<div class="report-section__title">内科</div>
<div class="report-sub">
<div class="report-sub__title">心肺听诊</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>心率</td><td>72</td><td>次/分</td><td>60~100</td></tr>
<tr><td>心律</td><td></td><td>-</td><td>节律整齐</td></tr>
<tr><td>呼吸音</td><td>清晰</td><td>-</td><td>呼吸音清晰</td></tr>
</tbody>
</table>
</div>
<div class="report-sub">
<div class="report-sub__title">腹部触诊</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>肝脏</td><td>未触及</td><td>-</td><td>无肿大</td></tr>
<tr><td>脾脏</td><td>未触及</td><td>-</td><td>无肿大</td></tr>
</tbody>
</table>
</div>
</div>
<!-- 外科 -->
<div class="report-section">
<div class="report-section__title">外科</div>
<div class="report-sub">
<div class="report-sub__title">皮肤与淋巴结</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>皮肤</td><td>无异常</td><td>-</td><td>皮肤黏膜无异常</td></tr>
<tr><td>浅表淋巴结</td><td>未触及肿大</td><td>-</td><td>无肿大</td></tr>
</tbody>
</table>
</div>
<div class="report-sub">
<div class="report-sub__title">甲状腺与脊柱四肢</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>甲状腺</td><td>无肿大</td><td>-</td><td>无肿大</td></tr>
<tr><td>脊柱、四肢关节</td><td>无异常</td><td>-</td><td>活动自如</td></tr>
</tbody>
</table>
</div>
</div>
<!-- 化学检查 -->
<div class="report-section">
<div class="report-section__title">化学检查</div>
<div class="report-sub">
<div class="report-sub__title">血常规</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>白细胞计数</td><td>6.2</td><td>×10⁹/L</td><td>3.5~9.5</td></tr>
<tr><td>红细胞计数</td><td>4.8</td><td>×10¹²/L</td><td>4.3~5.8</td></tr>
<tr><td>血红蛋白</td><td>145</td><td>g/L</td><td>130~175</td></tr>
<tr><td>血小板计数</td><td>220</td><td>×10⁹/L</td><td>125~350</td></tr>
</tbody>
</table>
</div>
<div class="report-sub">
<div class="report-sub__title">肝功能</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>丙氨酸氨基转移酶(ALT)</td><td>25</td><td>U/L</td><td>9~50</td></tr>
<tr><td>天门冬氨酸氨基转移酶(AST)</td><td>22</td><td>U/L</td><td>15~40</td></tr>
</tbody>
</table>
</div>
<div class="report-sub">
<div class="report-sub__title">血脂四项</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>总胆固醇</td><td>4.6</td><td>mmol/L</td><td>&lt;5.2</td></tr>
<tr><td>甘油三酯</td><td class="result-abnormal">1.8 ↑</td><td>mmol/L</td><td>&lt;1.7</td></tr>
<tr><td>高密度脂蛋白胆固醇</td><td>1.25</td><td>mmol/L</td><td>&gt;1.04</td></tr>
<tr><td>低密度脂蛋白胆固醇</td><td>2.8</td><td>mmol/L</td><td>&lt;3.4</td></tr>
</tbody>
</table>
</div>
<div class="report-sub">
<div class="report-sub__title">血糖</div>
<table>
<thead><tr><th>项目名称</th><th>结果</th><th>单位</th><th>参考值</th></tr></thead>
<tbody>
<tr><td>空腹血糖</td><td>5.3</td><td>mmol/L</td><td>3.9~6.1</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-primary" onclick="closeReport()">关闭</button>
</div>
</div>
</div>
</main>
<!-- 轻提示 -->
@@ -305,29 +487,53 @@ function buildHead(){
s.items.forEach(function(it){r3.push('<th class="item">'+it+'</th>');});
});
});
/* 列表最后为操作列,随右侧冻结便于横向浏览时随时可见 */
r1.push('<th class="th-op" rowspan="3">操作</th>');
return '<table><thead><tr>'+r1.join('')+'</tr><tr>'+r2.join('')+'</tr><tr>'+r3.join('')+'</tr></thead>';
}
function buildBody(){
var items=allItems();
var baseKeys=['idx','name','empNo','gender','age','idCard','unit','dept','hospital','checkDate'];
var rows=MASTER_ROWS.map(function(r){
var rows=getDisplayRows().map(function(r,ri){
var cells='';
baseKeys.forEach(function(k,i){
var cls='td-base'+(i<3?' col'+i:'');
cells+='<td class="'+cls+'">'+r[k]+'</td>';
var txt=k==='idx'?(ri+1):r[k];
cells+='<td class="'+cls+'">'+txt+'</td>';
});
items.forEach(function(col){
var val=r.r[col.cat+'|'+col.name]||r.r[col.name];
if(!val)val=[(CAT_DEFAULTS[col.cat]||['-'])[0]];
cells+='<td class="item'+(val[1]?' res-abn':'')+'">'+val[0]+'</td>';
});
cells+='<td class="td-op"><span class="link" onclick="openReport(\''+r.name+'\')">查看报告</span></td>';
return '<tr>'+cells+'</tr>';
}).join('');
return '<tbody>'+rows+'</tbody></table>';
}
/* 员工是否存在异常指标(任一项目结果带异常标记) */
function hasAbnormal(r){
for(var k in r.r){if(r.r[k][1])return true;}
return false;
}
/* 按筛选条件取当前展示行:异常员工 + 姓名/员工编号/身份证号模糊匹配 */
function getDisplayRows(){
var v=document.getElementById('abnormalFilter').value;
var name=document.getElementById('fName').value.trim();
var empNo=document.getElementById('fEmpNo').value.trim();
var idCard=document.getElementById('fIdCard').value.trim();
return MASTER_ROWS.filter(function(r){
if(v==='abnormal'&&!hasAbnormal(r))return false;
if(v==='normal'&&hasAbnormal(r))return false;
if(name&&r.name.indexOf(name)<0)return false;
if(empNo&&r.empNo.indexOf(empNo)<0)return false;
if(idCard&&r.idCard.indexOf(idCard)<0)return false;
return true;
});
}
function renderBigTable(){
document.getElementById('bigTable').innerHTML=buildHead()+buildBody();
document.getElementById('pageTotal').textContent='共 '+MASTER_ROWS.length+' 条';
document.getElementById('pageTotal').textContent='共 '+getDisplayRows().length+' 条';
var k=document.getElementById('keyCount');
if(k)k.textContent='重点项目 '+allItems().length+' 列';
}
@@ -345,6 +551,27 @@ function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
var sub=active.closest('.sidebar-subgroup');
while(sub){sub.classList.add('open');sub=sub.parentElement.closest('.sidebar-subgroup');}
})();
/* 查看体检报告弹窗(版式参考常规体检报告页) */
function openReport(name){
document.getElementById('report-title').textContent=name+' · 体检报告';
document.getElementById('report-modal').classList.add('open');
}
function closeReport(){
document.getElementById('report-modal').classList.remove('open');
}
document.addEventListener('keydown',function(e){if(e.key==='Escape')closeReport();});
function applyFilter(){
renderBigTable();
showToast('查询完成');
}
function resetFilter(){
document.getElementById('abnormalFilter').value='';
document.getElementById('fName').value='';
document.getElementById('fEmpNo').value='';
document.getElementById('fIdCard').value='';
renderBigTable();
showToast('已重置筛选条件');
}
renderBigTable();
</script>
</body>
+173 -12
View File
@@ -80,6 +80,36 @@
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.progress-bar{width:120px;height:8px;background:#f0f0f0;border-radius:4px;overflow:hidden;display:inline-block;vertical-align:middle;margin-right:8px;}
.progress-bar__fill{height:100%;border-radius:4px;background:var(--primary);}
/* 表头计算规则提示(问号+悬浮气泡),与单位体检人数统计页一致 */
.th-help{position:relative;display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;background:#BFBFBF;color:#fff;font-size:10px;font-weight:600;cursor:help;vertical-align:middle;margin-left:4px;}
.th-help:hover{background:var(--primary);}
.th-help__tip{visibility:hidden;opacity:0;position:absolute;top:calc(100% + 9px);left:50%;transform:translateX(-50%);background:rgba(0,0,0,0.8);color:#fff;font-size:var(--font-sm);font-weight:400;padding:7px 12px;border-radius:var(--radius-sm);white-space:nowrap;z-index:130;transition:opacity .15s;line-height:1.5;}
.th-help__tip::before{content:'';position:absolute;top:-4px;left:50%;margin-left:-4px;width:8px;height:8px;background:rgba(0,0,0,0.8);transform:rotate(45deg);}
.th-help__tip--right{left:auto;right:-7px;transform:none;}
.th-help__tip--right::before{left:auto;right:11px;margin-left:0;}
.th-help:hover .th-help__tip{visibility:visible;opacity:1;}
/* 三级单位tab下才显示的部门列 */
.col-dept{display:none;}
body.level-3 .col-dept{display:table-cell;}
/* 前三列冻结:序号/单位/部门,做法对齐个人体检数据大表 */
.th-frz{position:sticky;background:#FAFAFA;z-index:5;}
.td-frz{position:sticky;background:#fff;z-index:2;}
tr:hover .td-frz{background:#F8FBFF;}
.frz0{left:0;width:56px;min-width:56px;max-width:56px;}
.frz1{left:56px;width:110px;min-width:110px;max-width:110px;}
.frz2{left:166px;width:120px;min-width:120px;max-width:120px;}
/* 人数列表弹窗 */
.modal-mask{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;display:flex;align-items:center;justify-content:center;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);width:960px;max-width:92vw;display:flex;flex-direction:column;max-height:80vh;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);flex-shrink:0;}
.modal__title{font-size:var(--font-base);font-weight:600;}
.modal__close{font-size:22px;color:var(--text-placeholder);cursor:pointer;line-height:1;}
.modal__close:hover{color:var(--text-secondary);}
.modal__body{padding:0 24px;overflow:auto;}
.modal__body table{width:100%;}
.modal__footer{display:flex;align-items:center;justify-content:space-between;padding:12px 24px;border-top:1px solid var(--border);flex-shrink:0;}
.pager{display:flex;align-items:center;gap:6px;}
.pager .page-btn{width:28px;height:28px;}
</style>
</head>
<body>
@@ -119,8 +149,8 @@
<main class="main">
<!-- 单位切换Tab -->
<div style="display:flex;align-items:center;gap:0;margin-bottom:16px;">
<button class="btn btn-primary" style="border-radius:var(--radius-sm) 0 0 var(--radius-sm);">二级单位</button>
<button class="btn btn-default" style="border-radius:0 var(--radius-sm) var(--radius-sm) 0;border-left:none;">三级单位</button>
<button class="btn btn-primary unit-level-tab" style="border-radius:var(--radius-sm) 0 0 var(--radius-sm);" onclick="switchUnitLevel(this)">二级单位</button>
<button class="btn btn-default unit-level-tab" style="border-radius:0 var(--radius-sm) var(--radius-sm) 0;border-left:none;" onclick="switchUnitLevel(this)">三级单位</button>
</div>
<!-- 筛选栏 -->
@@ -159,21 +189,23 @@
<div class="table-card__title">单位报表数据</div>
</div>
<div class="table-card__content">
<table>
<table id="unitTable">
<thead>
<!-- 合并表头:重点指标异常人数 -->
<tr>
<th rowspan="2">序号</th><th rowspan="2">单位</th><th rowspan="2">总人数</th><th rowspan="2">应检人数</th><th rowspan="2">已检人数</th><th rowspan="2">未检人数</th><th rowspan="2">承检医院</th><th rowspan="2">签约医院</th><th rowspan="2">体检计划日期范围</th>
<th colspan="8" style="text-align:center;">重点指标异常人数</th>
<th rowspan="2">操作</th>
</tr>
<tr>
<th>BMI</th><th>血压mmHg</th><th>总胆固醇mmol/L</th><th>高密度胆固醇mmol/L</th><th>低密度胆固醇mmol/L</th><th>甘油三酯mmol/L</th><th>血糖mmol/L</th><th>尿酸μmol/L</th>
<th class="th-frz frz0">序号</th><th class="th-frz frz1">单位</th><th class="th-frz frz2 col-dept">部门</th><th>体检年份</th><th>签约医院</th><th>承检医院</th><th>体检计划日期范围</th>
<th>总人数</th><th>应检人数</th><th>已选项目人数</th><th>已预约人数</th><th>已检人数</th><th>未检人数</th>
<th>受检率<span class="th-help">?<span class="th-help__tip">受检率 = 实际检查人数 ÷ 应检人数</span></span></th>
<th>检出率<span class="th-help">?<span class="th-help__tip">检出率 = 异常人数 ÷ 实际检查人数</span></span></th>
<th>患病率<span class="th-help">?<span class="th-help__tip">患病率 = 单病种异常人数 ÷ 实际参加检查人数</span></span></th>
<th>重点指标异常人数</th><th>冠脉CTA异常人数</th><th>防癌筛查异常人数</th>
<th>计划总费用(元)</th><th>实际总费用(元)</th><th>人均费用(元)</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>公司机关</td><td>1000</td><td>1000</td><td>800</td><td>200</td><td>宝石花医院</td><td>宝石花医院</td><td>2025-06-23至2025-08-31</td><td>52</td><td>5</td><td>2</td><td>4</td><td>5</td><td>8</td><td>10</td><td>3</td><td><span class="link">查看详情</span></td></tr>
<tr><td>2</td><td>采油一厂</td><td>1000</td><td>1000</td><td>800</td><td>200</td><td>宝石花医院</td><td>宝石花医院</td><td>2025-06-23至2025-08-31</td><td>52</td><td>5</td><td>2</td><td>4</td><td>5</td><td>8</td><td>10</td><td>3</td><td><span class="link">查看详情</span></td></tr>
<tr><td class="td-frz frz0">1</td><td class="td-frz frz1">公司机关</td><td class="td-frz frz2 col-dept">综合管理部</td><td>2025</td><td>宝石花医院</td><td>宝石花医院</td><td>2025-06-23至2025-08-31</td><td>1000</td><td>1000</td><td>980</td><td>850</td><td>800</td><td>200</td><td>80.0%</td><td>41.0%</td><td>18.0%</td><td>328</td><td>9</td><td>12</td><td>2,600,000</td><td>2,180,000</td><td>2,725.00</td></tr>
<tr><td class="td-frz frz0">2</td><td class="td-frz frz1">采油一厂</td><td class="td-frz frz2 col-dept">采油作业一区</td><td>2025</td><td>宝石花医院</td><td>西安高新医院</td><td>2025-07-01至2025-09-15</td><td>3200</td><td>3000</td><td>2860</td><td>2450</td><td>2300</td><td>700</td><td>76.7%</td><td>40.0%</td><td>16.5%</td><td>920</td><td>24</td><td>35</td><td>7,800,000</td><td>6,210,000</td><td>2,700.00</td></tr>
<tr><td class="td-frz frz0">3</td><td class="td-frz frz1">采油二厂</td><td class="td-frz frz2 col-dept">采油作业二区</td><td>2025</td><td>宝石花医院</td><td>长安心血管医院</td><td>2025-07-10至2025-09-30</td><td>2800</td><td>2600</td><td>2480</td><td>2100</td><td>1950</td><td>650</td><td>75.0%</td><td>40.0%</td><td>17.2%</td><td>780</td><td>21</td><td>28</td><td>6,760,000</td><td>5,265,000</td><td>2,700.00</td></tr>
<tr><td class="td-frz frz0">4</td><td class="td-frz frz1">公司机关</td><td class="td-frz frz2 col-dept">综合管理部</td><td>2024</td><td>宝石花医院</td><td>宝石花医院</td><td>2024-06-20至2024-08-25</td><td>980</td><td>980</td><td>950</td><td>830</td><td>790</td><td>190</td><td>80.6%</td><td>39.0%</td><td>17.5%</td><td>308</td><td>8</td><td>10</td><td>2,450,000</td><td>2,020,000</td><td>2,556.96</td></tr>
</tbody>
</table>
</div>
@@ -189,7 +221,136 @@
</div>
</main>
<!-- 人数列表弹窗 -->
<div class="modal-mask" id="person-modal" style="display:none;" onclick="if(event.target===this)hidePersonList()">
<div class="modal">
<div class="modal__header">
<div class="modal__title" id="person-modal-title">人员列表</div>
<span class="modal__close" onclick="hidePersonList()"></span>
</div>
<div class="modal__body">
<div id="person-modal-toolbar" style="display:flex;justify-content:flex-end;padding:12px 0;">
<button class="btn btn-primary" style="height:32px;" onclick="exportPersonList()">
<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="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
导出人员列表
</button>
</div>
<table>
<thead id="person-modal-head"></thead>
<tbody id="person-modal-body"></tbody>
</table>
</div>
<div class="modal__footer">
<span style="font-size:var(--font-sm);color:var(--text-secondary);" id="person-modal-count"></span>
<div class="pager">
<button class="page-btn" onclick="personPrev()"></button>
<span style="font-size:var(--font-sm);color:var(--text-secondary);" id="person-modal-page">1 / 1</span>
<button class="page-btn" onclick="personNext()"></button>
</div>
</div>
</div>
</div>
<script>
/* ===== 人数列点击 → 人员列表弹窗 =====
除"总人数"外的人数列(td 索引 8应检/9已选项目/10已预约/11已检/12未检/16重点指标异常/17冠脉CTA异常/18防癌筛查异常)标蓝可点击 */
var COUNT_COLS=[8,9,10,11,12,16,17,18];
/* 各指标对应的名单附加列:[列名, 生成函数(i)] */
var PERSON_EXTRA={
8:['体检计划',function(row){return row.year+'年度员工体检';}],
9:['已选项目数',function(row,i){return 15+i%6;}],
10:['预约日期',function(row,i){return personDate(row,i+5);}],
11:['体检状态',function(){return '<span class="tag tag-green">已检</span>';}],
12:['未检原因',function(row,i){return ['未预约','已预约未体检','弃检'][i%3];}],
16:['异常指标',function(row,i){return ['血压 158/96 mmHg↑','尿酸 428 μmol/L↑','甘油三酯 1.80 mmol/L↑','总胆固醇 5.96 mmol/L↑','空腹血糖 8.2 mmol/L↑','BMI 28.4↑','低密度胆固醇 3.96 mmol/L↑','高密度胆固醇 0.89 mmol/L↓'][i%8];}],
17:['CTA结论',function(row,i){return ['LAD 中段狭窄 25%CAD-RADS 2','钙化积分 Agatston 156(中度)','RCA 近段非钙化斑块、轻度狭窄','LCX 远段钙化斑块、CAD-RADS 2'][i%4];}],
18:['筛查异常项',function(row,i){return ['Septin9 基因甲基化 阳性','CA724 ↑(38.6 U/mL','便潜血 阳性','CEA ↑(6.2 ng/mL'][i%4];}]
};
var SURNAMES=['张','王','李','赵','刘','陈','杨','黄','周','吴'];
var GIVEN_M=['建国','志强','海涛','明辉','文博','永刚','振华','晓东'];
var GIVEN_F=['丽华','晓燕','静怡','秀兰','雅琴','桂芳','玉梅','佳宁'];
var DEPTS=['综合管理部','安全环保部','生产技术部','设备物资部','采油作业一区','采油作业二区','输油大队','中心站'];
/* 依计划日期范围确定性生成体检/预约日期 */
function personDate(row,seed){
var m=row.range.match(/(\d{4})-(\d{2})-(\d{2})至(\d{4})-(\d{2})-(\d{2})/);
if(!m)return row.range;
var d1=new Date(+m[1],+m[2]-1,+m[3]),d2=new Date(+m[4],+m[5]-1,+m[6]);
var span=Math.round((d2-d1)/86400000);
var d=new Date(d1.getTime()+(((span*(seed%11))+7)%Math.max(span,1))*86400000);
return d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0')+'-'+String(d.getDate()).padStart(2,'0');
}
function showPersonList(r,c){
var tr=document.querySelectorAll('#unitTable tbody tr')[r];
var th=document.querySelectorAll('#unitTable thead th')[c];
var row={unit:tr.children[1].textContent,year:tr.children[3].textContent,hospital:tr.children[5].textContent,range:tr.children[6].textContent};
PERSON_LIST={col:c,row:row,total:parseInt(tr.children[c].textContent.replace(/,/g,''),10),page:0};
var colName=th.firstChild.textContent.trim();
PERSON_LIST.colName=colName;
document.getElementById('person-modal-title').textContent=row.unit+''+row.year+'年)「'+colName+'」人员列表';
renderPersonPage();
document.getElementById('person-modal').style.display='flex';
}
/* 第 i 人(全局序号)的名单行数据,渲染与导出共用同一确定性生成 */
function personRowData(i){
var row=PERSON_LIST.row;
var seed=PERSON_LIST.col*97+row.unit.charCodeAt(0)+i;
var sex=(seed+i)%2?'女':'男';
var name=SURNAMES[(seed*7+i)%10]+(sex==='男'?GIVEN_M[(seed+i)%8]:GIVEN_F[(seed+i)%8]);
var code='CQ'+String(100000+PERSON_LIST.col*1000+i*13+Math.floor(i/10));
var extra=PERSON_EXTRA[PERSON_LIST.col];
return [''+(i+1),name,code,sex,''+(28+(seed*7+i*11)%30),DEPTS[(seed+i*3)%8],row.hospital,personDate(row,i+1),String(extra[1](row,i)).replace(/<[^>]+>/g,'')];
}
function renderPersonPage(){
var extra=PERSON_EXTRA[PERSON_LIST.col];
document.getElementById('person-modal-head').innerHTML='<tr><th>序号</th><th>姓名</th><th>员工编号</th><th>性别</th><th>年龄</th><th>部门</th><th>体检医院</th><th>体检日期</th><th>'+extra[0]+'</th></tr>';
var start=PERSON_LIST.page*10,html='';
for(var i=start;i<Math.min(start+10,PERSON_LIST.total);i++){
var cells=personRowData(i);
/* 体检状态列回挂绿色标签样式 */
if(PERSON_LIST.col===11)cells[8]='<span class="tag tag-green">'+cells[8]+'</span>';
html+='<tr><td>'+cells.join('</td><td>')+'</td></tr>';
}
document.getElementById('person-modal-body').innerHTML=html;
var pages=Math.max(1,Math.ceil(PERSON_LIST.total/10));
document.getElementById('person-modal-count').textContent='共 '+PERSON_LIST.total+' 人';
document.getElementById('person-modal-page').textContent=(PERSON_LIST.page+1)+' / '+pages;
}
function personPrev(){if(PERSON_LIST.page>0){PERSON_LIST.page--;renderPersonPage();}}
function personNext(){var p=Math.max(1,Math.ceil(PERSON_LIST.total/10));if(PERSON_LIST.page<p-1){PERSON_LIST.page++;renderPersonPage();}}
function hidePersonList(){document.getElementById('person-modal').style.display='none';}
/* 导出当前口径全量人员名单(CSV,Excel 兼容) */
function exportPersonList(){
var extra=PERSON_EXTRA[PERSON_LIST.col];
var head=['序号','姓名','员工编号','性别','年龄','部门','体检医院','体检日期',extra[0]];
var rows=[head];
for(var i=0;i<PERSON_LIST.total;i++)rows.push(personRowData(i));
var csv=''+rows.map(function(r){return r.map(function(c){return '"'+String(c).replace(/"/g,'""')+'"';}).join(',');}).join('\r\n');
var a=document.createElement('a');
a.href=URL.createObjectURL(new Blob([csv],{type:'text/csv;charset=utf-8'}));
a.download=PERSON_LIST.row.unit+'_'+PERSON_LIST.row.year+'年_'+PERSON_LIST.colName+'_人员列表.csv';
document.body.appendChild(a);a.click();document.body.removeChild(a);
setTimeout(function(){URL.revokeObjectURL(a.href);},1000);
}
var PERSON_LIST=null;
/* 初始化:人数列标蓝并绑定点击 */
(function(){
document.querySelectorAll('#unitTable tbody tr').forEach(function(tr,r){
COUNT_COLS.forEach(function(c){
var td=tr.children[c];
td.innerHTML='<span class="link" onclick="showPersonList('+r+','+c+')">'+td.textContent+'</span>';
});
});
document.addEventListener('keydown',function(e){if(e.key==='Escape')hidePersonList();});
})();
/* 单位级别TAB切换:三级单位显示部门列 */
function switchUnitLevel(el){
document.querySelectorAll('.unit-level-tab').forEach(function(b){
b.classList.remove('btn-primary');b.classList.add('btn-default');
});
el.classList.remove('btn-default');el.classList.add('btn-primary');
document.body.classList.toggle('level-3', el.textContent.trim()==='三级单位');
}
/* 侧边栏展开/折叠交互 */
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
@@ -224,12 +224,12 @@
<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>开启冠脉CTA体检</th><th>排序序号</th><th>操作</th>
</tr>
</thead>
<tbody id="normal-tbody">
<tr><td>1</td><td>泾河医院</td><td>普通医院</td><td>西安市高陵区西安泾河开发区CQ西路20号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>西安宝石花CQ医院(高陵)</td><td></td><td>1</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
<tr><td>2</td><td>庆阳医院</td><td>指定医院</td><td>甘肃省庆阳市西峰区岐黄大道18号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>庆阳市人民医院体检中心</td><td></td><td>2</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
<tr><td>1</td><td>泾河医院</td><td>普通医院</td><td>西安市高陵区西安泾河开发区CQ西路20号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>西安宝石花CQ医院(高陵)</td><td></td><td></td><td>1</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
<tr><td>2</td><td>庆阳医院</td><td>指定医院</td><td>甘肃省庆阳市西峰区岐黄大道18号</td><td><img class="hospital-img" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='48' viewBox='0 0 72 48'%3E%3Crect width='72' height='48' fill='%231890ff'/%3E%3Crect x='18' y='14' width='36' height='26' rx='2' fill='%23ffffff'/%3E%3Cpath d='M32 20h8v6h6v8h-6v6h-8v-6h-6v-8h6z' fill='%231890ff'/%3E%3C/svg%3E" alt="医院图片"></td><td>庆阳市人民医院体检中心</td><td></td><td></td><td>2</td><td><span class="link" onclick="openEditDrawer(this)">编辑</span> <span class="link" style="margin-left:8px;" onclick="deleteRow(this)">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -321,6 +321,13 @@
<span class="switch-label">是否开启职业体检</span>
</div>
</div>
<div class="form-item">
<div class="form-label">开启冠脉CTA体检</div>
<div class="switch-row">
<div class="switch" id="switch-cta" onclick="this.classList.toggle('on')"></div>
<span class="switch-label">是否开启冠脉CTA体检</span>
</div>
</div>
<div class="form-item">
<div class="form-label">排序序号</div>
<input class="form-input" id="form-sort-normal" type="number" placeholder="数字越小越靠前">
@@ -415,6 +422,7 @@ function resetDrawerFields(){
document.getElementById('form-sort-gastro').value = '';
document.querySelectorAll('input[name="hos-type"]').forEach(function(r){ r.checked = false; });
document.getElementById('switch-oc').classList.remove('on');
document.getElementById('switch-cta').classList.remove('on');
document.getElementById('switch-card').classList.remove('on');
document.getElementById('card-reg-item').style.display = 'none';
document.getElementById('form-gastro-notice').value = '';
@@ -451,7 +459,8 @@ function openEditDrawer(btn){
setHospitalLocked(true, readTd(editingRow, 1), readTd(editingRow, 3));
document.querySelectorAll('input[name="hos-type"]').forEach(function(r){ r.checked = (r.value === readTd(editingRow, 2)); });
document.getElementById('switch-oc').classList.toggle('on', readTd(editingRow, 6) === '是');
document.getElementById('form-sort-normal').value = readTd(editingRow, 7);
document.getElementById('switch-cta').classList.toggle('on', readTd(editingRow, 7) === '是');
document.getElementById('form-sort-normal').value = readTd(editingRow, 8);
} else {
document.getElementById('drawer-title').textContent = '编辑胃肠镜体检医院';
document.getElementById('normal-fields').style.display = 'none';
@@ -554,7 +563,7 @@ function refreshSeq(tbody){
}
/* 生成常规体检行 HTML */
function buildNormalRow(data, hosType, oc, sort){
function buildNormalRow(data, hosType, oc, cta, sort){
return '<td></td>'
+ '<td>' + data.name + '</td>'
+ '<td>' + hosType + '</td>'
@@ -562,6 +571,7 @@ function buildNormalRow(data, hosType, oc, sort){
+ '<td><img class="hospital-img" src="' + HOSPITAL_IMG + '" alt="医院图片"></td>'
+ '<td>' + data.intro + '</td>'
+ '<td>' + (oc ? '是' : '否') + '</td>'
+ '<td>' + (cta ? '是' : '否') + '</td>'
+ '<td>' + sort + '</td>'
+ ROW_ACTIONS;
}
@@ -588,11 +598,13 @@ function saveHospital(){
if(isNormal){
var hosTypeEl = document.querySelector('input[name="hos-type"]:checked');
if(!hosTypeEl){ alert('请选择医院类型'); return; }
var sort = document.getElementById('form-sort-normal').value.trim() || editingRow.children[7].textContent.trim();
var sort = document.getElementById('form-sort-normal').value.trim() || editingRow.children[8].textContent.trim();
var oc = document.getElementById('switch-oc').classList.contains('on');
var cta = document.getElementById('switch-cta').classList.contains('on');
editingRow.children[2].textContent = hosTypeEl.value;
editingRow.children[6].textContent = oc ? '是' : '否';
editingRow.children[7].textContent = sort;
editingRow.children[7].textContent = cta ? '是' : '否';
editingRow.children[8].textContent = sort;
} else {
var needCard = document.getElementById('switch-card').classList.contains('on');
var sortG = document.getElementById('form-sort-gastro').value.trim() || editingRow.children[6].textContent.trim();
@@ -615,7 +627,7 @@ function saveHospital(){
var hosTypeEl = document.querySelector('input[name="hos-type"]:checked');
if(!hosTypeEl){ alert('请选择医院类型'); return; }
var sort = document.getElementById('form-sort-normal').value.trim() || String(seq);
tr.innerHTML = buildNormalRow(data, hosTypeEl.value, document.getElementById('switch-oc').classList.contains('on'), sort);
tr.innerHTML = buildNormalRow(data, hosTypeEl.value, document.getElementById('switch-oc').classList.contains('on'), document.getElementById('switch-cta').classList.contains('on'), sort);
} else {
var needCard = document.getElementById('switch-card').classList.contains('on');
var sortG = document.getElementById('form-sort-gastro').value.trim() || String(seq);
@@ -174,6 +174,7 @@
<div class="notice-tabs">
<div class="notice-tab active" onclick="switchTab('normal')">常规体检</div>
<div class="notice-tab" onclick="switchTab('gastro')">胃肠镜体检</div>
<div class="notice-tab" onclick="switchTab('cta')">冠脉CTA体检</div>
</div>
<!-- 常规体检 -->
@@ -309,6 +310,73 @@
</div>
</div>
</div>
<!-- 冠脉CTA体检 -->
<div class="tab-pane" id="pane-cta">
<div class="notice-card">
<div class="notice-card__header">
<div class="notice-card__title">冠脉CTA体检须知</div>
<div class="notice-card__actions">
<button class="btn btn-default" onclick="openHistory('cta')">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 1a6 6 0 106 6" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/><path d="M7 4v3.5l2.5 1.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
历史版本
</button>
<button class="btn btn-primary" onclick="saveNotice('cta')">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 7l3.5 3.5L12 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
发布生效
</button>
</div>
</div>
<div class="notice-layout">
<div class="notice-editor">
<div class="editor-section__label">弹窗标题</div>
<input class="editor-title-input" id="title-cta" type="text" value="冠脉CTA体检须知" placeholder="请输入弹窗标题" oninput="syncPreview('cta')">
<div class="editor-section__label">须知内容</div>
<div class="editor-toolbar">
<button class="toolbar-btn" title="加粗"><strong>B</strong></button>
<button class="toolbar-btn" title="斜体"><em>I</em></button>
<button class="toolbar-btn" title="下划线"><u>U</u></button>
<div class="toolbar-divider"></div>
<button class="toolbar-btn">有序列表</button>
<button class="toolbar-btn">无序列表</button>
<div class="toolbar-divider"></div>
<button class="toolbar-btn">字号 ▾</button>
<button class="toolbar-btn">颜色 ▾</button>
</div>
<div class="editor-body" id="editor-cta" contenteditable="true" oninput="syncPreview('cta')">1. 检前准备
检查前24小时请避免剧烈运动,检查当天避免吸烟,勿饮用咖啡、浓茶等刺激性饮品,保持情绪平稳。
2. 心率控制
冠脉CTA对心率要求较高,心率过快或心律不齐者,请遵医嘱在检查前服用控制心率药物(如β受体阻滞剂)。
3. 屏气练习
检查需屏气配合以保证图像质量,请提前练习平静状态下屏气10-15秒。检查当天请携带本人身份证。
4. 特别提醒
对碘对比剂过敏、甲状腺功能异常、肾功能不全或妊娠期,请提前告知医生。如需取消预约,请至少提前一天操作。</div>
<div class="editor-footer">
<span class="editor-footer__hint">支持富文本编辑,内容将展示在员工端发起冠脉CTA体检时的弹窗中</span>
</div>
</div>
<div class="notice-preview">
<div class="preview-panel">
<div class="preview-panel__label">
<svg viewBox="0 0 14 14" fill="none"><rect x="3" y="1" width="8" height="12" rx="1.5" stroke="currentColor" stroke-width="1.2"/><path d="M5.5 3h3M5.5 5h3M5.5 7h1.5" stroke="currentColor" stroke-width="1" stroke-linecap="round"/></svg>
移动端弹窗预览
</div>
<div class="preview-phone">
<div class="preview-phone__title" id="preview-title-cta">冠脉CTA体检须知</div>
<div class="preview-phone__content" id="preview-content-cta"></div>
<div class="preview-phone__btns">
<div class="preview-phone__btn preview-phone__btn--cancel">忽略</div>
<div class="preview-phone__btn preview-phone__btn--ok">知晓并继续</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- 历史版本弹窗 -->
@@ -380,11 +448,14 @@ function syncPreview(type) {
// 初始化预览
syncPreview('normal');
syncPreview('gastro');
syncPreview('cta');
// 体检类型名称映射
var TYPE_LABELS = { normal: '常规体检', gastro: '胃肠镜体检', cta: '冠脉CTA体检' };
// 历史版本弹窗
function openHistory(type) {
var label = type === 'normal' ? '常规体检' : '胃肠镜体检';
document.getElementById('history-modal-title').textContent = label + ' — 历史版本';
document.getElementById('history-modal-title').textContent = TYPE_LABELS[type] + ' — 历史版本';
document.getElementById('history-modal').classList.add('open');
}
function closeHistory() {
@@ -393,7 +464,7 @@ function closeHistory() {
// 发布(原型演示)
function saveNotice(type) {
alert((type === 'normal' ? '常规体检' : '胃肠镜体检') + '须知已发布生效');
alert(TYPE_LABELS[type] + '须知已发布生效');
}
</script>
</body>
+10
View File
@@ -1,5 +1,15 @@
# 健康体检模块 CHANGELOG
## [Unreleased] 2026-09-08
### Changed
- `archive-unit.html`(档案/单位报表数据):表头重做为单层不合并表头共 23 列,移除原"重点指标异常人数"BMI/血压/血脂四项/血糖/尿酸 8 个分项列、只保留重点指标异常人数聚合列;新增"体检年份"列(切筛选后行可自证所属年份)与三块口径——过程漏斗(已选项目人数/已预约人数/受检率)、疾病与专项(冠脉CTA异常人数——原大病人数口径替换、防癌筛查异常人数)、费用(计划总费用/实际总费用/人均费用(元)三列自带单位);受检率/检出率/患病率三列表头附问号公式气泡,口径与 `post-unit-count.html` 一致;示例数据 4 行(含 2024 年回看行)各率与费用勾稽一致;二级单位/三级单位 TAB 接通切换——三级单位显示"部门"列(沿用 col-dept 交互);表头 23 列无合并单元格,与数据行对齐已校验;除"总人数"外的人数列(应检/已选项目/已预约/已检/未检/重点指标异常/冠脉CTA异常/防癌筛查异常)数值标蓝可点击,点击弹窗查看该口径人员名单——弹窗标题"单位(年份)「列名」人员列表",列:序号/姓名/员工编号/性别/年龄/部门/体检医院/体检日期+按指标附加列(应检→体检计划、已选项目→已选项目数、已预约→预约日期、已检→体检状态绿色标签、未检→未检原因、重点指标异常→异常指标含↑↓、冠脉CTA异常→CTA结论含CAD-RADS分级、防癌筛查异常→筛查异常项如 Septin9 阳性),名单确定性生成每页 10 条、底部左"共 N 人"右页码"当前/总页"与 ‹/› 翻页按钮,✕/遮罩/Esc 关闭;弹窗列表上方右对齐新增"导出人员列表"主按钮(带导出图标),点击真实下载 CSV(UTF-8 BOM、全量名单与单元格数字一致、文件名"单位_年份_列名_人员列表.csv",体检状态标签去 HTML 取纯文本),行数据由渲染与导出共用的 personRowData 确定性生成函数保证两边一致;mock DOM 回归 5 组弹窗(1000/200/8/28/2300 人)标题/条数/分页/导出均通过,内联脚本语法校验通过;同日再移除"操作"列(含表头与 4 行"查看详情"链接),删列后 22 列与数据行对齐已校验,人数列点击穿透所用的单元格索引均在 18 以内不受影响;前三列(序号/单位/部门)冻结——做法对齐个人体检数据大表(th-frz/td-frz + frz0/1/2 固定宽 56/110/120px 与 left 偏移、表头 z-index 5、行悬停背景同步),部门列隐藏/显示切换不影响冻结偏移(display:none 不占位)
- `exception-result.html`(异常结果):列表移除"操作"列(含表头与 6 行"详情"链接),删列后 9 列表头与数据行对齐已校验;同日异常等级措辞简化——"危急值""异常值"统一去掉"值"字改为"危急""异常"(异常等级筛选下拉、6 行等级标签、页首异常数据定义文案同步),表头数据列"异常值"(指偏离数值本身)不受影响
- 检前三个配置页(`pre-item-combo-template.html` 组合模板新增/编辑抽屉与详情弹窗、`pre-item-exception.html` 例外配置新增/编辑抽屉与详情弹窗、`pre-item-required.html` 项目组合详情抽屉与费用审核弹窗):原"防癌筛查项目(Septin9""防癌筛查项目(CA724"两个 TAB 融合为单个"防癌筛查项目"TABSeptin9 与 CA724 两类项目合并列于同一 TAB 表格中;费用口径同步合并——组合模板默认费用为单一字段(费用框显隐与详情"防癌筛查默认费用"按合并键取值),必检项目页"防癌筛查项目费用合计"改为两类项目求和(680.00+260.00
- 检前"医院体检项目费用"菜单更名为"医院体检项目"(`pre-item-hospital-fee.html` 文件名不变),21 个检前页面侧边栏、该页浏览器标题及首页站点地图同步更新;页面内文案(各医院项目费用卡片标题、"新增医院体检项目费用"抽屉)不受影响
- `archive-personal.html`(个人体检数据):大表列表最后新增"操作"列(右侧冻结,横向浏览时始终可见),每行"查看报告"链接点击后弹窗查看体检报告——弹窗版式参考 `post-report-employee.html`(常规体检报告页)查看报告弹窗(宽 960px,含体检结论/体检建议/物理检查/内科/外科/化学检查六节带样式结论块与分组结果表、异常值红色标注),标题显示"姓名 · 体检报告",支持 ✕/关闭按钮/遮罩/Esc 关闭
- `post-employee-master.html`(员工体检大表)与 `archive-personal.html`(个人体检数据):筛选栏新增"异常员工"下拉筛选(全部/是/否,"是"指任一重点项目结果带异常标记),查询/重置按钮接通实际逻辑——查询按异常员工及姓名/员工编号/身份证号模糊匹配过滤大表行并重渲染(序号按过滤结果重排、底部条数同步更新),重置清空全部筛选条件并恢复完整列表,其余筛选控件(体检年份、单位部门)保持展示态
## [Unreleased] 2026-09-07
### Added
+10 -10
View File
@@ -137,7 +137,7 @@
<!-- 异常数据定义说明框 -->
<div class="desc-box">
<strong>异常数据定义:</strong>体检结果中存在指标超出正常参考范围的情形,包括:危急(指标严重偏离正常范围,需立即处理)、异常(指标超出参考范围但未达危急程度)等。系统自动检测并记录,供管理员跟进处理。
<strong>异常数据定义:</strong>体检结果中存在指标超出正常参考范围的情形,包括:危急(指标严重偏离正常范围,需立即处理)、异常(指标超出参考范围但未达危急程度)等。系统自动检测并记录,供管理员跟进处理。
</div>
<!-- 筛选栏 -->
@@ -170,8 +170,8 @@
<label>异常等级:</label>
<select class="filter-select">
<option>全部</option>
<option>危急</option>
<option>异常</option>
<option>危急</option>
<option>异常</option>
</select>
</div>
<button class="btn btn-primary">查询</button>
@@ -200,16 +200,16 @@
<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>
</tr>
</thead>
<tbody>
<tr><td>1</td><td><span class="tag tag-red">危急</span></td><td>张伟</td><td>CQ001234</td><td>采油一厂</td><td>空腹血糖</td><td>9.8 mmol/L</td><td>3.9~6.1 mmol/L</td><td>2026-05-01</td><td><span class="link">详情</span></td></tr>
<tr><td>2</td><td><span class="tag tag-red">危急</span></td><td>李明</td><td>CQ002571</td><td>采油二厂</td><td>血压(收缩压)</td><td>185 mmHg</td><td>90~140 mmHg</td><td>2026-05-01</td><td><span class="link">详情</span></td></tr>
<tr><td>3</td><td><span class="tag tag-orange">异常</span></td><td>刘洋</td><td>CQ004102</td><td>采油三厂</td><td>总胆固醇</td><td>7.2 mmol/L</td><td>2.8~5.7 mmol/L</td><td>2026-04-30</td><td><span class="link">详情</span></td></tr>
<tr><td>4</td><td><span class="tag tag-orange">异常</span></td><td>陈磊</td><td>CQ006890</td><td>采油一厂</td><td>肌酐</td><td>186 umol/L</td><td>44~133 umol/L</td><td>2026-04-30</td><td><span class="link">详情</span></td></tr>
<tr><td>5</td><td><span class="tag tag-orange">异常</span></td><td>周强</td><td>CQ008456</td><td>采油三厂</td><td>谷丙转氨酶</td><td>128 U/L</td><td>0~40 U/L</td><td>2026-04-29</td><td><span class="link">详情</span></td></tr>
<tr><td>6</td><td><span class="tag tag-red">危急</span></td><td>孙丽</td><td>CQ007234</td><td>采油二厂</td><td>心电图</td><td>ST段压低</td><td>正常心电图</td><td>2026-04-28</td><td><span class="link">详情</span></td></tr>
<tr><td>1</td><td><span class="tag tag-red">危急</span></td><td>张伟</td><td>CQ001234</td><td>采油一厂</td><td>空腹血糖</td><td>9.8 mmol/L</td><td>3.9~6.1 mmol/L</td><td>2026-05-01</td></tr>
<tr><td>2</td><td><span class="tag tag-red">危急</span></td><td>李明</td><td>CQ002571</td><td>采油二厂</td><td>血压(收缩压)</td><td>185 mmHg</td><td>90~140 mmHg</td><td>2026-05-01</td></tr>
<tr><td>3</td><td><span class="tag tag-orange">异常</span></td><td>刘洋</td><td>CQ004102</td><td>采油三厂</td><td>总胆固醇</td><td>7.2 mmol/L</td><td>2.8~5.7 mmol/L</td><td>2026-04-30</td></tr>
<tr><td>4</td><td><span class="tag tag-orange">异常</span></td><td>陈磊</td><td>CQ006890</td><td>采油一厂</td><td>肌酐</td><td>186 umol/L</td><td>44~133 umol/L</td><td>2026-04-30</td></tr>
<tr><td>5</td><td><span class="tag tag-orange">异常</span></td><td>周强</td><td>CQ008456</td><td>采油三厂</td><td>谷丙转氨酶</td><td>128 U/L</td><td>0~40 U/L</td><td>2026-04-29</td></tr>
<tr><td>6</td><td><span class="tag tag-red">危急</span></td><td>孙丽</td><td>CQ007234</td><td>采油二厂</td><td>心电图</td><td>ST段压低</td><td>正常心电图</td><td>2026-04-28</td></tr>
</tbody>
</table>
</div>
@@ -205,18 +205,26 @@
</div>
<div class="filter-item">
<label>姓名:</label>
<input class="filter-input" type="text" placeholder="请输入" style="width:130px;min-width:unset;">
<input class="filter-input" type="text" id="fName" placeholder="请输入" style="width:130px;min-width:unset;">
</div>
<div class="filter-item">
<label>员工编号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="width:130px;min-width:unset;">
<input class="filter-input" type="text" id="fEmpNo" placeholder="请输入" style="width:130px;min-width:unset;">
</div>
<div class="filter-item">
<label>身份证号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="width:160px;min-width:unset;">
<input class="filter-input" type="text" id="fIdCard" placeholder="请输入" style="width:160px;min-width:unset;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
<div class="filter-item">
<label>异常员工:</label>
<select class="filter-select" style="min-width:100px;" id="abnormalFilter">
<option value="">全部</option>
<option value="abnormal"></option>
<option value="normal"></option>
</select>
</div>
<button class="btn btn-primary" onclick="applyFilter()">查询</button>
<button class="btn btn-default" onclick="resetFilter()">重置</button>
</div>
<!-- 操作栏 -->
@@ -369,11 +377,12 @@ function buildHead(){
function buildBody(){
var items=allItems();
var baseKeys=['idx','name','empNo','gender','age','idCard','unit','dept','hospital','checkDate'];
var rows=MASTER_ROWS.map(function(r){
var rows=getDisplayRows().map(function(r,ri){
var cells='';
baseKeys.forEach(function(k,i){
var cls='td-base'+(i<3?' col'+i:'');
cells+='<td class="'+cls+'">'+r[k]+'</td>';
var txt=k==='idx'?(ri+1):r[k];
cells+='<td class="'+cls+'">'+txt+'</td>';
});
items.forEach(function(col){
var val=r.r[col.cat+'|'+col.name]||r.r[col.name];
@@ -384,9 +393,29 @@ function buildBody(){
}).join('');
return '<tbody>'+rows+'</tbody></table>';
}
/* 员工是否存在异常指标(任一项目结果带异常标记) */
function hasAbnormal(r){
for(var k in r.r){if(r.r[k][1])return true;}
return false;
}
/* 按筛选条件取当前展示行:异常员工 + 姓名/员工编号/身份证号模糊匹配 */
function getDisplayRows(){
var v=document.getElementById('abnormalFilter').value;
var name=document.getElementById('fName').value.trim();
var empNo=document.getElementById('fEmpNo').value.trim();
var idCard=document.getElementById('fIdCard').value.trim();
return MASTER_ROWS.filter(function(r){
if(v==='abnormal'&&!hasAbnormal(r))return false;
if(v==='normal'&&hasAbnormal(r))return false;
if(name&&r.name.indexOf(name)<0)return false;
if(empNo&&r.empNo.indexOf(empNo)<0)return false;
if(idCard&&r.idCard.indexOf(idCard)<0)return false;
return true;
});
}
function renderBigTable(){
document.getElementById('bigTable').innerHTML=buildHead()+buildBody();
document.getElementById('pageTotal').textContent='共 '+MASTER_ROWS.length+' 条';
document.getElementById('pageTotal').textContent='共 '+getDisplayRows().length+' 条';
var k=document.getElementById('keyCount');
if(k)k.textContent='重点项目 '+allItems().length+' 列';
}
@@ -404,6 +433,18 @@ function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
var sub=active.closest('.sidebar-subgroup');
while(sub){sub.classList.add('open');sub=sub.parentElement.closest('.sidebar-subgroup');}
})();
function applyFilter(){
renderBigTable();
showToast('查询完成');
}
function resetFilter(){
document.getElementById('abnormalFilter').value='';
document.getElementById('fName').value='';
document.getElementById('fEmpNo').value='';
document.getElementById('fIdCard').value='';
renderBigTable();
showToast('已重置筛选条件');
}
renderBigTable();
</script>
</body>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+288 -288
View File
@@ -1,187 +1,187 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 员工预选信息 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1100;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:560px;max-width:94vw;max-height:96vh;display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;overflow-y:auto;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目费用</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item active">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.html" class="sidebar-item">胃肠镜人员配置</a>
</div>
</div>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 员工预选信息 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1100;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:560px;max-width:94vw;max-height:96vh;display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;overflow-y:auto;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item active">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -193,107 +193,107 @@
<a href="pre-special-cta.html" class="sidebar-item">冠脉CTA体检人员</a>
</div>
</div>
</aside>
<main class="main">
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>预选计划名称:</label>
<select class="filter-select" style="min-width:180px;">
<option>请选择</option>
<option>2026年度胃肠镜预选</option>
</select>
</div>
<div class="filter-item">
<label>单位部门:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂</option>
<option>采油四厂-工程技术科</option>
<option>采油四厂-综合办</option>
<option>采油五厂-采油队</option>
<option>采油六厂-地质所</option>
</select>
</div>
<div class="filter-item">
<label>预选医院:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>宁夏宝石花医院</option>
<option>CQ油田医院</option>
<option>长安胃肠镜医院</option>
</select>
</div>
<div class="filter-item">
<label>姓名:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:110px;">
</div>
<div class="filter-item">
<label>员工编号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<div class="filter-item">
<label>身份证号:</label>
<input class="filter-input" type="text" placeholder="请输入身份证号" style="min-width:170px;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">员工预选信息</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>姓名</th><th>员工编号</th><th>身份证号</th><th>单位</th><th>部门</th><th>预选计划</th><th>预选医院</th><th>提交时间</th>
</tr>
</thead>
<tbody>
<tr><td>陈伟</td><td>30078912</td><td>610103197809220015</td><td>采油四厂</td><td>工程技术科</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td>2026-03-05 10:23</td></tr>
<tr><td>刘芳</td><td>30082345</td><td>610103197905120034</td><td>采油四厂</td><td>综合办</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td>2026-03-06 14:41</td></tr>
<tr><td>王强</td><td>30085678</td><td>610103197403080024</td><td>采油五厂</td><td>采油队</td><td>2026年度胃肠镜预选</td><td>CQ油田医院</td><td>2026-04-02 09:15</td></tr>
<tr><td>李娜</td><td>30088901</td><td>610103198511090026</td><td>采油五厂</td><td>财务科</td><td>2026年度胃肠镜预选</td><td>长安胃肠镜医院</td><td>2026-04-08 16:52</td></tr>
<tr><td>赵敏</td><td>30094567</td><td>610103196807260046</td><td>采油六厂</td><td>地质所</td><td>2026年度胃肠镜预选</td><td>CQ油田医院</td><td>2026-04-11 11:30</td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<script>
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
</script>
</body>
</html>
</aside>
<main class="main">
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>预选计划名称:</label>
<select class="filter-select" style="min-width:180px;">
<option>请选择</option>
<option>2026年度胃肠镜预选</option>
</select>
</div>
<div class="filter-item">
<label>单位部门:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂</option>
<option>采油四厂-工程技术科</option>
<option>采油四厂-综合办</option>
<option>采油五厂-采油队</option>
<option>采油六厂-地质所</option>
</select>
</div>
<div class="filter-item">
<label>预选医院:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>宁夏宝石花医院</option>
<option>CQ油田医院</option>
<option>长安胃肠镜医院</option>
</select>
</div>
<div class="filter-item">
<label>姓名:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:110px;">
</div>
<div class="filter-item">
<label>员工编号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<div class="filter-item">
<label>身份证号:</label>
<input class="filter-input" type="text" placeholder="请输入身份证号" style="min-width:170px;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">员工预选信息</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>姓名</th><th>员工编号</th><th>身份证号</th><th>单位</th><th>部门</th><th>预选计划</th><th>预选医院</th><th>提交时间</th>
</tr>
</thead>
<tbody>
<tr><td>陈伟</td><td>30078912</td><td>610103197809220015</td><td>采油四厂</td><td>工程技术科</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td>2026-03-05 10:23</td></tr>
<tr><td>刘芳</td><td>30082345</td><td>610103197905120034</td><td>采油四厂</td><td>综合办</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td>2026-03-06 14:41</td></tr>
<tr><td>王强</td><td>30085678</td><td>610103197403080024</td><td>采油五厂</td><td>采油队</td><td>2026年度胃肠镜预选</td><td>CQ油田医院</td><td>2026-04-02 09:15</td></tr>
<tr><td>李娜</td><td>30088901</td><td>610103198511090026</td><td>采油五厂</td><td>财务科</td><td>2026年度胃肠镜预选</td><td>长安胃肠镜医院</td><td>2026-04-08 16:52</td></tr>
<tr><td>赵敏</td><td>30094567</td><td>610103196807260046</td><td>采油六厂</td><td>地质所</td><td>2026年度胃肠镜预选</td><td>CQ油田医院</td><td>2026-04-11 11:30</td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<script>
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+402 -402
View File
@@ -1,187 +1,187 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 单位预选计划 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1100;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:560px;max-width:94vw;max-height:96vh;display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;overflow-y:auto;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目费用</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item active">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.html" class="sidebar-item">胃肠镜人员配置</a>
</div>
</div>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 单位预选计划 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1100;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:560px;max-width:94vw;max-height:96vh;display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;overflow-y:auto;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item active">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -193,221 +193,221 @@
<a href="pre-special-cta.html" class="sidebar-item">冠脉CTA体检人员</a>
</div>
</div>
</aside>
<main class="main">
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>预选计划名称:</label>
<input class="filter-input" type="text" placeholder="请输入预选计划名称" style="min-width:180px;">
</div>
<div class="filter-item">
<label>有效标志:</label>
<select class="filter-select" style="min-width:100px;">
<option>请选择</option>
<option>有效</option>
<option>无效</option>
</select>
</div>
<div class="filter-item">
<label>单位:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂</option>
<option>采油五厂</option>
<option>采油六厂</option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-primary" onclick="openEditModal()">+ 新增</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">单位预选计划</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>单位</th><th>体检年份</th><th>预选计划名称</th><th>预选开始日期</th><th>预选结束日期</th><th>创建日期</th><th>有效标志</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>采油四厂</td><td>2026</td><td>2026年度胃肠镜预选</td><td>2026-03-01</td><td>2026-03-31</td><td>2026-02-20</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span></td></tr>
<tr><td>采油五厂</td><td>2026</td><td>2026年度胃肠镜预选</td><td>2026-04-01</td><td>2026-04-30</td><td>2026-03-15</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span></td></tr>
<tr><td>采油六厂</td><td>2025</td><td>2025年度胃肠镜预选</td><td>2025-03-01</td><td>2025-03-31</td><td>2025-02-18</td><td><span class="tag tag-red">无效</span></td><td><span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 3 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 新增/编辑预选计划弹窗 -->
<div class="modal-overlay" id="edit-modal-overlay" onclick="if(event.target===this)closeEditModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title" id="edit-modal-title">新增预选计划</div>
<button class="modal__close" onclick="closeEditModal()"></button>
</div>
<div class="modal__body">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 单位</div>
<select class="form-select" id="form-unit">
<option value="">请选择单位</option>
<option>采油四厂</option>
<option>采油五厂</option>
<option>采油六厂</option>
</select>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 体检年份</div>
<input class="form-input" id="form-year" type="text" placeholder="请输入体检年份" value="2026">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 预选计划名称</div>
<input class="form-input" id="form-name" type="text" placeholder="请输入预选计划名称">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 预选开始日期</div>
<input class="form-input" id="form-start" type="date">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 预选结束日期</div>
<input class="form-input" id="form-end" type="date">
</div>
<div class="form-item">
<div class="form-label">有效标志</div>
<select class="form-select" id="form-valid">
<option>有效</option>
<option>无效</option>
</select>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeEditModal()">取消</button>
<button class="btn btn-primary" onclick="saveEditModal()">确定</button>
</div>
</div>
</div>
<script>
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 当前正在编辑的行(null 表示新增) */
var editingRow = null;
function openEditModal(row){
var isEdit = !!row;
editingRow = isEdit ? row.closest('tr') : null;
document.getElementById('edit-modal-title').textContent = isEdit ? '编辑预选计划' : '新增预选计划';
if(isEdit){
var tds = row.closest('tr').querySelectorAll('td');
document.getElementById('form-unit').value = tds[0].textContent;
document.getElementById('form-year').value = tds[1].textContent;
document.getElementById('form-name').value = tds[2].textContent;
document.getElementById('form-start').value = tds[3].textContent;
document.getElementById('form-end').value = tds[4].textContent;
document.getElementById('form-valid').value = tds[6].textContent.trim();
} else {
document.getElementById('form-unit').value = '';
document.getElementById('form-year').value = '2026';
document.getElementById('form-name').value = '';
document.getElementById('form-start').value = '';
document.getElementById('form-end').value = '';
document.getElementById('form-valid').value = '有效';
}
document.getElementById('edit-modal-overlay').classList.add('open');
}
function closeEditModal(){
document.getElementById('edit-modal-overlay').classList.remove('open');
}
function saveEditModal(){
var unit = document.getElementById('form-unit');
var year = document.getElementById('form-year').value.trim();
var name = document.getElementById('form-name').value.trim();
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
var valid = document.getElementById('form-valid').value;
if(!unit.value){ alert('请选择单位'); unit.focus(); return; }
if(!/^\d{4}$/.test(year)){ alert('请输入 4 位体检年份'); document.getElementById('form-year').focus(); return; }
if(!name){ alert('请输入预选计划名称'); document.getElementById('form-name').focus(); return; }
if(!start){ alert('请选择预选开始日期'); return; }
if(!end){ alert('请选择预选结束日期'); return; }
if(end < start){ alert('预选结束日期不能早于开始日期'); return; }
var validTag = valid === '有效'
? '<span class="tag tag-green">有效</span>'
: '<span class="tag tag-red">无效</span>';
var actions = '<span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span>';
if(editingRow){
/* 编辑:回写当前行 */
var tds = editingRow.querySelectorAll('td');
tds[0].textContent = unit.value;
tds[1].textContent = year;
tds[2].textContent = name;
tds[3].textContent = start;
tds[4].textContent = end;
tds[5].textContent = new Date().toISOString().slice(0,10);
tds[6].innerHTML = validTag;
editingRow = null;
} else {
/* 新增:插入到列表第一行 */
var tbody = document.querySelector('.table-card__content tbody');
var tr = document.createElement('tr');
tr.innerHTML =
'<td>' + unit.value + '</td>' +
'<td>' + year + '</td>' +
'<td>' + name + '</td>' +
'<td>' + start + '</td>' +
'<td>' + end + '</td>' +
'<td>' + new Date().toISOString().slice(0,10) + '</td>' +
'<td>' + validTag + '</td>' +
'<td>' + actions + '</td>';
tbody.insertBefore(tr, tbody.firstChild);
updateTotalCount(1);
}
closeEditModal();
}
/* 更新分页总数 */
function updateTotalCount(delta){
var el = document.querySelector('.pagination span');
if(!el) return;
var m = el.textContent.match(/共\s*(\d+)\s*条/);
if(m) el.textContent = '共 ' + (parseInt(m[1],10) + delta) + ' 条';
}
function deleteRow(el){
if(!confirm('确定删除该预选计划吗?')) return;
el.closest('tr').remove();
updateTotalCount(-1);
}
</script>
</body>
</html>
</aside>
<main class="main">
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>预选计划名称:</label>
<input class="filter-input" type="text" placeholder="请输入预选计划名称" style="min-width:180px;">
</div>
<div class="filter-item">
<label>有效标志:</label>
<select class="filter-select" style="min-width:100px;">
<option>请选择</option>
<option>有效</option>
<option>无效</option>
</select>
</div>
<div class="filter-item">
<label>单位:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂</option>
<option>采油五厂</option>
<option>采油六厂</option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-primary" onclick="openEditModal()">+ 新增</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">单位预选计划</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>单位</th><th>体检年份</th><th>预选计划名称</th><th>预选开始日期</th><th>预选结束日期</th><th>创建日期</th><th>有效标志</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>采油四厂</td><td>2026</td><td>2026年度胃肠镜预选</td><td>2026-03-01</td><td>2026-03-31</td><td>2026-02-20</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span></td></tr>
<tr><td>采油五厂</td><td>2026</td><td>2026年度胃肠镜预选</td><td>2026-04-01</td><td>2026-04-30</td><td>2026-03-15</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span></td></tr>
<tr><td>采油六厂</td><td>2025</td><td>2025年度胃肠镜预选</td><td>2025-03-01</td><td>2025-03-31</td><td>2025-02-18</td><td><span class="tag tag-red">无效</span></td><td><span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 3 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 新增/编辑预选计划弹窗 -->
<div class="modal-overlay" id="edit-modal-overlay" onclick="if(event.target===this)closeEditModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title" id="edit-modal-title">新增预选计划</div>
<button class="modal__close" onclick="closeEditModal()"></button>
</div>
<div class="modal__body">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 单位</div>
<select class="form-select" id="form-unit">
<option value="">请选择单位</option>
<option>采油四厂</option>
<option>采油五厂</option>
<option>采油六厂</option>
</select>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 体检年份</div>
<input class="form-input" id="form-year" type="text" placeholder="请输入体检年份" value="2026">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 预选计划名称</div>
<input class="form-input" id="form-name" type="text" placeholder="请输入预选计划名称">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 预选开始日期</div>
<input class="form-input" id="form-start" type="date">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 预选结束日期</div>
<input class="form-input" id="form-end" type="date">
</div>
<div class="form-item">
<div class="form-label">有效标志</div>
<select class="form-select" id="form-valid">
<option>有效</option>
<option>无效</option>
</select>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeEditModal()">取消</button>
<button class="btn btn-primary" onclick="saveEditModal()">确定</button>
</div>
</div>
</div>
<script>
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* 当前正在编辑的行(null 表示新增) */
var editingRow = null;
function openEditModal(row){
var isEdit = !!row;
editingRow = isEdit ? row.closest('tr') : null;
document.getElementById('edit-modal-title').textContent = isEdit ? '编辑预选计划' : '新增预选计划';
if(isEdit){
var tds = row.closest('tr').querySelectorAll('td');
document.getElementById('form-unit').value = tds[0].textContent;
document.getElementById('form-year').value = tds[1].textContent;
document.getElementById('form-name').value = tds[2].textContent;
document.getElementById('form-start').value = tds[3].textContent;
document.getElementById('form-end').value = tds[4].textContent;
document.getElementById('form-valid').value = tds[6].textContent.trim();
} else {
document.getElementById('form-unit').value = '';
document.getElementById('form-year').value = '2026';
document.getElementById('form-name').value = '';
document.getElementById('form-start').value = '';
document.getElementById('form-end').value = '';
document.getElementById('form-valid').value = '有效';
}
document.getElementById('edit-modal-overlay').classList.add('open');
}
function closeEditModal(){
document.getElementById('edit-modal-overlay').classList.remove('open');
}
function saveEditModal(){
var unit = document.getElementById('form-unit');
var year = document.getElementById('form-year').value.trim();
var name = document.getElementById('form-name').value.trim();
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
var valid = document.getElementById('form-valid').value;
if(!unit.value){ alert('请选择单位'); unit.focus(); return; }
if(!/^\d{4}$/.test(year)){ alert('请输入 4 位体检年份'); document.getElementById('form-year').focus(); return; }
if(!name){ alert('请输入预选计划名称'); document.getElementById('form-name').focus(); return; }
if(!start){ alert('请选择预选开始日期'); return; }
if(!end){ alert('请选择预选结束日期'); return; }
if(end < start){ alert('预选结束日期不能早于开始日期'); return; }
var validTag = valid === '有效'
? '<span class="tag tag-green">有效</span>'
: '<span class="tag tag-red">无效</span>';
var actions = '<span class="link" onclick="openEditModal(this)">编辑</span> <span class="link" style="margin-left:8px;color:var(--danger);" onclick="deleteRow(this)">删除</span>';
if(editingRow){
/* 编辑:回写当前行 */
var tds = editingRow.querySelectorAll('td');
tds[0].textContent = unit.value;
tds[1].textContent = year;
tds[2].textContent = name;
tds[3].textContent = start;
tds[4].textContent = end;
tds[5].textContent = new Date().toISOString().slice(0,10);
tds[6].innerHTML = validTag;
editingRow = null;
} else {
/* 新增:插入到列表第一行 */
var tbody = document.querySelector('.table-card__content tbody');
var tr = document.createElement('tr');
tr.innerHTML =
'<td>' + unit.value + '</td>' +
'<td>' + year + '</td>' +
'<td>' + name + '</td>' +
'<td>' + start + '</td>' +
'<td>' + end + '</td>' +
'<td>' + new Date().toISOString().slice(0,10) + '</td>' +
'<td>' + validTag + '</td>' +
'<td>' + actions + '</td>';
tbody.insertBefore(tr, tbody.firstChild);
updateTotalCount(1);
}
closeEditModal();
}
/* 更新分页总数 */
function updateTotalCount(delta){
var el = document.querySelector('.pagination span');
if(!el) return;
var m = el.textContent.match(/共\s*(\d+)\s*条/);
if(m) el.textContent = '共 ' + (parseInt(m[1],10) + delta) + ' 条';
}
function deleteRow(el){
if(!confirm('确定删除该预选计划吗?')) return;
el.closest('tr').remove();
updateTotalCount(-1);
}
</script>
</body>
</html>
+393 -393
View File
@@ -1,194 +1,194 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 预选信息统计 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1100;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:560px;max-width:94vw;max-height:96vh;display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;overflow-y:auto;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* Tab 切换 */
.tabs{display:flex;gap:0;background:#fff;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);padding:0 24px;margin-bottom:0;}
.tab{padding:14px 24px;font-size:var(--font-base);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;user-select:none;}
.tab:hover{color:var(--primary);}
.tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
.num-link{color:var(--primary);cursor:pointer;font-weight:600;}
.num-link:hover{color:#40a9ff;text-decoration:underline;}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目费用</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item active">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.html" class="sidebar-item">胃肠镜人员配置</a>
</div>
</div>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 预选信息统计 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1100;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:560px;max-width:94vw;max-height:96vh;display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;overflow-y:auto;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* Tab 切换 */
.tabs{display:flex;gap:0;background:#fff;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);padding:0 24px;margin-bottom:0;}
.tab{padding:14px 24px;font-size:var(--font-base);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;user-select:none;}
.tab:hover{color:var(--primary);}
.tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:600;}
.num-link{color:var(--primary);cursor:pointer;font-weight:600;}
.num-link:hover{color:#40a9ff;text-decoration:underline;}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item active">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -200,205 +200,205 @@
<a href="pre-special-cta.html" class="sidebar-item">冠脉CTA体检人员</a>
</div>
</div>
</aside>
<main class="main">
<div class="tabs">
<div class="tab active" data-tab="dept" onclick="switchTab('dept')">部门</div>
<div class="tab" data-tab="hospital" onclick="switchTab('hospital')">医院</div>
</div>
<!-- 部门tab -->
<div id="panel-dept">
<div class="filter-bar" style="border-radius:0 0 var(--radius-md) var(--radius-md);margin-bottom:16px;">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>单位部门:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂-工程技术科</option>
<option>采油四厂-综合办</option>
<option>采油五厂-采油队</option>
<option>采油六厂-地质所</option>
</select>
</div>
<div class="filter-item">
<label>预选医院:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>宁夏宝石花医院</option>
<option>CQ油田医院</option>
<option>长安胃肠镜医院</option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">预选信息统计(部门)</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>单位</th><th>部门</th><th>体检年份</th><th>预选计划</th><th>预选医院</th><th>预选人数</th>
</tr>
</thead>
<tbody>
<tr><td>采油四厂</td><td>工程技术科</td><td>2026</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td><span class="num-link" onclick="openDetail('采油四厂 工程技术科 / 宁夏宝石花医院')">12</span></td></tr>
<tr><td>采油四厂</td><td>综合办</td><td>2026</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td><span class="num-link" onclick="openDetail('采油四厂 综合办 / 宁夏宝石花医院')">8</span></td></tr>
<tr><td>采油五厂</td><td>采油队</td><td>2026</td><td>2026年度胃肠镜预选</td><td>CQ油田医院</td><td><span class="num-link" onclick="openDetail('采油五厂 采油队 / CQ油田医院')">23</span></td></tr>
<tr><td>采油六厂</td><td>地质所</td><td>2026</td><td>2026年度胃肠镜预选</td><td>长安胃肠镜医院</td><td><span class="num-link" onclick="openDetail('采油六厂 地质所 / 长安胃肠镜医院')">6</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</div>
<!-- 医院tab -->
<div id="panel-hospital" style="display:none;">
<div class="filter-bar" style="border-radius:0 0 var(--radius-md) var(--radius-md);margin-bottom:16px;">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>单位:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂</option>
<option>采油五厂</option>
<option>采油六厂</option>
</select>
</div>
<div class="filter-item">
<label>预选医院:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>宁夏宝石花医院</option>
<option>CQ油田医院</option>
<option>长安胃肠镜医院</option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">预选信息统计(医院)</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>预选医院</th><th>体检年份</th><th>单位</th><th>预选人数</th>
</tr>
</thead>
<tbody>
<tr><td>宁夏宝石花医院</td><td>2026</td><td>采油四厂</td><td><span class="num-link" onclick="openDetail('宁夏宝石花医院 / 采油四厂')">20</span></td></tr>
<tr><td>宁夏宝石花医院</td><td>2026</td><td>采油五厂</td><td><span class="num-link" onclick="openDetail('宁夏宝石花医院 / 采油五厂')">15</span></td></tr>
<tr><td>CQ油田医院</td><td>2026</td><td>采油五厂</td><td><span class="num-link" onclick="openDetail('CQ油田医院 / 采油五厂')">31</span></td></tr>
<tr><td>长安胃肠镜医院</td><td>2026</td><td>采油六厂</td><td><span class="num-link" onclick="openDetail('长安胃肠镜医院 / 采油六厂')">9</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</div>
</main>
<!-- 预选人数明细弹窗 -->
<div class="modal-overlay" id="detail-modal-overlay" onclick="if(event.target===this)closeDetail()">
<div class="modal" style="width:860px;">
<div class="modal__header">
<div class="modal__title" id="detail-title">预选人数明细</div>
<button class="modal__close" onclick="closeDetail()"></button>
</div>
<div class="modal__body">
<div style="display:flex;justify-content:flex-end;margin-bottom:12px;">
<button class="btn btn-default">导出列表数据</button>
</div>
<table>
<thead>
<tr><th>姓名</th><th>员工编号</th><th>身份证号</th><th>单位</th><th>部门</th><th>预选医院</th><th>提交时间</th></tr>
</thead>
<tbody>
<tr><td>陈伟</td><td>30078912</td><td>610103197809220015</td><td>采油四厂</td><td>工程技术科</td><td>宁夏宝石花医院</td><td>2026-03-05 10:23</td></tr>
<tr><td>刘芳</td><td>30082345</td><td>610103197905120034</td><td>采油四厂</td><td>综合办</td><td>宁夏宝石花医院</td><td>2026-03-06 14:41</td></tr>
<tr><td>王强</td><td>30085678</td><td>610103197403080024</td><td>采油五厂</td><td>采油队</td><td>CQ油田医院</td><td>2026-04-02 09:15</td></tr>
</tbody>
</table>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeDetail()">关闭</button>
</div>
</div>
</div>
<script>
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* tab 切换 */
function switchTab(key){
document.querySelectorAll('.tab').forEach(function(t){
t.classList.toggle('active', t.getAttribute('data-tab') === key);
});
document.getElementById('panel-dept').style.display = key === 'dept' ? '' : 'none';
document.getElementById('panel-hospital').style.display = key === 'hospital' ? '' : 'none';
}
/* 预选人数明细 */
function openDetail(title){
document.getElementById('detail-title').textContent = '预选人数明细 - ' + title;
document.getElementById('detail-modal-overlay').classList.add('open');
}
function closeDetail(){
document.getElementById('detail-modal-overlay').classList.remove('open');
}
</script>
</body>
</html>
</aside>
<main class="main">
<div class="tabs">
<div class="tab active" data-tab="dept" onclick="switchTab('dept')">部门</div>
<div class="tab" data-tab="hospital" onclick="switchTab('hospital')">医院</div>
</div>
<!-- 部门tab -->
<div id="panel-dept">
<div class="filter-bar" style="border-radius:0 0 var(--radius-md) var(--radius-md);margin-bottom:16px;">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>单位部门:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂-工程技术科</option>
<option>采油四厂-综合办</option>
<option>采油五厂-采油队</option>
<option>采油六厂-地质所</option>
</select>
</div>
<div class="filter-item">
<label>预选医院:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>宁夏宝石花医院</option>
<option>CQ油田医院</option>
<option>长安胃肠镜医院</option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">预选信息统计(部门)</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>单位</th><th>部门</th><th>体检年份</th><th>预选计划</th><th>预选医院</th><th>预选人数</th>
</tr>
</thead>
<tbody>
<tr><td>采油四厂</td><td>工程技术科</td><td>2026</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td><span class="num-link" onclick="openDetail('采油四厂 工程技术科 / 宁夏宝石花医院')">12</span></td></tr>
<tr><td>采油四厂</td><td>综合办</td><td>2026</td><td>2026年度胃肠镜预选</td><td>宁夏宝石花医院</td><td><span class="num-link" onclick="openDetail('采油四厂 综合办 / 宁夏宝石花医院')">8</span></td></tr>
<tr><td>采油五厂</td><td>采油队</td><td>2026</td><td>2026年度胃肠镜预选</td><td>CQ油田医院</td><td><span class="num-link" onclick="openDetail('采油五厂 采油队 / CQ油田医院')">23</span></td></tr>
<tr><td>采油六厂</td><td>地质所</td><td>2026</td><td>2026年度胃肠镜预选</td><td>长安胃肠镜医院</td><td><span class="num-link" onclick="openDetail('采油六厂 地质所 / 长安胃肠镜医院')">6</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</div>
<!-- 医院tab -->
<div id="panel-hospital" style="display:none;">
<div class="filter-bar" style="border-radius:0 0 var(--radius-md) var(--radius-md);margin-bottom:16px;">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select" style="min-width:110px;">
<option>2026</option>
<option>2025</option>
<option>2024</option>
</select>
</div>
<div class="filter-item">
<label>单位:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>采油四厂</option>
<option>采油五厂</option>
<option>采油六厂</option>
</select>
</div>
<div class="filter-item">
<label>预选医院:</label>
<select class="filter-select" style="min-width:160px;">
<option>请选择</option>
<option>宁夏宝石花医院</option>
<option>CQ油田医院</option>
<option>长安胃肠镜医院</option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">预选信息统计(医院)</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>预选医院</th><th>体检年份</th><th>单位</th><th>预选人数</th>
</tr>
</thead>
<tbody>
<tr><td>宁夏宝石花医院</td><td>2026</td><td>采油四厂</td><td><span class="num-link" onclick="openDetail('宁夏宝石花医院 / 采油四厂')">20</span></td></tr>
<tr><td>宁夏宝石花医院</td><td>2026</td><td>采油五厂</td><td><span class="num-link" onclick="openDetail('宁夏宝石花医院 / 采油五厂')">15</span></td></tr>
<tr><td>CQ油田医院</td><td>2026</td><td>采油五厂</td><td><span class="num-link" onclick="openDetail('CQ油田医院 / 采油五厂')">31</span></td></tr>
<tr><td>长安胃肠镜医院</td><td>2026</td><td>采油六厂</td><td><span class="num-link" onclick="openDetail('长安胃肠镜医院 / 采油六厂')">9</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</div>
</main>
<!-- 预选人数明细弹窗 -->
<div class="modal-overlay" id="detail-modal-overlay" onclick="if(event.target===this)closeDetail()">
<div class="modal" style="width:860px;">
<div class="modal__header">
<div class="modal__title" id="detail-title">预选人数明细</div>
<button class="modal__close" onclick="closeDetail()"></button>
</div>
<div class="modal__body">
<div style="display:flex;justify-content:flex-end;margin-bottom:12px;">
<button class="btn btn-default">导出列表数据</button>
</div>
<table>
<thead>
<tr><th>姓名</th><th>员工编号</th><th>身份证号</th><th>单位</th><th>部门</th><th>预选医院</th><th>提交时间</th></tr>
</thead>
<tbody>
<tr><td>陈伟</td><td>30078912</td><td>610103197809220015</td><td>采油四厂</td><td>工程技术科</td><td>宁夏宝石花医院</td><td>2026-03-05 10:23</td></tr>
<tr><td>刘芳</td><td>30082345</td><td>610103197905120034</td><td>采油四厂</td><td>综合办</td><td>宁夏宝石花医院</td><td>2026-03-06 14:41</td></tr>
<tr><td>王强</td><td>30085678</td><td>610103197403080024</td><td>采油五厂</td><td>采油队</td><td>CQ油田医院</td><td>2026-04-02 09:15</td></tr>
</tbody>
</table>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeDetail()">关闭</button>
</div>
</div>
</div>
<script>
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* tab 切换 */
function switchTab(key){
document.querySelectorAll('.tab').forEach(function(t){
t.classList.toggle('active', t.getAttribute('data-tab') === key);
});
document.getElementById('panel-dept').style.display = key === 'dept' ? '' : 'none';
document.getElementById('panel-hospital').style.display = key === 'hospital' ? '' : 'none';
}
/* 预选人数明细 */
function openDetail(title){
document.getElementById('detail-title').textContent = '预选人数明细 - ' + title;
document.getElementById('detail-modal-overlay').classList.add('open');
}
function closeDetail(){
document.getElementById('detail-modal-overlay').classList.remove('open');
}
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+364 -364
View File
@@ -1,204 +1,204 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 单位体检项目费用 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
/* 顶部导航 */
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
/* 主内容 */
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
/* 媒体预览图标 */
.media-icon{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:var(--radius-sm);cursor:pointer;transition:all .2s;}
.media-icon--active{background:var(--primary-light);color:var(--primary);}
.media-icon--empty{background:#F5F5F5;color:var(--text-placeholder);}
.media-icon:hover{opacity:.8;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-danger{background:#fff;color:var(--danger);border:1px solid var(--danger);}.btn-danger:hover{background:#fff1f0;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__actions{display:flex;gap:8px;align-items:center;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:999;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:460px;max-width:92vw;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 表单 */
.form-item{margin-bottom:20px;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* 信息展示 */
.fee-info{background:#FAFAFA;border-radius:var(--radius-sm);padding:14px 16px;margin-bottom:20px;display:flex;flex-direction:column;gap:10px;}
.fee-info__item{display:flex;font-size:var(--font-sm);color:var(--text-primary);}
.fee-info__item label{color:var(--text-secondary);width:88px;flex-shrink:0;}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目费用</a>
<a href="pre-item-unit-fee.html" class="sidebar-item active">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.html" class="sidebar-item">胃肠镜人员配置</a>
</div>
</div>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 单位体检项目费用 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
/* 顶部导航 */
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
/* 主内容 */
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
/* 媒体预览图标 */
.media-icon{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:var(--radius-sm);cursor:pointer;transition:all .2s;}
.media-icon--active{background:var(--primary-light);color:var(--primary);}
.media-icon--empty{background:#F5F5F5;color:var(--text-placeholder);}
.media-icon:hover{opacity:.8;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-danger{background:#fff;color:var(--danger);border:1px solid var(--danger);}.btn-danger:hover{background:#fff1f0;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__actions{display:flex;gap:8px;align-items:center;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:999;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:460px;max-width:92vw;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 表单 */
.form-item{margin-bottom:20px;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* 信息展示 */
.fee-info{background:#FAFAFA;border-radius:var(--radius-sm);padding:14px 16px;margin-bottom:20px;display:flex;flex-direction:column;gap:10px;}
.fee-info__item{display:flex;font-size:var(--font-sm);color:var(--text-primary);}
.fee-info__item label{color:var(--text-secondary);width:88px;flex-shrink:0;}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目</a>
<a href="pre-item-unit-fee.html" class="sidebar-item active">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -210,166 +210,166 @@
<a href="pre-special-cta.html" class="sidebar-item">冠脉CTA体检人员</a>
</div>
</div>
</aside>
<!-- 主内容 -->
<main class="main">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>请选择</option><option selected>2025</option><option>2024</option><option>2026</option>
</select>
</div>
<div class="filter-item">
<label>单位:</label>
<select class="filter-select">
<option>请选择</option><option>第一采油厂</option><option>第二采油厂</option><option>第三采油厂</option>
</select>
</div>
<div class="filter-item">
<label>体检医院:</label>
<select class="filter-select">
<option>请选择</option><option>泾河医院</option><option>庆阳医院</option><option>延安医院</option><option>兴隆园医院</option><option>宁夏宝石花医院</option>
</select>
</div>
<div class="filter-item">
<label>体检项目:</label>
<input class="filter-input" type="text" placeholder="请输入项目名称" style="min-width:160px;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div style="display:flex;gap:12px;margin-bottom:16px;">
<button class="btn btn-primary" onclick="openGenerateConfirm()">+ 生成单位本年度体检项目费用</button>
</div>
<!-- 数据表格 -->
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">单位体检项目费用</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>序号</th><th>单位</th><th>体检年份</th><th>医院名称</th><th>体检项目</th><th>体检项目图片</th><th>项目费用(元)</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>第一采油厂</td><td>2025</td><td>泾河医院</td><td>经颅多普勒</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>280.00</td><td><span class="link" onclick="openFeeModal(this)">更改费用</span></td></tr>
<tr><td>2</td><td>第二采油厂</td><td>2025</td><td>庆阳医院</td><td>腹部彩超</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>200.00</td><td><span class="link" onclick="openFeeModal(this)">更改费用</span></td></tr>
<tr><td>3</td><td>第三采油厂</td><td>2025</td><td>延安医院</td><td>血常规</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>40.00</td><td><span class="link" onclick="openFeeModal(this)">更改费用</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 243 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 更改费用弹窗 -->
<div class="modal-overlay" id="fee-modal-overlay" onclick="if(event.target===this)closeFeeModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title">更改费用</div>
<button class="modal__close" onclick="closeFeeModal()"></button>
</div>
<div class="modal__body">
<div class="fee-info">
<div class="fee-info__item"><label>单位:</label><span id="fee-unit"></span></div>
<div class="fee-info__item"><label>体检年份:</label><span id="fee-year"></span></div>
<div class="fee-info__item"><label>医院名称:</label><span id="fee-hospital"></span></div>
<div class="fee-info__item"><label>体检项目:</label><span id="fee-item"></span></div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 项目费用(元)</div>
<input class="form-input" id="fee-amount" type="number" min="0" step="0.01" placeholder="请输入项目费用">
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeFeeModal()">取消</button>
<button class="btn btn-primary" onclick="saveFee()">确认保存</button>
</div>
</div>
</div>
<!-- 生成费用二次确认弹窗 -->
<div class="modal-overlay" id="generate-confirm-overlay" onclick="if(event.target===this)closeGenerateConfirm()">
<div class="modal" style="width:420px;">
<div class="modal__header">
<div class="modal__title">生成确认</div>
<button class="modal__close" onclick="closeGenerateConfirm()"></button>
</div>
<div class="modal__body" style="display:flex;gap:12px;align-items:flex-start;">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" style="flex-shrink:0;margin-top:2px;"><circle cx="11" cy="11" r="10" fill="#FAAD14"/><path d="M11 6.5v6" stroke="#fff" stroke-width="2" stroke-linecap="round"/><circle cx="11" cy="15.5" r="1.2" fill="#fff"/></svg>
<div style="font-size:var(--font-sm);color:var(--text-primary);line-height:1.7;">
确定要生成单位本年度体检项目费用吗?<br>
<span style="color:var(--text-secondary);">生成后将按医院项目费用基准初始化本年度各单位的体检项目费用。</span>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeGenerateConfirm()">取消</button>
<button class="btn btn-primary" onclick="confirmGenerate()">确认生成</button>
</div>
</div>
</div>
<script>
/* 侧边栏展开/折叠交互 */
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
/* 页面加载时自动展开当前页面所在的子分组 */
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 更改费用弹窗 ===== */
var feeTr = null;
function openFeeModal(btn){
feeTr = btn.closest('tr');
var cells = feeTr.cells;
document.getElementById('fee-unit').textContent = cells[1].textContent.trim();
document.getElementById('fee-year').textContent = cells[2].textContent.trim();
document.getElementById('fee-hospital').textContent = cells[3].textContent.trim();
document.getElementById('fee-item').textContent = cells[4].textContent.trim();
document.getElementById('fee-amount').value = cells[6].textContent.trim();
document.getElementById('fee-modal-overlay').classList.add('open');
}
function closeFeeModal(){
document.getElementById('fee-modal-overlay').classList.remove('open');
}
function saveFee(){
if(!feeTr) return;
var amount = document.getElementById('fee-amount').value.trim();
if(!amount || Number(amount) < 0){ alert('请输入正确的项目费用'); return; }
feeTr.cells[6].textContent = Number(amount).toFixed(2);
closeFeeModal();
}
/* ===== 生成费用二次确认 ===== */
function openGenerateConfirm(){
document.getElementById('generate-confirm-overlay').classList.add('open');
}
function closeGenerateConfirm(){
document.getElementById('generate-confirm-overlay').classList.remove('open');
}
function confirmGenerate(){
closeGenerateConfirm();
alert('单位本年度体检项目费用生成任务已提交(原型演示)');
}
</script>
</body>
</html>
</aside>
<!-- 主内容 -->
<main class="main">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>体检年份:</label>
<select class="filter-select">
<option>请选择</option><option selected>2025</option><option>2024</option><option>2026</option>
</select>
</div>
<div class="filter-item">
<label>单位:</label>
<select class="filter-select">
<option>请选择</option><option>第一采油厂</option><option>第二采油厂</option><option>第三采油厂</option>
</select>
</div>
<div class="filter-item">
<label>体检医院:</label>
<select class="filter-select">
<option>请选择</option><option>泾河医院</option><option>庆阳医院</option><option>延安医院</option><option>兴隆园医院</option><option>宁夏宝石花医院</option>
</select>
</div>
<div class="filter-item">
<label>体检项目:</label>
<input class="filter-input" type="text" placeholder="请输入项目名称" style="min-width:160px;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div style="display:flex;gap:12px;margin-bottom:16px;">
<button class="btn btn-primary" onclick="openGenerateConfirm()">+ 生成单位本年度体检项目费用</button>
</div>
<!-- 数据表格 -->
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">单位体检项目费用</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>序号</th><th>单位</th><th>体检年份</th><th>医院名称</th><th>体检项目</th><th>体检项目图片</th><th>项目费用(元)</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>第一采油厂</td><td>2025</td><td>泾河医院</td><td>经颅多普勒</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>280.00</td><td><span class="link" onclick="openFeeModal(this)">更改费用</span></td></tr>
<tr><td>2</td><td>第二采油厂</td><td>2025</td><td>庆阳医院</td><td>腹部彩超</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>200.00</td><td><span class="link" onclick="openFeeModal(this)">更改费用</span></td></tr>
<tr><td>3</td><td>第三采油厂</td><td>2025</td><td>延安医院</td><td>血常规</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>40.00</td><td><span class="link" onclick="openFeeModal(this)">更改费用</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 243 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 更改费用弹窗 -->
<div class="modal-overlay" id="fee-modal-overlay" onclick="if(event.target===this)closeFeeModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title">更改费用</div>
<button class="modal__close" onclick="closeFeeModal()"></button>
</div>
<div class="modal__body">
<div class="fee-info">
<div class="fee-info__item"><label>单位:</label><span id="fee-unit"></span></div>
<div class="fee-info__item"><label>体检年份:</label><span id="fee-year"></span></div>
<div class="fee-info__item"><label>医院名称:</label><span id="fee-hospital"></span></div>
<div class="fee-info__item"><label>体检项目:</label><span id="fee-item"></span></div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 项目费用(元)</div>
<input class="form-input" id="fee-amount" type="number" min="0" step="0.01" placeholder="请输入项目费用">
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeFeeModal()">取消</button>
<button class="btn btn-primary" onclick="saveFee()">确认保存</button>
</div>
</div>
</div>
<!-- 生成费用二次确认弹窗 -->
<div class="modal-overlay" id="generate-confirm-overlay" onclick="if(event.target===this)closeGenerateConfirm()">
<div class="modal" style="width:420px;">
<div class="modal__header">
<div class="modal__title">生成确认</div>
<button class="modal__close" onclick="closeGenerateConfirm()"></button>
</div>
<div class="modal__body" style="display:flex;gap:12px;align-items:flex-start;">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" style="flex-shrink:0;margin-top:2px;"><circle cx="11" cy="11" r="10" fill="#FAAD14"/><path d="M11 6.5v6" stroke="#fff" stroke-width="2" stroke-linecap="round"/><circle cx="11" cy="15.5" r="1.2" fill="#fff"/></svg>
<div style="font-size:var(--font-sm);color:var(--text-primary);line-height:1.7;">
确定要生成单位本年度体检项目费用吗?<br>
<span style="color:var(--text-secondary);">生成后将按医院项目费用基准初始化本年度各单位的体检项目费用。</span>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeGenerateConfirm()">取消</button>
<button class="btn btn-primary" onclick="confirmGenerate()">确认生成</button>
</div>
</div>
</div>
<script>
/* 侧边栏展开/折叠交互 */
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
/* 页面加载时自动展开当前页面所在的子分组 */
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 更改费用弹窗 ===== */
var feeTr = null;
function openFeeModal(btn){
feeTr = btn.closest('tr');
var cells = feeTr.cells;
document.getElementById('fee-unit').textContent = cells[1].textContent.trim();
document.getElementById('fee-year').textContent = cells[2].textContent.trim();
document.getElementById('fee-hospital').textContent = cells[3].textContent.trim();
document.getElementById('fee-item').textContent = cells[4].textContent.trim();
document.getElementById('fee-amount').value = cells[6].textContent.trim();
document.getElementById('fee-modal-overlay').classList.add('open');
}
function closeFeeModal(){
document.getElementById('fee-modal-overlay').classList.remove('open');
}
function saveFee(){
if(!feeTr) return;
var amount = document.getElementById('fee-amount').value.trim();
if(!amount || Number(amount) < 0){ alert('请输入正确的项目费用'); return; }
feeTr.cells[6].textContent = Number(amount).toFixed(2);
closeFeeModal();
}
/* ===== 生成费用二次确认 ===== */
function openGenerateConfirm(){
document.getElementById('generate-confirm-overlay').classList.add('open');
}
function closeGenerateConfirm(){
document.getElementById('generate-confirm-overlay').classList.remove('open');
}
function confirmGenerate(){
closeGenerateConfirm();
alert('单位本年度体检项目费用生成任务已提交(原型演示)');
}
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
+321 -321
View File
@@ -1,203 +1,203 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 群体额度配置 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
/* 顶部导航 */
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
/* 主内容 */
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-danger{background:#fff;color:var(--danger);border:1px solid var(--danger);}.btn-danger:hover{background:#fff1f0;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__actions{display:flex;gap:8px;align-items:center;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:999;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:460px;max-width:92vw;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 弹窗表单 */
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 12px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* 群体信息(纯展示) */
.group-info{background:#F5F7FA;border-radius:var(--radius-sm);padding:12px 14px;margin-bottom:20px;display:flex;flex-wrap:wrap;gap:8px 28px;}
.group-info__item{font-size:var(--font-sm);}
.group-info__item label{color:var(--text-secondary);}
.group-info__item span{color:var(--text-primary);font-weight:500;}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item active">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目费用</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.html" class="sidebar-item">胃肠镜人员配置</a>
</div>
</div>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 群体额度配置 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
/* 顶部导航 */
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
/* 主内容 */
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-danger{background:#fff;color:var(--danger);border:1px solid var(--danger);}.btn-danger:hover{background:#fff1f0;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__actions{display:flex;gap:8px;align-items:center;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:999;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:460px;max-width:92vw;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 弹窗表单 */
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
.form-select{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 12px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* 群体信息(纯展示) */
.group-info{background:#F5F7FA;border-radius:var(--radius-sm);padding:12px 14px;margin-bottom:20px;display:flex;flex-wrap:wrap;gap:8px 28px;}
.group-info__item{font-size:var(--font-sm);}
.group-info__item label{color:var(--text-secondary);}
.group-info__item span{color:var(--text-primary);font-weight:500;}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item active">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -209,124 +209,124 @@
<a href="pre-special-cta.html" class="sidebar-item">冠脉CTA体检人员</a>
</div>
</div>
</aside>
<!-- 主内容 -->
<main class="main">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>性别:</label>
<select class="filter-select" style="min-width:90px;">
<option>请选择</option><option></option><option></option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 数据表格 - 群体额度 -->
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">群体额度列表</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>序号</th><th>群体名称</th><th>年龄区间</th><th>性别</th><th>体检额度(元)</th><th>批量更新规则</th><th>是否已生成</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>45岁及以上-女</td><td>45岁及以上</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>2</td><td>45岁及以上-男</td><td>45岁及以上</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>3</td><td>36~44岁-女</td><td>35岁至44岁</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>4</td><td>36~44岁-男</td><td>35岁至44岁</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>5</td><td>35岁及以下-女</td><td>35岁以下</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>6</td><td>35岁及以下-男</td><td>35岁以下</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 6 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 设置群体额度弹窗 -->
<div class="modal-overlay" id="quota-modal-overlay" onclick="if(event.target===this)closeQuotaModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title">设置群体额度</div>
<button class="modal__close" onclick="closeQuotaModal()"></button>
</div>
<div class="modal__body">
<div class="group-info">
<div class="group-info__item"><label>群体名称:</label><span id="quota-group-name"></span></div>
<div class="group-info__item"><label>年龄区间:</label><span id="quota-age"></span></div>
<div class="group-info__item"><label>性别:</label><span id="quota-gender"></span></div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 体检额度(元)</div>
<input class="form-input" id="quota-amount" type="number" min="0" step="0.01" placeholder="请输入体检额度">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 批量更新规则</div>
<select class="form-select" id="quota-rule">
<option value="全量">全量</option>
<option value="忽略手动修改">忽略手动修改</option>
</select>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeQuotaModal()">取消</button>
<button class="btn btn-primary" onclick="saveQuota()">确认保存</button>
</div>
</div>
</div>
<script>
/* 侧边栏展开/折叠交互 */
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
/* 页面加载时自动展开当前页面所在的子分组 */
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 设置群体额度弹窗 ===== */
var quotaTr = null;
function openQuotaModal(btn){
quotaTr = btn.closest('tr');
var cells = quotaTr.cells;
document.getElementById('quota-group-name').textContent = cells[1].textContent.trim();
document.getElementById('quota-age').textContent = cells[2].textContent.trim();
document.getElementById('quota-gender').textContent = cells[3].textContent.trim();
document.getElementById('quota-amount').value = cells[4].textContent.trim();
document.getElementById('quota-rule').value = cells[5].textContent.trim() || '全量';
document.getElementById('quota-modal-overlay').classList.add('open');
}
function closeQuotaModal(){
document.getElementById('quota-modal-overlay').classList.remove('open');
}
function saveQuota(){
if(!quotaTr) return;
var amount = document.getElementById('quota-amount').value.trim();
if(!amount || Number(amount) < 0){ alert('请输入正确的体检额度'); return; }
quotaTr.cells[4].textContent = Number(amount).toFixed(2);
quotaTr.cells[5].textContent = document.getElementById('quota-rule').value;
closeQuotaModal();
}
</script>
</body>
</html>
</aside>
<!-- 主内容 -->
<main class="main">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>性别:</label>
<select class="filter-select" style="min-width:90px;">
<option>请选择</option><option></option><option></option>
</select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 数据表格 - 群体额度 -->
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">群体额度列表</div>
</div>
<div class="table-card__content">
<table>
<thead>
<tr>
<th>序号</th><th>群体名称</th><th>年龄区间</th><th>性别</th><th>体检额度(元)</th><th>批量更新规则</th><th>是否已生成</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>45岁及以上-女</td><td>45岁及以上</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>2</td><td>45岁及以上-男</td><td>45岁及以上</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>3</td><td>36~44岁-女</td><td>35岁至44岁</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>4</td><td>36~44岁-男</td><td>35岁至44岁</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>5</td><td>35岁及以下-女</td><td>35岁以下</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
<tr><td>6</td><td>35岁及以下-男</td><td>35岁以下</td><td></td><td>2500.00</td><td>全量</td><td><span class="tag tag-green">已生成</span></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span> <span class="link" style="margin-left:8px;">生成额度</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 6 条</span>
<button class="page-btn active">1</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 设置群体额度弹窗 -->
<div class="modal-overlay" id="quota-modal-overlay" onclick="if(event.target===this)closeQuotaModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title">设置群体额度</div>
<button class="modal__close" onclick="closeQuotaModal()"></button>
</div>
<div class="modal__body">
<div class="group-info">
<div class="group-info__item"><label>群体名称:</label><span id="quota-group-name"></span></div>
<div class="group-info__item"><label>年龄区间:</label><span id="quota-age"></span></div>
<div class="group-info__item"><label>性别:</label><span id="quota-gender"></span></div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 体检额度(元)</div>
<input class="form-input" id="quota-amount" type="number" min="0" step="0.01" placeholder="请输入体检额度">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 批量更新规则</div>
<select class="form-select" id="quota-rule">
<option value="全量">全量</option>
<option value="忽略手动修改">忽略手动修改</option>
</select>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeQuotaModal()">取消</button>
<button class="btn btn-primary" onclick="saveQuota()">确认保存</button>
</div>
</div>
</div>
<script>
/* 侧边栏展开/折叠交互 */
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
/* 页面加载时自动展开当前页面所在的子分组 */
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 设置群体额度弹窗 ===== */
var quotaTr = null;
function openQuotaModal(btn){
quotaTr = btn.closest('tr');
var cells = quotaTr.cells;
document.getElementById('quota-group-name').textContent = cells[1].textContent.trim();
document.getElementById('quota-age').textContent = cells[2].textContent.trim();
document.getElementById('quota-gender').textContent = cells[3].textContent.trim();
document.getElementById('quota-amount').value = cells[4].textContent.trim();
document.getElementById('quota-rule').value = cells[5].textContent.trim() || '全量';
document.getElementById('quota-modal-overlay').classList.add('open');
}
function closeQuotaModal(){
document.getElementById('quota-modal-overlay').classList.remove('open');
}
function saveQuota(){
if(!quotaTr) return;
var amount = document.getElementById('quota-amount').value.trim();
if(!amount || Number(amount) < 0){ alert('请输入正确的体检额度'); return; }
quotaTr.cells[4].textContent = Number(amount).toFixed(2);
quotaTr.cells[5].textContent = document.getElementById('quota-rule').value;
closeQuotaModal();
}
</script>
</body>
</html>
+344 -344
View File
@@ -1,208 +1,208 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 员工额度配置 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
/* 顶部导航 */
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
/* 主内容 */
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-danger{background:#fff;color:var(--danger);border:1px solid var(--danger);}.btn-danger:hover{background:#fff1f0;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__actions{display:flex;gap:8px;align-items:center;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:999;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:460px;max-width:92vw;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 表单 */
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* 人员信息 */
.person-info{background:#F5F7FA;border-radius:var(--radius-sm);padding:12px 14px;margin-bottom:20px;display:flex;flex-wrap:wrap;gap:8px 28px;}
.person-info__item{font-size:var(--font-sm);}
.person-info__item label{color:var(--text-secondary);}
.person-info__item span{color:var(--text-primary);font-weight:500;}
/* 开关 */
.switch-row{display:flex;align-items:center;gap:12px;}
.switch{width:40px;height:22px;border-radius:11px;background:#E8E8E8;cursor:pointer;position:relative;transition:.2s;flex-shrink:0;}
.switch.on{background:var(--primary);}
.switch::after{content:'';position:absolute;width:18px;height:18px;border-radius:50%;background:#fff;top:2px;left:2px;transition:.2s;box-shadow:0 1px 3px rgba(0,0,0,0.2);}
.switch.on::after{left:20px;}
.switch-label{font-size:var(--font-sm);color:var(--text-primary);}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目费用</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.html" class="sidebar-item">胃肠镜人员配置</a>
</div>
</div>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康体检 - 员工额度配置 | 健康CQ原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;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;--font-xl:20px;--font-xxl:24px;
--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.12);
}
/* 顶部导航 */
.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:240px;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 16px;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);}
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.top-bar__right .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;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 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:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
/* 主内容 */
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.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-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:120px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-danger{background:#fff;color:var(--danger);border:1px solid var(--danger);}.btn-danger:hover{background:#fff1f0;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__actions{display:flex;gap:8px;align-items:center;}
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
.table-card__content table{min-width:100%;white-space:nowrap;}
table{width:100%;border-collapse:collapse;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.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{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:999;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{background:#fff;border-radius:var(--radius-md);box-shadow:0 4px 16px rgba(0,0,0,0.15);width:460px;max-width:92vw;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{padding:24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 表单 */
.form-item{margin-bottom:20px;}
.form-item:last-child{margin-bottom:0;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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;}
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
/* 人员信息 */
.person-info{background:#F5F7FA;border-radius:var(--radius-sm);padding:12px 14px;margin-bottom:20px;display:flex;flex-wrap:wrap;gap:8px 28px;}
.person-info__item{font-size:var(--font-sm);}
.person-info__item label{color:var(--text-secondary);}
.person-info__item span{color:var(--text-primary);font-weight:500;}
/* 开关 */
.switch-row{display:flex;align-items:center;gap:12px;}
.switch{width:40px;height:22px;border-radius:11px;background:#E8E8E8;cursor:pointer;position:relative;transition:.2s;flex-shrink:0;}
.switch.on{background:var(--primary);}
.switch::after{content:'';position:absolute;width:18px;height:18px;border-radius:50%;background:#fff;top:2px;left:2px;transition:.2s;box-shadow:0 1px 3px rgba(0,0,0,0.2);}
.switch.on::after{left:20px;}
.switch-label{font-size:var(--font-sm);color:var(--text-primary);}
</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="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
健康体检
</div>
<nav class="top-bar__nav">
<a href="archive-personal.html">档案</a>
<a href="config-material-notice.html">基础配置</a>
<a href="pre-hospital-scope.html" class="active">检前</a>
<a href="mid-appointment-track.html">检中</a>
<a href="post-unit-count.html">检后</a>
<a href="exception-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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
常规体检
</div>
<div class="sidebar-subgroup__body">
<a href="pre-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-plan.html" class="sidebar-item">单位体检计划管理</a>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检额度配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-quota-group.html" class="sidebar-item">群体额度配置</a>
<a href="pre-quota-personal.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
体检项目配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-item-hospital-fee.html" class="sidebar-item">医院体检项目</a>
<a href="pre-item-unit-fee.html" class="sidebar-item">单位体检项目费用</a>
<a href="pre-item-combo-template.html" class="sidebar-item">体检项目组合模板</a>
<a href="pre-item-exception.html" class="sidebar-item">组合模板例外配置</a>
<a href="pre-item-required.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
特殊人员配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-special-cancer.html" class="sidebar-item">防癌筛查人员</a>
<a href="pre-special-occupation.html" class="sidebar-item">职业体检人员</a>
<a href="pre-special-hospital.html" class="sidebar-item">指定员工体检医院</a>
</div>
</div>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜体检
</div>
<div class="sidebar-subgroup__body">
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
胃肠镜预选配置
</div>
<div class="sidebar-subgroup__body">
<a href="pre-gastro-plan.html" class="sidebar-item">单位预选计划</a>
<a href="pre-gastro-employee.html" class="sidebar-item">员工预选信息</a>
<a href="pre-gastro-stat.html" class="sidebar-item">预选信息统计</a>
</div>
</div>
<a href="pre-gastro-hospital-scope.html" class="sidebar-item">医院承检范围配置</a>
<a href="pre-gastro-plan-mgmt.html" class="sidebar-item">单位体检计划管理</a>
<a href="pre-special-gastro.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 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -214,142 +214,142 @@
<a href="pre-special-cta.html" class="sidebar-item">冠脉CTA体检人员</a>
</div>
</div>
</aside>
<!-- 主内容 -->
<main class="main">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>单位部门:</label>
<select class="filter-select">
<option>全部</option>
<option>采油一厂</option>
<option>公司机关</option>
</select>
</div>
<div class="filter-item">
<label>姓名:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<div class="filter-item">
<label>员工编号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<div class="filter-item">
<label>身份证号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作栏 -->
<div style="display:flex;gap:12px;margin-bottom:16px;">
<button class="btn btn-primary">
<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="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
导出列表数据
</button>
<button class="btn btn-default">
<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__header">
<div class="table-card__title">个人额度列表</div>
</div>
<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>
<tbody>
<tr><td>1</td><td>张明</td><td>100234</td><td></td><td>38</td><td>610113199602632255</td><td>公司机关</td><td>人事部</td><td>2500.00</td><td></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span></td></tr>
<tr><td>2</td><td>李芳</td><td>100567</td><td></td><td>42</td><td>610113199602632255</td><td>公司机关</td><td>财务部</td><td>2500.00</td><td></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span></td></tr>
<tr><td>3</td><td>王强</td><td>200891</td><td></td><td>50</td><td>610113199602632255</td><td>采油一厂</td><td>生产办</td><td>2500.00</td><td></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 1260 条</span>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<span>...</span>
<button class="page-btn">126</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 设置个人额度弹窗 -->
<div class="modal-overlay" id="quota-modal-overlay" onclick="if(event.target===this)closeQuotaModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title">设置个人额度</div>
<button class="modal__close" onclick="closeQuotaModal()"></button>
</div>
<div class="modal__body">
<div class="person-info">
<div class="person-info__item"><label>姓名:</label><span id="quota-name"></span></div>
<div class="person-info__item"><label>员工编号:</label><span id="quota-code"></span></div>
<div class="person-info__item"><label>单位部门:</label><span id="quota-unit"></span></div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 体检额度(元)</div>
<input class="form-input" id="quota-amount" type="number" min="0" step="0.01" placeholder="请输入体检额度">
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeQuotaModal()">取消</button>
<button class="btn btn-primary" onclick="saveQuota()">确认保存</button>
</div>
</div>
</div>
<script>
/* 侧边栏展开/折叠交互 */
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
/* 页面加载时自动展开当前页面所在的子分组 */
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 设置个人额度弹窗 ===== */
var quotaTr = null;
function openQuotaModal(btn){
quotaTr = btn.closest('tr');
var cells = quotaTr.cells;
document.getElementById('quota-name').textContent = cells[1].textContent.trim();
document.getElementById('quota-code').textContent = cells[2].textContent.trim();
document.getElementById('quota-unit').textContent = cells[6].textContent.trim() + ' / ' + cells[7].textContent.trim();
document.getElementById('quota-amount').value = cells[8].textContent.trim();
document.getElementById('quota-modal-overlay').classList.add('open');
}
function closeQuotaModal(){
document.getElementById('quota-modal-overlay').classList.remove('open');
}
function saveQuota(){
if(!quotaTr) return;
var amount = document.getElementById('quota-amount').value.trim();
if(!amount || Number(amount) < 0){ alert('请输入正确的体检额度'); return; }
quotaTr.cells[8].textContent = Number(amount).toFixed(2);
closeQuotaModal();
}
</script>
</body>
</html>
</aside>
<!-- 主内容 -->
<main class="main">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-item">
<label>单位部门:</label>
<select class="filter-select">
<option>全部</option>
<option>采油一厂</option>
<option>公司机关</option>
</select>
</div>
<div class="filter-item">
<label>姓名:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<div class="filter-item">
<label>员工编号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<div class="filter-item">
<label>身份证号:</label>
<input class="filter-input" type="text" placeholder="请输入" style="min-width:130px;">
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作栏 -->
<div style="display:flex;gap:12px;margin-bottom:16px;">
<button class="btn btn-primary">
<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="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
导出列表数据
</button>
<button class="btn btn-default">
<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__header">
<div class="table-card__title">个人额度列表</div>
</div>
<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>
<tbody>
<tr><td>1</td><td>张明</td><td>100234</td><td></td><td>38</td><td>610113199602632255</td><td>公司机关</td><td>人事部</td><td>2500.00</td><td></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span></td></tr>
<tr><td>2</td><td>李芳</td><td>100567</td><td></td><td>42</td><td>610113199602632255</td><td>公司机关</td><td>财务部</td><td>2500.00</td><td></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span></td></tr>
<tr><td>3</td><td>王强</td><td>200891</td><td></td><td>50</td><td>610113199602632255</td><td>采油一厂</td><td>生产办</td><td>2500.00</td><td></td><td><span class="link" onclick="openQuotaModal(this)">设置额度</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 1260 条</span>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<span>...</span>
<button class="page-btn">126</button>
<span>每页</span>
<select class="filter-select" style="min-width:70px;height:32px;"><option>10条</option><option>50条</option></select>
</div>
</div>
</main>
<!-- 设置个人额度弹窗 -->
<div class="modal-overlay" id="quota-modal-overlay" onclick="if(event.target===this)closeQuotaModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title">设置个人额度</div>
<button class="modal__close" onclick="closeQuotaModal()"></button>
</div>
<div class="modal__body">
<div class="person-info">
<div class="person-info__item"><label>姓名:</label><span id="quota-name"></span></div>
<div class="person-info__item"><label>员工编号:</label><span id="quota-code"></span></div>
<div class="person-info__item"><label>单位部门:</label><span id="quota-unit"></span></div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 体检额度(元)</div>
<input class="form-input" id="quota-amount" type="number" min="0" step="0.01" placeholder="请输入体检额度">
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeQuotaModal()">取消</button>
<button class="btn btn-primary" onclick="saveQuota()">确认保存</button>
</div>
</div>
</div>
<script>
/* 侧边栏展开/折叠交互 */
function toggleSubgroup(header){
header.parentElement.classList.toggle('open');
}
/* 页面加载时自动展开当前页面所在的子分组 */
(function(){
var active=document.querySelector('.sidebar-item.active');
if(!active)return;
var sub=active.closest('.sidebar-subgroup');
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 设置个人额度弹窗 ===== */
var quotaTr = null;
function openQuotaModal(btn){
quotaTr = btn.closest('tr');
var cells = quotaTr.cells;
document.getElementById('quota-name').textContent = cells[1].textContent.trim();
document.getElementById('quota-code').textContent = cells[2].textContent.trim();
document.getElementById('quota-unit').textContent = cells[6].textContent.trim() + ' / ' + cells[7].textContent.trim();
document.getElementById('quota-amount').value = cells[8].textContent.trim();
document.getElementById('quota-modal-overlay').classList.add('open');
}
function closeQuotaModal(){
document.getElementById('quota-modal-overlay').classList.remove('open');
}
function saveQuota(){
if(!quotaTr) return;
var amount = document.getElementById('quota-amount').value.trim();
if(!amount || Number(amount) < 0){ alert('请输入正确的体检额度'); return; }
quotaTr.cells[8].textContent = Number(amount).toFixed(2);
closeQuotaModal();
}
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,11 @@
# CHANGELOG | 体重管理 Web 管理端
## 2026-09-08 | 结果异常页表格错位修复 + 异常判定指标收敛
- **`exception-result-abnormal.html`**:列表第 9、10 行(陈静、郑飞)缺失"序号"单元格导致整行向左错位一格(姓名显示在序号列、异常等级显示在发现时间列),补齐序号 9/10;修复后表头 10 列与全部 10 个数据行的单元格数及序号序列(1-10)已脚本校验对齐
- **`exception-result-abnormal.html`**:结果异常判定收敛为五类指标——体重异常、体脂率异常、腰围异常、未提交审核、未通过审核;10 条示例数据每类 2 条重排(体重/体脂率/腰围异常来源个人体重管理、异常值为测量值;未提交审核/未通过审核来源报名管理目标体重审核流程,未通过审核异常值显示驳回原因;原 BMI异常/目标值偏差/体重反弹/数据缺失指标移除);筛选栏新增"异常指标"下拉(全部+五类),"业务模块"下拉收敛为全部/报名管理/个人体重管理;同日再移除"异常等级"——筛选下拉、表头列与 10 行等级标签单元格一并删除,删列后 9 列表头与数据行对齐已校验,页面不再使用标签样式故清理无引用的 .tag 系列 CSS
- **PRD.md**:结果异常节同步——筛选条件补异常指标下拉与业务模块收敛、表格列补序号、业务规则写明五类判定指标口径(未提交审核↔报名跟踪"未提交目标"、未通过审核↔目标体重审核"已驳回"),异常等级标签轻微颜色描述由绿色修正为与页面一致的蓝色;随后随页面移除异常等级,筛选条件/表格列/业务规则中相关条目同步删除
## 2026-09-01 | 蓝牙称成员管理弹窗增加移除操作
- **`bluetooth-device.html`**:成员管理弹窗成员列表新增"操作"列,未同步的成员显示"移除"链接(点击确认后从列表移除并刷新),已同步成员不显示操作
+6 -4
View File
@@ -1395,13 +1395,15 @@
**功能说明:** 汇总展示体重管理各业务模块产生的结果异常数据,支持多维度筛选。
**筛选条件:** 员工名称(输入框)、员工编号(输入框)、单位部门(二级联动面板)、业务模块(下拉:全部/档案管理/活动管理/报名管理/过程管理/历史活动/个人体重管理/设备管理)、异常等级(下拉:全部/严重/中等/轻微)、年份(下拉)
**筛选条件:** 员工名称(输入框)、员工编号(输入框)、单位部门(二级联动面板)、业务模块(下拉:全部/报名管理/个人体重管理)、异常指标(下拉:全部/体重异常/体脂率异常/腰围异常/未提交审核/未通过审核)、年份(下拉)
**表格列:** 员工、员工编号、单位名称、部门名称、业务模块、异常指标、异常值、异常等级(标签)、发现时间
**表格列:** 序号、员工、员工编号、单位名称、部门名称、业务模块、异常指标、异常值、发现时间
**业务规则:**
- 异常等级标签:严重(红色)、中等(橙色)、轻微(绿色)
- 异常指标含体重异常波动、BMI异常变化、设备数据异常等
- 结果异常判定共五类指标:
- 体重异常 / 体脂率异常 / 腰围异常:员工测量结果超出异常判定阈值,来源业务模块为个人体重管理,异常值显示发现时的测量值(如 95.6 kg、34.2%、105 cm
- 未提交审核:员工未提交目标体重审核(对应报名跟踪"未提交目标"状态),来源业务模块为报名管理
- 未通过审核:员工目标体重审核被驳回(对应目标体重审核"已驳回"状态),来源业务模块为报名管理,异常值显示驳回原因
**交互说明:**
- 支持导出列表数据、查看导出任务
@@ -76,13 +76,6 @@ tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);bo
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
/* 标签 */
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-blue{background:var(--primary-light);color:var(--primary);}
.tag-green{background:#F6FFED;color:var(--success);}
/* 分页 */
.pagination{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-top:1px solid var(--border);}
.pagination__left{display:flex;align-items:center;gap:8px;font-size:var(--font-sm);color:var(--text-secondary);}
@@ -163,22 +156,20 @@ tbody tr:hover{background:#F8FBFF;}
<label>业务模块</label>
<select class="filter-select">
<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">
<label>异常指标</label>
<!-- [交互] 结果异常判定指标:体重异常 / 体脂率异常 / 腰围异常 / 未提交审核 / 未通过审核 -->
<select class="filter-select" style="min-width:120px;">
<option>全部</option>
<option>严重</option>
<option>中等</option>
<option>轻微</option>
<option>体重异常</option>
<option>体脂率异常</option>
<option>腰围异常</option>
<option>未提交审核</option>
<option>未通过审核</option>
</select>
</div>
<div class="filter-item">
@@ -218,129 +209,120 @@ tbody tr:hover{background:#F8FBFF;}
<th>业务模块</th>
<th>异常指标</th>
<th>异常值</th>
<th>异常等级</th>
<th>发现时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>张伟</td>
<td>EMP-10001</td>
<td>采油一厂</td>
<td>生产运行科</td>
<td>个人体重管理</td>
<td>BMI异常</td>
<td>28.5</td>
<td><span class="tag tag-orange">中等</span></td>
<td>2026-05-14 10:30</td>
</tr>
<tr>
<td>2</td>
<td>李娜</td>
<td>EMP-10002</td>
<td>采油一厂</td>
<td>安全环保科</td>
<td>个人体重管理</td>
<td>体脂率异常</td>
<td>34.2%</td>
<td><span class="tag tag-red">严重</span></td>
<td>2026-05-13 14:22</td>
</tr>
<tr>
<td>3</td>
<td>王强</td>
<td>EMP-10003</td>
<td>采油二厂</td>
<td>综合管理科</td>
<td>个人体重管理</td>
<td>腰围异常</td>
<td>105 cm</td>
<td><span class="tag tag-red">严重</span></td>
<td>2026-05-12 09:15</td>
</tr>
<tr>
<td>4</td>
<td>赵敏</td>
<td>EMP-10004</td>
<td>采油二厂</td>
<td>生产运行科</td>
<td>活动管理</td>
<td>目标值偏差</td>
<td>距目标差8.5kg</td>
<td><span class="tag tag-orange">中等</span></td>
<td>2026-05-11 16:45</td>
</tr>
<tr>
<td>5</td>
<td>刘洋</td>
<td>EMP-10005</td>
<td>采气一厂</td>
<td>安全环保科</td>
<td>过程管理</td>
<td>体重反弹</td>
<td>+3.2 kg30天)</td>
<td><span class="tag tag-orange">中等</span></td>
<td>2026-05-10 11:20</td>
</tr>
<tr>
<td>6</td>
<td>孙磊</td>
<td>EMP-10101</td>
<td>采油一厂</td>
<td>生产运行科</td>
<td>个人体重管理</td>
<td>数据缺失</td>
<td>未设置目标</td>
<td><span class="tag tag-blue">轻微</span></td>
<td>2026-05-09 08:55</td>
</tr>
<tr>
<td>7</td>
<td>周婷</td>
<td>EMP-10102</td>
<td>采油二厂</td>
<td>安全环保科</td>
<td>个人体重管理</td>
<td>体重异常</td>
<td>80.2 kg</td>
<td><span class="tag tag-red">严重</span></td>
<td>2026-05-08 15:38</td>
</tr>
<tr>
<td>8</td>
<td>吴刚</td>
<td>EMP-10103</td>
<td>采气一厂</td>
<td>综合管理科</td>
<td>个人体重管理</td>
<td>BMI异常</td>
<td>32.1</td>
<td><span class="tag tag-red">严重</span></td>
<td>2026-05-07 10:12</td>
</tr>
<tr>
<td>陈静</td>
<td>EMP-10104</td>
<td>天然气处理厂</td>
<td>综合管理科</td>
<td>活动管理</td>
<td>目标值偏差</td>
<td>距目标差6.3kg</td>
<td><span class="tag tag-orange">中等</span></td>
<td>2026-05-06 14:05</td>
<tbody>
<tr>
<td>1</td>
<td>张伟</td>
<td>EMP-10001</td>
<td>采油一厂</td>
<td>生产运行科</td>
<td>个人体重管理</td>
<td>体重异常</td>
<td>95.6 kg</td>
<td>2026-05-14 10:30</td>
</tr>
<tr>
<td>2</td>
<td>周婷</td>
<td>EMP-10102</td>
<td>采油二厂</td>
<td>安全环保科</td>
<td>个人体重管理</td>
<td>体重异常</td>
<td>80.2 kg</td>
<td>2026-05-08 15:38</td>
</tr>
<tr>
<td>3</td>
<td>李娜</td>
<td>EMP-10002</td>
<td>采油一厂</td>
<td>安全环保科</td>
<td>个人体重管理</td>
<td>体脂率异常</td>
<td>34.2%</td>
<td>2026-05-13 14:22</td>
</tr>
<tr>
<td>4</td>
<td>吴刚</td>
<td>EMP-10103</td>
<td>采气一厂</td>
<td>综合管理科</td>
<td>个人体重管理</td>
<td>体脂率异常</td>
<td>29.8%</td>
<td>2026-05-07 10:12</td>
</tr>
<tr>
<td>5</td>
<td>王强</td>
<td>EMP-10003</td>
<td>采油二厂</td>
<td>综合管理科</td>
<td>个人体重管理</td>
<td>腰围异常</td>
<td>105 cm</td>
<td>2026-05-12 09:15</td>
</tr>
<tr>
<td>6</td>
<td>郑飞</td>
<td>EMP-10105</td>
<td>采油二厂</td>
<td>生产运行科</td>
<td>过程管理</td>
<td>个人体重管理</td>
<td>腰围异常</td>
<td>98 cm</td>
<td><span class="tag tag-orange">中等</span></td>
<td>2026-05-05 17:42</td>
</tr>
<tr>
<td>7</td>
<td>赵敏</td>
<td>EMP-10004</td>
<td>采油二厂</td>
<td>生产运行科</td>
<td>报名管理</td>
<td>未提交审核</td>
<td>目标体重未提交审核</td>
<td>2026-05-11 16:45</td>
</tr>
<tr>
<td>8</td>
<td>孙磊</td>
<td>EMP-10101</td>
<td>采油一厂</td>
<td>生产运行科</td>
<td>报名管理</td>
<td>未提交审核</td>
<td>目标体重未提交审核</td>
<td>2026-05-09 08:55</td>
</tr>
<tr>
<td>9</td>
<td>刘洋</td>
<td>EMP-10005</td>
<td>采气一厂</td>
<td>安全环保科</td>
<td>报名管理</td>
<td>未通过审核</td>
<td>审核驳回:减重目标过于激进</td>
<td>2026-05-10 11:20</td>
</tr>
<tr>
<td>10</td>
<td>陈静</td>
<td>EMP-10104</td>
<td>天然气处理厂</td>
<td>综合管理科</td>
<td>报名管理</td>
<td>未通过审核</td>
<td>审核驳回:目标体重与身高不匹配</td>
<td>2026-05-06 14:05</td>
</tr>
</tbody>
</table>
</div>