| <!DOCTYPE html> |
| <html lang="th"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>ระบบรายงานและวิเคราะห์ตัวชี้วัด สนอ. 2568</title> |
| |
| <script src="https://cdn.tailwindcss.com"></script> |
| |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
| |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| |
| <link rel="preconnect" href="https://fonts.googleapis.com"> |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| <link href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap" rel="stylesheet"> |
| |
| <style> |
| body { |
| font-family: 'Sarabun', sans-serif; |
| background-color: #f3f4f6; |
| } |
| </style> |
| </head> |
| <body class="min-h-screen text-slate-800 flex flex-col"> |
|
|
| |
| <header class="bg-gradient-to-r from-blue-700 to-indigo-800 text-white shadow-md"> |
| <div class="max-w-7xl mx-auto px-4 py-5 sm:px-6 lg:px-8 flex flex-col md:flex-row justify-between items-center gap-4"> |
| <div class="flex items-center space-x-3"> |
| <div class="p-2.5 bg-white/10 rounded-lg"> |
| <i class="fa-solid fa-chart-line text-2xl text-yellow-300"></i> |
| </div> |
| <div> |
| <h1 class="text-xl md:text-2xl font-bold tracking-tight">ระบบแสดงผลและวิเคราะห์ตัวชี้วัด สนอ. 68</h1> |
| <p class="text-xs md:text-sm text-blue-200">ปีงบประมาณ 2568 - ข้อมูลคะแนนประเมินเต็ม 5</p> |
| </div> |
| </div> |
| <div class="flex items-center space-x-2 bg-white/10 px-4 py-2 rounded-full border border-white/20 text-xs md:text-sm"> |
| <span class="inline-block w-2.5 h-2.5 bg-emerald-400 rounded-full animate-pulse"></span> |
| <span>เชื่อมโยงข้อมูล สนอ.68 เรียบร้อย</span> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <main class="flex-grow max-w-7xl mx-auto px-4 py-6 sm:px-6 lg:px-8 w-full"> |
| |
| |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6"> |
| <div class="bg-white p-5 rounded-xl shadow-sm border border-slate-100 flex items-center space-x-4"> |
| <div class="p-3 bg-blue-100 text-blue-700 rounded-lg"> |
| <i class="fa-solid fa-folder-open text-xl"></i> |
| </div> |
| <div> |
| <p class="text-xs text-slate-500 font-medium">มิติการทำงานหลัก</p> |
| <p class="text-lg font-bold text-slate-800">4 ด้านหลัก</p> |
| </div> |
| </div> |
| <div class="bg-white p-5 rounded-xl shadow-sm border border-slate-100 flex items-center space-x-4"> |
| <div class="p-3 bg-indigo-100 text-indigo-700 rounded-lg"> |
| <i class="fa-solid fa-list-check text-xl"></i> |
| </div> |
| <div> |
| <p class="text-xs text-slate-500 font-medium">จำนวนตัวชี้วัดย่อย</p> |
| <p class="text-lg font-bold text-slate-800" id="indicator-count">14 รายการ</p> |
| </div> |
| </div> |
| <div class="bg-white p-5 rounded-xl shadow-sm border border-slate-100 flex items-center space-x-4"> |
| <div class="p-3 bg-emerald-100 text-emerald-700 rounded-lg"> |
| <i class="fa-solid fa-users text-xl"></i> |
| </div> |
| <div> |
| <p class="text-xs text-slate-500 font-medium">หน่วยงานที่ประเมิน</p> |
| <p class="text-lg font-bold text-slate-800">7 หน่วยงาน</p> |
| </div> |
| </div> |
| <div class="bg-white p-5 rounded-xl shadow-sm border border-slate-100 flex items-center space-x-4"> |
| <div class="p-3 bg-amber-100 text-amber-700 rounded-lg"> |
| <i class="fa-solid fa-star text-xl"></i> |
| </div> |
| <div> |
| <p class="text-xs text-slate-500 font-medium">คะแนนเฉลี่ยรวมทุกแผนก</p> |
| <p class="text-lg font-bold text-slate-800" id="overall-average">0.00 / 5.00</p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white p-6 rounded-xl shadow-sm border border-slate-100 mb-6"> |
| <h2 class="text-lg font-semibold mb-4 flex items-center text-slate-800"> |
| <i class="fa-solid fa-filter text-indigo-600 mr-2"></i> ตัวเลือกการกรองและแสดงผลตัวชี้วัด |
| </h2> |
| |
| <div class="grid grid-cols-1 md:grid-cols-12 gap-4"> |
| |
| <div class="md:col-span-4"> |
| <label class="block text-sm font-medium text-slate-600 mb-2">มิติงาน / กลุ่มเป้าหมายหลัก</label> |
| <select id="group-filter" class="w-full bg-slate-50 border border-slate-200 rounded-lg p-2.5 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none"> |
| <option value="all">-- แสดงทุกตัวชี้วัด (ทั้งหมด) --</option> |
| <option value="1">ด้านที่ 1 : พัฒนาระบบบริหารจัดการสู่องค์กรที่มีธรรมาภิบาล</option> |
| <option value="2">ด้านที่ 2 : การพัฒนาเทคโนโลยีดิจิทัลและนวัตกรรมเพื่อการบริหารและการบริการ</option> |
| <option value="3">ด้านที่ 3 : การบริหารจัดการสิ่งแวดล้อม และสนับสนุนการพัฒนาองค์กรอย่างยั่งยืน</option> |
| <option value="4">ด้านที่ 4 : บุคลากรมีความรู้ ทักษะ และสมรรถนะที่สอดคล้องกับยุคดิจิทัล</option> |
| </select> |
| </div> |
|
|
| |
| <div class="md:col-span-8"> |
| <label class="block text-sm font-medium text-slate-600 mb-2">เลือกตัวชี้วัดเฉพาะรายการ</label> |
| <select id="indicator-filter" class="w-full bg-slate-50 border border-slate-200 rounded-lg p-2.5 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none"> |
| <option value="all">-- แสดงผลเปรียบเทียบทุกตัวชี้วัดตามด้านที่เลือก --</option> |
| |
| </select> |
| </div> |
| </div> |
|
|
| |
| <div class="mt-4 pt-4 border-t border-slate-100 flex flex-wrap items-center gap-2"> |
| <span class="text-xs font-semibold text-slate-500 uppercase tracking-wider mr-2">หน่วยงานที่วิเคราะห์:</span> |
| <span class="px-3 py-1 bg-blue-50 text-blue-700 text-xs font-medium rounded-full border border-blue-100">สนอ. (สำนักงานอธิการบดี)</span> |
| <span class="px-3 py-1 bg-indigo-50 text-indigo-700 text-xs font-medium rounded-full border border-indigo-100">กก. (กองกลาง)</span> |
| <span class="px-3 py-1 bg-purple-50 text-purple-700 text-xs font-medium rounded-full border border-purple-100">กนผ. (กองแผนงาน)</span> |
| <span class="px-3 py-1 bg-sky-50 text-sky-700 text-xs font-medium rounded-full border border-sky-100">กบค. (กองบริหารงานบุคคล)</span> |
| <span class="px-3 py-1 bg-teal-50 text-teal-700 text-xs font-medium rounded-full border border-teal-100">กบศ. (กองบริการการศึกษา)</span> |
| <span class="px-3 py-1 bg-emerald-50 text-emerald-700 text-xs font-medium rounded-full border border-emerald-100">กพน. (กองพัฒนานักศึกษา)</span> |
| <span class="px-3 py-1 bg-rose-50 text-rose-700 text-xs font-medium rounded-full border border-rose-100">กค. (กองคลัง)</span> |
| </div> |
| </div> |
|
|
| |
| <div class="grid grid-cols-1 lg:grid-cols-12 gap-6 mb-6"> |
| |
| <div class="bg-white p-6 rounded-xl shadow-sm border border-slate-100 lg:col-span-8 flex flex-col justify-between"> |
| <div> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-base font-bold text-slate-800 flex items-center"> |
| <i class="fa-solid fa-chart-column text-blue-600 mr-2"></i> กราฟเปรียบเทียบคะแนนเฉลยในแต่ละหน่วยงาน |
| </h3> |
| <span class="text-xs bg-indigo-50 text-indigo-700 py-1 px-2.5 rounded-md font-semibold" id="chart-mode-tag">โหมดทั้งหมด</span> |
| </div> |
| <div class="relative w-full h-[320px] md:h-[350px]"> |
| <canvas id="indicatorChart"></canvas> |
| </div> |
| </div> |
| <div class="mt-4 text-xs text-slate-400 italic"> |
| * หมายเหตุ: แสดงคะแนนการประเมินเทียบกับเป้าหมายคะแนนเต็ม 5 คะแนน |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white p-6 rounded-xl shadow-sm border border-slate-100 lg:col-span-4 flex flex-col justify-between"> |
| <div> |
| <h3 class="text-base font-bold text-slate-800 mb-4 flex items-center"> |
| <i class="fa-solid fa-award text-yellow-500 mr-2"></i> สรุปผลการประเมินเบื้องต้น |
| </h3> |
| |
| |
| <div class="bg-emerald-50 border border-emerald-100 p-4 rounded-xl mb-4"> |
| <p class="text-xs text-emerald-600 font-bold uppercase tracking-wider mb-1">หน่วยงานที่มีคะแนนเฉลี่ยสูงสุดในกลุ่มที่เลือก</p> |
| <div class="flex items-baseline space-x-2"> |
| <span class="text-2xl font-black text-emerald-800" id="top-dept">-</span> |
| <span class="text-sm font-semibold text-emerald-700" id="top-score">0.00 / 5.00</span> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-rose-50 border border-rose-100 p-4 rounded-xl mb-4"> |
| <p class="text-xs text-rose-600 font-bold uppercase tracking-wider mb-1">หน่วยงานที่ควรส่งเสริมพัฒนาการประเมินเพิ่ม</p> |
| <div class="flex items-baseline space-x-2"> |
| <span class="text-2xl font-black text-rose-800" id="low-dept">-</span> |
| <span class="text-sm font-semibold text-rose-700" id="low-score">0.00 / 5.00</span> |
| </div> |
| </div> |
|
|
| |
| <div class="p-3 border border-slate-100 rounded-lg"> |
| <p class="text-xs text-slate-500 font-medium mb-2">ความสำเร็จเทียบกับเกณฑ์ร้อยละความพึงพอใจเป้าหมาย (คะแนนสะสม 4.0 ขึ้นไป)</p> |
| <div class="w-full bg-slate-100 rounded-full h-2"> |
| <div id="target-progress-bar" class="bg-indigo-600 h-2 rounded-full" style="width: 0%"></div> |
| </div> |
| <div class="flex justify-between items-center mt-1 text-[11px] text-slate-400"> |
| <span>ผ่านเกณฑ์ <strong id="success-pct">0%</strong> ของตัวชี้วัด</span> |
| <span>เป้าหมาย 4.0 คะแนน</span> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="mt-4 pt-4 border-t border-slate-100 text-xs text-slate-500"> |
| <i class="fa-solid fa-circle-info text-blue-500 mr-1"></i> เลือกเปลี่ยนตัวชี้วัดหรือมิติงานหลัก เพื่อให้กราฟแสดงข้อมูลที่เจาะจงขึ้น |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden"> |
| <div class="px-6 py-4 border-b border-slate-100 flex flex-col md:flex-row justify-between items-start md:items-center gap-2 bg-slate-50/70"> |
| <div> |
| <h3 class="text-base font-bold text-slate-800 flex items-center"> |
| <i class="fa-solid fa-table-list text-emerald-600 mr-2"></i> ตารางรายละเอียดคะแนนตัวชี้วัด (จำแนกตามรายด้าน) |
| </h3> |
| <p class="text-xs text-slate-500 mt-0.5">ตารางประมวลผลสรุปคะแนนประเมินปี 2568 ของทุกฝ่ายงาน</p> |
| </div> |
| <div class="flex items-center space-x-2"> |
| <button onclick="resetFilters()" class="text-xs font-semibold px-3 py-1.5 bg-slate-200 text-slate-700 rounded-lg hover:bg-slate-300 transition flex items-center gap-1"> |
| <i class="fa-solid fa-rotate-left"></i> ล้างค่าตัวเลือก |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="overflow-x-auto"> |
| <table class="w-full text-left border-collapse"> |
| <thead> |
| <tr class="bg-slate-100 text-slate-600 text-[13px] font-bold border-b border-slate-200"> |
| <th class="py-3 px-4 min-w-[280px]">รายละเอียดตัวชี้วัด</th> |
| <th class="py-3 px-3 text-center bg-blue-50/50">สนอ.</th> |
| <th class="py-3 px-3 text-center">กก.</th> |
| <th class="py-3 px-3 text-center">กนผ.</th> |
| <th class="py-3 px-3 text-center">กบค.</th> |
| <th class="py-3 px-3 text-center">กบศ.</th> |
| <th class="py-3 px-3 text-center">กพน.</th> |
| <th class="py-3 px-3 text-center">กค.</th> |
| </tr> |
| </thead> |
| <tbody id="indicators-table-body" class="divide-y divide-slate-100 text-[13.5px]"> |
| |
| </tbody> |
| </table> |
| </div> |
| </div> |
|
|
| </main> |
|
|
| |
| <footer class="bg-slate-800 text-slate-400 py-6 mt-12 border-t border-slate-700"> |
| <div class="max-w-7xl mx-auto px-4 text-center text-xs space-y-2"> |
| <p>ระบบนำเสนอและประเมินผลตัวชี้วัด สนอ.68 | จัดทำขึ้นจากระบบจำลองข้อมูลโครงสร้างแฟ้มข้อมูล ปีงบประมาณ 2568</p> |
| <p class="text-slate-500">พัฒนาด้วยเครื่องมือภาพระดับสูงแบบปรับตามสัดส่วนจอภาพ (Responsive & Reactive View)</p> |
| </div> |
| </footer> |
|
|
| |
| <script> |
| |
| const dataset = [ |
| |
| { id: "1.1", text: "1.1 ร้อยละความสำเร็จของแผนปฏิบัติการของแต่ละหน่วยงาน", isCategory: false, parent: "1", values: { s_no: 5.0, k_k: 5.0, k_np: 5.0, k_bk: 4.0, k_bs: 5.0, k_pn: 4.0, k_k_fin: 5.0 } }, |
| { id: "1.2", text: "1.2 ระดับความพึงพอใจของบุคลากรต่อระบบบริหารจัดการ", isCategory: false, parent: "1", values: { s_no: 4.41, k_k: 4.65, k_np: 4.32, k_bk: 4.51, k_bs: 4.24, k_pn: 4.31, k_k_fin: 4.47 } }, |
| { id: "avg1", text: "คะแนนเฉลี่ย มิติที่ 1 (ธรรมาภิบาล)", isCategory: true, parent: "1", values: { s_no: 4.705, k_k: 4.825, k_np: 4.66, k_bk: 4.255, k_bs: 4.62, k_pn: 4.155, k_k_fin: 4.735 } }, |
| |
| |
| { id: "2.1", text: "2.1 ระดับความพึงพอใจของบุคลากรต่อระบบเทคโนโลยีดิจิทัล", isCategory: false, parent: "2", values: { s_no: 4.02, k_k: 3.85, k_np: 4.05, k_bk: 4.01, k_bs: 3.91, k_pn: 4.22, k_k_fin: 4.25 } }, |
| { id: "2.2", text: "2.2 จำนวนกระบวนงานที่มีการนำเทคโนโลยีดิจิทัลมาใช้ในกระบวนการบริหาร", isCategory: false, parent: "2", values: { s_no: 5.0, k_k: 4.72, k_np: 5.0, k_bk: 5.0, k_bs: 5.0, k_pn: 3.4, k_k_fin: 5.0 } }, |
| { id: "2.3", text: "2.3 ร้อยละความสำเร็จของการบริหารจัดการความปลอดภัยสารสนเทศ", isCategory: false, parent: "2", values: { s_no: 5.0, k_k: 5.0, k_np: 5.0, k_bk: 4.0, k_bs: 5.0, k_pn: 5.0, k_k_fin: 5.0 } }, |
| { id: "avg2", text: "คะแนนเฉลี่ย มิติที่ 2 (เทคโนโลยีดิจิทัล)", isCategory: true, parent: "2", values: { s_no: 4.673, k_k: 4.523, k_np: 4.683, k_bk: 4.337, k_bs: 4.637, k_pn: 4.207, k_k_fin: 4.75 } }, |
| |
| |
| { id: "3.1", text: "3.1 ร้อยละที่ลดลงของปริมาณพลังงานที่ใช้เดิม", isCategory: false, parent: "3", values: { s_no: 4.0, k_k: 4.0, k_np: null, k_bk: null, k_bs: null, k_pn: null, k_k_fin: null } }, |
| { id: "3.2", text: "3.2 ระดับความสำเร็จของกระบวนการส่งเสริมการมีส่วนร่วมเพื่อการได้รับรางวัล Thailand Sustainability Awards", isCategory: false, parent: "3", values: { s_no: 5.0, k_k: 5.0, k_np: null, k_bk: null, k_bs: null, k_pn: null, k_k_fin: null } }, |
| { id: "avg3", text: "คะแนนเฉลี่ย มิติที่ 3 (สิ่งแวดล้อม)", isCategory: true, parent: "3", values: { s_no: 4.5, k_k: 4.5, k_np: 0.0, k_bk: 0.0, k_bs: 0.0, k_pn: 0.0, k_k_fin: 0.0 } }, |
| |
| |
| { id: "4.1", text: "4.1 ร้อยละของบุคลากรที่เข้าร่วมอบรมพัฒนาทักษะทางวิชาการและทางวิชาชีพ", isCategory: false, parent: "4", values: { s_no: 5.0, k_k: 4.72, k_np: 5.0, k_bk: 5.0, k_bs: 5.0, k_pn: 3.4, k_k_fin: 5.0 } }, |
| { id: "4.2", text: "4.2 ร้อยละของบุคลากรที่เข้าร่วมอบรมพัฒนาทักษะดิจิทัลและนวัตกรรม", isCategory: false, parent: "4", values: { s_no: 5.0, k_k: 4.06, k_np: 5.0, k_bk: 5.0, k_bs: 5.0, k_pn: 4.84, k_k_fin: 4.7 } }, |
| { id: "4.3", text: "4.3 ระดับความพึงพอใจของบุคลากรต่อการพัฒนาทรัพยากรบุคคล", isCategory: false, parent: "4", values: { s_no: 4.28, k_k: 4.22, k_np: 3.89, k_bk: 4.69, k_bs: 3.94, k_pn: 4.43, k_k_fin: 4.52 } }, |
| { id: "4.4", text: "4.4 ร้อยละของบุคลากรที่เข้าสู่ตำแหน่งที่สูงขึ้น", isCategory: false, parent: "4", values: { s_no: 5.0, k_k: 0.0, k_np: 0.0, k_bk: 0.0, k_bs: 5.0, k_pn: 0.0, k_k_fin: 0.0 } }, |
| { id: "4.5", text: "4.5 จำนวนโครงการแลกเปลี่ยนเรียนรู้ระหว่างบุคลากรรุ่นเก่าและรุ่นใหม่", isCategory: false, parent: "4", values: { s_no: 5.0, k_k: 5.0, k_np: 5.0, k_bk: 5.0, k_bs: 0.0, k_pn: 0.0, k_k_fin: 0.0 } }, |
| { id: "avg4", text: "คะแนนเฉลี่ย มิติที่ 4 (บุคลากร)", isCategory: true, parent: "4", values: { s_no: 4.856, k_k: 4.333, k_np: 3.778, k_bk: 3.938, k_bs: 3.788, k_pn: 3.168, k_k_fin: 3.32 } } |
| ]; |
| |
| |
| const deptLabels = ['สนอ.', 'กก.', 'กนผ.', 'กบค.', 'กบศ.', 'กพน.', 'กค.']; |
| const deptKeys = ['s_no', 'k_k', 'k_np', 'k_bk', 'k_bs', 'k_pn', 'k_k_fin']; |
| const deptColors = [ |
| 'rgba(59, 130, 246, 0.85)', |
| 'rgba(99, 102, 241, 0.85)', |
| 'rgba(168, 85, 247, 0.85)', |
| 'rgba(14, 165, 233, 0.85)', |
| 'rgba(20, 184, 166, 0.85)', |
| 'rgba(16, 185, 129, 0.85)', |
| 'rgba(244, 63, 94, 0.85)' |
| ]; |
| const deptBorders = [ |
| 'rgb(59, 130, 246)', |
| 'rgb(99, 102, 241)', |
| 'rgb(168, 85, 247)', |
| 'rgb(14, 165, 233)', |
| 'rgb(20, 184, 166)', |
| 'rgb(16, 185, 129)', |
| 'rgb(244, 63, 94)' |
| ]; |
| |
| let myChart = null; |
| |
| |
| document.addEventListener('DOMContentLoaded', () => { |
| initTable(); |
| populateIndicatorDropdown(); |
| updateDashboard(); |
| |
| |
| document.getElementById('group-filter').addEventListener('change', () => { |
| populateIndicatorDropdown(); |
| updateDashboard(); |
| }); |
| document.getElementById('indicator-filter').addEventListener('change', updateDashboard); |
| }); |
| |
| |
| function initTable() { |
| const tbody = document.getElementById('indicators-table-body'); |
| tbody.innerHTML = ''; |
| |
| let currentHeader = ""; |
| |
| dataset.forEach(item => { |
| |
| let headerText = ""; |
| if (item.parent === "1" && currentHeader !== "1") { |
| headerText = "มิติที่ 1 : พัฒนาระบบบริหารจัดการสู่องค์กรที่มีธรรมาภิบาล"; |
| currentHeader = "1"; |
| } else if (item.parent === "2" && currentHeader !== "2") { |
| headerText = "มิติที่ 2 : การพัฒนาเทคโนโลยีดิจิทัลและนวัตกรรมเพื่อการบริหารและการบริการ"; |
| currentHeader = "2"; |
| } else if (item.parent === "3" && currentHeader !== "3") { |
| headerText = "มิติที่ 3 : การบริหารจัดการสิ่งแวดล้อม และสนับสนุนการพัฒนาองค์กรอย่างยั่งยืน"; |
| currentHeader = "3"; |
| } else if (item.parent === "4" && currentHeader !== "4") { |
| headerText = "มิติที่ 4 : บุคลากรมีความรู้ ทักษะ และสมรรถนะที่สอดคล้องกับยุคดิจิทัล"; |
| currentHeader = "4"; |
| } |
| |
| if (headerText) { |
| const hRow = document.createElement('tr'); |
| hRow.className = "bg-slate-50 text-slate-700 font-bold text-xs"; |
| hRow.innerHTML = `<td colspan="8" class="py-2.5 px-4 border-y border-slate-200">${headerText}</td>`; |
| tbody.appendChild(hRow); |
| } |
| |
| const row = document.createElement('tr'); |
| |
| if (item.isCategory) { |
| row.className = "bg-indigo-50/40 text-indigo-900 font-semibold border-b border-indigo-100"; |
| } else { |
| row.className = "hover:bg-slate-50 border-b border-slate-100"; |
| } |
| |
| |
| let rowHTML = `<td class="py-3 px-4 font-medium">${item.text}</td>`; |
| |
| |
| deptKeys.forEach((key, idx) => { |
| const val = item.values[key]; |
| const valDisplay = (val === null) ? '<span class="text-slate-300">-</span>' : val.toFixed(2); |
| |
| let cellBg = ""; |
| if (idx === 0) cellBg = "bg-blue-50/20"; |
| |
| let scoreColor = "text-slate-700"; |
| if (val >= 4.5 && !item.isCategory && val !== null) { |
| scoreColor = "text-emerald-600 font-semibold"; |
| } else if (val < 3.5 && val !== null && val > 0 && !item.isCategory) { |
| scoreColor = "text-amber-600 font-semibold"; |
| } else if (val === 0 && val !== null && !item.isCategory) { |
| scoreColor = "text-rose-500 font-semibold"; |
| } |
| |
| rowHTML += `<td class="py-3 px-3 text-center ${cellBg} ${scoreColor}">${valDisplay}</td>`; |
| }); |
| |
| row.innerHTML = rowHTML; |
| tbody.appendChild(row); |
| }); |
| } |
| |
| |
| function populateIndicatorDropdown() { |
| const groupVal = document.getElementById('group-filter').value; |
| const indSelect = document.getElementById('indicator-filter'); |
| |
| |
| indSelect.innerHTML = '<option value="all">-- แสดงผลเปรียบเทียบทุกตัวชี้วัดตามด้านที่เลือก --</option>'; |
| |
| |
| const filtered = dataset.filter(item => { |
| if (item.isCategory) return false; |
| if (groupVal === 'all') return true; |
| return item.parent === groupVal; |
| }); |
| |
| filtered.forEach(item => { |
| const opt = document.createElement('option'); |
| opt.value = item.id; |
| opt.textContent = item.text; |
| indSelect.appendChild(opt); |
| }); |
| } |
| |
| |
| function updateDashboard() { |
| const groupVal = document.getElementById('group-filter').value; |
| const indVal = document.getElementById('indicator-filter').value; |
| |
| let targetIndicators = []; |
| let chartModeLabel = ""; |
| |
| |
| if (indVal !== 'all') { |
| |
| const match = dataset.find(x => x.id === indVal); |
| if (match) targetIndicators.push(match); |
| chartModeLabel = `ตัวชี้วัดรายข้อ: ${indVal}`; |
| } else { |
| |
| targetIndicators = dataset.filter(item => { |
| if (item.isCategory) return false; |
| if (groupVal === 'all') return true; |
| return item.parent === groupVal; |
| }); |
| |
| if (groupVal === 'all') { |
| chartModeLabel = "ทุกมิติตัวชี้วัด (เฉลี่ยร่วม)"; |
| } else { |
| chartModeLabel = `ทุกข้อในมิติที่ ${groupVal}`; |
| } |
| } |
| |
| |
| calculateSummaryAndMetrics(targetIndicators); |
| |
| |
| renderChart(targetIndicators, chartModeLabel); |
| } |
| |
| |
| function calculateSummaryAndMetrics(indicators) { |
| if (indicators.length === 0) return; |
| |
| let deptSums = {}; |
| let deptCounts = {}; |
| |
| |
| deptKeys.forEach(k => { |
| deptSums[k] = 0; |
| deptCounts[k] = 0; |
| }); |
| |
| let totalValidScoreSum = 0; |
| let totalValidCount = 0; |
| let targetSuccessCount = 0; |
| let targetTotalChecked = 0; |
| |
| indicators.forEach(ind => { |
| deptKeys.forEach(k => { |
| const val = ind.values[k]; |
| if (val !== null) { |
| deptSums[k] += val; |
| deptCounts[k] += 1; |
| |
| totalValidScoreSum += val; |
| totalValidCount += 1; |
| |
| |
| targetTotalChecked += 1; |
| if (val >= 4.0) { |
| targetSuccessCount += 1; |
| } |
| } |
| }); |
| }); |
| |
| |
| const overallAvg = totalValidCount > 0 ? (totalValidScoreSum / totalValidCount) : 0; |
| document.getElementById('overall-average').textContent = `${overallAvg.toFixed(2)} / 5.00`; |
| document.getElementById('indicator-count').textContent = `${indicators.length} รายการ`; |
| |
| |
| const successPct = targetTotalChecked > 0 ? Math.round((targetSuccessCount / targetTotalChecked) * 100) : 0; |
| document.getElementById('success-pct').textContent = `${successPct}%`; |
| document.getElementById('target-progress-bar').style.width = `${successPct}%`; |
| |
| |
| let bestDept = "-"; |
| let bestScore = -1; |
| let worstDept = "-"; |
| let worstScore = 999; |
| |
| deptKeys.forEach((k, idx) => { |
| const count = deptCounts[k]; |
| if (count > 0) { |
| const avg = deptSums[k] / count; |
| |
| if (avg > bestScore) { |
| bestScore = avg; |
| bestDept = deptLabels[idx]; |
| } |
| if (avg < worstScore) { |
| worstScore = avg; |
| worstDept = deptLabels[idx]; |
| } |
| } |
| }); |
| |
| |
| document.getElementById('top-dept').textContent = bestDept; |
| document.getElementById('top-score').textContent = bestScore >= 0 ? `${bestScore.toFixed(2)} / 5.00` : "0.00 / 5.00"; |
| |
| document.getElementById('low-dept').textContent = worstDept; |
| document.getElementById('low-score').textContent = worstScore < 999 ? `${worstScore.toFixed(2)} / 5.00` : "0.00 / 5.00"; |
| } |
| |
| |
| function renderChart(indicators, modeLabel) { |
| document.getElementById('chart-mode-tag').textContent = modeLabel; |
| |
| |
| const chartDataValues = deptKeys.map(k => { |
| let sum = 0; |
| let count = 0; |
| indicators.forEach(ind => { |
| const val = ind.values[k]; |
| if (val !== null) { |
| sum += val; |
| count += 1; |
| } |
| }); |
| return count > 0 ? parseFloat((sum / count).toFixed(2)) : 0; |
| }); |
| |
| const ctx = document.getElementById('indicatorChart').getContext('2d'); |
| |
| if (myChart) { |
| myChart.destroy(); |
| } |
| |
| myChart = new Chart(ctx, { |
| type: 'bar', |
| data: { |
| labels: deptLabels, |
| datasets: [{ |
| label: 'คะแนนเฉลี่ยประเมิน (เต็ม 5)', |
| data: chartDataValues, |
| backgroundColor: deptColors, |
| borderColor: deptBorders, |
| borderWidth: 1.5, |
| borderRadius: 6, |
| maxBarThickness: 45 |
| }] |
| }, |
| options: { |
| responsive: true, |
| maintainAspectRatio: false, |
| plugins: { |
| legend: { |
| display: false |
| }, |
| tooltip: { |
| callbacks: { |
| label: function(context) { |
| return ` คะแนนเฉลี่ย: ${context.parsed.y} / 5.00`; |
| } |
| } |
| } |
| }, |
| scales: { |
| y: { |
| min: 0, |
| max: 5, |
| ticks: { |
| stepSize: 1 |
| }, |
| grid: { |
| color: 'rgba(226, 232, 240, 0.6)' |
| } |
| }, |
| x: { |
| grid: { |
| display: false |
| } |
| } |
| } |
| } |
| }); |
| } |
| |
| |
| function resetFilters() { |
| document.getElementById('group-filter').value = 'all'; |
| populateIndicatorDropdown(); |
| document.getElementById('indicator-filter').value = 'all'; |
| updateDashboard(); |
| } |
| </script> |
| </body> |
| </html> |