| Server IP : 104.21.73.108 / Your IP : 216.73.216.59 Web Server : Apache/2 System : Linux cat167-197.static.lnwhostname.com 5.10.0-20-amd64 #1 SMP Debian 5.10.158-2 (2022-12-13) x86_64 User : paphayomho ( 1042) PHP Version : 5.6.40 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/paphayomho/domains/paphayomhospital.go.th/private_html/ |
Upload File : |
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ตัวชี้วัดและผลลัพธ์ 5 ปี 2566-2570 | รพ.ป่าพะยอม</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&family=Noto+Sans+Thai:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
<style>
:root {
--primary: #0d5c8f;
--primary-light: #1a7bbf;
--primary-dark: #093d61;
--secondary: #1a9e6e;
--secondary-light: #22c587;
--accent: #f59e0b;
--accent2: #e74c3c;
--bg: #f0f4f8;
--card: #ffffff;
--text: #1a2942;
--text-muted: #5c7a99;
--border: #d1dde8;
--good: #16a34a;
--good-bg: #dcfce7;
--warn: #ca8a04;
--warn-bg: #fef9c3;
--bad: #dc2626;
--bad-bg: #fee2e2;
--na: #6b7280;
--na-bg: #f3f4f6;
--shadow: 0 2px 16px rgba(13,92,143,0.08);
--shadow-lg: 0 8px 32px rgba(13,92,143,0.12);
--radius: 12px;
--radius-sm: 8px;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
font-family: 'Sarabun', 'Noto Sans Thai', sans-serif;
background: var(--bg);
color: var(--text);
font-size: 15px;
line-height: 1.6;
}
/* ── HERO ── */
.hero {
background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 50%, var(--primary-light) 100%);
color: #fff;
padding: 56px 32px 48px;
text-align: center;
position: relative;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute; inset: 0;
background: radial-gradient(ellipse at 80% 20%, rgba(26,155,110,0.2) 0%, transparent 60%),
radial-gradient(ellipse at 20% 80%, rgba(245,158,11,0.1) 0%, transparent 60%);
}
.hero-badge {
display: inline-block;
background: rgba(255,255,255,0.15);
border: 1px solid rgba(255,255,255,0.3);
border-radius: 20px;
padding: 5px 18px;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.5px;
margin-bottom: 16px;
position: relative;
}
.hero h1 {
font-size: clamp(22px, 4vw, 38px);
font-weight: 700;
margin-bottom: 10px;
position: relative;
}
.hero .subtitle {
font-size: 15px;
opacity: 0.85;
margin-bottom: 20px;
position: relative;
}
.hero .description {
font-size: 14px;
opacity: 0.75;
max-width: 700px;
margin: 0 auto;
position: relative;
line-height: 1.8;
}
.hero-dots {
display: flex; gap: 8px; justify-content: center; margin-top: 24px; position: relative;
}
.hero-dot {
width: 10px; height: 10px; border-radius: 50%;
background: rgba(255,255,255,0.4);
}
.hero-dot.active { background: var(--accent); width: 28px; border-radius: 5px; }
/* ── NAV ── */
.sticky-nav {
position: sticky; top: 0; z-index: 100;
background: var(--primary-dark);
border-bottom: 2px solid var(--primary-light);
display: flex; gap: 0; overflow-x: auto;
scrollbar-width: none;
}
.sticky-nav::-webkit-scrollbar { display: none; }
.nav-btn {
padding: 13px 20px;
color: rgba(255,255,255,0.7);
font-size: 13px; font-weight: 500;
white-space: nowrap;
cursor: pointer;
border: none; background: none;
font-family: inherit;
transition: all 0.2s;
border-bottom: 3px solid transparent;
}
.nav-btn:hover { color: #fff; background: rgba(255,255,255,0.08); }
.nav-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
/* ── CONTAINER ── */
.container { max-width: 1280px; margin: 0 auto; padding: 0 24px; }
.section { padding: 40px 0; }
.section-title {
font-size: 20px; font-weight: 700;
color: var(--primary-dark);
margin-bottom: 24px;
display: flex; align-items: center; gap: 10px;
}
.section-title::after {
content: ''; flex: 1; height: 2px;
background: linear-gradient(to right, var(--border), transparent);
}
/* ── SUMMARY CARDS ── */
.summary-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 16px;
margin-bottom: 32px;
}
.summary-card {
background: var(--card);
border-radius: var(--radius);
padding: 22px 20px;
box-shadow: var(--shadow);
border-top: 4px solid var(--primary);
text-align: center;
transition: transform 0.2s, box-shadow 0.2s;
}
.summary-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.summary-card.good { border-top-color: var(--good); }
.summary-card.warn { border-top-color: var(--warn); }
.summary-card.bad { border-top-color: var(--bad); }
.summary-card.accent { border-top-color: var(--accent); }
.summary-num {
font-size: 40px; font-weight: 700; color: var(--primary);
line-height: 1;
}
.summary-card.good .summary-num { color: var(--good); }
.summary-card.warn .summary-num { color: var(--warn); }
.summary-card.bad .summary-num { color: var(--bad); }
.summary-card.accent .summary-num { color: var(--accent); }
.summary-label { font-size: 13px; color: var(--text-muted); margin-top: 6px; }
/* ── PILLAR CARDS ── */
.pillar-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 20px;
}
.pillar-card {
background: var(--card);
border-radius: var(--radius);
box-shadow: var(--shadow);
overflow: hidden;
transition: transform 0.2s, box-shadow 0.2s;
}
.pillar-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.pillar-header {
padding: 18px 20px 14px;
display: flex; align-items: flex-start; gap: 14px;
}
.pillar-icon {
width: 42px; height: 42px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
font-size: 20px; flex-shrink: 0;
background: var(--primary);
}
.pillar-info { flex: 1; }
.pillar-code { font-size: 11px; font-weight: 700; letter-spacing: 1px; color: var(--text-muted); }
.pillar-name { font-size: 14px; font-weight: 600; color: var(--text); margin-top: 2px; line-height: 1.4; }
.pillar-status {
padding: 3px 10px; border-radius: 12px;
font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.status-good { background: var(--good-bg); color: var(--good); }
.status-warn { background: var(--warn-bg); color: var(--warn); }
.status-bad { background: var(--bad-bg); color: var(--bad); }
.status-na { background: var(--na-bg); color: var(--na); }
.pillar-body { padding: 0 20px 18px; }
.pillar-stats {
display: flex; gap: 16px; margin-bottom: 14px;
font-size: 13px;
}
.pillar-stat { text-align: center; }
.pillar-stat-num { font-size: 22px; font-weight: 700; color: var(--primary); }
.pillar-stat-lbl { color: var(--text-muted); font-size: 11px; }
.progress-bar-wrap { margin-bottom: 14px; }
.progress-bar-bg {
height: 8px; border-radius: 4px;
background: var(--border);
overflow: hidden;
}
.progress-bar-fill {
height: 100%; border-radius: 4px;
background: linear-gradient(to right, var(--secondary), var(--primary-light));
transition: width 1s ease;
}
.progress-label {
display: flex; justify-content: space-between;
font-size: 12px; color: var(--text-muted); margin-top: 4px;
}
.pillar-highlights { list-style: none; }
.pillar-highlights li {
font-size: 13px; padding: 5px 0;
border-bottom: 1px solid var(--border);
display: flex; gap: 6px; align-items: flex-start;
color: var(--text);
}
.pillar-highlights li:last-child { border-bottom: none; }
.hl-dot {
width: 6px; height: 6px; border-radius: 50%;
background: var(--secondary); flex-shrink: 0; margin-top: 6px;
}
/* ── FILTERS ── */
.filter-bar {
background: var(--card);
border-radius: var(--radius);
padding: 20px;
box-shadow: var(--shadow);
margin-bottom: 20px;
display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
}
.filter-group { display: flex; flex-direction: column; gap: 5px; }
.filter-label { font-size: 12px; font-weight: 600; color: var(--text-muted); }
.filter-select, .filter-input {
padding: 8px 12px;
border: 1.5px solid var(--border);
border-radius: var(--radius-sm);
font-family: inherit; font-size: 13px;
color: var(--text);
background: var(--bg);
outline: none;
transition: border-color 0.2s;
}
.filter-select:focus, .filter-input:focus { border-color: var(--primary); }
.filter-input { min-width: 220px; }
.filter-reset {
padding: 8px 16px;
background: var(--primary);
color: #fff;
border: none; border-radius: var(--radius-sm);
font-family: inherit; font-size: 13px; font-weight: 500;
cursor: pointer;
transition: background 0.2s;
}
.filter-reset:hover { background: var(--primary-dark); }
.filter-count {
font-size: 13px; color: var(--text-muted);
align-self: center;
margin-left: auto;
}
/* ── TABLE ── */
.table-wrap {
background: var(--card);
border-radius: var(--radius);
box-shadow: var(--shadow);
overflow: auto;
}
table {
width: 100%; border-collapse: collapse;
font-size: 13px;
}
thead th {
background: var(--primary-dark);
color: #fff;
padding: 11px 12px;
text-align: left;
white-space: nowrap;
font-weight: 600;
font-size: 12px;
position: sticky; top: 0;
cursor: pointer;
user-select: none;
}
thead th:hover { background: var(--primary); }
thead th .sort-icon { margin-left: 4px; opacity: 0.5; }
tbody tr { transition: background 0.15s; }
tbody tr:nth-child(even) { background: #f8fbff; }
tbody tr:hover { background: #e8f4ff; }
td { padding: 9px 12px; vertical-align: top; border-bottom: 1px solid var(--border); }
.td-kpi { max-width: 200px; font-weight: 500; }
.td-okr { max-width: 280px; font-size: 12px; color: var(--text-muted); }
.td-year { text-align: center; }
.badge-level {
display: inline-block; padding: 2px 8px;
border-radius: 10px; font-size: 11px; font-weight: 700;
}
.badge-R { background: #dbeafe; color: #1d4ed8; }
.badge-P { background: #ede9fe; color: #6d28d9; }
.badge-U { background: #fee2e2; color: #991b1b; }
.badge-I { background: #dcfce7; color: #166534; }
.badge-status {
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 10px; border-radius: 10px;
font-size: 11px; font-weight: 600; white-space: nowrap;
}
.badge-บรรลุ { background: var(--good-bg); color: var(--good); }
.badge-ใกล้บรรลุ { background: var(--warn-bg); color: var(--warn); }
.badge-ไม่บรรลุ { background: var(--bad-bg); color: var(--bad); }
.badge-ไม่มีข้อมูล { background: var(--na-bg); color: var(--na); }
.trend-arrow { font-size: 16px; }
.gap-val { font-size: 12px; font-weight: 600; }
.gap-pos { color: var(--good); }
.gap-neg { color: var(--bad); }
.gap-na { color: var(--na); }
/* ── CHARTS ── */
.charts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
gap: 20px;
}
.chart-card {
background: var(--card);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 22px;
}
.chart-title {
font-size: 15px; font-weight: 600; color: var(--primary-dark);
margin-bottom: 16px;
}
.chart-container { position: relative; height: 280px; }
.heatmap-wrap { overflow-x: auto; }
.heatmap-table {
width: 100%; border-collapse: separate; border-spacing: 3px;
font-size: 12px;
}
.heatmap-table th {
padding: 8px 12px; text-align: center;
background: var(--primary-dark); color: #fff;
border-radius: 6px; font-size: 11px;
}
.heatmap-table td {
padding: 10px 8px; text-align: center;
border-radius: 6px; font-weight: 600; font-size: 12px;
cursor: default;
}
.hm-good { background: #bbf7d0; color: #15803d; }
.hm-warn { background: #fef08a; color: #92400e; }
.hm-bad { background: #fecaca; color: #991b1b; }
.hm-na { background: #f3f4f6; color: #9ca3af; }
.hm-mixed { background: #ddd6fe; color: #5b21b6; }
.hm-row-label { font-weight: 600; color: var(--text); background: #f8fbff !important; text-align: left; border-radius: 6px; padding: 10px 12px; }
/* ── KPI SELECTOR ── */
.kpi-selector {
display: flex; flex-wrap: wrap; gap: 8px;
margin-bottom: 14px;
}
.kpi-chip {
padding: 5px 12px; border-radius: 20px;
border: 1.5px solid var(--border);
font-size: 12px; cursor: pointer;
background: #fff; color: var(--text-muted);
font-family: inherit;
transition: all 0.2s; white-space: nowrap;
}
.kpi-chip.active {
background: var(--primary); border-color: var(--primary);
color: #fff;
}
/* ── HIGHLIGHT SECTION ── */
.highlight-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 20px;
}
.highlight-card {
background: var(--card);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 22px;
}
.highlight-card-title {
font-size: 15px; font-weight: 700;
margin-bottom: 16px;
display: flex; align-items: center; gap: 8px;
}
.highlight-icon { font-size: 20px; }
.highlight-list { list-style: none; }
.highlight-list li {
padding: 9px 0;
border-bottom: 1px solid var(--border);
font-size: 13px;
display: flex; gap: 8px; align-items: flex-start;
line-height: 1.5;
}
.highlight-list li:last-child { border-bottom: none; }
/* ── RECOMMENDATION ── */
.rec-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
gap: 14px;
}
.rec-card {
background: var(--card);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 20px;
border-left: 4px solid var(--primary);
display: flex; gap: 14px;
}
.rec-num {
width: 32px; height: 32px; border-radius: 50%;
background: var(--primary); color: #fff;
display: flex; align-items: center; justify-content: center;
font-size: 14px; font-weight: 700; flex-shrink: 0;
}
.rec-content { flex: 1; }
.rec-title { font-size: 14px; font-weight: 600; color: var(--primary-dark); margin-bottom: 5px; }
.rec-detail { font-size: 13px; color: var(--text-muted); line-height: 1.6; }
/* ── DISCLAIMER ── */
.disclaimer {
background: #fffbeb;
border: 1px solid #fcd34d;
border-radius: var(--radius-sm);
padding: 12px 16px;
font-size: 12px;
color: #92400e;
margin: 24px 0;
display: flex; gap: 8px; align-items: flex-start;
}
/* ── FOOTER ── */
.footer {
background: var(--primary-dark);
color: rgba(255,255,255,0.7);
text-align: center;
padding: 24px;
font-size: 13px;
}
/* ── PRINT ── */
@media print {
.sticky-nav, .filter-bar, .filter-reset { display: none !important; }
.section { page-break-inside: avoid; }
body { background: #fff; font-size: 12px; }
.chart-container { height: 220px; }
.hero { padding: 24px; }
.hero h1 { font-size: 22px; }
}
@media (max-width: 640px) {
.summary-grid { grid-template-columns: repeat(2, 1fr); }
.pillar-grid { grid-template-columns: 1fr; }
.charts-grid { grid-template-columns: 1fr; }
.filter-bar { flex-direction: column; }
}
</style>
</head>
<body>
<!-- HERO -->
<section class="hero">
<div class="hero-badge">โรงพยาบาลป่าพะยอม · จ.พัทลุง | HCODE 11422</div>
<h1>ตัวชี้วัดและผลลัพธ์ 5 ปี 2566–2570</h1>
<p class="subtitle">Strategic KPI & Quality Outcome Roadmap | แผนยุทธศาสตร์ รพ.ป่าพะยอม</p>
<p class="description">
รายงานการติดตามเป้าหมายระยะ 5 ปี เชื่อมโยงยุทธศาสตร์ P1–P7<br>
ครอบคลุมผลลัพธ์บริการ คุณภาพ ความปลอดภัย การเงินการคลัง และการพัฒนาบุคลากร<br>
จัดทำเพื่อสื่อสารต่อ สรพ. และผู้บริหาร โดยอ้างอิงข้อมูลจริงจากไฟล์ตัวชี้วัด ปีงบประมาณ 2566–2569
</p>
<div class="hero-dots">
<div class="hero-dot"></div><div class="hero-dot active"></div><div class="hero-dot"></div>
</div>
</section>
<!-- STICKY NAV -->
<nav class="sticky-nav" id="stickyNav">
<button class="nav-btn active" onclick="scrollToSection('summary')">📊 ภาพรวม</button>
<button class="nav-btn" onclick="scrollToSection('pillars')">🏛️ ยุทธศาสตร์ P1–P7</button>
<button class="nav-btn" onclick="scrollToSection('table')">📋 ตาราง KPI</button>
<button class="nav-btn" onclick="scrollToSection('charts')">📈 กราฟ</button>
<button class="nav-btn" onclick="scrollToSection('highlights')">💡 ประเด็น สรพ.</button>
<button class="nav-btn" onclick="scrollToSection('recs')">✅ ข้อเสนอแนะ</button>
</nav>
<div class="container">
<!-- DISCLAIMER -->
<div class="disclaimer" style="margin-top:20px">
⚠️ <span><strong>หมายเหตุ:</strong> ข้อมูลอ้างอิงจากไฟล์ตัวชี้วัดที่แนบ และควรตรวจสอบความครบถ้วนก่อนใช้เป็นเอกสารทางการ ข้อมูลปี 2569 เป็นผลดำเนินงานช่วง ต.ค.–มี.ค. และข้อมูลปี 2570 ยังไม่มีผลการดำเนินงาน</span>
</div>
<!-- ── SECTION 1: SUMMARY ── -->
<section class="section" id="summary">
<h2 class="section-title">📊 Executive Summary – ภาพรวมตัวชี้วัด</h2>
<div class="summary-grid" id="summaryGrid"></div>
</section>
<!-- ── SECTION 2: PILLARS ── -->
<section class="section" id="pillars">
<h2 class="section-title">🏛️ Strategic Pillar Dashboard – ผลลัพธ์รายยุทธศาสตร์</h2>
<div class="pillar-grid" id="pillarGrid"></div>
</section>
<!-- ── SECTION 3: TABLE ── -->
<section class="section" id="table">
<h2 class="section-title">📋 ตาราง KPI แบบ Interactive</h2>
<div class="filter-bar">
<div class="filter-group">
<label class="filter-label">ยุทธศาสตร์</label>
<select class="filter-select" id="filterPillar" onchange="applyFilters()">
<option value="">ทั้งหมด</option>
<option value="P1">P1 – ลดป่วยรายใหม่</option>
<option value="P2">P2 – ลดป่วยตาย</option>
<option value="P3">P3 – IT มาตรฐาน</option>
<option value="P4">P4 – คุณภาพบริการ</option>
<option value="P5">P5 – ภาคีเครือข่าย</option>
<option value="P6">P6 – การเงิน</option>
<option value="P7">P7 – บุคลากร</option>
</select>
</div>
<div class="filter-group">
<label class="filter-label">ระดับตัวชี้วัด</label>
<select class="filter-select" id="filterLevel" onchange="applyFilters()">
<option value="">ทั้งหมด</option>
<option value="R">R</option>
<option value="P">P</option>
<option value="U">U</option>
<option value="I">I</option>
</select>
</div>
<div class="filter-group">
<label class="filter-label">สถานะปี 2569</label>
<select class="filter-select" id="filterStatus" onchange="applyFilters()">
<option value="">ทั้งหมด</option>
<option value="บรรลุ">✅ บรรลุ</option>
<option value="ใกล้บรรลุ">🟡 ใกล้บรรลุ</option>
<option value="ไม่บรรลุ">❌ ไม่บรรลุ</option>
<option value="ไม่มีข้อมูล">➖ ไม่มีข้อมูล</option>
</select>
</div>
<div class="filter-group">
<label class="filter-label">ค้นหา KPI / OKRs</label>
<input class="filter-input" id="filterSearch" placeholder="พิมพ์คำค้นหา..." oninput="applyFilters()">
</div>
<button class="filter-reset" onclick="resetFilters()">รีเซ็ต</button>
<span class="filter-count" id="filterCount"></span>
</div>
<div class="table-wrap">
<table id="kpiTable">
<thead>
<tr>
<th onclick="sortTable('pillar')">ยุทธศาสตร์ <span class="sort-icon">↕</span></th>
<th onclick="sortTable('level')">ระดับ <span class="sort-icon">↕</span></th>
<th onclick="sortTable('kpi')">KPI <span class="sort-icon">↕</span></th>
<th>OKRs/KRA</th>
<th class="td-year">เป้า 66</th>
<th class="td-year">เป้า 67</th>
<th class="td-year">เป้า 68</th>
<th class="td-year">เป้า 69</th>
<th class="td-year">ผล 66</th>
<th class="td-year">ผล 67</th>
<th class="td-year">ผล 68</th>
<th class="td-year">ผล 69</th>
<th onclick="sortTable('status')">สถานะ 69 <span class="sort-icon">↕</span></th>
<th>Gap</th>
<th>Trend</th>
<th>ข้อสังเกต</th>
</tr>
</thead>
<tbody id="tableBody"></tbody>
</table>
</div>
</section>
<!-- ── SECTION 4: CHARTS ── -->
<section class="section" id="charts">
<h2 class="section-title">📈 Trend Visualization – การวิเคราะห์แนวโน้ม</h2>
<div class="charts-grid">
<div class="chart-card">
<div class="chart-title">สถานะตัวชี้วัดปี 2569 แยกตามยุทธศาสตร์</div>
<div class="chart-container"><canvas id="chartStatus"></canvas></div>
</div>
<div class="chart-card" style="grid-column: span 1;">
<div class="chart-title">เปรียบเทียบ Target vs Actual – เลือก KPI</div>
<div class="kpi-selector" id="kpiSelector"></div>
<div class="chart-container"><canvas id="chartTrend"></canvas></div>
</div>
<div class="chart-card" style="grid-column: 1 / -1;">
<div class="chart-title">Heatmap ผลลัพธ์ P1–P7 × ปี 2566–2569 (สีแสดงสัดส่วนการบรรลุเป้าหมาย)</div>
<div class="heatmap-wrap" id="heatmapWrap"></div>
</div>
</div>
</section>
<!-- ── SECTION 5: HIGHLIGHTS ── -->
<section class="section" id="highlights">
<h2 class="section-title">💡 ประเด็นสื่อสารต่อ สรพ.</h2>
<div class="highlight-grid">
<div class="highlight-card">
<div class="highlight-card-title"><span class="highlight-icon">🌟</span> จุดแข็ง – Strong Points</div>
<ul class="highlight-list" id="hlStrengths"></ul>
</div>
<div class="highlight-card">
<div class="highlight-card-title"><span class="highlight-icon">🔧</span> โอกาสพัฒนา – Improvement Areas</div>
<ul class="highlight-list" id="hlOpportunities"></ul>
</div>
<div class="highlight-card" style="grid-column: 1 / -1;">
<div class="highlight-card-title"><span class="highlight-icon">🔗</span> ความเชื่อมโยงเชิงระบบ – System Linkage</div>
<ul class="highlight-list" id="hlSystemic"></ul>
</div>
</div>
</section>
<!-- ── SECTION 6: RECOMMENDATIONS ── -->
<section class="section" id="recs">
<h2 class="section-title">✅ ข้อเสนอแนะเชิงบริหาร</h2>
<div class="rec-list" id="recList"></div>
</section>
<div class="disclaimer">
📄 <span>รายงานนี้จัดทำจากไฟล์ตัวชี้วัดและค่าเป้าหมายท้าทายความสำเร็จ (Roadmap) โรงพยาบาลป่าพะยอม ปีงบประมาณ 2566–2570 อัปเดตผลปี 2569 | ข้อมูลที่ไม่มีในไฟล์แสดงเป็น "ไม่มีข้อมูล" และผลปี 2569 เป็นข้อมูลช่วง ต.ค.–มี.ค. | ควรตรวจสอบและรับรองโดยผู้รับผิดชอบก่อนใช้เป็นเอกสารทางการ</span>
</div>
</div><!-- /container -->
<footer class="footer">
โรงพยาบาลป่าพะยอม | อำเภอป่าพะยอม จังหวัดพัทลุง | โรงพยาบาลชุมชนขนาด 45 เตียง | HCODE 11422<br>
Strategic KPI Dashboard 2566–2570 | จัดทำด้วย Data Storytelling & HA Quality Framework
</footer>
<script>
// ════════════════════════════════════════════════════════════════
// DATA EMBEDDED FROM EXCEL (ข้อมูลจากไฟล์ตัวชี้วัดที่แนบ)
// โครงสร้าง: pillar, kpiGroup, level (R/P/U/I), kpi, okr,
// target:{66,67,68,69,70}, actual:{66,67,68,69,70}
// ════════════════════════════════════════════════════════════════
const RAW_DATA = [
{
"pillar": "P1",
"kpiGroup": "1. อัตราการเจ็บป่วยรายใหม่ DM",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ DM",
"okr": "ร้อยละการตรวจติดตามยืนยันวินิจฉัยกลุ่มสงสัยป่วยโรคเบาหวาน",
"target": {
"66": "≥80",
"67": "≥80",
"68": "≥85",
"69": "≥90",
"70": "≥95"
},
"actual": {
"66": 72.8,
"67": 78.16,
"68": 80.77,
"69": 87.5,
"70": null
},
"direction": ">",
"owner": "สาลี"
},
{
"pillar": "P1",
"kpiGroup": "1. อัตราการเจ็บป่วยรายใหม่ DM",
"level": "R",
"kpi": "อัตราการเจ็บป่วยรายใหม่ DM",
"okr": "อัตราผู้ป่วยเบาหวานรายใหม่กลุ่มในเสี่ยง <2%",
"target": {
"66": 1.9,
"67": 1.8,
"68": 1.7,
"69": 1.6,
"70": 1.5
},
"actual": {
"66": 1.16,
"67": 2.72,
"68": 1.86,
"69": 1.38,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P1",
"kpiGroup": "2. อัตราการเจ็บป่วยรายใหม่ HT",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ HT",
"okr": "ร้อยละการตรวจติดตามยืนยันวินิจฉัยกลุ่มสงสัยป่วยความดันโลหิตสูง",
"target": {
"66": "≥80",
"67": "≥80",
"68": "≥85",
"69": "≥90",
"70": "≥95"
},
"actual": {
"66": 94.64,
"67": 88.58,
"68": 95.6,
"69": 92.05,
"70": null
},
"direction": ">",
"owner": "สาลี"
},
{
"pillar": "P1",
"kpiGroup": "2. อัตราการเจ็บป่วยรายใหม่ HT",
"level": "R",
"kpi": "อัตราการเจ็บป่วยรายใหม่ HT",
"okr": "อัตราผู้ป่วยความดันรายใหม่ในกลุ่มเสี่ยง <2%",
"target": {
"66": 3.5,
"67": 3,
"68": 2.5,
"69": 2,
"70": 1.5
},
"actual": {
"66": 4.66,
"67": 7.34,
"68": 2.24,
"69": 2.87,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P1",
"kpiGroup": "3.อัตราการเจ็บป่วยรายใหม่ Stroke",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ Stroke",
"okr": "อัตราการเจ็บป่วยรายใหม่ stroke ในผู้ป่วยกลุ่มโรค HT DM<1%",
"target": {
"66": 1.5,
"67": 1.4,
"68": 1.3,
"69": 1.2,
"70": 1
},
"actual": {
"66": 1.49,
"67": 8.13,
"68": 3.31,
"69": 0.39,
"70": null
},
"direction": "<",
"owner": "จำรูญศรี"
},
{
"pillar": "P1",
"kpiGroup": "4. อัตราการเจ็บป่วยรายใหม่COPD/Asthma",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่COPD/Asthma",
"okr": "อัตราการป่วยรายใหม่ในผู้ป่วย Asthma < 5 : แสนประชากร",
"target": {
"66": 5,
"67": 5,
"68": 5,
"69": 5,
"70": 5
},
"actual": {
"66": 28.05,
"67": 8.45,
"68": 2.38,
"69": 2.84,
"70": null
},
"direction": "<",
"owner": "กมวรรณ"
},
{
"pillar": "P1",
"kpiGroup": "4. อัตราการเจ็บป่วยรายใหม่COPD/Asthma",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่COPD/Asthma",
"okr": "อัตราการป่วยรายใหม่ในผู้ป่วย COPD < 5 : แสนประชากร",
"target": {
"66": 5,
"67": 5,
"68": 5,
"69": 5,
"70": 5
},
"actual": {
"66": 2.8,
"67": 0,
"68": 2.82,
"69": 0,
"70": null
},
"direction": "<",
"owner": "กมวรรณ"
},
{
"pillar": "P1",
"kpiGroup": "5. อัตราการเจ็บป่วยรายใหม่ ACS",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ ACS",
"okr": "อัตราการเจ็บป่วยรายใหม่ ACS ในผู้ป่วยกลุ่มเสี่ยง HT, DM,DLP <0.2%",
"target": {
"66": 0.5,
"67": 0.4,
"68": 0.3,
"69": 0.2,
"70": 0.2
},
"actual": {
"66": 0.11,
"67": 1.44,
"68": 0.36,
"69": 0.13,
"70": null
},
"direction": "<",
"owner": "จำรูญศรี"
},
{
"pillar": "P1",
"kpiGroup": "6.อัตราการเจ็บป่วยรายใหม่ Head injury",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ Head injury",
"okr": "ร้อยละความสำเร็จมาตรการขับขี่ปลอดภัย (สวมหมวกนิรภัย) 100%",
"target": {
"66": 60,
"67": 70,
"68": 80,
"69": 90,
"70": 100
},
"actual": {
"66": 50,
"67": 90,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P1",
"kpiGroup": "6.อัตราการเจ็บป่วยรายใหม่ Head injury",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ Head injury",
"okr": "ร้อยละความสำเร็จมาตรการป้องกันจุดเสี่ยง 100%",
"target": {
"66": 50,
"67": 60,
"68": 70,
"69": 80,
"70": 100
},
"actual": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P1",
"kpiGroup": "7.อัตราการเจ็บป่วยรายใหม่ DHF",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ DHF",
"okr": "ค่าลูกน้ำยุงลายHI<5,CI<5 (ชุมชน)สถานพยาบาล CI=0",
"target": {
"66": "<10/0",
"67": "<10/0",
"68": "<10/0",
"69": "<10/0",
"70": "<10/0"
},
"actual": {
"66": 0.874,
"67": 0.912,
"68": 0.8083,
"69": 0,
"70": null
},
"direction": "<",
"owner": "สาลี"
},
{
"pillar": "P1",
"kpiGroup": "7.อัตราการเจ็บป่วยรายใหม่ DHF",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ DHF",
"okr": "อัตราป่วยด้วยโรคไข้เลือดออกต่อแสนประชากร(ตำบลป่าพะยอม)",
"target": {
"66": 50,
"67": 50,
"68": 50,
"69": 50,
"70": 50
},
"actual": {
"66": 0,
"67": 1.338,
"68": 1.3216,
"69": 33.18,
"70": null
},
"direction": ">",
"owner": "สาลี"
},
{
"pillar": "P1",
"kpiGroup": "8. อัตราการเข้ารับบริการผู้ป่วยยาเสพติด",
"level": "I",
"kpi": "อัตราการเข้ารับบริการผู้ป่วยยาเสพติด",
"okr": "จำนวนผู้ป่วยยาเสพติดเข้ารับการบำบัด 1 ตำบล/1คน/เดือน",
"target": {
"66": null,
"67": null,
"68": 24,
"69": 36,
"70": 48
},
"actual": {
"66": null,
"67": null,
"68": null,
"69": null,
"70": null
},
"direction": ">",
"owner": "มนสิชา"
},
{
"pillar": "P1",
"kpiGroup": "9.อัตราการเจ็บป่วยรายใหม่ TB",
"level": "I",
"kpi": "อัตราการเจ็บป่วยรายใหม่ TB",
"okr": "อัตราการเกิดวัณโรครายใหม่จากลุ่มสัมผัสผู้ป่วย",
"target": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": 0
},
"actual": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": null
},
"direction": "<",
"owner": "เสาวนีย์"
},
{
"pillar": "P1",
"kpiGroup": "9.อัตราการเจ็บป่วยรายใหม่ TB",
"level": "I",
"kpi": "อัตราการเจ็บป่วยรายใหม่ TB",
"okr": "อัตราสำเร็จของการรักษาวัณโรคปอดรายใหม่",
"target": {
"66": "≥85%",
"67": "≥85%",
"68": "≥85%",
"69": "≥85%",
"70": "≥85%"
},
"actual": {
"66": 100,
"67": 96.58,
"68": 91.03,
"69": 77.78,
"70": null
},
"direction": ">",
"owner": "เสาวณีย์"
},
{
"pillar": "P1",
"kpiGroup": "10. อัตราการเจ็บป่วยรายใหม่ HIV",
"level": "I",
"kpi": "อัตราการเจ็บป่วยรายใหม่ HIV",
"okr": "ร้อยละของผู้เข้ารับบริการที่ได้รับคำแนะนำให้ใช้ PrEP/PEP ได้เริ่มใช้ PrEP/PEP",
"target": {
"66": 55,
"67": 65,
"68": 75,
"69": 85,
"70": 95
},
"actual": {
"66": 99.84,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "สุวิทย์"
},
{
"pillar": "P1",
"kpiGroup": "10. อัตราการเจ็บป่วยรายใหม่ HIV",
"level": "I",
"kpi": "อัตราการเจ็บป่วยรายใหม่ HIV",
"okr": "ร้อยละของผู้เข้ารับบริการเริ่มใช้ PrEP ที่ใช้ต่อเนื่อง ครบ 3 เดือน",
"target": {
"66": 80,
"67": 85,
"68": 90,
"69": 95,
"70": 100
},
"actual": {
"66": 99.84,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "สุวิทย์"
},
{
"pillar": "P1",
"kpiGroup": "10. อัตราการเจ็บป่วยรายใหม่ HIV",
"level": "I",
"kpi": "อัตราการเจ็บป่วยรายใหม่ HIV",
"okr": "ร้อยละของผู้เข้ารับบริการเริ่มใช้ PrEP/PEP ใช้ต่อเนื่อง ครบ 1 เดือน",
"target": {
"66": 80,
"67": 85,
"68": 90,
"69": 95,
"70": 100
},
"actual": {
"66": 99.84,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "สุวิทย์"
},
{
"pillar": "P1",
"kpiGroup": "11.ประสิทธิภาพการบริหารจัดการความเสี่ยงด้านคลินิก",
"level": "P",
"kpi": "ประสิทธิภาพการบริหารจัดการความเสี่ยงด้านคลินิก",
"okr": "ร้อยละการได้รับ Antibiotic ภายใน 1 ชม. ผู้ป่วย Sepsis(≥90%)",
"target": {
"66": 90,
"67": 90,
"68": 90,
"69": 90,
"70": 90
},
"actual": {
"66": 68.85,
"67": 80.58,
"68": 90.41,
"69": 88.89,
"70": null
},
"direction": ">",
"owner": "อรวรรณ"
},
{
"pillar": "P1",
"kpiGroup": "11.ประสิทธิภาพการบริหารจัดการความเสี่ยงด้านคลินิก",
"level": "R",
"kpi": "ประสิทธิภาพการบริหารจัดการความเสี่ยงด้านคลินิก",
"okr": "อัตราการติดเชื้อในโรงพยาบาล (<0.5 : 1000 วันนอน)",
"target": {
"66": 0.5,
"67": 0.5,
"68": 0.5,
"69": 0.5,
"70": 0.4
},
"actual": {
"66": 0.56,
"67": 1.5,
"68": 0.26,
"69": 0.22,
"70": null
},
"direction": "<",
"owner": "อรวรรณ"
},
{
"pillar": "P1",
"kpiGroup": "11.ประสิทธิภาพการบริหารจัดการความเสี่ยงด้านคลินิก",
"level": "P",
"kpi": "ประสิทธิภาพการบริหารจัดการความเสี่ยงด้านคลินิก",
"okr": "อุบัติการณ์ความเสี่ยงระดับ E ขึ้นไปได้รับการวางมาตรการ(RCA)",
"target": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": 100
},
"actual": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "สาลี"
},
{
"pillar": "P1",
"kpiGroup": "12.Dental carie",
"level": "U",
"kpi": "Dental carie",
"okr": "ร้อยละของเด็กอายุ 0-2 ปีได้รับการแคลือบ/ทาฟลูออไรด์เฉพาะที่",
"target": {
"66": 55,
"67": 55,
"68": 55,
"69": 55,
"70": 55
},
"actual": {
"66": null,
"67": null,
"68": null,
"69": null,
"70": null
},
"direction": ">",
"owner": "วสัน"
},
{
"pillar": "P1",
"kpiGroup": "12.Dental carie",
"level": "U",
"kpi": "Dental carie",
"okr": "ร้อยละผู้สูงอายุได้รับดารคัดกรองรอยโรคก่อระเร็ง PMD",
"target": {
"66": null,
"67": 65,
"68": 70,
"69": 75,
"70": 80
},
"actual": {
"66": 31.44,
"67": 59.2,
"68": 83.55,
"69": 61.08,
"70": null
},
"direction": ">",
"owner": "วสัน"
},
{
"pillar": "P1",
"kpiGroup": "13.อัตราการเจ็บป่วยรายใหม่ ผู้ป่วยเสพติดเข้าถึงบริการและอยู่ในระบบ (ร้อยละ 70)",
"level": "U",
"kpi": "อัตราการเจ็บป่วยรายใหม่ ผู้ป่วยเสพติดเข้าถึงบริการและอยู่ในระบบ (ร้อยละ 70)",
"okr": "ร้อยละของผู้ป่วยยาเสพติดเข้าสู่กระบวนการรักษาและได้รับการดูแลต่อเนื่องจนถึงการติดตาม",
"target": {
"66": 55,
"67": 60,
"68": 65,
"69": 70,
"70": 75
},
"actual": {
"66": 78.47,
"67": 66.67,
"68": 79,
"69": 90,
"70": null
},
"direction": ">",
"owner": "มนสิชา"
},
{
"pillar": "P2",
"kpiGroup": "14. อัตราการป่วยตาย DM",
"level": "U",
"kpi": "อัตราการป่วยตาย DM",
"okr": "ร้อยละผู้ป่วยเบาหวานที่ควบคุมระดับน้ำตาลได้ดี >40%",
"target": {
"66": 40,
"67": 41,
"68": 42,
"69": 43,
"70": 44
},
"actual": {
"66": 28.24,
"67": 35.36,
"68": 41.24,
"69": 36.96,
"70": null
},
"direction": ">",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "14. อัตราการป่วยตาย DM",
"level": "U",
"kpi": "อัตราการป่วยตาย DM",
"okr": "อัตราการขาดนัดในผู้ป่วยเบาหวาน<5%",
"target": {
"66": 50,
"67": 55,
"68": 60,
"69": 65,
"70": 70
},
"actual": {
"66": 1.82,
"67": 3.71,
"68": 4.22,
"69": 3.05,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "14. อัตราการป่วยตาย DM",
"level": "U",
"kpi": "อัตราการป่วยตาย DM",
"okr": "อัตราการแทรกซ้อนในผู้ป่วยเบาหวาน <5%",
"target": {
"66": 5,
"67": 4,
"68": 3,
"69": 2,
"70": 1
},
"actual": {
"66": 0.52,
"67": 4.17,
"68": 4.04,
"69": 3.93,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "14. อัตราการป่วยตาย DM",
"level": "U",
"kpi": "อัตราการป่วยตาย DM",
"okr": "อัตราผู้ป่วยเบาหวานมาโรงพยาบาลก่อนนัดด้วยภาวะน้ำตาลต่ำ <5%",
"target": {
"66": 10,
"67": 12,
"68": 14,
"69": 16,
"70": 18
},
"actual": {
"66": 1.29,
"67": 0.77,
"68": 2.11,
"69": 1.4,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "14. อัตราการป่วยตาย DM",
"level": "U",
"kpi": "อัตราการป่วยตาย DM",
"okr": "อัตราผู้ป่วยเบาหวานมาโรงพยาบาลก่อนนัดด้วยภาวะน้ำตาลสูงวิกฤติ<10%",
"target": {
"66": 5,
"67": 4.5,
"68": 4,
"69": 3.5,
"70": 3
},
"actual": {
"66": 2.01,
"67": 2.21,
"68": 6.7,
"69": 4.45,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "15. อัตราการป่วยตาย HT",
"level": "U",
"kpi": "อัตราการป่วยตาย HT",
"okr": "ร้อยละผู้ป่วย HT ที่ความคุมระดับ BP >70%",
"target": {
"66": 68,
"67": 69,
"68": 70,
"69": 71,
"70": 72
},
"actual": {
"66": 66.09,
"67": 69.69,
"68": 58.73,
"69": 56,
"70": null
},
"direction": ">",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "15. อัตราการป่วยตาย HT",
"level": "U",
"kpi": "อัตราการป่วยตาย HT",
"okr": "อัตราการขาดนัดในผู้ป่วย HT<5%",
"target": {
"66": 9,
"67": 8,
"68": 7,
"69": 6,
"70": 5
},
"actual": {
"66": 3.34,
"67": 4.78,
"68": 3.99,
"69": 4.84,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "15. อัตราการป่วยตาย HT",
"level": "U",
"kpi": "อัตราการป่วยตาย HT",
"okr": "อัตราผู้ป่วยความดันโลหิตสูงมีภาวะความดันโลหิตสูงวิกฤติ <2%",
"target": {
"66": 0.6,
"67": 0.5,
"68": 0.4,
"69": 0.3,
"70": 0.2
},
"actual": {
"66": 0.23,
"67": 0.17,
"68": 0.22,
"69": 0.2,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "15. อัตราการป่วยตาย HT",
"level": "U",
"kpi": "อัตราการป่วยตาย HT",
"okr": "อัตราผู้ป่วยแทรกซ้อนรายใหม่ในผู้ป่วย HT <5%",
"target": {
"66": 5,
"67": 4,
"68": 3,
"69": 2,
"70": 1
},
"actual": {
"66": 0.2,
"67": 0.21,
"68": 0.2,
"69": 0.76,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P2",
"kpiGroup": "16. อัตราการป่วยตาย Stroke",
"level": "P",
"kpi": "อัตราการป่วยตาย Stroke",
"okr": "Stroke รายใหม่ได้รับการติดตามเยี่ยมจนครบ 6 เดือน >80%",
"target": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": 100
},
"actual": {
"66": 100,
"67": 96.25,
"68": 93.87,
"69": 90.24,
"70": null
},
"direction": ">",
"owner": "ทิพวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "16. อัตราการป่วยตาย Stroke",
"level": "U",
"kpi": "อัตราการป่วยตาย Stroke",
"okr": "ผู้ป่วย Stroke ไดรับการฟื้นฟูมีคะแนน Bathel index > 15 คะแนน",
"target": {
"66": 60,
"67": 65,
"68": 70,
"69": 75,
"70": 80
},
"actual": {
"66": 70.83,
"67": 72.22,
"68": 85.71,
"69": 65.85,
"70": null
},
"direction": ">",
"owner": "ทิพวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "16. อัตราการป่วยตาย Stroke",
"level": "P",
"kpi": "อัตราการป่วยตาย Stroke",
"okr": "ภาวะแทรกซ้อนในผู้ป่วย Stroke<20",
"target": {
"66": 5,
"67": 5,
"68": 5,
"69": 5,
"70": 5
},
"actual": {
"66": 5.26,
"67": 14.81,
"68": 6.12,
"69": 2.43,
"70": null
},
"direction": "<",
"owner": "ทิพวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "16. อัตราการป่วยตาย Stroke",
"level": "R",
"kpi": "อัตราการป่วยตาย Stroke",
"okr": "อัตราผู้ป่วย Stroke fast tract ได้รับการส่งต่อภายใน 30นาที>80%",
"target": {
"66": 40,
"67": 50,
"68": 60,
"69": 70,
"70": 80
},
"actual": {
"66": 33.55,
"67": 51,
"68": 42.3,
"69": 70,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "16. อัตราการป่วยตาย Stroke",
"level": "P",
"kpi": "อัตราการป่วยตาย Stroke",
"okr": "อัตราผู้ป่วย Stroke ที่มาถึงรพ.ภายใน 3 ชม.>50%",
"target": {
"66": 40,
"67": 42,
"68": 46,
"69": 48,
"70": 50
},
"actual": {
"66": 48.34,
"67": 31.7,
"68": 35.13,
"69": 60,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "16. อัตราการป่วยตาย Stroke",
"level": "U",
"kpi": "อัตราการป่วยตาย Stroke",
"okr": "อัตราผู้ป่วย Stroke มาด้วยระบบ EMS>50%",
"target": {
"66": 20,
"67": 30,
"68": 40,
"69": 50,
"70": 50
},
"actual": {
"66": 20.61,
"67": 9.63,
"68": 12.16,
"69": 15,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "17. อัตราการป่วยตาย COPD/Asthma",
"level": "U",
"kpi": "อัตราการป่วยตาย COPD/Asthma",
"okr": "ผู้ป่วยคลินิก COPD/Asthma ใช้ยาพ่นถูกต้องร้อยละ 80",
"target": {
"66": 80,
"67": 82,
"68": 84,
"69": 86,
"70": 88
},
"actual": {
"66": 81.07,
"67": 85,
"68": 85,
"69": 80.07,
"70": null
},
"direction": ">",
"owner": "กมลวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "17. อัตราการป่วยตาย COPD/Asthma",
"level": "R",
"kpi": "อัตราการป่วยตาย COPD/Asthma",
"okr": "อัตราการเกิด respirayory failure COPD/Asthma ในหอผู้ป่วยใน",
"target": {
"66": 5,
"67": 4,
"68": 3,
"69": 2,
"70": 1
},
"actual": {
"66": 1.29,
"67": 2.09,
"68": 4.02,
"69": 1.02,
"70": null
},
"direction": ">",
"owner": "กมลวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "17. อัตราการป่วยตาย COPD/Asthma",
"level": "U",
"kpi": "อัตราการป่วยตาย COPD/Asthma",
"okr": "อัตราป่วยตายด้วยโรค Asthma< 5 ในโรงพยาบาล",
"target": {
"66": 5,
"67": 4,
"68": 3,
"69": 2,
"70": 1
},
"actual": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": null
},
"direction": "<",
"owner": "กมลวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "17. อัตราการป่วยตาย COPD/Asthma",
"level": "U",
"kpi": "อัตราการป่วยตาย COPD/Asthma",
"okr": "อัตราป่วยตายด้วยโรค COPD< 5 ในโรงพยาบาล",
"target": {
"66": 5,
"67": 4,
"68": 3,
"69": 2,
"70": 1
},
"actual": {
"66": 6.34,
"67": 5.35,
"68": 6.45,
"69": 2.88,
"70": null
},
"direction": "<",
"owner": "กมลวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "18. อัตราการป่วยตาย ACS",
"level": "U",
"kpi": "อัตราการป่วยตาย ACS",
"okr": "อัตราการได้รับ SK ในผู้ป่วย ASC ภายใน 30 นาที หลังจากได้รับการวินิจฉัยแล้วภายใน 100 %",
"target": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": 100
},
"actual": {
"66": null,
"67": null,
"68": null,
"69": null,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "18. อัตราการป่วยตาย ACS",
"level": "P",
"kpi": "อัตราการป่วยตาย ACS",
"okr": "อัตราผู้ป่วย ACS ที่มาถึงรพ.ภายใน 3 ชม.≥80%",
"target": {
"66": 85,
"67": 90,
"68": 95,
"69": 100,
"70": 100
},
"actual": {
"66": 100,
"67": 41.6,
"68": 85.7,
"69": 71.42,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "18. อัตราการป่วยตาย ACS",
"level": "U",
"kpi": "อัตราการป่วยตาย ACS",
"okr": "อัตราผู้ป่วย ACS มาด้วยระบบ EMS>50%",
"target": {
"66": 20,
"67": 25,
"68": 30,
"69": 40,
"70": 50
},
"actual": {
"66": 20,
"67": 8.33,
"68": 0,
"69": 0,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "18. อัตราการป่วยตาย ACS",
"level": "R",
"kpi": "อัตราการป่วยตาย ACS",
"okr": "อัตราผู้ป่วย ACS ได้รับการวินิจฉัยประเมิน EKG ภายใน10 นาที 100%",
"target": {
"66": 85,
"67": 90,
"68": 95,
"69": 100,
"70": 100
},
"actual": {
"66": 20,
"67": 62.5,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "18. อัตราการป่วยตาย ACS",
"level": "U",
"kpi": "อัตราการป่วยตาย ACS",
"okr": "อัตราผู้ป่วย ACS ได้รับการส่งต่อถึงศูนย์หัวใจ ภายใน 80 นาที 100%",
"target": {
"66": 60,
"67": 70,
"68": 80,
"69": 90,
"70": 100
},
"actual": {
"66": 56.25,
"67": 41.6,
"68": 48.18,
"69": 100,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "19. อัตราการป่วยตาย Head injury",
"level": "U",
"kpi": "อัตราการป่วยตาย Head injury",
"okr": "อัตราผู้ป่วย moderate head injury ได้รับการส่งต่อภายใน 45 นาที 100%",
"target": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": 100
},
"actual": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "19. อัตราการป่วยตาย Head injury",
"level": "U",
"kpi": "อัตราการป่วยตาย Head injury",
"okr": "อัตราผู้ป่วย severe head injury ได้รับการส่งต่อภายใน 1 ชั่วโมง 100%",
"target": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": 100
},
"actual": {
"66": 100,
"67": 100,
"68": 91.66,
"69": 100,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "19. อัตราการป่วยตาย Head injury",
"level": "U",
"kpi": "อัตราการป่วยตาย Head injury",
"okr": "อัตราผู้ป่วยบาดเจ็บศีรษะและลำคอมาด้วยระบบ EMS>80%",
"target": {
"66": 50,
"67": 60,
"68": 70,
"69": 80,
"70": 80
},
"actual": {
"66": 26.31,
"67": 27.27,
"68": 24.75,
"69": 14.54,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P2",
"kpiGroup": "20. อัตราการป่วยตาย DHF",
"level": "P",
"kpi": "อัตราการป่วยตาย DHF",
"okr": "- อัตราการป่วยตาย DHF",
"target": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": 0
},
"actual": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": null
},
"direction": "<",
"owner": "กมลวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "20. อัตราการป่วยตาย DHF",
"level": "P",
"kpi": "อัตราการป่วยตาย DHF",
"okr": "อัตราการเกิด DSS ในโรงพยาบาล",
"target": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": 0
},
"actual": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": null
},
"direction": "<",
"owner": "กมลวรรณ"
},
{
"pillar": "P2",
"kpiGroup": "21. อัตราฆ่าตัวตาย",
"level": "R",
"kpi": "อัตราฆ่าตัวตาย",
"okr": "ร้อยละของผู้ป่วยพยายามฆ่าตัวตายเข้าถึงบริการที่มีประสิทธิภาพ",
"target": {
"66": 80,
"67": 80,
"68": 90,
"69": 90,
"70": 90
},
"actual": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": "<",
"owner": "มนสิชา"
},
{
"pillar": "P2",
"kpiGroup": "22. อัตราการป่วยตาย TB",
"level": "U",
"kpi": "อัตราการป่วยตาย TB",
"okr": "อัตราการตายด้วยโรควัณโรค ไม่เกินร้อยละ5",
"target": {
"66": "<5",
"67": "<5",
"68": "<5",
"69": "<5",
"70": "<5"
},
"actual": {
"66": 7.33,
"67": 2.04,
"68": 11.71,
"69": 9.09,
"70": null
},
"direction": "<",
"owner": "เสาวณีย์"
},
{
"pillar": "P2",
"kpiGroup": "23. อัตราการป่วยตาย HIV",
"level": "U",
"kpi": "อัตราการป่วยตาย HIV",
"okr": "ร้อยละของผู้ป่วยที่มีค่า VL < 40 copies",
"target": {
"66": 90,
"67": 95,
"68": 95,
"69": 100,
"70": 100
},
"actual": {
"66": 16.5,
"67": 92.43,
"68": 97.5,
"69": 96.4,
"70": null
},
"direction": "<",
"owner": "สุวิทย์"
},
{
"pillar": "P2",
"kpiGroup": "23. อัตราการป่วยตาย HIV",
"level": "U",
"kpi": "อัตราการป่วยตาย HIV",
"okr": "ร้อยละของผู้ป่วยรับประทานยาต่อเนื่อง (Adherence) >ร้อยละ 90",
"target": {
"66": 90,
"67": 95,
"68": 95,
"69": 100,
"70": 100
},
"actual": {
"66": 57.33,
"67": 98,
"68": 97.5,
"69": 98,
"70": null
},
"direction": ">",
"owner": "สุวิทย์"
},
{
"pillar": "P3",
"kpiGroup": "24.ความมั่นคงปลอดภัยไซเบอร์",
"level": "R",
"kpi": "ความมั่นคงปลอดภัยไซเบอร์",
"okr": "ประเมินความมั่นคงปลอดภัยไซเบอร์",
"target": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": "ผ่าน"
},
"actual": {
"66": "na",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": null
},
"direction": "text",
"owner": "จริยาพร"
},
{
"pillar": "P3",
"kpiGroup": "25. โรงพยาบาลอัจฉริยะ",
"level": "R",
"kpi": "โรงพยาบาลอัจฉริยะ",
"okr": "ประเมินโรงพยาบาลอัจฉริยะ",
"target": {
"66": "เงิน",
"67": "ทอง",
"68": "ทอง",
"69": "ทอง",
"70": "เพชร"
},
"actual": {
"66": "na",
"67": "เงิน",
"68": "เงิน",
"69": "เงิน",
"70": null
},
"direction": "text",
"owner": "จริยาพร"
},
{
"pillar": "P3",
"kpiGroup": "26 มาตรฐาน HAIT",
"level": "R",
"kpi": "มาตรฐาน HAIT",
"okr": "ผ่านมาตรฐาน HAIT",
"target": {
"66": "ได้รับคัดเลือกเป็น รพ. นำร่องของจังหวัด",
"67": null,
"68": null,
"69": "ผ่านการประเมิน HAIT",
"70": null
},
"actual": {
"66": "รอรับการประเมิน",
"67": "รอรับการประเมิน",
"68": "รอรับการประเมิน",
"69": "รอดำเนินการ",
"70": null
},
"direction": "text",
"owner": "จริยาพร"
},
{
"pillar": "P3",
"kpiGroup": "27. ระบบบริหารจัดการสารสนเทศและพัสดุ",
"level": "I",
"kpi": "ระบบบริหารจัดการสารสนเทศและพัสดุ",
"okr": "การประยุกต์ใช้งานระบบบริหารจัดการสารสนเทศและพัสดุ>80%",
"target": {
"66": 60,
"67": 65,
"68": 70,
"69": 75,
"70": 80
},
"actual": {
"66": 12.12,
"67": 85,
"68": 88.88,
"69": 88.88,
"70": null
},
"direction": ">",
"owner": "จริยาพร"
},
{
"pillar": "P4",
"kpiGroup": "28.มาตรฐานระบบบริการสุขภาพ(HS4)",
"level": "P",
"kpi": "มาตรฐานระบบบริการสุขภาพ(HS4)",
"okr": "ผ่านมาตรฐานระบบบริการสุขภาพ >60%",
"target": {
"66": 70,
"67": 75,
"68": 80,
"69": 85,
"70": 90
},
"actual": {
"66": 25.33,
"67": 63.33,
"68": 93,
"69": "รอผลการประเมิน",
"70": null
},
"direction": ">",
"owner": "จริยาพร"
},
{
"pillar": "P4",
"kpiGroup": "29.ได้รับมาตรฐาน Green & Clean Hospital Challenge",
"level": "I",
"kpi": "ได้รับมาตรฐาน Green & Clean Hospital Challenge",
"okr": "ได้รับมาตรฐาน Green & Clean Hospital Excellence",
"target": {
"66": "ระดับดีมาก Plus",
"67": "ระดับดีมากPlus",
"68": "ระดับดีมากPlus",
"69": "ระดับดีมากPlus",
"70": "ระดับดีมากPlus"
},
"actual": {
"66": null,
"67": null,
"68": "ผ่านเกณฑ์มาตราฐาน",
"69": "ไม่ผ่าน",
"70": null
},
"direction": "text",
"owner": "อรวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "30.นโยบายEMS",
"level": "I",
"kpi": "นโยบายEMS",
"okr": "ผ่านการประเมินการพัฒนาสถานบริการตามนโยบายEMS>80%",
"target": {
"66": "> 80",
"67": "> 85",
"68": "> 90",
"69": "> 95",
"70": "> 100"
},
"actual": {
"66": "รอรับการประเมิน",
"67": 92.86,
"68": 92.86,
"69": null,
"70": null
},
"direction": ">",
"owner": "นิภารัตน์"
},
{
"pillar": "P4",
"kpiGroup": "31. มาตรฐาน HA",
"level": "R",
"kpi": "มาตรฐาน HA",
"okr": "ผ่านมาตรฐาน HA",
"target": {
"66": "ผ่านการรับรอง",
"67": "ผ่านการรับรอง",
"68": "ผ่านการรับรอง",
"69": "ผ่านการรับรอง",
"70": "ผ่านการรับรอง"
},
"actual": {
"66": "ผ่านการรับรอง",
"67": "ผ่านการรับรอง",
"68": "ผ่านการรับรอง",
"69": "ผ่านการรับรอง",
"70": null
},
"direction": "text",
"owner": "สุวิทย์"
},
{
"pillar": "P4",
"kpiGroup": "32. คลินิก COPD/Asthma คุณภาพ",
"level": "I",
"kpi": "คลินิก COPD/Asthma คุณภาพ",
"okr": "ผ่านเกณฑ์ประเมิน easy asthma clinic",
"target": {
"66": "ผ่านเกณฑ์ประเมิน easy asthma clinic",
"67": "ผ่านเกณฑ์ประเมิน easy asthma clinic",
"68": "ผ่านเกณฑ์ประเมิน easy asthma clinic",
"69": "ผ่านเกณฑ์ประเมิน easy asthma clinic",
"70": "ผ่านเกณฑ์ประเมิน easy asthma clinic"
},
"actual": {
"66": "ผ่านเกณฑ์",
"67": "ผ่านเกณฑ์",
"68": "ผ่านเกณฑ์",
"69": "รอรับการประเมิน",
"70": null
},
"direction": "text",
"owner": "กมลวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "33. คลินิก NCD plus คุณภาพ",
"level": "R",
"kpi": "คลินิก NCD plus คุณภาพ",
"okr": "ผ่านเกณฑ์ NCD Clinic Award",
"target": {
"66": "ดีเด่น",
"67": "ดีเด่น",
"68": "ดีเด่น",
"69": "ดีเด่น",
"70": "ดีเด่น"
},
"actual": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ระดับดีมาก",
"69": "รอรับประเมิน",
"70": null
},
"direction": "text",
"owner": "ศศิธร"
},
{
"pillar": "P4",
"kpiGroup": "33. คลินิก NCD plus คุณภาพ",
"level": "I",
"kpi": "คลินิก NCD plus คุณภาพ",
"okr": "ระยะเวลารอคอยภายในคลินิก<2ชม.",
"target": {
"66": 150,
"67": 140,
"68": 130,
"69": 120,
"70": 110
},
"actual": {
"66": 61.5,
"67": 60.2,
"68": 59.6,
"69": 56.42,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P4",
"kpiGroup": "34. คลินิกจิตเวชและยาเสพติด คุณภาพ",
"level": "U",
"kpi": "คลินิกจิตเวชและยาเสพติด คุณภาพ",
"okr": "ผ่านมาตรฐานบริการยาเสพติด",
"target": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": "ผ่าน"
},
"actual": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": null
},
"direction": "text",
"owner": null
},
{
"pillar": "P4",
"kpiGroup": "34. คลินิกจิตเวชและยาเสพติด คุณภาพ",
"level": "U",
"kpi": "คลินิกจิตเวชและยาเสพติด คุณภาพ",
"okr": "ผ่านมาตรฐานบริการสุขภาพจิตและจิตเวช ระดับ 1",
"target": {
"66": 2,
"67": 2,
"68": 1,
"69": 1,
"70": 1
},
"actual": {
"66": "เตรียมการ",
"67": 2,
"68": 2,
"69": "ระดับ 2",
"70": null
},
"direction": ">",
"owner": "มนสิชา"
},
{
"pillar": "P4",
"kpiGroup": "35. คลินิก HIV คุณภาพ",
"level": "I",
"kpi": "คลินิก HIV คุณภาพ",
"okr": "ผ่านการประเมินหน่วยบริการคุณภาพโรคเอดส์",
"target": {
"66": "เตรียม",
"67": "เตรียม",
"68": "เตรียม",
"69": "ผ่านการรับรอง",
"70": "ผ่านการรับรอง"
},
"actual": {
"66": "อยู่ระหว่างการเตรียม",
"67": "อยู่ระหว่างการเตรียม",
"68": "อยู่ระหว่างการเตรียม",
"69": "กำลังดำเนินการ",
"70": null
},
"direction": "text",
"owner": "สุวิทย์"
},
{
"pillar": "P4",
"kpiGroup": "36. การจัดตั้ง Premium service",
"level": "I",
"kpi": "การจัดตั้ง Premium service",
"okr": "การจัดตั้ง Premium service",
"target": {
"66": "ห้องตรวจพิเศษ",
"67": "หอผู้ป่วยพิเศษ",
"68": null,
"69": null,
"70": null
},
"actual": {
"66": "ห้องตรวจพิเศษ",
"67": "หอพิเศษ",
"68": "หอพิเศษ",
"69": "ตึกพิเศษ 11 ห้อง",
"70": null
},
"direction": ">",
"owner": "กมลวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "37. ห้องยาคุณภาพ",
"level": "R",
"kpi": "ห้องยาคุณภาพ",
"okr": "ผ่านเกณฑ์ความปลอดภัยด้านยา",
"target": {
"66": "ระดับ3",
"67": "ระดับ3",
"68": "ระดับ4",
"69": "ระดับ4",
"70": "ระดับ4"
},
"actual": {
"66": 3,
"67": 3,
"68": 4,
"69": "ผ่าน",
"70": null
},
"direction": ">",
"owner": "สุนิสา"
},
{
"pillar": "P4",
"kpiGroup": "38. บริการกายภาพบำบัดคุณภาพ",
"level": "I",
"kpi": "บริการกายภาพบำบัดคุณภาพ",
"okr": "ผ่านเกณฑ์มาตรฐานกายภาพบำบัด",
"target": {
"66": "ดีเยี่ยม",
"67": null,
"68": null,
"69": "ผ่านการรับรองคุณภาพบริการกายภาพบำบัดจากสภากายภาพบำบัด",
"70": null
},
"actual": {
"66": "ระดับดี",
"67": "ระดับดี",
"68": "ระดับดี",
"69": "ระดับดีมาก",
"70": null
},
"direction": "text",
"owner": "ทิพวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "38. บริการกายภาพบำบัดคุณภาพ",
"level": "P",
"kpi": "บริการกายภาพบำบัดคุณภาพ",
"okr": "พัฒนาศูนย์ฟื้นฟูผู้สูงอายุและผู้ป่วยระยะกลาง",
"target": {
"66": "จัดตั้งศูนย์ฟื้นฟูผู้สูงอายุและผู้ป่วยระยะกลาง",
"67": null,
"68": null,
"69": "มีศูนย์ฟื้นฟูผู้สูงอายุและผู้ป่วยระยะกลางให้บริการ",
"70": null
},
"actual": {
"66": "ยังไม่ได้จัดตั้งศูนย์",
"67": "ยังไม่ได้จัดตั้งศูนย์",
"68": "ยังไม่ได้จัดตั้งศูนย์",
"69": null,
"70": null
},
"direction": ">",
"owner": "ทิพวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "39.มาตรฐานทางห้องปฏิบัติการ (LA)และรังสีวินิจฉัย",
"level": "U",
"kpi": "มาตรฐานทางห้องปฏิบัติการ (LA)และรังสีวินิจฉัย",
"okr": "ตรวจประเมินระบบบริหารคุณภาพตามมาตรฐานห้องปฏิบัติการรังสีวินิจฉัย",
"target": {
"66": "ผ่าน **3 ปีครั้ง",
"67": null,
"68": null,
"69": "ผ่าน **3 ปีครั้ง",
"70": null
},
"actual": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่่าน",
"70": null
},
"direction": ">",
"owner": "วรรณ์สิริย์"
},
{
"pillar": "P4",
"kpiGroup": "39.มาตรฐานทางห้องปฏิบัติการ (LA)และรังสีวินิจฉัย",
"level": "U",
"kpi": "มาตรฐานทางห้องปฏิบัติการ (LA)และรังสีวินิจฉัย",
"okr": "ผ่านเกณฑ์คุณภาพตามมาตรฐานห้องปฏิบัติการ(LA)",
"target": {
"66": "ผ่าน **3 ปีครั้ง",
"67": null,
"68": null,
"69": "ผ่าน **3 ปีครั้ง",
"70": null
},
"actual": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": null
},
"direction": ">",
"owner": "นันท์นภัส"
},
{
"pillar": "P4",
"kpiGroup": "39.มาตรฐานทางห้องปฏิบัติการ (LA)และรังสีวินิจฉัย",
"level": "U",
"kpi": "มาตรฐานทางห้องปฏิบัติการ (LA)และรังสีวินิจฉัย",
"okr": "มีใบอนุญาตมีไว้ในครอบครองหรือใช้เครื่องกำเนิดรังสี",
"target": {
"66": "มี",
"67": "มี",
"68": "มี",
"69": "มี",
"70": "มี"
},
"actual": {
"66": "มี",
"67": "มี",
"68": "มี",
"69": "มี",
"70": null
},
"direction": ">",
"owner": "วรรณ์สิริย์"
},
{
"pillar": "P4",
"kpiGroup": "40. คลินิกวัยรุ่น",
"level": "U",
"kpi": "คลินิกวัยรุ่น",
"okr": "ผ่านเกณฑ์คุณภาพตามมาตรฐานคลินิกวัยรุ่น",
"target": {
"66": "ผ่าน",
"67": "รอปรับตามเกณฑ์ กรมอนามัย",
"68": null,
"69": null,
"70": null
},
"actual": {
"66": "รอรับการประเมิน",
"67": "รอรับการประเมิน",
"68": "รอรับการประเมิน",
"69": "รอประเมิน ปี 2569",
"70": null
},
"direction": "text",
"owner": "เสาวณีย์"
},
{
"pillar": "P4",
"kpiGroup": "41. บริการแพทย์แผนไทยคุณภาพ",
"level": "U",
"kpi": "บริการแพทย์แผนไทยคุณภาพ",
"okr": "มาตรฐานรพ.สส.พท",
"target": {
"66": "ดีมาก",
"67": "ดีมาก",
"68": "ดีเยี่ยม",
"69": "ดีเยี่ยม",
"70": "ดีเยี่ยม"
},
"actual": {
"66": "รอรับการประเมิน",
"67": "ดีเยี่ยม",
"68": "ดีเยี่ยม",
"69": "รอผลการประเมิน",
"70": null
},
"direction": "text",
"owner": "ไพลิน"
},
{
"pillar": "P4",
"kpiGroup": "41. บริการแพทย์แผนไทยคุณภาพ",
"level": "U",
"kpi": "บริการแพทย์แผนไทยคุณภาพ",
"okr": "ร้อยละของผู้ป่วยนอกที่ได้รับบริการการแพทย์แผนไทยและการแพทย์ทางเลือก > 16%",
"target": {
"66": 16,
"67": 16,
"68": 18,
"69": 18,
"70": 20
},
"actual": {
"66": 15.37,
"67": 9.7,
"68": 76.85,
"69": 11.55,
"70": null
},
"direction": ">",
"owner": "ไพลิน"
},
{
"pillar": "P4",
"kpiGroup": "42. ห้องฉุกเฉินคุณภาพ",
"level": "U",
"kpi": "ห้องฉุกเฉินคุณภาพ",
"okr": "ผ่านเกณฑ์ห้องฉุกเฉินคุณภาพ≥50คะแนน",
"target": {
"66": 50,
"67": 60,
"68": 60,
"69": 60,
"70": 70
},
"actual": {
"66": 56.6,
"67": 58.5,
"68": 60.1,
"69": 57.25,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P4",
"kpiGroup": "42. ห้องฉุกเฉินคุณภาพ",
"level": "U",
"kpi": "ห้องฉุกเฉินคุณภาพ",
"okr": "ระดับความพึงพอใจของผู้รับบริการแผนกอุบัติเหตุ-ฉุกเฉิน >80%",
"target": {
"66": 80,
"67": 80,
"68": 80,
"69": 80,
"70": 80
},
"actual": {
"66": 89.38,
"67": 88.48,
"68": 88.51,
"69": 86.75,
"70": null
},
"direction": ">",
"owner": "จำรูญศรี"
},
{
"pillar": "P4",
"kpiGroup": "43. หอผู้ป่วยในคุณภาพ",
"level": "U",
"kpi": "หอผู้ป่วยในคุณภาพ",
"okr": "case manager",
"target": {
"66": 4,
"67": 5,
"68": 6,
"69": 8,
"70": 10
},
"actual": {
"66": null,
"67": 5,
"68": 3,
"69": 3,
"70": null
},
"direction": ">",
"owner": "กมลวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "43. หอผู้ป่วยในคุณภาพ",
"level": "U",
"kpi": "หอผู้ป่วยในคุณภาพ",
"okr": "ข้อร้องเรียน",
"target": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": 0
},
"actual": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": null
},
"direction": "<",
"owner": "กมลวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "43. หอผู้ป่วยในคุณภาพ",
"level": "U",
"kpi": "หอผู้ป่วยในคุณภาพ",
"okr": "ระดับความพึงพอใจ>90%",
"target": {
"66": 90,
"67": 90,
"68": 90,
"69": 90,
"70": 90
},
"actual": {
"66": 88.46,
"67": 89.23,
"68": 88.61,
"69": 89.26,
"70": null
},
"direction": ">",
"owner": "กมลวรรณ"
},
{
"pillar": "P4",
"kpiGroup": "44. OPD คุณภาพ",
"level": "U",
"kpi": "OPD คุณภาพ",
"okr": "ผ่านการรับรองOPDคุณภาพ",
"target": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": "ผ่าน"
},
"actual": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": null
},
"direction": "text",
"owner": "ศศิธร"
},
{
"pillar": "P4",
"kpiGroup": "44. OPD คุณภาพ",
"level": "U",
"kpi": "OPD คุณภาพ",
"okr": "ระดับความพึงพอใจ>85%",
"target": {
"66": 0.9,
"67": 0.91,
"68": 0.92,
"69": 0.93,
"70": 0.94
},
"actual": {
"66": 89.46,
"67": 91.5,
"68": 92.3,
"69": 88.99,
"70": null
},
"direction": ">",
"owner": "ศศิธร"
},
{
"pillar": "P4",
"kpiGroup": "44. OPD คุณภาพ",
"level": "U",
"kpi": "OPD คุณภาพ",
"okr": "ระยะเวลาเวลารอคอย<60นาที waiting time",
"target": {
"66": 56,
"67": 54,
"68": 52,
"69": 50,
"70": 48
},
"actual": {
"66": 56,
"67": 45.43,
"68": 48.25,
"69": 54.14,
"70": null
},
"direction": "<",
"owner": "ศศิธร"
},
{
"pillar": "P4",
"kpiGroup": "45. LR คุณภาพ",
"level": "U",
"kpi": "LR คุณภาพ",
"okr": "ผ่านการรับรองห้องคลอดคุณภาพ",
"target": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": "ผ่าน"
},
"actual": {
"66": "ผ่าน",
"67": "ผ่าน",
"68": "ผ่าน",
"69": "ผ่าน",
"70": null
},
"direction": "text",
"owner": "ณาตยา"
},
{
"pillar": "P5",
"kpiGroup": "46.การขับเคลื่อนงานป้องกันควบคุมโรคและภัยสุขภาพด้วยกลไกการพัฒนาคุณภาพชีวิตระดับอำเภอ (พชอ.)",
"level": "R",
"kpi": "การขับเคลื่อนงานป้องกันควบคุมโรคและภัยสุขภาพด้วยกลไกการพัฒนาคุณภาพชีวิตระดับอำเภอ (พชอ.)",
"okr": "ร้อยละแผนงานโครงการที่ชุมชนมีส่วนร่วม > 50%",
"target": {
"66": 50,
"67": 50,
"68": 50,
"69": 50,
"70": 50
},
"actual": {
"66": 100,
"67": 100,
"68": 100,
"69": 100,
"70": null
},
"direction": ">",
"owner": "สาลี"
},
{
"pillar": "P6",
"kpiGroup": "47.ระดับความเสี่ยงทางการเงิน(Risk Score) ≤ 3",
"level": "R",
"kpi": "ระดับความเสี่ยงทางการเงิน(Risk Score) ≤ 3",
"okr": "ระดับความเสี่ยงทางการเงิน(Risk Score) ≤ 3",
"target": {
"66": 0,
"67": 0,
"68": 0,
"69": 0,
"70": 0
},
"actual": {
"66": 1,
"67": 1,
"68": 1,
"69": 0.16,
"70": null
},
"direction": "<",
"owner": "นิภารัตน์"
},
{
"pillar": "P6",
"kpiGroup": "48.CMI",
"level": "U",
"kpi": "CMI",
"okr": "การเพิ่มขึ้นของค่า CMI >=0.6",
"target": {
"66": 0.5,
"67": 0.52,
"68": 0.56,
"69": 0.58,
"70": 0.6
},
"actual": {
"66": 0.56,
"67": 0.58,
"68": 0.6434,
"69": 0.69,
"70": null
},
"direction": ">",
"owner": "สริยาภรณ์"
},
{
"pillar": "P6",
"kpiGroup": "49. อัตราครองเตียง > 85 %",
"level": "U",
"kpi": "อัตราครองเตียง > 85 %",
"okr": "อัตราการครองเตียง>85%",
"target": {
"66": ">85",
"67": ">90",
"68": ">95",
"69": 100,
"70": 100
},
"actual": {
"66": 52.47,
"67": 66.48,
"68": 73.76,
"69": 77.19,
"70": null
},
"direction": ">",
"owner": "สริยาภรณ์"
},
{
"pillar": "P6",
"kpiGroup": "50. sum Adj RW",
"level": "U",
"kpi": "sum Adj RW",
"okr": "Sum Adj-RW>1,400",
"target": {
"66": 1200,
"67": 1250,
"68": 1300,
"69": 1350,
"70": 1400
},
"actual": {
"66": 1646,
"67": 2254,
"68": 2584,
"69": 1477.94,
"70": null
},
"direction": ">",
"owner": "สริยาภรณ์"
},
{
"pillar": "P6",
"kpiGroup": "51. Current ratio ,cash ratio ,Quick ratio",
"level": "U",
"kpi": "Current ratio ,cash ratio ,Quick ratio",
"okr": "Current ratio",
"target": {
"66": 1.5,
"67": 1.5,
"68": 1.5,
"69": 1.5,
"70": 1.5
},
"actual": {
"66": 3.53,
"67": 5.41,
"68": 2.32,
"69": 2.08,
"70": null
},
"direction": ">",
"owner": null
},
{
"pillar": "P6",
"kpiGroup": "51. Current ratio ,cash ratio ,Quick ratio",
"level": "U",
"kpi": "Current ratio ,cash ratio ,Quick ratio",
"okr": "QR",
"target": {
"66": 1,
"67": 1,
"68": 1,
"69": 1,
"70": 1
},
"actual": {
"66": 3.41,
"67": 5.02,
"68": 1.94,
"69": 1.84,
"70": null
},
"direction": ">",
"owner": "นิภารัตน์"
},
{
"pillar": "P6",
"kpiGroup": "51. Current ratio ,cash ratio ,Quick ratio",
"level": "U",
"kpi": "Current ratio ,cash ratio ,Quick ratio",
"okr": "cash ratio",
"target": {
"66": 0.8,
"67": 0.8,
"68": 0.8,
"69": 0.8,
"70": 0.8
},
"actual": {
"66": 3.13,
"67": 4.09,
"68": 1.1,
"69": 1.17,
"70": null
},
"direction": ">",
"owner": null
},
{
"pillar": "P6",
"kpiGroup": "52. EBIDA",
"level": "U",
"kpi": "EBIDA",
"okr": ">3000000",
"target": {
"66": ">3000000",
"67": ">3000000",
"68": ">3000000",
"69": ">3000000",
"70": ">3000000"
},
"actual": {
"66": -11665498.65,
"67": -7154891.12,
"68": -16409487.77,
"69": 5558815.645,
"70": null
},
"direction": ">",
"owner": "นิภารัตน์"
},
{
"pillar": "P6",
"kpiGroup": "53. OPD/IPD unit cost",
"level": "P",
"kpi": "OPD/IPD unit cost",
"okr": "IPD unit cost",
"target": {
"66": 24396.36,
"67": "21.581.28",
"68": 20429.37,
"69": 18347.55,
"70": 18000
},
"actual": {
"66": 25646.09,
"67": 15127.64,
"68": 17628.9,
"69": 15122.8,
"70": null
},
"direction": ">",
"owner": "พรทิพย์"
},
{
"pillar": "P6",
"kpiGroup": "53. OPD/IPD unit cost",
"level": "P",
"kpi": "OPD/IPD unit cost",
"okr": "OPD unit cost",
"target": {
"66": 1054.22,
"67": 1023.26,
"68": 1062.11,
"69": 1040.59,
"70": 1050
},
"actual": {
"66": 674.69,
"67": 898.02,
"68": 805.77,
"69": 740.76,
"70": null
},
"direction": ">",
"owner": "พรทิพย์"
},
{
"pillar": "P6",
"kpiGroup": "54.ค่าสาธารณูปโภค",
"level": "I",
"kpi": "ค่าสาธารณูปโภค",
"okr": "หน่วยการใช้ไฟฟ้าลดลงปีละ >= 5%",
"target": {
"66": ">5%",
"67": ">5%",
"68": ">5%",
"69": ">5%",
"70": ">5%"
},
"actual": {
"66": 311.1,
"67": 302.52,
"68": 233.67,
"69": null,
"70": null
},
"direction": ">",
"owner": "นิภารัตน์"
},
{
"pillar": "P7",
"kpiGroup": "55.ร้อยละความพึงพอใจของบุคลากร >70",
"level": "R",
"kpi": "ร้อยละความพึงพอใจของบุคลากร >70",
"okr": "ร้ออยละความพึงพอใจของบุคลากร >70",
"target": {
"66": 70,
"67": 75,
"68": 80,
"69": 85,
"70": 90
},
"actual": {
"66": 75.08,
"67": null,
"68": 81.64,
"69": 81.64,
"70": null
},
"direction": ">",
"owner": "ทีม HRD"
},
{
"pillar": "P7",
"kpiGroup": "56.อัตราความคงอยู่ของบุคลากรด้านสุขภาพ >70",
"level": "R",
"kpi": "อัตราความคงอยู่ของบุคลากรด้านสุขภาพ >70",
"okr": "อัตราความคงอยู่ของบุคลากรด้านสุขภาพ >70",
"target": {
"66": 70,
"67": 72,
"68": 74,
"69": 76,
"70": 78
},
"actual": {
"66": 98.03,
"67": 98.25,
"68": 97.25,
"69": 97.25,
"70": null
},
"direction": ">",
"owner": "ทีม HRD"
},
{
"pillar": "P7",
"kpiGroup": "57.จำนวน CQI/R2R//Innovation/งานวิจัย >5 เรื่อง/ปี",
"level": "R",
"kpi": "จำนวน CQI/R2R//Innovation/งานวิจัย >5 เรื่อง/ปี",
"okr": "จำนวน CQI/R2R//Innovation/งานวิจัย >5 เรื่อง/ปี",
"target": {
"66": 5,
"67": 5,
"68": 5,
"69": 5,
"70": 5
},
"actual": {
"66": 7,
"67": 15,
"68": 15,
"69": 19,
"70": null
},
"direction": ">",
"owner": "ทีม HRD"
}
];
// ════════════════════════════════════════════════════════════
// PILLAR METADATA
// ════════════════════════════════════════════════════════════
const PILLAR_META = {
P1: { name:'ลดการเจ็บป่วยรายใหม่ในโรคยุทธศาสตร์ทุกกลุ่มวัย', icon:'🦠', color:'#0d9488' },
P2: { name:'ลดการป่วยตายในโรคยุทธศาสตร์ในทุกกลุ่มวัย', icon:'❤️🩹', color:'#dc2626' },
P3: { name:'ระบบเทคโนโลยีและสารสนเทศได้มาตรฐานสากล', icon:'💻', color:'#2563eb' },
P4: { name:'หน่วยบริการทุกระดับผ่านเกณฑ์คุณภาพ', icon:'🏥', color:'#7c3aed' },
P5: { name:'เพิ่มศักยภาพภาคีเครือข่ายระดับอำเภอ', icon:'🤝', color:'#059669' },
P6: { name:'โรงพยาบาลมีเสถียรภาพด้านการเงินการคลัง', icon:'💰', color:'#d97706' },
P7: { name:'บุคลากรเป็นเลิศ', icon:'👥', color:'#db2777' }
};
// ════════════════════════════════════════════════════════════
// STATUS EVALUATION LOGIC
// direction: '>' = higher better, '<' = lower better
// '=' = must equal target, 'text' = qualitative
// ════════════════════════════════════════════════════════════
function evalStatus(row, year = 68) {
const t = row.target[year];
const a = row.actual[year];
if (a === null || a === undefined || a === '') return 'ไม่มีข้อมูล';
const aStr = String(a).trim();
const tStr = t !== null && t !== undefined ? String(t).trim() : '';
// ── Special cases: direction = 'special' ──────────────────────────
// ใช้ evalFn แทน direction เพื่อ handle logic เฉพาะรายตัวชี้วัด
if (typeof row.evalFn === 'function') {
return row.evalFn(a, t, aStr, tStr, row, year);
}
// ── Qualitative / text ──────────────────────────────────────────
if (row.direction === 'text') {
const passWords = ['ผ่าน','ระดับดี','ดีเยี่ยม','ดีมาก','ดี','ระดับ','มี'];
const failWords = ['รอรับ','ยังไม่','ไม่ได้','เตรียม','อยู่ระหว่าง'];
const goodMatch = passWords.some(w => aStr.includes(w));
const failMatch = failWords.some(w => aStr.includes(w));
if (goodMatch && !failMatch) return 'บรรลุ';
if (failMatch) return 'ไม่บรรลุ';
return 'ไม่มีข้อมูล';
}
// ── Must equal ──────────────────────────────────────────────────
if (row.direction === '=') {
if (tStr === '' || t === null) return 'ไม่มีข้อมูล';
const aNum = parseFloat(aStr);
const tNum = parseFloat(tStr);
if (!isNaN(aNum) && !isNaN(tNum)) return aNum === tNum ? 'บรรลุ' : 'ไม่บรรลุ';
return aStr === tStr ? 'บรรลุ' : 'ไม่บรรลุ';
}
// ── Numeric: higher better / lower better ───────────────────────
const aNum = parseFloat(aStr);
if (isNaN(aNum)) return 'ไม่มีข้อมูล';
const tClean = tStr.replace(/[≥≤<>]/g,'').replace(/%/g,'').trim();
const tNum = parseFloat(tClean);
if (isNaN(tNum)) return 'ไม่มีข้อมูล';
if (row.direction === '>') {
if (aNum >= tNum) return 'บรรลุ';
if (aNum >= tNum * 0.9) return 'ใกล้บรรลุ';
return 'ไม่บรรลุ';
}
if (row.direction === '<') {
if (aNum <= tNum) return 'บรรลุ';
if (aNum <= tNum * 1.1) return 'ใกล้บรรลุ';
return 'ไม่บรรลุ';
}
return 'ไม่มีข้อมูล';
}
function getTrend(row) {
const vals = [66, 67, 68, 69]
.map(y => parseFloat(row.actual[y]))
.filter(v => !isNaN(v));
if (vals.length < 2) return '➖';
const last = vals[vals.length - 1];
const first = vals[0];
const diff = last - first;
if (row.direction === '>') return diff > 0.5 ? '📈' : diff < -0.5 ? '📉' : '➡️';
if (row.direction === '<') return diff < -0.5 ? '📈' : diff > 0.5 ? '📉' : '➡️';
return '➡️';
}
function getGap(row, year = 68) {
const a = row.actual[year];
const t = row.target[year];
if (a === null || t === null || row.direction === 'text' || row.direction === '=') return null;
const aNum = parseFloat(String(a).replace(/[≥≤<>%]/g,''));
const tNum = parseFloat(String(t).replace(/[≥≤<>%]/g,''));
if (isNaN(aNum) || isNaN(tNum)) return null;
return aNum - tNum;
}
function fmtNum(v) {
if (v === null || v === undefined) return '–';
if (typeof v === 'string') return v;
if (typeof v === 'number') {
if (Number.isInteger(v)) return v.toLocaleString('th-TH');
return v.toLocaleString('th-TH', {maximumFractionDigits:2});
}
return String(v);
}
// ════════════════════════════════════════════════════════════
// COMPUTE SUMMARY
// ════════════════════════════════════════════════════════════
function computeSummary() {
const latestYear = 69;
const total = RAW_DATA.length;
const pillars = 7;
const has68 = RAW_DATA.filter(r => r.actual[latestYear] !== null && r.actual[latestYear] !== undefined && r.actual[latestYear] !== '').length;
const statuses = RAW_DATA.map(r => evalStatus(r, latestYear));
const achieved = statuses.filter(s => s === 'บรรลุ').length;
const near = statuses.filter(s => s === 'ใกล้บรรลุ').length;
const fail = statuses.filter(s => s === 'ไม่บรรลุ').length;
const noData = statuses.filter(s => s === 'ไม่มีข้อมูล').length;
return { total, pillars, has68, achieved, near, fail, noData };
}
// ════════════════════════════════════════════════════════════
// BUILD SUMMARY CARDS
// ════════════════════════════════════════════════════════════
function buildSummary() {
const s = computeSummary();
const grid = document.getElementById('summaryGrid');
const cards = [
{ num: s.pillars, label: 'ยุทธศาสตร์ P1–P7', cls: '' },
{ num: s.total, label: 'ตัวชี้วัด/OKRs ทั้งหมด', cls: '' },
{ num: s.has68, label: 'มีผลดำเนินงานปี 2569', cls: 'accent' },
{ num: s.achieved, label: '✅ บรรลุเป้าหมายปี 2569', cls: 'good' },
{ num: s.near, label: '🟡 ใกล้บรรลุ (±10%)', cls: 'warn' },
{ num: s.fail, label: '❌ ไม่บรรลุ / ต้องเร่งพัฒนา', cls: 'bad' },
{ num: s.noData, label: '➖ ไม่มีข้อมูลปี 2569', cls: '' },
];
grid.innerHTML = cards.map(c => `
<div class="summary-card ${c.cls}">
<div class="summary-num">${c.num}</div>
<div class="summary-label">${c.label}</div>
</div>
`).join('');
}
// ════════════════════════════════════════════════════════════
// BUILD PILLAR CARDS
// ════════════════════════════════════════════════════════════
function buildPillars() {
const grid = document.getElementById('pillarGrid');
const pillars = ['P1','P2','P3','P4','P5','P6','P7'];
grid.innerHTML = pillars.map(p => {
const rows = RAW_DATA.filter(r => r.pillar === p);
const statuses = rows.map(r => evalStatus(r, 69));
const good = statuses.filter(s => s === 'บรรลุ').length;
const near = statuses.filter(s => s === 'ใกล้บรรลุ').length;
const fail = statuses.filter(s => s === 'ไม่บรรลุ').length;
const hasData = rows.filter(r => r.actual[69] !== null && r.actual[69] !== undefined && r.actual[69] !== '').length;
const total = rows.length;
const pct = total > 0 ? Math.round((good / total) * 100) : 0;
let overallStatus = 'status-na';
let statusLabel = 'ไม่มีข้อมูล';
if (hasData > 0) {
if (fail > good && fail > 1) { overallStatus = 'status-bad'; statusLabel = 'ต้องเร่งพัฒนา'; }
else if (good >= fail) { overallStatus = 'status-good'; statusLabel = 'ดี'; }
else { overallStatus = 'status-warn'; statusLabel = 'เฝ้าระวัง'; }
}
const meta = PILLAR_META[p];
const highlights = getPillarHighlights(p, rows);
return `
<div class="pillar-card">
<div class="pillar-header">
<div class="pillar-icon" style="background:${meta.color};">${meta.icon}</div>
<div class="pillar-info">
<div class="pillar-code">${p}</div>
<div class="pillar-name">${meta.name}</div>
</div>
<div class="pillar-status ${overallStatus}">${statusLabel}</div>
</div>
<div class="pillar-body">
<div class="pillar-stats">
<div class="pillar-stat"><div class="pillar-stat-num">${total}</div><div class="pillar-stat-lbl">OKRs</div></div>
<div class="pillar-stat"><div class="pillar-stat-num" style="color:var(--good)">${good}</div><div class="pillar-stat-lbl">บรรลุ</div></div>
<div class="pillar-stat"><div class="pillar-stat-num" style="color:var(--warn)">${near}</div><div class="pillar-stat-lbl">ใกล้บรรลุ</div></div>
<div class="pillar-stat"><div class="pillar-stat-num" style="color:var(--bad)">${fail}</div><div class="pillar-stat-lbl">ไม่บรรลุ</div></div>
</div>
<div class="progress-bar-wrap">
<div class="progress-bar-bg">
<div class="progress-bar-fill" style="width:${pct}%; background:linear-gradient(to right,${meta.color},${meta.color}aa)"></div>
</div>
<div class="progress-label"><span>ความสำเร็จปี 2569</span><span>${pct}% (${good}/${total})</span></div>
</div>
<ul class="pillar-highlights">
${highlights.map(h => `<li><span class="hl-dot" style="background:${meta.color}"></span>${h}</li>`).join('')}
</ul>
</div>
</div>`;
}).join('');
}
function getPillarHighlights(p, rows) {
const withData = rows.filter(r => r.actual[69] !== null && r.actual[69] !== undefined && r.actual[69] !== '');
const good = withData.filter(r => evalStatus(r, 69) === 'บรรลุ').slice(0, 3);
const fail = withData.filter(r => evalStatus(r, 69) === 'ไม่บรรลุ').slice(0, 2);
const hl = [];
good.forEach(r => hl.push(`${r.kpi}: ปี 2569 = ${fmtNum(r.actual[69])} บรรลุเป้า ${fmtNum(r.target[69])}`));
fail.forEach(r => hl.push(`${r.kpi}: ปี 2569 = ${fmtNum(r.actual[69])} ต่ำ/เกินเป้า ${fmtNum(r.target[69])} ต้องติดตาม`));
if (hl.length === 0) hl.push('ยังไม่มีข้อมูลปี 2569 เพียงพอสำหรับสรุปประเด็นรายยุทธศาสตร์');
return hl.slice(0, 5);
}
// ════════════════════════════════════════════════════════════
// BUILD TABLE
// ════════════════════════════════════════════════════════════
let currentData = [...RAW_DATA];
let sortKey = null;
let sortAsc = true;
function buildTable(data) {
const tbody = document.getElementById('tableBody');
document.getElementById('filterCount').textContent = `แสดง ${data.length} รายการ จาก ${RAW_DATA.length}`;
tbody.innerHTML = data.map(row => {
const status69 = evalStatus(row, 69);
const trend = getTrend(row);
const gap = getGap(row, 69);
let gapHtml = '<span class="gap-na">–</span>';
if (gap !== null) {
const sign = gap > 0 ? '+' : '';
const cls = (row.direction === '<' && gap <= 0) || (row.direction === '>' && gap >= 0) ? 'gap-pos' : 'gap-neg';
gapHtml = `<span class="gap-val ${cls}">${sign}${fmtNum(gap)}</span>`;
}
const note = getNote(row);
return `
<tr>
<td><span style="font-weight:700;color:${PILLAR_META[row.pillar].color}">${row.pillar}</span></td>
<td><span class="badge-level badge-${row.level}">${row.level}</span></td>
<td class="td-kpi">${row.kpi}</td>
<td class="td-okr">${row.okr}</td>
<td class="td-year">${fmtNum(row.target[66])}</td>
<td class="td-year">${fmtNum(row.target[67])}</td>
<td class="td-year">${fmtNum(row.target[68])}</td>
<td class="td-year">${fmtNum(row.target[69])}</td>
<td class="td-year">${fmtNum(row.actual[66])}</td>
<td class="td-year">${fmtNum(row.actual[67])}</td>
<td class="td-year">${fmtNum(row.actual[68])}</td>
<td class="td-year">${fmtNum(row.actual[69])}</td>
<td><span class="badge-status badge-${status69}">${status69}</span></td>
<td>${gapHtml}</td>
<td class="trend-arrow">${trend}</td>
<td style="font-size:12px;color:var(--text-muted);max-width:180px;">${note}</td>
</tr>`;
}).join('');
}
function getNote(row) {
const s = evalStatus(row, 69);
if (s === 'บรรลุ') return '✅ บรรลุเป้าหมายปี 2569';
if (s === 'ใกล้บรรลุ') return '🟡 ใกล้บรรลุ ควรติดตามต่อเนื่อง';
if (s === 'ไม่บรรลุ') return '❌ ต้องวางแผนปรับปรุง';
if (row.actual[69] === null || row.actual[69] === undefined || row.actual[69] === '') {
if (row.actual[68] !== null && row.actual[68] !== undefined && row.actual[68] !== '') return '⚠️ ขาดข้อมูลปี 69 (มีปี 68)';
return '➖ ยังไม่มีข้อมูลผลดำเนินงาน';
}
return '➖ ประเมินไม่ได้ (ตัวชี้วัดเชิงคุณภาพ)';
}
function applyFilters() {
const pillar = document.getElementById('filterPillar').value;
const level = document.getElementById('filterLevel').value;
const status = document.getElementById('filterStatus').value;
const search = document.getElementById('filterSearch').value.toLowerCase();
currentData = RAW_DATA.filter(row => {
if (pillar && row.pillar !== pillar) return false;
if (level && row.level !== level) return false;
if (status && evalStatus(row, 69) !== status) return false;
if (search) {
const haystack = (row.kpi + ' ' + row.okr + ' ' + row.kpiGroup).toLowerCase();
if (!haystack.includes(search)) return false;
}
return true;
});
if (sortKey) doSort();
else buildTable(currentData);
}
function resetFilters() {
document.getElementById('filterPillar').value = '';
document.getElementById('filterLevel').value = '';
document.getElementById('filterStatus').value = '';
document.getElementById('filterSearch').value = '';
currentData = [...RAW_DATA];
buildTable(currentData);
}
function sortTable(key) {
if (sortKey === key) sortAsc = !sortAsc;
else { sortKey = key; sortAsc = true; }
doSort();
}
function doSort() {
currentData.sort((a, b) => {
let va = a[sortKey] || '';
let vb = b[sortKey] || '';
if (sortKey === 'status') { va = evalStatus(a,69); vb = evalStatus(b,69); }
return sortAsc ? String(va).localeCompare(String(vb), 'th') : String(vb).localeCompare(String(va), 'th');
});
buildTable(currentData);
}
// ════════════════════════════════════════════════════════════
// BUILD CHARTS
// ════════════════════════════════════════════════════════════
let trendChart = null;
let selectedKpiIdx = 0;
// chart 1: status by pillar
function buildStatusChart() {
const pillars = ['P1','P2','P3','P4','P5','P6','P7'];
const achieved = [], near = [], fail = [], nodata = [];
pillars.forEach(p => {
const rows = RAW_DATA.filter(r => r.pillar === p);
const statuses = rows.map(r => evalStatus(r, 69));
achieved.push(statuses.filter(s => s === 'บรรลุ').length);
near.push(statuses.filter(s => s === 'ใกล้บรรลุ').length);
fail.push(statuses.filter(s => s === 'ไม่บรรลุ').length);
nodata.push(statuses.filter(s => s === 'ไม่มีข้อมูล').length);
});
const ctx = document.getElementById('chartStatus').getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: pillars,
datasets: [
{ label: 'บรรลุ', data: achieved, backgroundColor: '#16a34a' },
{ label: 'ใกล้บรรลุ', data: near, backgroundColor: '#ca8a04' },
{ label: 'ไม่บรรลุ', data: fail, backgroundColor: '#dc2626' },
{ label: 'ไม่มีข้อมูล', data: nodata, backgroundColor: '#d1d5db' }
]
},
options: {
responsive: true, maintainAspectRatio: false,
plugins: { legend: { position: 'bottom', labels: { font: { family: 'Sarabun', size: 12 } } } },
scales: {
x: { stacked: true, ticks: { font: { family: 'Sarabun', size: 12 } } },
y: { stacked: true, ticks: { font: { family: 'Sarabun' } }, title: { display: true, text: 'จำนวนตัวชี้วัด', font: { family: 'Sarabun' } } }
}
}
});
}
// chart 2: trend for selected KPI
const TREND_KPIS = [
{ label:'HIV PrEP เริ่มใช้', row: RAW_DATA.find(r => r.okr.includes('PrEP/PEP') && r.okr.includes('เริ่มใช้ PrEP/PEP')) },
{ label:'DM ควบคุมน้ำตาล', row: RAW_DATA.find(r => r.okr.includes('ควบคุมระดับน้ำตาล')) },
{ label:'HT แทรกซ้อน', row: RAW_DATA.find(r => r.okr.includes('แทรกซ้อนรายใหม่ในผู้ป่วย HT')) },
{ label:'Sepsis AB', row: RAW_DATA.find(r => r.okr.includes('Antibiotic ภายใน 1 ชม')) },
{ label:'Sum Adj-RW', row: RAW_DATA.find(r => r.okr.includes('Adj-RW')) },
{ label:'ความพึงพอใจบุคลากร', row: RAW_DATA.find(r => r.okr.includes('ความพึงพอใจของบุคลากร')) },
{ label:'CQI/R2R', row: RAW_DATA.find(r => r.okr.includes('CQI/R2R')) },
{ label:'HS4', row: RAW_DATA.find(r => r.okr.includes('มาตรฐานระบบบริการสุขภาพ')) },
{ label:'CMI', row: RAW_DATA.find(r => r.okr.includes('CMI')) },
{ label:'TB อัตราตาย', row: RAW_DATA.find(r => r.okr.includes('ตายด้วยโรควัณโรค')) },
].filter(k => k.row);
function buildKpiSelector() {
const sel = document.getElementById('kpiSelector');
sel.innerHTML = TREND_KPIS.map((k, i) => `
<button class="kpi-chip ${i === 0 ? 'active' : ''}" onclick="selectKpi(${i})">${k.label}</button>
`).join('');
}
function selectKpi(idx) {
selectedKpiIdx = idx;
document.querySelectorAll('.kpi-chip').forEach((c, i) => c.classList.toggle('active', i === idx));
buildTrendChart();
}
function buildTrendChart() {
const k = TREND_KPIS[selectedKpiIdx];
const row = k.row;
const years = ['66','67','68','69'];
const targets = years.map(y => {
const t = row.target[parseInt(y)];
if (t === null || t === undefined) return null;
const num = parseFloat(String(t).replace(/[≥≤<>%]/g,''));
return isNaN(num) ? null : num;
});
const actuals = years.map(y => {
const a = row.actual[parseInt(y)];
if (a === null || a === undefined) return null;
const num = parseFloat(String(a));
return isNaN(num) ? null : num;
});
const ctx = document.getElementById('chartTrend').getContext('2d');
if (trendChart) trendChart.destroy();
trendChart = new Chart(ctx, {
type: 'line',
data: {
labels: years.map(y => `ปี 25${y}`),
datasets: [
{
label: 'เป้าหมาย', data: targets,
borderColor: '#94a3b8', borderDash: [6,3],
pointStyle: 'rectRot', pointRadius: 5,
backgroundColor: 'transparent'
},
{
label: 'ผลจริง', data: actuals,
borderColor: '#0d5c8f', borderWidth: 2.5,
pointRadius: 6, pointBackgroundColor: '#0d5c8f',
backgroundColor: 'rgba(13,92,143,0.08)',
fill: true, tension: 0.35
}
]
},
options: {
responsive: true, maintainAspectRatio: false,
plugins: {
title: { display: true, text: k.label + ' – Target vs Actual', font: { family: 'Sarabun', size: 14 } },
legend: { position: 'bottom', labels: { font: { family: 'Sarabun' } } }
},
scales: {
x: { ticks: { font: { family: 'Sarabun' } } },
y: { ticks: { font: { family: 'Sarabun' } } }
}
}
});
}
// chart 3: heatmap
function buildHeatmap() {
const pillars = ['P1','P2','P3','P4','P5','P6','P7'];
const years = [66, 67, 68, 69];
const wrap = document.getElementById('heatmapWrap');
const getCellClass = (p, y) => {
const rows = RAW_DATA.filter(r => r.pillar === p);
const hasActual = rows.filter(r => r.actual[y] !== null && r.actual[y] !== undefined && r.actual[y] !== '');
if (hasActual.length === 0) return { cls:'hm-na', label:'–' };
const statuses = hasActual.map(r => evalStatus(r, y));
const good = statuses.filter(s => s === 'บรรลุ').length;
const fail = statuses.filter(s => s === 'ไม่บรรลุ').length;
const total = statuses.length;
const pct = Math.round((good / total) * 100);
if (pct >= 70) return { cls:'hm-good', label:`${pct}%` };
if (pct >= 40) return { cls:'hm-mixed', label:`${pct}%` };
if (pct >= 1) return { cls:'hm-bad', label:`${pct}%` };
return { cls:'hm-warn', label:`${pct}%` };
};
let html = `<table class="heatmap-table"><thead><tr>
<th>ยุทธศาสตร์</th>
<th>ปี 2566</th><th>ปี 2567</th><th>ปี 2568</th><th>ปี 2569</th>
</tr></thead><tbody>`;
pillars.forEach(p => {
html += `<tr><td class="hm-row-label">${p} – ${PILLAR_META[p].name.substring(0,20)}...</td>`;
years.forEach(y => {
const c = getCellClass(p, y);
html += `<td class="${c.cls}" title="${p} ปี 25${y} : ${c.label} ของตัวชี้วัดที่มีข้อมูล">${c.label}</td>`;
});
html += '</tr>';
});
html += '</tbody></table>';
html += `<p style="font-size:12px;color:var(--text-muted);margin-top:8px">
🟢 ≥70% บรรลุ | 🟣 40–69% | 🔴 1–39% | ⬛ ไม่มีข้อมูล | ตัวเลขแสดงสัดส่วนตัวชี้วัดที่มีข้อมูลและบรรลุเป้าหมาย</p>`;
wrap.innerHTML = html;
}
// ════════════════════════════════════════════════════════════
// HIGHLIGHTS
// ════════════════════════════════════════════════════════════
function buildHighlights() {
const rows69 = RAW_DATA.filter(r => r.actual[69] !== null && r.actual[69] !== undefined && r.actual[69] !== '');
const strengths = rows69.filter(r => evalStatus(r, 69) === 'บรรลุ').slice(0, 10).map(r =>
`✅ <strong>${r.pillar} ${r.kpi}:</strong> ปี 2569 = ${fmtNum(r.actual[69])} บรรลุเป้า ${fmtNum(r.target[69])}`
);
const opportunities = rows69.filter(r => evalStatus(r, 69) === 'ไม่บรรลุ').slice(0, 10).map(r =>
`⚠️ <strong>${r.pillar} ${r.kpi}:</strong> ปี 2569 = ${fmtNum(r.actual[69])} เป้า ${fmtNum(r.target[69])} ควรวิเคราะห์สาเหตุและกำหนดผู้รับผิดชอบติดตาม`
);
const systemic = [
`🔗 <strong>Data completeness:</strong> มีข้อมูลผลดำเนินงานปี 2569 จำนวน ${rows69.length} รายการจากทั้งหมด ${RAW_DATA.length} รายการ`,
'🔗 <strong>P1→P2:</strong> ผลลัพธ์การป้องกันโรคสำคัญเชื่อมต่อกับภาระโรคและการเสียชีวิตในกลุ่ม NCD/Stroke/ACS',
'🔗 <strong>P4→P6:</strong> คุณภาพบริการและมาตรฐานคลินิกส่งผลต่อ CMI, Adj-RW และเสถียรภาพทางการเงิน',
'🔗 <strong>P7→ทุกยุทธศาสตร์:</strong> กำลังคนและ CQI/R2R เป็นปัจจัยสนับสนุนการบรรลุ KPI รายยุทธศาสตร์'
];
function buildList(id, items) {
const el = document.getElementById(id);
el.innerHTML = (items.length ? items : ['➖ ยังไม่มีข้อมูลเพียงพอ']).map(i => `<li><span>•</span><span>${i}</span></li>`).join('');
}
buildList('hlStrengths', strengths);
buildList('hlOpportunities', opportunities);
buildList('hlSystemic', systemic);
}
// ════════════════════════════════════════════════════════════
// RECOMMENDATIONS
// ════════════════════════════════════════════════════════════
function buildRecommendations() {
const failing = RAW_DATA.filter(r => r.actual[69] !== null && r.actual[69] !== undefined && r.actual[69] !== '' && evalStatus(r, 69) === 'ไม่บรรลุ').slice(0, 5);
const recs = failing.map(r => ({
title: `จัดทำ Action Plan ปี 2569: ${r.pillar} ${r.kpi}`,
detail: `${r.okr} มีผลปี 2569 = ${fmtNum(r.actual[69])} เทียบเป้า ${fmtNum(r.target[69])} ผู้รับผิดชอบ: ${r.owner || 'ควรกำหนดเจ้าภาพ'} ควรวิเคราะห์ gap รายไตรมาสและติดตามในการประชุมบริหาร`
}));
recs.push({
title: 'ยกระดับระบบ Dashboard รายไตรมาส',
detail: 'ข้อมูลปี 2569 เป็นช่วง ต.ค.–มี.ค. ควรกำหนดรอบอัปเดตทุกไตรมาส ระบุเจ้าภาพข้อมูล และตรวจสอบ KPI ที่ยังไม่มีผลดำเนินงานก่อนใช้เป็นเอกสารทางการ'
});
const el = document.getElementById('recList');
el.innerHTML = recs.map((r, i) => `
<div class="rec-card">
<div class="rec-num">${i + 1}</div>
<div class="rec-content">
<div class="rec-title">${r.title}</div>
<div class="rec-detail">${r.detail}</div>
</div>
</div>
`).join('');
}
// ════════════════════════════════════════════════════════════
// NAV SCROLL
// ════════════════════════════════════════════════════════════
function scrollToSection(id) {
const el = document.getElementById(id);
if (el) {
const offset = el.getBoundingClientRect().top + window.pageYOffset - 50;
window.scrollTo({ top: offset, behavior: 'smooth' });
}
}
// highlight active nav on scroll
const sectionIds = ['summary','pillars','table','charts','highlights','recs'];
window.addEventListener('scroll', () => {
let current = sectionIds[0];
sectionIds.forEach(id => {
const el = document.getElementById(id);
if (el && el.getBoundingClientRect().top < 120) current = id;
});
document.querySelectorAll('.nav-btn').forEach((btn, i) => {
btn.classList.toggle('active', sectionIds[i] === current);
});
});
// ════════════════════════════════════════════════════════════
// INIT
// ════════════════════════════════════════════════════════════
document.addEventListener('DOMContentLoaded', () => {
buildSummary();
buildPillars();
buildTable(RAW_DATA);
buildHighlights();
buildRecommendations();
// Charts – with CDN fallback check
if (typeof Chart !== 'undefined') {
buildStatusChart();
buildKpiSelector();
buildTrendChart();
buildHeatmap();
} else {
document.getElementById('charts').innerHTML = `
<div style="padding:40px;text-align:center;background:#fff;border-radius:12px;box-shadow:var(--shadow)">
<p style="font-size:16px;color:var(--text-muted)">⚠️ ไม่สามารถโหลด Chart.js ได้ (อาจไม่มีการเชื่อมต่ออินเทอร์เน็ต)<br>กราฟจะแสดงได้เมื่อมีการเชื่อมต่อ</p>
</div>`;
}
document.getElementById('filterCount').textContent = `แสดง ${RAW_DATA.length} รายการ`;
});
</script>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v833ccba57c9e4d2798f2e76cebdd09a11778172276447" integrity="sha512-57MDmcccJXYtNnH+ZiBwzC4jb2rvgVCEokYN+L/nLlmO8rfYT/gIpW2A569iJ/3b+0UEasghjuZH/ma3wIs/EQ==" data-cf-beacon='{"version":"2024.11.0","token":"f90a79f4a0d64129aa8b9445b8d95ffc","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>