Skip to content

Commit 5c70189

Browse files
authored
Refactor index.html and add monthly trend chart
Removed unnecessary comments and added a new chart for monthly trend analysis.
1 parent aeb6bfd commit 5c70189

File tree

1 file changed

+82
-29
lines changed

1 file changed

+82
-29
lines changed

index.html

Lines changed: 82 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>大興里空氣異味監測與分析報告</title>
7-
<!-- 載入 Tailwind CSS -->
87
<script src="https://cdn.tailwindcss.com"></script>
9-
<!-- 載入 Chart.js (用於圖表繪製) -->
108
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
11-
<!-- 載入 PapaParse (用於快速解析 CSV) -->
129
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js"></script>
1310
<style>
1411
/* 使用 Inter 字體 */
@@ -23,7 +20,6 @@
2320
<body class="bg-gray-50 min-h-screen p-4 sm:p-8">
2421

2522
<div class="max-w-7xl mx-auto">
26-
<!-- 標題與更新時間 -->
2723
<header class="text-center mb-8">
2824
<h1 class="text-4xl font-extrabold text-blue-700 tracking-tight mb-2">
2925
大興里空氣異味監測與分析報告
@@ -33,30 +29,25 @@ <h1 class="text-4xl font-extrabold text-blue-700 tracking-tight mb-2">
3329
</p>
3430
</header>
3531

36-
<!-- 錯誤訊息顯示區 (新增) -->
3732
<div id="error-message" class="hidden bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4" role="alert">
3833
<strong class="font-bold">資料載入錯誤:</strong>
3934
<span id="error-text" class="block sm:inline"></span>
4035
</div>
4136

42-
<!-- 全域篩選器區 -->
4337
<section class="bg-white p-6 rounded-xl shadow-lg mb-8 transition-shadow duration-300 hover:shadow-xl">
4438
<h2 class="text-xl font-semibold text-gray-700 mb-4 border-b pb-2">
4539
篩選條件
4640
</h2>
4741
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
48-
<!-- 地點篩選器 -->
4942
<div>
5043
<label for="location-filter" class="block text-sm font-medium text-gray-700 mb-1">
5144
發生位置
5245
</label>
5346
<select id="location-filter" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition duration-150">
5447
<option value="all">所有地點</option>
55-
<!-- 選項將由 JS 動態載入 -->
56-
</select>
48+
</select>
5749
</div>
5850

59-
<!-- 濃度篩選器 -->
6051
<div>
6152
<label for="concentration-filter" class="block text-sm font-medium text-gray-700 mb-1">
6253
氣味濃度
@@ -69,7 +60,6 @@ <h2 class="text-xl font-semibold text-gray-700 mb-4 border-b pb-2">
6960
</select>
7061
</div>
7162

72-
<!-- 重設按鈕 -->
7363
<div class="flex items-end">
7464
<button id="reset-button" class="w-full bg-indigo-500 text-white p-2 rounded-lg font-medium hover:bg-indigo-600 transition duration-200 shadow-md">
7565
重設篩選
@@ -78,67 +68,63 @@ <h2 class="text-xl font-semibold text-gray-700 mb-4 border-b pb-2">
7868
</div>
7969
</section>
8070

81-
<!-- 關鍵數據指標 (KPIs) -->
8271
<section class="grid grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
83-
<!-- 總回報筆數 -->
8472
<div class="bg-white p-5 rounded-xl shadow-md border-b-4 border-blue-500">
8573
<p class="text-sm font-medium text-gray-500">總回報筆數</p>
8674
<p id="kpi-total" class="text-3xl font-bold text-gray-900 mt-1">0</p>
8775
</div>
88-
<!-- 發生異味天數 -->
8976
<div class="bg-white p-5 rounded-xl shadow-md border-b-4 border-green-500">
9077
<p class="text-sm font-medium text-gray-500">發生異味天數</p>
9178
<p id="kpi-days" class="text-3xl font-bold text-gray-900 mt-1">0</p>
9279
</div>
93-
<!-- 最高濃度回報比例 -->
9480
<div class="bg-white p-5 rounded-xl shadow-md border-b-4 border-red-500">
9581
<p class="text-sm font-medium text-gray-500">重度回報比例</p>
9682
<p id="kpi-heavy-ratio" class="text-3xl font-bold text-gray-900 mt-1">0%</p>
9783
</div>
98-
<!-- 最常發生時段 -->
9984
<div class="bg-white p-5 rounded-xl shadow-md border-b-4 border-yellow-500">
10085
<p class="text-sm font-medium text-gray-500">最常發生時段</p>
10186
<p id="kpi-peak-time" class="text-2xl font-bold text-gray-900 mt-2">--</p>
10287
</div>
10388
</section>
10489

105-
<!-- 圖表區 -->
10690
<section class="grid grid-cols-1 lg:grid-cols-2 gap-8">
107-
<!-- 1. 污染類型佔比 (圓餅圖) -->
10891
<div class="bg-white p-6 rounded-xl shadow-md transition-shadow duration-300 hover:shadow-xl">
10992
<h3 class="text-lg font-semibold text-gray-700 mb-4">污染類型佔比</h3>
11093
<div class="chart-container">
11194
<canvas id="typeChart"></canvas>
11295
</div>
11396
</div>
11497

115-
<!-- 2. 地點與濃度交叉分析 (長條圖) -->
11698
<div class="bg-white p-6 rounded-xl shadow-md transition-shadow duration-300 hover:shadow-xl">
11799
<h3 class="text-lg font-semibold text-gray-700 mb-4">地點與濃度交叉分析</h3>
118100
<div class="chart-container">
119101
<canvas id="locationConcentrationChart"></canvas>
120102
</div>
121103
</div>
122104

123-
<!-- 3. 異味發生熱點時段 (柱狀圖) -->
124105
<div class="lg:col-span-2 bg-white p-6 rounded-xl shadow-md transition-shadow duration-300 hover:shadow-xl">
125106
<h3 class="text-lg font-semibold text-gray-700 mb-4">異味發生熱點時段 (12小時制)</h3>
126107
<div class="chart-container h-96">
127108
<canvas id="timeChart"></canvas>
128109
</div>
129110
</div>
130111

131-
<!-- 4. 近七日回報紀錄趨勢 (折線圖) - NEW -->
132112
<div class="lg:col-span-2 bg-white p-6 rounded-xl shadow-md transition-shadow duration-300 hover:shadow-xl">
133113
<h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢</h3>
134114
<div class="chart-container h-96">
135115
<canvas id="weeklyTrendChart"></canvas>
136116
</div>
137117
</div>
118+
119+
<div class="lg:col-span-2 bg-white p-6 rounded-xl shadow-md transition-shadow duration-300 hover:shadow-xl">
120+
<h3 class="text-lg font-semibold text-gray-700 mb-4">近一個月回報紀錄趨勢</h3>
121+
<div class="chart-container h-96">
122+
<canvas id="monthlyTrendChart"></canvas>
123+
</div>
124+
</div>
138125
</section>
139126
</div>
140127

141-
<!-- 載入中/錯誤訊息 -->
142128
<div id="loading-overlay" class="fixed inset-0 bg-gray-900 bg-opacity-75 flex justify-center items-center z-50">
143129
<p class="text-white text-xl font-semibold">
144130
<svg class="animate-spin -ml-1 mr-3 h-8 w-8 text-white inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
@@ -224,7 +210,7 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
224210
return dateString; // 解析失敗,返回原始字串
225211
};
226212

227-
// 【新修正】時間轉換函數:將 12 小時制 (如 3:00 PM) 或 24 小時制 (如 14:00) 轉換為 0-23 的小時整數
213+
// 時間轉換函數:將 12 小時制 (如 3:00 PM) 或 24 小時制 (如 14:00) 轉換為 0-23 的小時整數
228214
const convertTo24Hour = (timeString) => {
229215
if (!timeString) return NaN;
230216

@@ -310,7 +296,7 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
310296
const concentration = row[concentrationKey] ? String(row[concentrationKey]).trim() : null;
311297
const type = row[typeKey] ? String(row[typeKey]).trim() : null;
312298

313-
// 【修正】在此處預先轉換為 24 小時制的小時數
299+
// 在此處預先轉換為 24 小時制的小時數
314300
const hour24 = convertTo24Hour(time);
315301

316302
return { date, time, location, concentration, type, hour24 };
@@ -395,7 +381,7 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
395381

396382
if (totalCount > 0) {
397383
const hourCounts = data.reduce((acc, row) => {
398-
// 【修正】直接使用預先計算好的 24 小時制小時數
384+
// 直接使用預先計算好的 24 小時制小時數
399385
const hour = row.hour24;
400386

401387
if (!isNaN(hour)) {
@@ -438,7 +424,6 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
438424
};
439425

440426
const renderTypeChart = (data) => {
441-
// 修正 reduce 函數的箭頭函數語法 (已修正)
442427
const typeCounts = data.reduce((acc, row) => {
443428
const type = row.type || '未知異味';
444429
acc[type] = (acc[type] || 0) + 1;
@@ -471,7 +456,7 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
471456
const renderTimeChart = (data) => {
472457
const hourCounts = Array(24).fill(0); // 0-23 小時
473458

474-
// 【修正】優化 12 小時制標籤生成邏輯,確保 0 點是 12 AM,12 點是 12 PM (來自前一次修正)
459+
// 優化 12 小時制標籤生成邏輯
475460
const hours = Array.from({ length: 24 }, (_, i) => {
476461
const hour = i;
477462
let hour12;
@@ -494,7 +479,7 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
494479
});
495480

496481
data.forEach(row => {
497-
// 【修正】直接使用預先計算好的 24 小時制小時數
482+
// 直接使用預先計算好的 24 小時制小時數
498483
const hour = row.hour24;
499484

500485
if (!isNaN(hour) && hour >= 0 && hour <= 23) {
@@ -600,7 +585,6 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
600585

601586
// 2. 計算過去 7 天的回報筆數
602587
const counts = dateKeys.map(key => {
603-
// 這裡 row.date 已經是 normalized (YYYY/MM/DD) 格式
604588
return data.filter(row => row.date === key).length;
605589
});
606590

@@ -644,6 +628,74 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
644628
});
645629
};
646630

631+
// 近一個月 (30天) 回報紀錄趨勢 (折線圖)
632+
const renderMonthlyTrendChart = (data) => {
633+
const today = new Date();
634+
today.setHours(0, 0, 0, 0);
635+
636+
let dateLabels = []; // 標籤 (月/日)
637+
let dateKeys = []; // 資料比對鍵 (年/月/日)
638+
639+
// 產生過去 30 天的日期列表 (從 29 天前到今天)
640+
for (let i = 29; i >= 0; i--) {
641+
const d = new Date(today);
642+
d.setDate(today.getDate() - i);
643+
644+
const label = `${(d.getMonth() + 1).toString().padStart(2, '0')}/${d.getDate().toString().padStart(2, '0')}`;
645+
dateLabels.push(label);
646+
647+
dateKeys.push(formatDateKey(d));
648+
}
649+
650+
// 計算過去 30 天的回報筆數
651+
const counts = dateKeys.map(key => {
652+
return data.filter(row => row.date === key).length;
653+
});
654+
655+
// 繪製折線圖
656+
initializeChart('monthlyTrendChart', 'line', {
657+
data: {
658+
labels: dateLabels,
659+
datasets: [{
660+
label: '回報筆數',
661+
data: counts,
662+
backgroundColor: 'rgba(16, 185, 129, 0.5)', // 綠色透明背景
663+
borderColor: '#10b981',
664+
borderWidth: 3,
665+
tension: 0.3,
666+
fill: true,
667+
pointRadius: 3,
668+
pointHoverRadius: 5,
669+
}]
670+
},
671+
options: {
672+
responsive: true,
673+
maintainAspectRatio: false,
674+
scales: {
675+
y: {
676+
beginAtZero: true,
677+
title: { display: true, text: '回報筆數' },
678+
ticks: { precision: 0 }
679+
},
680+
x: {
681+
title: { display: true, text: '日期' },
682+
// 調整刻度以避免 30 個標籤過於擁擠,大約每 5 天顯示一次
683+
ticks: {
684+
autoSkip: true,
685+
maxRotation: 0,
686+
minRotation: 0,
687+
maxTicksLimit: 7
688+
}
689+
}
690+
},
691+
plugins: {
692+
legend: { position: 'top' },
693+
title: { display: false }
694+
}
695+
}
696+
});
697+
};
698+
647699

648700
// --- 主渲染函數 ---
649701
const renderDashboard = (data) => {
@@ -652,6 +704,7 @@ <h3 class="text-lg font-semibold text-gray-700 mb-4">近七日回報紀錄趨勢
652704
renderTimeChart(data);
653705
renderLocationConcentrationChart(data);
654706
renderWeeklyTrendChart(data);
707+
renderMonthlyTrendChart(data);
655708
};
656709

657710
// --- 初始化與事件監聽 ---

0 commit comments

Comments
 (0)