<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>江苏省OPO可视化调度平台 - 态势总览分析 V1.9</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* ==================== 1. 全局与背景 ==================== */
:root {
--color-clue: #007aff; /* 蓝 */
--color-case: #30d158; /* 绿 */
--color-organ: #bf5af2; /* 紫 */
--color-trans: #00f0ff; /* 青 */
--tech-bg: #050b16;
--text-main: #ffffff;
--text-sub: #8fb4d9;
/* 筛选器专用色 */
--input-bg: rgba(20, 40, 70, 0.8);
--input-border: #284875;
--active-blue: #007aff;
}
body {
margin: 0; padding: 0;
background-color: var(--tech-bg);
font-family: "Microsoft YaHei", sans-serif;
color: var(--text-main);
height: 100vh; width: 100vw;
overflow: hidden;
}
.bg-layer {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
background-image: radial-gradient(circle at 50% 50%, #112240 0%, #02050a 100%),
url('https://api.mapbox.com/styles/v1/mapbox/dark-v10/static/118.78,32.07,7,0/1600x1200?access_token=pk.eyJ1IjoiZGVtb3VzZXIiLCJhIjoiY2x4eH..."');
background-size: cover; filter: blur(4px); transform: scale(1.05);
z-index: 0;
}
/* ==================== 2. 容器与通用样式 ==================== */
.analysis-modal {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
width: 90vw; height: 90vh;
background: rgba(10, 20, 35, 0.95);
border: 1px solid var(--color-trans);
box-shadow: 0 0 50px rgba(0, 240, 255, 0.15);
border-radius: 8px;
display: flex; flex-direction: column;
z-index: 100;
backdrop-filter: blur(10px);
}
.modal-header {
height: 60px; border-bottom: 1px solid rgba(255,255,255,0.1);
display: flex; align-items: center; justify-content: space-between;
padding: 0 25px; background: linear-gradient(90deg, rgba(0,240,255,0.1) 0%, transparent 100%);
}
.mh-title { font-size: 20px; font-weight: bold; color: #fff; letter-spacing: 2px; display: flex; align-items: center; gap: 10px; }
.mh-title::before { content: ''; width: 4px; height: 20px; background: var(--color-trans); display: block; box-shadow: 0 0 10px var(--color-trans); }
.mh-close { width: 32px; height: 32px; border: 1px solid rgba(255,69,58,0.5); background: rgba(255,69,58,0.1); color: #ff453a; border-radius: 4px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: 0.3s; }
.mh-close:hover { background: #ff453a; color: #fff; }
.modal-body { flex: 1; padding: 0 20px 20px 20px; display: flex; flex-direction: column; gap: 15px; overflow-y: auto; }
.panel-box {
background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.05); border-radius: 6px;
padding: 15px; display: flex; flex-direction: column; position: relative;
}
.panel-box::after { content: ''; position: absolute; top: 0; right: 0; width: 10px; height: 10px; border-top: 2px solid var(--color-trans); border-right: 2px solid var(--color-trans); }
.box-title { font-size: 14px; color: var(--text-sub); margin-bottom: 15px; font-weight: bold; display: flex; justify-content: space-between; align-items: center; border-left: 3px solid var(--color-clue); padding-left: 8px; line-height: 1; }
/* ==================== 3. 筛选控制栏 (V1.9 E-Charts Style) ==================== */
.filter-bar {
display: flex; align-items: center; gap: 20px; /* 左对齐+间距 */
padding: 15px 5px; border-bottom: 1px dashed rgba(255,255,255,0.1); margin-bottom: 5px;
}
.fb-item { display: flex; align-items: center; gap: 8px; }
.fb-label { font-size: 13px; color: #ddd; white-space: nowrap; }
/* 区域选择 */
.region-select {
background: var(--input-bg); border: 1px solid var(--input-border); color: #fff;
padding: 5px 10px; border-radius: 4px; font-size: 13px; outline: none; cursor: pointer; min-width: 140px;
}
/* E-Charts 风格时间组件容器 */
.time-picker-container { display: flex; align-items: center; position: relative; }
/* 左侧:输入框显示区 */
.tp-display {
background: var(--input-bg); border: 1px solid var(--input-border);
border-radius: 4px 0 0 4px;
padding: 5px 12px; font-size: 13px; color: #fff;
width: 160px; cursor: pointer; position: relative;
display: flex; align-items: center; gap: 8px;
}
.tp-display:hover { border-color: var(--active-blue); }
.tp-icon { color: var(--color-trans); }
/* 右侧:类型切换按钮组 */
.tp-toggles { display: flex; }
.tp-btn {
background: transparent; border: 1px solid var(--input-border); border-left: none;
color: #aaa; padding: 5px 12px; font-size: 13px; cursor: pointer; transition: 0.2s;
}
.tp-btn:last-child { border-radius: 0 4px 4px 0; }
.tp-btn:hover { color: #fff; }
.tp-btn.active { background: var(--active-blue); color: #fff; border-color: var(--active-blue); font-weight: bold; }
/* 下拉面板 */
.tp-popup {
position: absolute; top: 100%; left: 0; margin-top: 5px;
width: 280px; background: #0f223d; border: 1px solid var(--input-border);
box-shadow: 0 4px 20px rgba(0,0,0,0.5); z-index: 50; border-radius: 4px;
display: none; flex-direction: column;
}
.tp-popup.show { display: flex; }
.tp-pop-header {
display: flex; justify-content: space-between; align-items: center; padding: 10px;
border-bottom: 1px solid rgba(255,255,255,0.1); color: #fff; font-size: 14px;
}
.tp-pop-arrow { cursor: pointer; color: #aaa; padding: 0 5px; }
.tp-pop-arrow:hover { color: #fff; }
.tp-pop-grid { display: grid; padding: 10px; gap: 8px; }
/* 月度 grid */
.grid-month { grid-template-columns: repeat(4, 1fr); }
/* 季度 grid */
.grid-quarter { grid-template-columns: repeat(2, 1fr); }
.tp-grid-item {
text-align: center; padding: 8px 0; font-size: 12px; color: #ccc; border-radius: 4px; cursor: pointer;
}
.tp-grid-item:hover { background: rgba(255,255,255,0.1); color: #fff; }
.tp-grid-item.active { background: var(--active-blue); color: #fff; }
/* ==================== ROW 1: KPI 指标 ==================== */
.kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; height: 120px; }
.kpi-card {
background: linear-gradient(135deg, rgba(255,255,255,0.05) 0%, rgba(0,0,0,0.3) 100%);
display: flex; flex-direction: column; justify-content: center; padding: 0 25px;
border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; position: relative; overflow: hidden;
}
.kpi-icon-bg { position: absolute; right: 10px; bottom: -10px; font-size: 70px; opacity: 0.1; color: #fff; transform: rotate(-15deg); }
.kpi-lbl { font-size: 14px; color: #fff; margin-bottom: 8px; font-weight: 500; text-shadow: 0 0 5px rgba(0,0,0,0.5); }
.kpi-num { font-family: Impact, sans-serif; font-size: 36px; color: #fff; letter-spacing: 1px; line-height: 1; text-shadow: 0 0 10px rgba(0,0,0,0.5); }
.kpi-trend { font-size: 12px; margin-top: 10px; display: flex; align-items: center; gap: 5px; color: #ddd; }
.c-clue { color: var(--color-clue); }
.c-case { color: var(--color-case); }
.c-organ { color: var(--color-organ); }
.c-trans { color: var(--color-trans); }
/* ==================== ROW 2: 中部图表 ==================== */
.mid-row { display: flex; gap: 20px; height: 350px; }
.mid-left { flex: 2; }
.mid-right { flex: 3; }
/* 漏斗 (V1.7 样式) */
.funnel-container { flex: 1; display: flex; flex-direction: column; gap: 15px; padding: 0 10px; justify-content: center; }
.funnel-block { display: flex; flex-direction: column; gap: 4px; padding: 10px; border-radius: 8px; border: 1px solid transparent; transition: all 0.4s ease; cursor: pointer; position: relative; opacity: 0.5; filter: grayscale(0.5); }
.funnel-block:hover { opacity: 0.8; filter: grayscale(0.2); }
.funnel-block.active-block-upper { opacity: 1; filter: grayscale(0); background: rgba(0, 122, 255, 0.1); border-color: var(--color-case); box-shadow: inset 0 0 20px rgba(0, 122, 255, 0.1), 0 0 15px rgba(48, 209, 88, 0.3); }
.funnel-block.active-block-lower { opacity: 1; filter: grayscale(0); background: rgba(191, 90, 242, 0.1); border-color: var(--color-trans); box-shadow: inset 0 0 20px rgba(191, 90, 242, 0.1), 0 0 15px rgba(0, 240, 255, 0.3); }
.funnel-step { display: flex; align-items: center; justify-content: center; position: relative; height: 40px; color: #fff; font-weight: bold; clip-path: polygon(2% 0%, 98% 0%, 92% 100%, 8% 100%); margin: 0 auto; box-shadow: 0 4px 10px rgba(0,0,0,0.3); }
.fs-content { display: flex; align-items: center; gap: 15px; z-index: 2; text-shadow: 0 1px 3px rgba(0,0,0,0.8); }
.fs-name { font-size: 13px; opacity: 0.9; }
.fs-val { font-family: monospace; font-size: 16px; color: #fff; }
.fs-1 { width: 95%; background: linear-gradient(90deg, #003870 0%, var(--color-clue) 50%, #003870 100%); }
.fs-2 { width: 80%; background: linear-gradient(90deg, #004c4c 0%, var(--color-case) 50%, #004c4c 100%); }
.fs-3 { width: 65%; background: linear-gradient(90deg, #4c2060 0%, var(--color-organ) 50%, #4c2060 100%); }
.fs-4 { width: 50%; background: linear-gradient(90deg, #004040 0%, var(--color-trans) 50%, #004040 100%); }
.funnel-arrow { text-align: center; color: rgba(255,255,255,0.8); font-size: 11px; margin: 2px 0; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 4px; }
.tag-rate { background: rgba(0,0,0,0.4); padding: 1px 8px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.2); }
/* 趋势图 */
.chart-legend { display: flex; gap: 15px; font-size: 12px; color: #aaa; }
.legend-item { display: flex; align-items: center; gap: 5px; }
.dot { width: 10px; height: 10px; border-radius: 2px; }
.chart-tag { font-size: 10px; color: #666; background: rgba(255,255,255,0.05); padding: 2px 6px; border-radius: 4px; margin-left: 10px; border: 1px solid rgba(255,255,255,0.1); }
.chart-wrapper { flex: 1; display: flex; position: relative; padding: 10px 0 0 0; }
.chart-y-axis { display: flex; flex-direction: column; justify-content: space-between; padding-bottom: 25px; padding-right: 10px; color: #666; font-size: 10px; text-align: right; width: 30px; border-right: 1px solid #333; height: 100%; }
.chart-grid-area { flex: 1; position: relative; display: flex; align-items: flex-end; justify-content: space-between; border-bottom: 1px solid #333; padding-bottom: 0px; background: repeating-linear-gradient(0deg, #222 0px, transparent 1px, transparent 20%); }
.chart-col { display: flex; flex-direction: column; justify-content: flex-end; align-items: center; height: 100%; flex: 1; position: relative; }
.bar-group { display: flex; align-items: flex-end; justify-content: center; gap: 4px; height: 100%; width: 80%; }
.bar { width: 10px; border-radius: 2px 2px 0 0; position: relative; opacity: 0.9; animation: growUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards; height: 0; }
.bar:hover { opacity: 1; filter: brightness(1.2); }
.bar-val-top { position: absolute; top: -16px; left: 50%; transform: translateX(-50%); font-size: 9px; color: #fff; font-family: Arial; opacity: 1; }
@keyframes growUp { from { height: 0; } to { height: var(--h); } }
.x-axis-lbl { position: absolute; bottom: -25px; font-size: 10px; color: #888; width: 100%; text-align: center; }
/* ==================== ROW 3: 底部画像 ==================== */
.bot-row { display: flex; gap: 20px; flex: 1; min-height: 0; }
.bot-col { flex: 1; display: flex; flex-direction: column; }
.donut-wrap { display: flex; align-items: center; justify-content: center; height: 100%; gap: 10px; padding: 10px; }
.donut-chart { width: 170px; height: 170px; border-radius: 50%; background: conic-gradient(var(--color-trans) 0% 35%, var(--color-clue) 35% 60%, var(--color-case) 60% 80%, var(--color-organ) 80% 95%, #ff453a 95% 100%); position: relative; box-shadow: 0 0 20px rgba(0,0,0,0.6); }
.donut-chart::before { content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 110px; height: 110px; background: rgba(16, 36, 68, 1); border-radius: 50%; }
.donut-center-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #fff; }
.dc-val { font-size: 24px; font-weight: bold; font-family: Impact; }
.dc-lbl { font-size: 11px; color: #888; }
.donut-legend { display: flex; flex-direction: column; gap: 8px; justify-content: center; }
.dl-item { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #ccc; }
.dl-color { width: 10px; height: 10px; border-radius: 2px; }
.age-chart-container { flex: 1; display: flex; position: relative; padding-left: 30px; padding-bottom: 20px; }
.age-y-axis { position: absolute; left: 0; top: 0; bottom: 20px; width: 30px; display: flex; flex-direction: column; justify-content: space-between; font-size: 9px; color: #666; border-right: 1px solid #333; text-align: right; padding-right: 5px; }
.age-bars-area { flex: 1; border-bottom: 1px solid #333; display: flex; align-items: flex-end; justify-content: space-around; height: 100%; padding-top: 20px; }
.age-col { display: flex; flex-direction: column; align-items: center; width: 12%; height: 100%; justify-content: flex-end; position: relative; }
.age-bar { width: 100%; background: linear-gradient(0deg, rgba(0,240,255,0.2), rgba(0,240,255,0.8)); border-top: 2px solid #fff; border-radius: 2px 2px 0 0; position: relative; }
.age-val { position: absolute; top: -16px; left: 50%; transform: translateX(-50%); font-size: 10px; color: var(--color-trans); }
.age-lbl { position: absolute; bottom: -20px; font-size: 10px; color: #888; white-space: nowrap; }
.profile-container { flex: 1; display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 0.8fr; grid-template-areas: "left center right" "bot-left center bot-right"; gap: 10px 20px; padding: 5px 15px; }
.area-left { grid-area: left; display: flex; flex-direction: column; justify-content: center; }
.area-right { grid-area: right; display: flex; flex-direction: column; justify-content: center; }
.area-center { grid-area: center; display: flex; align-items: center; justify-content: center; position: relative; }
.area-bot-left { grid-area: bot-left; display: flex; flex-direction: column; justify-content: flex-start; }
.area-bot-right { grid-area: bot-right; display: flex; flex-direction: column; justify-content: flex-start; }
.human-silhouette { font-size: 120px; color: rgba(255,255,255,0.05); text-shadow: 0 0 15px var(--color-clue); z-index: 1; }
.prof-group { display: flex; flex-direction: column; gap: 4px; }
.prof-title { font-size: 11px; color: var(--color-trans); border-bottom: 1px solid rgba(0,240,255,0.3); padding-bottom: 2px; margin-bottom: 4px; display: flex; align-items: center; gap: 5px; }
.data-row { display: flex; align-items: center; justify-content: space-between; font-size: 10px; color: #ccc; margin-bottom: 1px; }
.data-bar-bg { width: 100%; height: 3px; background: rgba(255,255,255,0.1); border-radius: 2px; margin-bottom: 4px; }
.data-bar-fill { height: 100%; border-radius: 2px; }
</style>
</head>
<body>
<div class="bg-layer"></div>
<div class="analysis-modal">
<!-- 头部 -->
<div class="modal-header">
<div class="mh-title">态势总览分析 <span style="font-size:12px; color:#666; margin-left:10px; border:1px solid #444; padding:2px 6px; border-radius:4px;">V1.9</span></div>
<div class="mh-close" onclick="alert('返回地图主页')"><i class="fas fa-times"></i></div>
</div>
<div class="modal-body">
<!-- 筛选控制栏 (V1.9) -->
<div class="filter-bar">
<!-- 区域 -->
<div class="fb-item">
<span class="fb-label">所属区域:</span>
<select class="region-select">
<option>江苏全省</option>
<option>南京市</option>
<option>苏州市</option>
</select>
</div>
<!-- 时间 (E-Charts 风格) -->
<div class="fb-item">
<span class="fb-label">数据时间:</span>
<div class="time-picker-container">
<!-- 输入显示框 -->
<div class="tp-display" onclick="togglePopup()">
<i class="far fa-calendar-alt tp-icon"></i>
<span id="tp-value">2023</span>
</div>
<!-- 类型切换 -->
<div class="tp-toggles">
<button class="tp-btn" onclick="switchTimeType('month')">月度</button>
<button class="tp-btn" onclick="switchTimeType('quarter')">季度</button>
<button class="tp-btn active" onclick="switchTimeType('year')">年度</button>
</div>
<!-- 下拉选择面板 -->
<div class="tp-popup" id="tp-popup">
<!-- 动态渲染内容 -->
</div>
</div>
</div>
</div>
<!-- Row 1: KPI 指标 -->
<div class="kpi-row">
<div class="kpi-card">
<i class="fas fa-notes-medical kpi-icon-bg"></i>
<div class="kpi-lbl">线索上报</div>
<div class="kpi-num c-clue">1,248</div>
<div class="kpi-trend"><span style="color:#30d158"><i class="fas fa-arrow-up"></i> 同比增长 12.5%</span></div>
</div>
<div class="kpi-card">
<i class="fas fa-hands-holding-heart kpi-icon-bg"></i>
<div class="kpi-lbl">捐赠案例</div>
<div class="kpi-num c-case">356</div>
<div class="kpi-trend"><span style="color:#30d158"><i class="fas fa-arrow-up"></i> 同比增长 8.2%</span></div>
</div>
<div class="kpi-card">
<i class="fas fa-box-open kpi-icon-bg"></i>
<div class="kpi-lbl">器官获取</div>
<div class="kpi-num c-organ">1,089</div>
<div class="kpi-trend"><span style="color:#30d158"><i class="fas fa-arrow-up"></i> 同比增长 5.4%</span></div>
</div>
<div class="kpi-card">
<i class="fas fa-user-check kpi-icon-bg"></i>
<div class="kpi-lbl">成功移植</div>
<div class="kpi-num c-trans">1,067</div>
<div class="kpi-trend"><span style="color:#30d158"><i class="fas fa-arrow-up"></i> 同比增长 4.9%</span></div>
</div>
</div>
<!-- Row 2: 中部图表 -->
<div class="mid-row">
<!-- 左:效能分析 -->
<div class="panel-box mid-left">
<div class="box-title">效能分析</div>
<div class="funnel-container">
<div class="funnel-block active-block-upper" id="block-upper" onclick="switchChart('case')">
<div class="funnel-step fs-1"><div class="fs-content"><span class="fs-name">上报线索</span><span class="fs-val">1,248</span></div></div>
<div class="funnel-arrow"><span class="tag-rate"><i class="fas fa-filter"></i> 转化率 45%</span></div>
<div class="funnel-step fs-2"><div class="fs-content"><span class="fs-name">案例维护</span><span class="fs-val">561</span></div></div>
<div class="funnel-arrow mt-1"><span class="tag-rate text-yellow-300 border-yellow-500/30"><i class="fas fa-exchange-alt"></i> 平均器官获取数 1.94</span></div>
</div>
<div class="funnel-block" id="block-lower" onclick="switchChart('organ')">
<div class="funnel-step fs-3"><div class="fs-content"><span class="fs-name">获取/转运完成</span><span class="fs-val">1,089</span></div></div>
<div class="funnel-arrow"><span class="tag-rate"><i class="fas fa-check-circle"></i> 成功率 98%</span></div>
<div class="funnel-step fs-4"><div class="fs-content"><span class="fs-name">移植成功</span><span class="fs-val">1,067</span></div></div>
</div>
</div>
</div>
<!-- 右:趋势分析 -->
<div class="panel-box mid-right">
<div class="box-title">
<span>趋势分析 <span class="chart-tag">年度全量</span></span>
<div class="chart-legend" id="chartLegend"></div>
</div>
<div class="chart-wrapper">
<div class="chart-y-axis"><span>150</span><span>100</span><span>50</span><span>0</span></div>
<div class="chart-grid-area" id="trendChartContainer"></div>
</div>
</div>
</div>
<!-- Row 3: 底部画像 -->
<div class="bot-row">
<!-- 器官分布 -->
<div class="panel-box bot-col">
<div class="box-title">获取器官类型分布</div>
<div class="donut-wrap">
<div class="donut-chart"><div class="donut-center-text"><div class="dc-val">1089</div><div class="dc-lbl">总量</div></div></div>
<div class="donut-legend">
<div class="dl-item"><div class="dl-color" style="background:var(--color-trans)"></div> 肝脏 (35%)</div>
<div class="dl-item"><div class="dl-color" style="background:var(--color-clue)"></div> 肾脏 (25%)</div>
<div class="dl-item"><div class="dl-color" style="background:var(--color-case)"></div> 心脏 (20%)</div>
<div class="dl-item"><div class="dl-color" style="background:var(--color-organ)"></div> 肺脏 (15%)</div>
<div class="dl-item"><div class="dl-color" style="background:#ff453a"></div> 其他 (5%)</div>
</div>
</div>
</div>
<!-- 年龄分布 -->
<div class="panel-box bot-col">
<div class="box-title">捐献者年龄分布</div>
<div class="age-chart-container">
<div class="age-y-axis"><span>40%</span><span>20%</span><span>0%</span></div>
<div class="age-bars-area">
<div class="age-col"><div class="age-val">5%</div><div class="age-bar" style="height:12%"></div><span class="age-lbl"><18</span></div>
<div class="age-col"><div class="age-val">25%</div><div class="age-bar" style="height:62%"></div><span class="age-lbl">18-35</span></div>
<div class="age-col"><div class="age-val">40%</div><div class="age-bar" style="height:100%"></div><span class="age-lbl">36-50</span></div>
<div class="age-col"><div class="age-val">20%</div><div class="age-bar" style="height:50%"></div><span class="age-lbl">51-65</span></div>
<div class="age-col"><div class="age-val">10%</div><div class="age-bar" style="height:25%"></div><span class="age-lbl">>65</span></div>
</div>
</div>
</div>
<!-- 供体画像 -->
<div class="panel-box bot-col">
<div class="box-title">供体生物学画像</div>
<div class="profile-container">
<div class="area-left">
<div class="prof-group">
<div class="prof-title"><i class="fas fa-tint"></i> 血型分布</div>
<div class="data-row"><span>A型</span> <span>32%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-blue-500" style="width:32%"></div></div>
<div class="data-row"><span>O型</span> <span>30%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-green-500" style="width:30%"></div></div>
<div class="data-row"><span>B型</span> <span>28%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-yellow-500" style="width:28%"></div></div>
<div class="data-row"><span>AB型</span> <span>10%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-red-500" style="width:10%"></div></div>
</div>
</div>
<div class="area-center"><i class="fas fa-male human-silhouette"></i></div>
<div class="area-right">
<div class="prof-group">
<div class="prof-title"><i class="fas fa-file-signature"></i> 意愿分布</div>
<div class="data-row"><span>全部同意</span> <span>40%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-green-500" style="width:40%"></div></div>
<div class="data-row"><span>部分同意</span> <span>20%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-teal-500" style="width:20%"></div></div>
<div class="data-row"><span>犹豫</span> <span>15%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-yellow-500" style="width:15%"></div></div>
<div class="data-row"><span>不同意</span> <span>25%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-red-500" style="width:25%"></div></div>
</div>
</div>
<div class="area-bot-left">
<div class="prof-group">
<div class="prof-title"><i class="fas fa-venus-mars"></i> 性别分布</div>
<div class="data-row"><span>男</span> <span>62%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-blue-400" style="width:62%"></div></div>
<div class="data-row"><span>女</span> <span>38%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-pink-400" style="width:38%"></div></div>
</div>
</div>
<div class="area-bot-right">
<div class="prof-group">
<div class="prof-title"><i class="fas fa-users"></i> 民族分布</div>
<div class="data-row"><span>汉族</span> <span>96%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-indigo-500" style="width:96%"></div></div>
<div class="data-row"><span>少数民族</span> <span>4%</span></div><div class="data-bar-bg"><div class="data-bar-fill bg-orange-500" style="width:4%"></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// --- 1. 时间筛选器逻辑 (E-Charts Style) ---
let timeMode = 'year';
let currentTime = '2023';
function switchTimeType(mode) {
timeMode = mode;
// Update Buttons
document.querySelectorAll('.tp-btn').forEach(btn => btn.classList.remove('active'));
event.target.classList.add('active');
// Update Display Text Placeholder
const valDisplay = document.getElementById('tp-value');
if (mode === 'year') valDisplay.innerText = '2023';
if (mode === 'quarter') valDisplay.innerText = '2023 第一季度';
if (mode === 'month') valDisplay.innerText = '2023-01';
renderPopupContent();
}
function togglePopup() {
const popup = document.getElementById('tp-popup');
popup.classList.toggle('show');
if(popup.classList.contains('show')) renderPopupContent();
}
function selectTimeValue(val) {
document.getElementById('tp-value').innerText = val;
document.getElementById('tp-popup').classList.remove('show');
}
function renderPopupContent() {
const popup = document.getElementById('tp-popup');
let header = `
<div class="tp-pop-header">
<span class="tp-pop-arrow"><i class="fas fa-angle-double-left"></i></span>
<span>2023年</span>
<span class="tp-pop-arrow"><i class="fas fa-angle-double-right"></i></span>
</div>
`;
let grid = '';
if (timeMode === 'month') {
let items = ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'];
grid = `<div class="tp-pop-grid grid-month">` +
items.map(m => `<div class="tp-grid-item" onclick="selectTimeValue('2023-${m}')">${m}</div>`).join('') +
`</div>`;
} else if (timeMode === 'quarter') {
let items = ['第一季度','第二季度','第三季度','第四季度'];
grid = `<div class="tp-pop-grid grid-quarter">` +
items.map(q => `<div class="tp-grid-item" onclick="selectTimeValue('2023 ${q}')">${q}</div>`).join('') +
`</div>`;
} else { // Year
// Simple placeholder for year grid
grid = `<div class="tp-pop-grid grid-quarter">
<div class="tp-grid-item active" onclick="selectTimeValue('2023')">2023</div>
<div class="tp-grid-item" onclick="selectTimeValue('2022')">2022</div>
<div class="tp-grid-item" onclick="selectTimeValue('2021')">2021</div>
<div class="tp-grid-item" onclick="selectTimeValue('2020')">2020</div>
</div>`;
}
popup.innerHTML = header + grid;
}
// --- 2. 趋势图逻辑 (V1.7 保持不变) ---
const dataCase = [ { m: '1月', v1: 80, v2: 20 }, { m: '2月', v1: 65, v2: 15 }, { m: '3月', v1: 90, v2: 30 }, { m: '4月', v1: 110, v2: 35 }, { m: '5月', v1: 100, v2: 28 }, { m: '6月', v1: 120, v2: 40 }, { m: '7月', v1: 130, v2: 45 }, { m: '8月', v1: 115, v2: 38 }, { m: '9月', v1: 125, v2: 42 }, { m: '10月', v1: 140, v2: 50 }, { m: '11月', v1: 100, v2: 30 }, { m: '12月', v1: 70, v2: 18 } ];
const dataOrgan = [ { m: '1月', v1: 55, v2: 53 }, { m: '2月', v1: 40, v2: 38 }, { m: '3月', v1: 85, v2: 82 }, { m: '4月', v1: 95, v2: 95 }, { m: '5月', v1: 75, v2: 70 }, { m: '6月', v1: 110, v2: 108 }, { m: '7月', v1: 125, v2: 120 }, { m: '8月', v1: 100, v2: 98 }, { m: '9月', v1: 115, v2: 112 }, { m: '10月', v1: 135, v2: 135 }, { m: '11月', v1: 80, v2: 80 }, { m: '12月', v1: 50, v2: 48 } ];
let currentChart = 'case';
function switchChart(type) {
currentChart = type;
renderChart();
updateBlockStyles();
}
function updateBlockStyles() {
const up = document.getElementById('block-upper');
const low = document.getElementById('block-lower');
up.classList.remove('active-block-upper');
low.classList.remove('active-block-lower');
if(currentChart === 'case') { up.classList.add('active-block-upper'); } else { low.classList.add('active-block-lower'); }
}
function renderChart() {
const container = document.getElementById('trendChartContainer');
const legend = document.getElementById('chartLegend');
const data = currentChart === 'case' ? dataCase : dataOrgan;
const maxVal = 150;
const col1 = currentChart === 'case' ? 'var(--color-clue)' : 'var(--color-organ)';
const col2 = currentChart === 'case' ? 'var(--color-case)' : 'var(--color-trans)';
const name1 = currentChart === 'case' ? '线索上报' : '器官获取';
const name2 = currentChart === 'case' ? '捐赠案例' : '成功移植';
legend.innerHTML = `<div class="legend-item"><div class="dot" style="background:${col1}"></div>${name1}</div><div class="legend-item"><div class="dot" style="background:${col2}"></div>${name2}</div>`;
container.innerHTML = data.map(d => {
const h1 = (d.v1 / maxVal) * 100;
const h2 = (d.v2 / maxVal) * 100;
return `<div class="chart-col"><div class="bar-group"><div class="bar" style="--h: ${h1}%; background:${col1}"><span class="bar-val-top">${d.v1}</span></div><div class="bar" style="--h: ${h2}%; background:${col2}"><span class="bar-val-top">${d.v2}</span></div></div><div class="x-axis-lbl">${d.m}</div></div>`;
}).join('');
}
switchChart('case');
// 点击外部关闭下拉
document.addEventListener('click', function(e) {
if (!e.target.closest('.time-picker-container')) {
document.getElementById('tp-popup').classList.remove('show');
}
});
</script>
</body>
</html>
index.html
style.css
index.js
index.html