外師課表
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>瑞平國小雙語教師課表系統 | Rueiping ES Bilingual Teacher Schedule</title>
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- Google Fonts -->
<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=Noto+Sans+TC:wght@300;400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
brand: {
50: '#f0f7ff',
100: '#e0effe',
500: '#2563eb',
600: '#1d4ed8',
700: '#1e40af',
900: '#1e3a8a',
},
stone: {
50: '#fbfbfa',
100: '#f5f5f4',
200: '#e7e5e4',
800: '#292524',
},
amber: {
50: '#fffbeb',
100: '#fef3c7',
800: '#92400e',
},
teal: {
50: '#f0fdfa',
600: '#0d9488',
700: '#0f766e',
}
},
fontFamily: {
sans: ['"Plus Jakarta Sans"', '"Noto Sans TC"', 'sans-serif'],
}
}
}
}
</script>
<style>
/* Custom chart container strict constraints */
.chart-container {
position: relative;
width: 100%;
max-width: 600px;
margin-left: auto;
margin-right: auto;
height: 300px;
max-height: 380px;
}
@media (min-width: 768px) {
.chart-container {
height: 340px;
}
}
@media print {
.no-print { display: none !important; }
.print-only { display: block !important; }
body { background: white !important; color: black !important; }
.shadow-lg, .shadow-md, .shadow-sm { box-shadow: none !important; }
}
</style>
</head>
<!-- Chosen Palette: Warm Neutral & Indigo Accent (Warm stone gray background #fbfbfa, clean indigo #2563eb main buttons/accents, soft teal/amber tags) -->
<!-- Application Structure Plan:
1. Header Banner: School title, semester tag, view switcher (Chris/Theol/All), search bar & print action.
2. Quick Stats Dashboard: KPI cards showing total teaching periods, prep sessions, active days, class types.
3. Main Timetable Matrix: Interactive grid showing P1-P8 & Noon break with clear bilingual tags, color coded by class type (Lab, English, School-based, Prep, Kindergarten).
4. Interactive Analytics Section: Chart.js visualization of Workload Distribution (Teaching vs Prep) and Course Category Breakdown.
5. Bilingual Glossary Tool: Searchable reference table for school terms and grade titles.
6. Detail Modal: Click on any period card to open a full context breakdown card.
Rationale: Allows administrators, foreign teachers, and co-teachers to effortlessly inspect weekly flow, filter by specific teacher or day, and export printouts cleanly.
-->
<!-- Visualization & Content Choices:
- Workload Comparison: Chart.js Bar Chart (Canvas) -> Compares Teaching vs Prep periods for each teacher -> Interaction: Hover tooltips -> Justification: Clear quantitative comparison.
- Course Category Distribution: Chart.js Doughnut Chart (Canvas) -> Visualizes proportions of Lab, General English, School-Based, Prep -> Interaction: Legend toggle -> Justification: Helps analyze curriculum focus.
- Interactive Timetable Grid: HTML Grid + Tailwind + JS filtering -> Filter by Teacher, Day, Search Keyword -> Justification: Responsive and immediate visual feedback.
- NO SVG graphics used. NO Mermaid JS used.
-->
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
<body class="bg-stone-50 font-sans text-stone-800 antialiased min-h-screen flex flex-col">
<!-- Header Section -->
<header class="bg-white border-b border-stone-200 sticky top-0 z-30 shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div>
<div class="flex items-center gap-2 text-xs font-semibold tracking-wider text-brand-600 uppercase">
<span class="inline-block w-2 h-2 rounded-full bg-brand-600"></span>
新北市林口區瑞平國民小學 • Linkou Dist., New Taipei City
</div>
<h1 class="text-xl sm:text-2xl font-bold text-stone-900 mt-1">
115學年度第1學期 外籍/雙語教師課表
</h1>
<p class="text-xs sm:text-sm text-stone-500">
115th Academic Year, 1st Semester Foreign & Bilingual Teacher Timetable
</p>
</div>
<!-- Navigation & Action Buttons -->
<div class="flex flex-wrap items-center gap-2 no-print">
<div class="bg-stone-100 p-1 rounded-lg flex items-center border border-stone-200">
<button id="btn-view-all" onclick="setTeacherFilter('all')" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm">
全體雙語教師 (All)
</button>
<button id="btn-view-chris" onclick="setTeacherFilter('chris')" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-stone-600 hover:text-stone-900">
白德華 (Chris)
</button>
<button id="btn-view-theol" onclick="setTeacherFilter('theol')" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-stone-600 hover:text-stone-900">
丁國盛 (Theol)
</button>
</div>
<button onclick="window.print()" class="px-3 py-2 text-xs font-medium bg-stone-900 hover:bg-stone-800 text-white rounded-lg transition-colors flex items-center gap-1.5">
<span>🖨️</span> 列印 / 印表 (Print)
</button>
</div>
</div>
</div>
</header>
<!-- Main Content Container -->
<main class="flex-grow max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-6 space-y-8">
<!-- Intro Banner & Section Description -->
<section class="bg-white rounded-2xl p-5 sm:p-6 border border-stone-200 shadow-sm">
<div class="flex flex-col md:flex-row gap-6 items-start justify-between">
<div class="space-y-2 max-w-3xl">
<h2 class="text-lg font-bold text-stone-900 flex items-center gap-2">
<span>🗓️</span> 雙語教學課表互動探索中心 (Interactive Timetable Center)
</h2>
<p class="text-sm text-stone-600 leading-relaxed">
本系統旨在整合瑞平國小雙語及外籍教師之課程規劃。您可以透過頂部切換檢視特定教師之單獨課表,或使用下方搜尋框依據「年級」、「科目」或「節次」進行動態篩選。點擊任意課堂區塊即可調閱完整雙語課程說明與教學備註。
</p>
<p class="text-xs text-stone-500">
This system translates and visualizes weekly course schedules for bilingual and foreign teaching staff. Click any period block to view detailed class information or use search filters to locate specific grade classes.
</p>
</div>
<!-- Search Box -->
<div class="w-full md:w-72 no-print">
<label for="search-input" class="block text-xs font-medium text-stone-600 mb-1">搜尋課程 / Search Keyword</label>
<div class="relative">
<input type="text" id="search-input" onkeyup="handleSearch()" placeholder="輸入 5甲, 英語, 備課..." class="w-full pl-8 pr-3 py-2 text-sm bg-stone-50 border border-stone-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 focus:bg-white transition-all">
<span class="absolute left-2.5 top-2.5 text-xs text-stone-400">🔍</span>
</div>
</div>
</div>
<!-- Quick Metrics Grid -->
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 mt-6 pt-6 border-t border-stone-100">
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">總授課節次 / Total Teaching</span>
<span id="metric-teaching" class="text-xl font-bold text-brand-600 mt-0.5 block">21 節</span>
</div>
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">課程準備節次 / Prep Hours</span>
<span id="metric-prep" class="text-xl font-bold text-amber-800 mt-0.5 block">7 節</span>
</div>
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">主要授課天數 / Active Days</span>
<span id="metric-days" class="text-xl font-bold text-teal-700 mt-0.5 block">週三 ~ 週五</span>
</div>
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">涵蓋學階 / Grade Levels</span>
<span class="text-xl font-bold text-stone-800 mt-0.5 block">幼兒園 - 6年級</span>
</div>
</div>
</section>
<!-- Timetable Section -->
<section class="bg-white rounded-2xl border border-stone-200 shadow-sm overflow-hidden">
<div class="p-4 sm:p-5 border-b border-stone-200 bg-stone-50/50 flex flex-wrap items-center justify-between gap-3">
<div class="flex items-center gap-3">
<h3 id="current-view-title" class="font-bold text-stone-900 text-base sm:text-lg">
全體雙語教師綜合課表 (Master Timetable)
</h3>
<span id="teacher-badge" class="px-2.5 py-0.5 text-xs font-semibold bg-brand-50 text-brand-700 rounded-full border border-brand-100">
2 位雙語/外籍教師
</span>
</div>
<!-- Legend -->
<div class="flex flex-wrap items-center gap-2 text-xs no-print">
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-blue-100 border border-blue-300"></span> 英語實驗班</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-teal-100 border border-teal-300"></span> 正規英語課</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-purple-100 border border-purple-300"></span> 校本課程</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-amber-100 border border-amber-300"></span> 課後/幼兒園</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-gray-100 border border-gray-300"></span> 課程準備</span>
</div>
</div>
<!-- Interactive Matrix Table -->
<div class="overflow-x-auto">
<table class="w-full text-left border-collapse min-w-[700px]">
<thead>
<tr class="bg-stone-100/80 text-stone-700 text-xs font-semibold uppercase tracking-wider border-b border-stone-200">
<th class="py-3 px-4 w-32 border-r border-stone-200">節次 \ 時間<br><span class="text-[10px] font-normal text-stone-500">Period \ Time</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期一<br><span class="text-[10px] font-normal text-stone-500">Monday</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期二<br><span class="text-[10px] font-normal text-stone-500">Tuesday</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期三<br><span class="text-[10px] font-normal text-stone-500">Wednesday</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期四<br><span class="text-[10px] font-normal text-stone-500">Thursday</span></th>
<th class="py-3 px-3 w-1/5">星期五<br><span class="text-[10px] font-normal text-stone-500">Friday</span></th>
</tr>
</thead>
<tbody id="timetable-body" class="divide-y divide-stone-200 text-sm">
<!-- Dynamic timetable content loaded by JavaScript -->
</tbody>
</table>
</div>
</section>
<!-- Workload Analytics & Subject Visualizations -->
<section class="space-y-4">
<div class="bg-white rounded-2xl p-5 border border-stone-200 shadow-sm">
<h3 class="text-base sm:text-lg font-bold text-stone-900 mb-1 flex items-center gap-2">
<span>📊</span> 教學配課與工作量數據分析 (Teaching Workload Analytics)
</h3>
<p class="text-xs sm:text-sm text-stone-600 mb-6">
此區塊提供雙語師資教學時數分配圖表。包含授課與備課比例分析,以及各年級與專案課程的資源投入分佈,協助教學團隊進行課務管理與協同檢討。
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Chart 1: Workload Comparison -->
<div class="bg-stone-50 p-4 rounded-xl border border-stone-200 flex flex-col items-center">
<h4 class="text-xs sm:text-sm font-bold text-stone-800 mb-3 text-center">
教師授課與備課節次比較 (Teaching vs Lesson Prep)
</h4>
<div class="chart-container">
<canvas id="chart-workload"></canvas>
</div>
<span class="text-[11px] text-stone-500 mt-2">單位:每週節次 (Periods per week)</span>
</div>
<!-- Chart 2: Course Category Breakdown -->
<div class="bg-stone-50 p-4 rounded-xl border border-stone-200 flex flex-col items-center">
<h4 class="text-xs sm:text-sm font-bold text-stone-800 mb-3 text-center">
雙語課程類型分佈 (Course Category Distribution)
</h4>
<div class="chart-container">
<canvas id="chart-categories"></canvas>
</div>
<span class="text-[11px] text-stone-500 mt-2">含實驗班、校本課程、課後班與幼兒園</span>
</div>
</div>
</div>
</section>
<!-- Bilingual Terminology Reference Matrix -->
<section class="bg-white rounded-2xl p-5 sm:p-6 border border-stone-200 shadow-sm">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4">
<div>
<h3 class="text-base sm:text-lg font-bold text-stone-900 flex items-center gap-2">
<span>📖</span> 雙語課表名詞對照與說明 (Bilingual Reference Dictionary)
</h3>
<p class="text-xs sm:text-sm text-stone-500">
方便外籍教師、雙語協同教師及家長迅速了解課表專業詞彙。
</p>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full text-left text-xs sm:text-sm border-collapse">
<thead>
<tr class="bg-stone-100 text-stone-700 font-semibold border-b border-stone-200">
<th class="p-3">中文名稱 (Chinese)</th>
<th class="p-3">英文翻譯 (English Translation)</th>
<th class="p-3">適用對象 / 說明 (Description & Target)</th>
</tr>
</thead>
<tbody class="divide-y divide-stone-100 text-stone-600">
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">高年級英語實驗班</td>
<td class="p-3 text-brand-700">Senior Grade English Experimental Class (Lab)</td>
<td class="p-3">國小 5-6 年級延伸深耕英語實驗課程</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">中年級英語實驗班</td>
<td class="p-3 text-brand-700">Middle Grade English Experimental Class (Lab)</td>
<td class="p-3">國小 3-4 年級雙語聽說實驗體驗課程</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">課後班英語</td>
<td class="p-3 text-brand-700">After-School English Enrichment</td>
<td class="p-3">低年級 (1甲/2甲) 課後照顧英語活化輔導</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">校本課程 / 校本</td>
<td class="p-3 text-brand-700">School-Based Curriculum (SBC)</td>
<td class="p-3">結合林口瑞平在地特色發展之跨領域課程</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">課程準備</td>
<td class="p-3 text-brand-700">Lesson Preparation & Planning</td>
<td class="p-3">教師研討、教具製作、教材編撰與備課時段</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">幼兒園</td>
<td class="p-3 text-brand-700">Kindergarten / Preschool English Time</td>
<td class="p-3">學前教育階段英語故事與遊戲互動體驗</td>
</tr>
</tbody>
</table>
</div>
</section>
</main>
<!-- Detail Drawer / Modal -->
<div id="detail-modal" class="fixed inset-0 bg-stone-900/40 backdrop-blur-sm z-50 flex items-center justify-center p-4 hidden no-print" onclick="closeModal(event)">
<div class="bg-white rounded-2xl max-w-lg w-full p-6 shadow-xl border border-stone-200 transform transition-all" onclick="event.stopPropagation()">
<div class="flex items-start justify-between border-b border-stone-100 pb-3 mb-4">
<div>
<span id="modal-period-tag" class="text-xs font-semibold px-2 py-0.5 rounded bg-brand-50 text-brand-700">第 5 節 (13:00-13:40)</span>
<h3 id="modal-title" class="text-lg font-bold text-stone-900 mt-1">課程名稱</h3>
</div>
<button onclick="closeModalDirect()" class="text-stone-400 hover:text-stone-600 text-xl font-bold p-1">✕</button>
</div>
<div class="space-y-3 text-sm text-stone-600">
<div class="flex justify-between py-1 border-b border-stone-100">
<span class="font-medium text-stone-500">授課教師 (Teacher):</span>
<span id="modal-teacher" class="font-semibold text-stone-800">-</span>
</div>
<div class="flex justify-between py-1 border-b border-stone-100">
<span class="font-medium text-stone-500">授課對象 (Class/Grade):</span>
<span id="modal-grade" class="font-semibold text-stone-800">-</span>
</div>
<div class="flex justify-between py-1 border-b border-stone-100">
<span class="font-medium text-stone-500">課程屬性 (Category):</span>
<span id="modal-category" class="font-semibold text-stone-800">-</span>
</div>
<div class="pt-2">
<span class="font-medium text-stone-500 block mb-1">課堂簡介與教學目標 (Note):</span>
<p id="modal-desc" class="bg-stone-50 p-3 rounded-lg border border-stone-200 text-xs leading-relaxed text-stone-700">
無詳細備註
</p>
</div>
</div>
<div class="mt-6 flex justify-end">
<button onclick="closeModalDirect()" class="px-4 py-2 bg-stone-900 text-white text-xs font-medium rounded-lg hover:bg-stone-800 transition-colors">
關閉 (Close)
</button>
</div>
</div>
</div>
<!-- Footer -->
<footer class="bg-white border-t border-stone-200 py-6 mt-12 text-center text-xs text-stone-500">
<div class="max-w-7xl mx-auto px-4">
<p>新北市林口區瑞平國民小學 雙語教育推動小組 編製 • Rueiping Elementary School Bilingual Team</p>
<p class="mt-1 text-stone-400">系統時間:115學年度第1學期 • System Version 2.0 (Interactive)</p>
</div>
</footer>
<!-- JavaScript Logic -->
<script>
// Data Structure
const periodsData = [
{ id: 'p1', name: '第 1 節', time: '08:35 - 09:15' },
{ id: 'p2', name: '第 2 節', time: '09:25 - 10:05' },
{ id: 'p3', name: '第 3 節', time: '10:20 - 11:00' },
{ id: 'p4', name: '第 4 節', time: '11:10 - 11:50' },
{ id: 'noon', name: '午間時段', time: '11:50 - 12:50' },
{ id: 'p5', name: '第 5 節', time: '13:00 - 13:40' },
{ id: 'p6', name: '第 6 節', time: '13:50 - 14:30' },
{ id: 'p7', name: '第 7 節', time: '14:50 - 15:30' },
{ id: 'p8', name: '第 8 節', time: '15:40 - 16:20' }
];
// Master Schedule Entries
const scheduleEntries = [
// Chris Payk
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'noon', title: '幼兒園', enTitle: 'Kindergarten English', category: 'kindergarten', grade: '幼兒園', desc: '幼兒園雙語主題沉浸與帶動唱活動' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p5', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p6', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p7', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p8', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p5', title: '1甲 課後班英語', enTitle: 'Class 1A After-School English', category: 'afterschool', grade: '1甲', desc: '一年級課後英語生活美語引導' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p6', title: '1甲 課後班英語', enTitle: 'Class 1A After-School English', category: 'afterschool', grade: '1甲', desc: '一年級課後英語生活美語引導' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p7', title: '2甲 課後班英語', enTitle: 'Class 2A After-School English', category: 'afterschool', grade: '2甲', desc: '二年級課後英語繪本導讀與互動' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p8', title: '2甲 課後班英語', enTitle: 'Class 2A After-School English', category: 'afterschool', grade: '2甲', desc: '二年級課後英語繪本導讀與互動' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p5', title: '中年級英語實驗班', enTitle: 'Middle Grade English Lab', category: 'lab', grade: '中年級 (3-4年級)', desc: '中年級英語實驗班,遊戲化教學與日常生活對話' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p6', title: '中年級英語實驗班', enTitle: 'Middle Grade English Lab', category: 'lab', grade: '中年級 (3-4年級)', desc: '中年級英語實驗班,遊戲化教學與日常生活對話' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p7', title: '中年級英語實驗班', enTitle: 'Middle Grade English Lab', category: 'lab', grade: '中年級 (3-4年級)', desc: '中年級英語實驗班,遊戲化教學與日常生活對話' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p8', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '課堂教具準備、實驗課程教案修訂與成績評量' },
// Dinh Quoc Thinh (Theol)
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p1', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '英語教學準備、教案設計與跨領域課程討論' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p2', title: '5甲 英語', enTitle: 'Class 5A English', category: 'english', grade: '5甲', desc: '五年級正規英語課程教學' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p3', title: '2甲 校本課程', enTitle: 'Class 2A School-Based', category: 'schoolbound', grade: '2甲', desc: '二年級校本特色雙語融合課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p4', title: '4甲 英語', enTitle: 'Class 4A English', category: 'english', grade: '4甲', desc: '四年級正規英語課程教學' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p5', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學媒體製作與學習單設計' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p6', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學媒體製作與學習單設計' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p1', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '跨領域雙語教學備課' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p2', title: '3甲 校本課程', enTitle: 'Class 3A School-Based', category: 'schoolbound', grade: '3甲', desc: '三年級校本特色雙語融合課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p3', title: '1甲 校本課程', enTitle: 'Class 1A School-Based', category: 'schoolbound', grade: '1甲', desc: '一年級校本特色雙語探究課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p4', title: '6甲 英語', enTitle: 'Class 6A English', category: 'english', grade: '6甲', desc: '六年級正規英語課程教學' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p5', title: '4甲 校本課程', enTitle: 'Class 4A School-Based', category: 'schoolbound', grade: '4甲', desc: '四年級校本特色雙語融合課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p6', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學共同備課與檢討' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p7', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學研討與班級學習記錄整理' }
];
let currentFilter = 'all'; // 'all', 'chris', 'theol'
let searchQuery = '';
// Category Styles Mapping
const categoryStyles = {
lab: { bg: 'bg-blue-50 hover:bg-blue-100 border-blue-200 text-blue-900', badge: 'bg-blue-200 text-blue-800' },
english: { bg: 'bg-teal-50 hover:bg-teal-100 border-teal-200 text-teal-900', badge: 'bg-teal-200 text-teal-800' },
schoolbound: { bg: 'bg-purple-50 hover:bg-purple-100 border-purple-200 text-purple-900', badge: 'bg-purple-200 text-purple-800' },
afterschool: { bg: 'bg-amber-50 hover:bg-amber-100 border-amber-200 text-amber-900', badge: 'bg-amber-200 text-amber-800' },
kindergarten: { bg: 'bg-emerald-50 hover:bg-emerald-100 border-emerald-200 text-emerald-900', badge: 'bg-emerald-200 text-emerald-800' },
prep: { bg: 'bg-gray-50 hover:bg-gray-100 border-gray-200 text-stone-700', badge: 'bg-gray-200 text-stone-700' }
};
// Render Timetable Grid
function renderTimetable() {
const tbody = document.getElementById('timetable-body');
tbody.innerHTML = '';
periodsData.forEach(p => {
const tr = document.createElement('tr');
tr.className = p.id === 'noon' ? 'bg-amber-50/40 border-y-2 border-amber-200' : 'hover:bg-stone-50/50';
// Period Header Cell
let periodHtml = `
<td class="py-3 px-4 border-r border-stone-200 font-medium text-xs">
<span class="text-stone-900 font-bold block">${p.name}</span>
<span class="text-[11px] text-stone-500 block">${p.time}</span>
</td>
`;
// Days 1 to 5 (Mon to Fri)
for (let day = 1; day <= 5; day++) {
const matches = scheduleEntries.filter(entry => {
const matchTeacher = (currentFilter === 'all') || (entry.teacher === currentFilter);
const matchDay = entry.day === day;
const matchPeriod = entry.period === p.id;
const matchSearch = searchQuery === '' ||
entry.title.toLowerCase().includes(searchQuery) ||
entry.enTitle.toLowerCase().includes(searchQuery) ||
entry.teacherName.toLowerCase().includes(searchQuery) ||
entry.grade.toLowerCase().includes(searchQuery);
return matchTeacher && matchDay && matchPeriod && matchSearch;
});
periodHtml += `<td class="p-2 border-r border-stone-200 align-top h-20">`;
if (matches.length > 0) {
matches.forEach(m => {
const style = categoryStyles[m.category] || categoryStyles.prep;
periodHtml += `
<div onclick="openModal('${encodeURIComponent(JSON.stringify(m))}', '${p.name} ${p.time}')"
class="p-2 rounded-lg border ${style.bg} cursor-pointer transition-all shadow-sm hover:shadow mb-1.5 group">
<div class="flex items-center justify-between gap-1 mb-1">
<span class="font-bold text-xs truncate">${m.title}</span>
</div>
<div class="text-[10px] opacity-80 truncate">${m.enTitle}</div>
<div class="mt-1.5 flex items-center justify-between text-[10px]">
<span class="px-1.5 py-0.5 rounded ${style.badge} font-semibold">
${m.teacher === 'chris' ? 'Chris' : 'Theol'}
</span>
<span class="text-stone-500 group-hover:text-stone-800 font-medium">${m.grade}</span>
</div>
</div>
`;
});
} else {
periodHtml += `<div class="h-full flex items-center justify-center text-[11px] text-stone-300 font-light">—</div>`;
}
periodHtml += `</td>`;
}
tr.innerHTML = periodHtml;
tbody.appendChild(tr);
});
updateMetrics();
}
// Set Teacher Filter
function setTeacherFilter(teacher) {
currentFilter = teacher;
// Toggle active classes on buttons
const btnAll = document.getElementById('btn-view-all');
const btnChris = document.getElementById('btn-view-chris');
const btnTheol = document.getElementById('btn-view-theol');
const title = document.getElementById('current-view-title');
const badge = document.getElementById('teacher-badge');
[btnAll, btnChris, btnTheol].forEach(b => {
b.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all text-stone-600 hover:text-stone-900";
});
if (teacher === 'all') {
btnAll.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm";
title.innerText = "全體雙語教師綜合課表 (Master Timetable)";
badge.innerText = "2 位雙語/外籍教師";
} else if (teacher === 'chris') {
btnChris.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm";
title.innerText = "白德華 老師課表 (Teacher Payk Christopher)";
badge.innerText = "外籍英語教師 (Teacher Chris)";
} else if (teacher === 'theol') {
btnTheol.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm";
title.innerText = "丁國盛 老師課表 (Teacher Dinh Quoc Thinh)";
badge.innerText = "雙語教學教師 (Teacher Theol)";
}
renderTimetable();
}
// Handle Search Input
function handleSearch() {
const input = document.getElementById('search-input');
searchQuery = input.value.trim().toLowerCase();
renderTimetable();
}
// Update Dynamic Metrics
function updateMetrics() {
let filtered = scheduleEntries;
if (currentFilter !== 'all') {
filtered = scheduleEntries.filter(e => e.teacher === currentFilter);
}
const teachingCount = filtered.filter(e => e.category !== 'prep').length;
const prepCount = filtered.filter(e => e.category === 'prep').length;
document.getElementById('metric-teaching').innerText = `${teachingCount} 節`;
document.getElementById('metric-prep').innerText = `${prepCount} 節`;
if (currentFilter === 'chris') {
document.getElementById('metric-days').innerText = "週三 ~ 週五 (Wed-Fri)";
} else if (currentFilter === 'theol') {
document.getElementById('metric-days').innerText = "週三 ~ 週四 (Wed-Thu)";
} else {
document.getElementById('metric-days').innerText = "週三 ~ 週五 (Wed-Fri)";
}
}
// Modal Control Functions
function openModal(dataStr, periodInfo) {
const data = JSON.parse(decodeURIComponent(dataStr));
document.getElementById('modal-period-tag').innerText = periodInfo;
document.getElementById('modal-title').innerText = `${data.title} (${data.enTitle})`;
document.getElementById('modal-teacher').innerText = data.teacherName;
document.getElementById('modal-grade').innerText = data.grade;
const catMap = {
lab: '英語實驗班 (Experimental Class)',
english: '正規英語課 (General English)',
schoolbound: '校本特色課程 (School-Based)',
afterschool: '課後班英語 (After-School Enrichment)',
kindergarten: '幼兒園活動 (Kindergarten)',
prep: '課程準備時段 (Lesson Prep)'
};
document.getElementById('modal-category').innerText = catMap[data.category] || data.category;
document.getElementById('modal-desc').innerText = data.desc;
document.getElementById('detail-modal').classList.remove('hidden');
}
function closeModal(event) {
if (event.target.id === 'detail-modal') {
document.getElementById('detail-modal').classList.add('hidden');
}
}
function closeModalDirect() {
document.getElementById('detail-modal').classList.add('hidden');
}
// Initialize Charts with Chart.js
let workloadChart, categoriesChart;
function initCharts() {
// Chart 1: Workload Comparison
const ctx1 = document.getElementById('chart-workload').getContext('2d');
workloadChart = new Chart(ctx1, {
type: 'bar',
data: {
labels: ['白德華 (Chris)', '丁國盛 (Theol)'],
datasets: [
{
label: '授課節次 (Teaching)',
data: [12, 6],
backgroundColor: '#2563eb',
borderRadius: 6
},
{
label: '課程準備 (Lesson Prep)',
data: [1, 6],
backgroundColor: '#93c5fd',
borderRadius: 6
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'bottom' },
tooltip: {
callbacks: {
label: function(context) {
return `${context.dataset.label}: ${context.raw} 節`;
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: { stepSize: 2 }
}
}
}
});
// Chart 2: Course Category Breakdown
const ctx2 = document.getElementById('chart-categories').getContext('2d');
categoriesChart = new Chart(ctx2, {
type: 'doughnut',
data: {
labels: [
'英語實驗班 (Lab)',
'正規英語課 (English)',
'校本課程 (School-Based)',
'課後英語 (After-School)',
'幼兒園 (Preschool)',
'課程準備 (Prep)'
],
datasets: [{
data: [7, 3, 4, 4, 1, 7],
backgroundColor: [
'#3b82f6', // Lab
'#0d9488', // English
'#a855f7', // Schoolbound
'#f59e0b', // Afterschool
'#10b981', // Kindergarten
'#9ca3af' // Prep
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'bottom', labels: { boxWidth: 12, font: { size: 11 } } },
tooltip: {
callbacks: {
label: function(context) {
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const val = context.raw;
const pct = ((val / total) * 100).toFixed(1);
return `${context.label}: ${val} 節 (${pct}%)`;
}
}
}
}
}
});
}
// Page Load Init
window.addEventListener('DOMContentLoaded', () => {
renderTimetable();
initCharts();
});
</script>
</body>
</html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>瑞平國小雙語教師課表系統 | Rueiping ES Bilingual Teacher Schedule</title>
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- Google Fonts -->
<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=Noto+Sans+TC:wght@300;400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
brand: {
50: '#f0f7ff',
100: '#e0effe',
500: '#2563eb',
600: '#1d4ed8',
700: '#1e40af',
900: '#1e3a8a',
},
stone: {
50: '#fbfbfa',
100: '#f5f5f4',
200: '#e7e5e4',
800: '#292524',
},
amber: {
50: '#fffbeb',
100: '#fef3c7',
800: '#92400e',
},
teal: {
50: '#f0fdfa',
600: '#0d9488',
700: '#0f766e',
}
},
fontFamily: {
sans: ['"Plus Jakarta Sans"', '"Noto Sans TC"', 'sans-serif'],
}
}
}
}
</script>
<style>
/* Custom chart container strict constraints */
.chart-container {
position: relative;
width: 100%;
max-width: 600px;
margin-left: auto;
margin-right: auto;
height: 300px;
max-height: 380px;
}
@media (min-width: 768px) {
.chart-container {
height: 340px;
}
}
@media print {
.no-print { display: none !important; }
.print-only { display: block !important; }
body { background: white !important; color: black !important; }
.shadow-lg, .shadow-md, .shadow-sm { box-shadow: none !important; }
}
</style>
</head>
<!-- Chosen Palette: Warm Neutral & Indigo Accent (Warm stone gray background #fbfbfa, clean indigo #2563eb main buttons/accents, soft teal/amber tags) -->
<!-- Application Structure Plan:
1. Header Banner: School title, semester tag, view switcher (Chris/Theol/All), search bar & print action.
2. Quick Stats Dashboard: KPI cards showing total teaching periods, prep sessions, active days, class types.
3. Main Timetable Matrix: Interactive grid showing P1-P8 & Noon break with clear bilingual tags, color coded by class type (Lab, English, School-based, Prep, Kindergarten).
4. Interactive Analytics Section: Chart.js visualization of Workload Distribution (Teaching vs Prep) and Course Category Breakdown.
5. Bilingual Glossary Tool: Searchable reference table for school terms and grade titles.
6. Detail Modal: Click on any period card to open a full context breakdown card.
Rationale: Allows administrators, foreign teachers, and co-teachers to effortlessly inspect weekly flow, filter by specific teacher or day, and export printouts cleanly.
-->
<!-- Visualization & Content Choices:
- Workload Comparison: Chart.js Bar Chart (Canvas) -> Compares Teaching vs Prep periods for each teacher -> Interaction: Hover tooltips -> Justification: Clear quantitative comparison.
- Course Category Distribution: Chart.js Doughnut Chart (Canvas) -> Visualizes proportions of Lab, General English, School-Based, Prep -> Interaction: Legend toggle -> Justification: Helps analyze curriculum focus.
- Interactive Timetable Grid: HTML Grid + Tailwind + JS filtering -> Filter by Teacher, Day, Search Keyword -> Justification: Responsive and immediate visual feedback.
- NO SVG graphics used. NO Mermaid JS used.
-->
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
<body class="bg-stone-50 font-sans text-stone-800 antialiased min-h-screen flex flex-col">
<!-- Header Section -->
<header class="bg-white border-b border-stone-200 sticky top-0 z-30 shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div>
<div class="flex items-center gap-2 text-xs font-semibold tracking-wider text-brand-600 uppercase">
<span class="inline-block w-2 h-2 rounded-full bg-brand-600"></span>
新北市林口區瑞平國民小學 • Linkou Dist., New Taipei City
</div>
<h1 class="text-xl sm:text-2xl font-bold text-stone-900 mt-1">
115學年度第1學期 外籍/雙語教師課表
</h1>
<p class="text-xs sm:text-sm text-stone-500">
115th Academic Year, 1st Semester Foreign & Bilingual Teacher Timetable
</p>
</div>
<!-- Navigation & Action Buttons -->
<div class="flex flex-wrap items-center gap-2 no-print">
<div class="bg-stone-100 p-1 rounded-lg flex items-center border border-stone-200">
<button id="btn-view-all" onclick="setTeacherFilter('all')" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm">
全體雙語教師 (All)
</button>
<button id="btn-view-chris" onclick="setTeacherFilter('chris')" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-stone-600 hover:text-stone-900">
白德華 (Chris)
</button>
<button id="btn-view-theol" onclick="setTeacherFilter('theol')" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-stone-600 hover:text-stone-900">
丁國盛 (Theol)
</button>
</div>
<button onclick="window.print()" class="px-3 py-2 text-xs font-medium bg-stone-900 hover:bg-stone-800 text-white rounded-lg transition-colors flex items-center gap-1.5">
<span>🖨️</span> 列印 / 印表 (Print)
</button>
</div>
</div>
</div>
</header>
<!-- Main Content Container -->
<main class="flex-grow max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-6 space-y-8">
<!-- Intro Banner & Section Description -->
<section class="bg-white rounded-2xl p-5 sm:p-6 border border-stone-200 shadow-sm">
<div class="flex flex-col md:flex-row gap-6 items-start justify-between">
<div class="space-y-2 max-w-3xl">
<h2 class="text-lg font-bold text-stone-900 flex items-center gap-2">
<span>🗓️</span> 雙語教學課表互動探索中心 (Interactive Timetable Center)
</h2>
<p class="text-sm text-stone-600 leading-relaxed">
本系統旨在整合瑞平國小雙語及外籍教師之課程規劃。您可以透過頂部切換檢視特定教師之單獨課表,或使用下方搜尋框依據「年級」、「科目」或「節次」進行動態篩選。點擊任意課堂區塊即可調閱完整雙語課程說明與教學備註。
</p>
<p class="text-xs text-stone-500">
This system translates and visualizes weekly course schedules for bilingual and foreign teaching staff. Click any period block to view detailed class information or use search filters to locate specific grade classes.
</p>
</div>
<!-- Search Box -->
<div class="w-full md:w-72 no-print">
<label for="search-input" class="block text-xs font-medium text-stone-600 mb-1">搜尋課程 / Search Keyword</label>
<div class="relative">
<input type="text" id="search-input" onkeyup="handleSearch()" placeholder="輸入 5甲, 英語, 備課..." class="w-full pl-8 pr-3 py-2 text-sm bg-stone-50 border border-stone-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 focus:bg-white transition-all">
<span class="absolute left-2.5 top-2.5 text-xs text-stone-400">🔍</span>
</div>
</div>
</div>
<!-- Quick Metrics Grid -->
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 mt-6 pt-6 border-t border-stone-100">
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">總授課節次 / Total Teaching</span>
<span id="metric-teaching" class="text-xl font-bold text-brand-600 mt-0.5 block">21 節</span>
</div>
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">課程準備節次 / Prep Hours</span>
<span id="metric-prep" class="text-xl font-bold text-amber-800 mt-0.5 block">7 節</span>
</div>
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">主要授課天數 / Active Days</span>
<span id="metric-days" class="text-xl font-bold text-teal-700 mt-0.5 block">週三 ~ 週五</span>
</div>
<div class="bg-stone-50 p-3 rounded-xl border border-stone-100">
<span class="text-xs font-medium text-stone-500 block">涵蓋學階 / Grade Levels</span>
<span class="text-xl font-bold text-stone-800 mt-0.5 block">幼兒園 - 6年級</span>
</div>
</div>
</section>
<!-- Timetable Section -->
<section class="bg-white rounded-2xl border border-stone-200 shadow-sm overflow-hidden">
<div class="p-4 sm:p-5 border-b border-stone-200 bg-stone-50/50 flex flex-wrap items-center justify-between gap-3">
<div class="flex items-center gap-3">
<h3 id="current-view-title" class="font-bold text-stone-900 text-base sm:text-lg">
全體雙語教師綜合課表 (Master Timetable)
</h3>
<span id="teacher-badge" class="px-2.5 py-0.5 text-xs font-semibold bg-brand-50 text-brand-700 rounded-full border border-brand-100">
2 位雙語/外籍教師
</span>
</div>
<!-- Legend -->
<div class="flex flex-wrap items-center gap-2 text-xs no-print">
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-blue-100 border border-blue-300"></span> 英語實驗班</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-teal-100 border border-teal-300"></span> 正規英語課</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-purple-100 border border-purple-300"></span> 校本課程</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-amber-100 border border-amber-300"></span> 課後/幼兒園</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-gray-100 border border-gray-300"></span> 課程準備</span>
</div>
</div>
<!-- Interactive Matrix Table -->
<div class="overflow-x-auto">
<table class="w-full text-left border-collapse min-w-[700px]">
<thead>
<tr class="bg-stone-100/80 text-stone-700 text-xs font-semibold uppercase tracking-wider border-b border-stone-200">
<th class="py-3 px-4 w-32 border-r border-stone-200">節次 \ 時間<br><span class="text-[10px] font-normal text-stone-500">Period \ Time</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期一<br><span class="text-[10px] font-normal text-stone-500">Monday</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期二<br><span class="text-[10px] font-normal text-stone-500">Tuesday</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期三<br><span class="text-[10px] font-normal text-stone-500">Wednesday</span></th>
<th class="py-3 px-3 w-1/5 border-r border-stone-200">星期四<br><span class="text-[10px] font-normal text-stone-500">Thursday</span></th>
<th class="py-3 px-3 w-1/5">星期五<br><span class="text-[10px] font-normal text-stone-500">Friday</span></th>
</tr>
</thead>
<tbody id="timetable-body" class="divide-y divide-stone-200 text-sm">
<!-- Dynamic timetable content loaded by JavaScript -->
</tbody>
</table>
</div>
</section>
<!-- Workload Analytics & Subject Visualizations -->
<section class="space-y-4">
<div class="bg-white rounded-2xl p-5 border border-stone-200 shadow-sm">
<h3 class="text-base sm:text-lg font-bold text-stone-900 mb-1 flex items-center gap-2">
<span>📊</span> 教學配課與工作量數據分析 (Teaching Workload Analytics)
</h3>
<p class="text-xs sm:text-sm text-stone-600 mb-6">
此區塊提供雙語師資教學時數分配圖表。包含授課與備課比例分析,以及各年級與專案課程的資源投入分佈,協助教學團隊進行課務管理與協同檢討。
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Chart 1: Workload Comparison -->
<div class="bg-stone-50 p-4 rounded-xl border border-stone-200 flex flex-col items-center">
<h4 class="text-xs sm:text-sm font-bold text-stone-800 mb-3 text-center">
教師授課與備課節次比較 (Teaching vs Lesson Prep)
</h4>
<div class="chart-container">
<canvas id="chart-workload"></canvas>
</div>
<span class="text-[11px] text-stone-500 mt-2">單位:每週節次 (Periods per week)</span>
</div>
<!-- Chart 2: Course Category Breakdown -->
<div class="bg-stone-50 p-4 rounded-xl border border-stone-200 flex flex-col items-center">
<h4 class="text-xs sm:text-sm font-bold text-stone-800 mb-3 text-center">
雙語課程類型分佈 (Course Category Distribution)
</h4>
<div class="chart-container">
<canvas id="chart-categories"></canvas>
</div>
<span class="text-[11px] text-stone-500 mt-2">含實驗班、校本課程、課後班與幼兒園</span>
</div>
</div>
</div>
</section>
<!-- Bilingual Terminology Reference Matrix -->
<section class="bg-white rounded-2xl p-5 sm:p-6 border border-stone-200 shadow-sm">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4">
<div>
<h3 class="text-base sm:text-lg font-bold text-stone-900 flex items-center gap-2">
<span>📖</span> 雙語課表名詞對照與說明 (Bilingual Reference Dictionary)
</h3>
<p class="text-xs sm:text-sm text-stone-500">
方便外籍教師、雙語協同教師及家長迅速了解課表專業詞彙。
</p>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full text-left text-xs sm:text-sm border-collapse">
<thead>
<tr class="bg-stone-100 text-stone-700 font-semibold border-b border-stone-200">
<th class="p-3">中文名稱 (Chinese)</th>
<th class="p-3">英文翻譯 (English Translation)</th>
<th class="p-3">適用對象 / 說明 (Description & Target)</th>
</tr>
</thead>
<tbody class="divide-y divide-stone-100 text-stone-600">
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">高年級英語實驗班</td>
<td class="p-3 text-brand-700">Senior Grade English Experimental Class (Lab)</td>
<td class="p-3">國小 5-6 年級延伸深耕英語實驗課程</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">中年級英語實驗班</td>
<td class="p-3 text-brand-700">Middle Grade English Experimental Class (Lab)</td>
<td class="p-3">國小 3-4 年級雙語聽說實驗體驗課程</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">課後班英語</td>
<td class="p-3 text-brand-700">After-School English Enrichment</td>
<td class="p-3">低年級 (1甲/2甲) 課後照顧英語活化輔導</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">校本課程 / 校本</td>
<td class="p-3 text-brand-700">School-Based Curriculum (SBC)</td>
<td class="p-3">結合林口瑞平在地特色發展之跨領域課程</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">課程準備</td>
<td class="p-3 text-brand-700">Lesson Preparation & Planning</td>
<td class="p-3">教師研討、教具製作、教材編撰與備課時段</td>
</tr>
<tr class="hover:bg-stone-50">
<td class="p-3 font-semibold text-stone-800">幼兒園</td>
<td class="p-3 text-brand-700">Kindergarten / Preschool English Time</td>
<td class="p-3">學前教育階段英語故事與遊戲互動體驗</td>
</tr>
</tbody>
</table>
</div>
</section>
</main>
<!-- Detail Drawer / Modal -->
<div id="detail-modal" class="fixed inset-0 bg-stone-900/40 backdrop-blur-sm z-50 flex items-center justify-center p-4 hidden no-print" onclick="closeModal(event)">
<div class="bg-white rounded-2xl max-w-lg w-full p-6 shadow-xl border border-stone-200 transform transition-all" onclick="event.stopPropagation()">
<div class="flex items-start justify-between border-b border-stone-100 pb-3 mb-4">
<div>
<span id="modal-period-tag" class="text-xs font-semibold px-2 py-0.5 rounded bg-brand-50 text-brand-700">第 5 節 (13:00-13:40)</span>
<h3 id="modal-title" class="text-lg font-bold text-stone-900 mt-1">課程名稱</h3>
</div>
<button onclick="closeModalDirect()" class="text-stone-400 hover:text-stone-600 text-xl font-bold p-1">✕</button>
</div>
<div class="space-y-3 text-sm text-stone-600">
<div class="flex justify-between py-1 border-b border-stone-100">
<span class="font-medium text-stone-500">授課教師 (Teacher):</span>
<span id="modal-teacher" class="font-semibold text-stone-800">-</span>
</div>
<div class="flex justify-between py-1 border-b border-stone-100">
<span class="font-medium text-stone-500">授課對象 (Class/Grade):</span>
<span id="modal-grade" class="font-semibold text-stone-800">-</span>
</div>
<div class="flex justify-between py-1 border-b border-stone-100">
<span class="font-medium text-stone-500">課程屬性 (Category):</span>
<span id="modal-category" class="font-semibold text-stone-800">-</span>
</div>
<div class="pt-2">
<span class="font-medium text-stone-500 block mb-1">課堂簡介與教學目標 (Note):</span>
<p id="modal-desc" class="bg-stone-50 p-3 rounded-lg border border-stone-200 text-xs leading-relaxed text-stone-700">
無詳細備註
</p>
</div>
</div>
<div class="mt-6 flex justify-end">
<button onclick="closeModalDirect()" class="px-4 py-2 bg-stone-900 text-white text-xs font-medium rounded-lg hover:bg-stone-800 transition-colors">
關閉 (Close)
</button>
</div>
</div>
</div>
<!-- Footer -->
<footer class="bg-white border-t border-stone-200 py-6 mt-12 text-center text-xs text-stone-500">
<div class="max-w-7xl mx-auto px-4">
<p>新北市林口區瑞平國民小學 雙語教育推動小組 編製 • Rueiping Elementary School Bilingual Team</p>
<p class="mt-1 text-stone-400">系統時間:115學年度第1學期 • System Version 2.0 (Interactive)</p>
</div>
</footer>
<!-- JavaScript Logic -->
<script>
// Data Structure
const periodsData = [
{ id: 'p1', name: '第 1 節', time: '08:35 - 09:15' },
{ id: 'p2', name: '第 2 節', time: '09:25 - 10:05' },
{ id: 'p3', name: '第 3 節', time: '10:20 - 11:00' },
{ id: 'p4', name: '第 4 節', time: '11:10 - 11:50' },
{ id: 'noon', name: '午間時段', time: '11:50 - 12:50' },
{ id: 'p5', name: '第 5 節', time: '13:00 - 13:40' },
{ id: 'p6', name: '第 6 節', time: '13:50 - 14:30' },
{ id: 'p7', name: '第 7 節', time: '14:50 - 15:30' },
{ id: 'p8', name: '第 8 節', time: '15:40 - 16:20' }
];
// Master Schedule Entries
const scheduleEntries = [
// Chris Payk
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'noon', title: '幼兒園', enTitle: 'Kindergarten English', category: 'kindergarten', grade: '幼兒園', desc: '幼兒園雙語主題沉浸與帶動唱活動' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p5', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p6', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p7', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 3, period: 'p8', title: '高年級英語實驗班', enTitle: 'Senior Grade English Lab', category: 'lab', grade: '高年級 (5-6年級)', desc: '高年級英語實驗課程,著重聽說與主題專題研討' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p5', title: '1甲 課後班英語', enTitle: 'Class 1A After-School English', category: 'afterschool', grade: '1甲', desc: '一年級課後英語生活美語引導' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p6', title: '1甲 課後班英語', enTitle: 'Class 1A After-School English', category: 'afterschool', grade: '1甲', desc: '一年級課後英語生活美語引導' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p7', title: '2甲 課後班英語', enTitle: 'Class 2A After-School English', category: 'afterschool', grade: '2甲', desc: '二年級課後英語繪本導讀與互動' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 4, period: 'p8', title: '2甲 課後班英語', enTitle: 'Class 2A After-School English', category: 'afterschool', grade: '2甲', desc: '二年級課後英語繪本導讀與互動' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p5', title: '中年級英語實驗班', enTitle: 'Middle Grade English Lab', category: 'lab', grade: '中年級 (3-4年級)', desc: '中年級英語實驗班,遊戲化教學與日常生活對話' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p6', title: '中年級英語實驗班', enTitle: 'Middle Grade English Lab', category: 'lab', grade: '中年級 (3-4年級)', desc: '中年級英語實驗班,遊戲化教學與日常生活對話' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p7', title: '中年級英語實驗班', enTitle: 'Middle Grade English Lab', category: 'lab', grade: '中年級 (3-4年級)', desc: '中年級英語實驗班,遊戲化教學與日常生活對話' },
{ teacher: 'chris', teacherName: '白德華 (Teacher Chris)', day: 5, period: 'p8', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '課堂教具準備、實驗課程教案修訂與成績評量' },
// Dinh Quoc Thinh (Theol)
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p1', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '英語教學準備、教案設計與跨領域課程討論' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p2', title: '5甲 英語', enTitle: 'Class 5A English', category: 'english', grade: '5甲', desc: '五年級正規英語課程教學' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p3', title: '2甲 校本課程', enTitle: 'Class 2A School-Based', category: 'schoolbound', grade: '2甲', desc: '二年級校本特色雙語融合課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p4', title: '4甲 英語', enTitle: 'Class 4A English', category: 'english', grade: '4甲', desc: '四年級正規英語課程教學' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p5', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學媒體製作與學習單設計' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 3, period: 'p6', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學媒體製作與學習單設計' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p1', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '跨領域雙語教學備課' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p2', title: '3甲 校本課程', enTitle: 'Class 3A School-Based', category: 'schoolbound', grade: '3甲', desc: '三年級校本特色雙語融合課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p3', title: '1甲 校本課程', enTitle: 'Class 1A School-Based', category: 'schoolbound', grade: '1甲', desc: '一年級校本特色雙語探究課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p4', title: '6甲 英語', enTitle: 'Class 6A English', category: 'english', grade: '6甲', desc: '六年級正規英語課程教學' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p5', title: '4甲 校本課程', enTitle: 'Class 4A School-Based', category: 'schoolbound', grade: '4甲', desc: '四年級校本特色雙語融合課程' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p6', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學共同備課與檢討' },
{ teacher: 'theol', teacherName: '丁國盛 (Teacher Theol)', day: 4, period: 'p7', title: '課程準備', enTitle: 'Lesson Preparation', category: 'prep', grade: '教師備課', desc: '教學研討與班級學習記錄整理' }
];
let currentFilter = 'all'; // 'all', 'chris', 'theol'
let searchQuery = '';
// Category Styles Mapping
const categoryStyles = {
lab: { bg: 'bg-blue-50 hover:bg-blue-100 border-blue-200 text-blue-900', badge: 'bg-blue-200 text-blue-800' },
english: { bg: 'bg-teal-50 hover:bg-teal-100 border-teal-200 text-teal-900', badge: 'bg-teal-200 text-teal-800' },
schoolbound: { bg: 'bg-purple-50 hover:bg-purple-100 border-purple-200 text-purple-900', badge: 'bg-purple-200 text-purple-800' },
afterschool: { bg: 'bg-amber-50 hover:bg-amber-100 border-amber-200 text-amber-900', badge: 'bg-amber-200 text-amber-800' },
kindergarten: { bg: 'bg-emerald-50 hover:bg-emerald-100 border-emerald-200 text-emerald-900', badge: 'bg-emerald-200 text-emerald-800' },
prep: { bg: 'bg-gray-50 hover:bg-gray-100 border-gray-200 text-stone-700', badge: 'bg-gray-200 text-stone-700' }
};
// Render Timetable Grid
function renderTimetable() {
const tbody = document.getElementById('timetable-body');
tbody.innerHTML = '';
periodsData.forEach(p => {
const tr = document.createElement('tr');
tr.className = p.id === 'noon' ? 'bg-amber-50/40 border-y-2 border-amber-200' : 'hover:bg-stone-50/50';
// Period Header Cell
let periodHtml = `
<td class="py-3 px-4 border-r border-stone-200 font-medium text-xs">
<span class="text-stone-900 font-bold block">${p.name}</span>
<span class="text-[11px] text-stone-500 block">${p.time}</span>
</td>
`;
// Days 1 to 5 (Mon to Fri)
for (let day = 1; day <= 5; day++) {
const matches = scheduleEntries.filter(entry => {
const matchTeacher = (currentFilter === 'all') || (entry.teacher === currentFilter);
const matchDay = entry.day === day;
const matchPeriod = entry.period === p.id;
const matchSearch = searchQuery === '' ||
entry.title.toLowerCase().includes(searchQuery) ||
entry.enTitle.toLowerCase().includes(searchQuery) ||
entry.teacherName.toLowerCase().includes(searchQuery) ||
entry.grade.toLowerCase().includes(searchQuery);
return matchTeacher && matchDay && matchPeriod && matchSearch;
});
periodHtml += `<td class="p-2 border-r border-stone-200 align-top h-20">`;
if (matches.length > 0) {
matches.forEach(m => {
const style = categoryStyles[m.category] || categoryStyles.prep;
periodHtml += `
<div onclick="openModal('${encodeURIComponent(JSON.stringify(m))}', '${p.name} ${p.time}')"
class="p-2 rounded-lg border ${style.bg} cursor-pointer transition-all shadow-sm hover:shadow mb-1.5 group">
<div class="flex items-center justify-between gap-1 mb-1">
<span class="font-bold text-xs truncate">${m.title}</span>
</div>
<div class="text-[10px] opacity-80 truncate">${m.enTitle}</div>
<div class="mt-1.5 flex items-center justify-between text-[10px]">
<span class="px-1.5 py-0.5 rounded ${style.badge} font-semibold">
${m.teacher === 'chris' ? 'Chris' : 'Theol'}
</span>
<span class="text-stone-500 group-hover:text-stone-800 font-medium">${m.grade}</span>
</div>
</div>
`;
});
} else {
periodHtml += `<div class="h-full flex items-center justify-center text-[11px] text-stone-300 font-light">—</div>`;
}
periodHtml += `</td>`;
}
tr.innerHTML = periodHtml;
tbody.appendChild(tr);
});
updateMetrics();
}
// Set Teacher Filter
function setTeacherFilter(teacher) {
currentFilter = teacher;
// Toggle active classes on buttons
const btnAll = document.getElementById('btn-view-all');
const btnChris = document.getElementById('btn-view-chris');
const btnTheol = document.getElementById('btn-view-theol');
const title = document.getElementById('current-view-title');
const badge = document.getElementById('teacher-badge');
[btnAll, btnChris, btnTheol].forEach(b => {
b.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all text-stone-600 hover:text-stone-900";
});
if (teacher === 'all') {
btnAll.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm";
title.innerText = "全體雙語教師綜合課表 (Master Timetable)";
badge.innerText = "2 位雙語/外籍教師";
} else if (teacher === 'chris') {
btnChris.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm";
title.innerText = "白德華 老師課表 (Teacher Payk Christopher)";
badge.innerText = "外籍英語教師 (Teacher Chris)";
} else if (teacher === 'theol') {
btnTheol.className = "px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white text-stone-900 shadow-sm";
title.innerText = "丁國盛 老師課表 (Teacher Dinh Quoc Thinh)";
badge.innerText = "雙語教學教師 (Teacher Theol)";
}
renderTimetable();
}
// Handle Search Input
function handleSearch() {
const input = document.getElementById('search-input');
searchQuery = input.value.trim().toLowerCase();
renderTimetable();
}
// Update Dynamic Metrics
function updateMetrics() {
let filtered = scheduleEntries;
if (currentFilter !== 'all') {
filtered = scheduleEntries.filter(e => e.teacher === currentFilter);
}
const teachingCount = filtered.filter(e => e.category !== 'prep').length;
const prepCount = filtered.filter(e => e.category === 'prep').length;
document.getElementById('metric-teaching').innerText = `${teachingCount} 節`;
document.getElementById('metric-prep').innerText = `${prepCount} 節`;
if (currentFilter === 'chris') {
document.getElementById('metric-days').innerText = "週三 ~ 週五 (Wed-Fri)";
} else if (currentFilter === 'theol') {
document.getElementById('metric-days').innerText = "週三 ~ 週四 (Wed-Thu)";
} else {
document.getElementById('metric-days').innerText = "週三 ~ 週五 (Wed-Fri)";
}
}
// Modal Control Functions
function openModal(dataStr, periodInfo) {
const data = JSON.parse(decodeURIComponent(dataStr));
document.getElementById('modal-period-tag').innerText = periodInfo;
document.getElementById('modal-title').innerText = `${data.title} (${data.enTitle})`;
document.getElementById('modal-teacher').innerText = data.teacherName;
document.getElementById('modal-grade').innerText = data.grade;
const catMap = {
lab: '英語實驗班 (Experimental Class)',
english: '正規英語課 (General English)',
schoolbound: '校本特色課程 (School-Based)',
afterschool: '課後班英語 (After-School Enrichment)',
kindergarten: '幼兒園活動 (Kindergarten)',
prep: '課程準備時段 (Lesson Prep)'
};
document.getElementById('modal-category').innerText = catMap[data.category] || data.category;
document.getElementById('modal-desc').innerText = data.desc;
document.getElementById('detail-modal').classList.remove('hidden');
}
function closeModal(event) {
if (event.target.id === 'detail-modal') {
document.getElementById('detail-modal').classList.add('hidden');
}
}
function closeModalDirect() {
document.getElementById('detail-modal').classList.add('hidden');
}
// Initialize Charts with Chart.js
let workloadChart, categoriesChart;
function initCharts() {
// Chart 1: Workload Comparison
const ctx1 = document.getElementById('chart-workload').getContext('2d');
workloadChart = new Chart(ctx1, {
type: 'bar',
data: {
labels: ['白德華 (Chris)', '丁國盛 (Theol)'],
datasets: [
{
label: '授課節次 (Teaching)',
data: [12, 6],
backgroundColor: '#2563eb',
borderRadius: 6
},
{
label: '課程準備 (Lesson Prep)',
data: [1, 6],
backgroundColor: '#93c5fd',
borderRadius: 6
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'bottom' },
tooltip: {
callbacks: {
label: function(context) {
return `${context.dataset.label}: ${context.raw} 節`;
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: { stepSize: 2 }
}
}
}
});
// Chart 2: Course Category Breakdown
const ctx2 = document.getElementById('chart-categories').getContext('2d');
categoriesChart = new Chart(ctx2, {
type: 'doughnut',
data: {
labels: [
'英語實驗班 (Lab)',
'正規英語課 (English)',
'校本課程 (School-Based)',
'課後英語 (After-School)',
'幼兒園 (Preschool)',
'課程準備 (Prep)'
],
datasets: [{
data: [7, 3, 4, 4, 1, 7],
backgroundColor: [
'#3b82f6', // Lab
'#0d9488', // English
'#a855f7', // Schoolbound
'#f59e0b', // Afterschool
'#10b981', // Kindergarten
'#9ca3af' // Prep
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'bottom', labels: { boxWidth: 12, font: { size: 11 } } },
tooltip: {
callbacks: {
label: function(context) {
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const val = context.raw;
const pct = ((val / total) * 100).toFixed(1);
return `${context.label}: ${val} 節 (${pct}%)`;
}
}
}
}
}
});
}
// Page Load Init
window.addEventListener('DOMContentLoaded', () => {
renderTimetable();
initCharts();
});
</script>
</body>
</html>
瀏覽數:
