功能概覽
- 三種搜尋模式:單日、週範圍、月份
- 下拉選單切換模式,動態顯示對應輸入介面
- 週模式:選擇年/月後,AJAX 載入該月週範圍選單
- 前端整合 ECharts 顯示統計圖表
- 後端提供日期計算工具函數
核心後端檔案
1. ajax.php - 週選單動態載入
<?php
$year = $_GET['y'] ?? date('Y');
$month = $_GET['m'] ?? date('m');
function getMonthWeekArr($year, $month) {
$firstDay = strtotime("$year-$month-01");
$firstWeekDays = 7 - date('N', $firstDay) + 1;
$startTime = $firstDay - 86400 * (7 - $firstWeekDays);
$lastDay = strtotime("$year-$month-01 +1 month -1 day");
$lastWeekDay = date('N', $lastDay);
$endTime = $lastDay - 86400 * ($lastWeekDay % 7);
$weeks = [];
for ($i = $startTime; $i < $endTime; $i += 604800) { // 7*86400
$weeks[] = [
'key' => date('Y-m-d', $i) . '|' . date('Y-m-d', $i + 518400), // 6*86400
'val' => date('Y-m-d', $i) . '~' . date('Y-m-d', $i + 518400)
];
}
return $weeks;
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode(getMonthWeekArr($year, $month));
?>
2. datehelper.php - 日期計算工具函數庫
<?php
function getSystemYearArr() {
return array_combine(range(2010, 2025), range(2010, 2025));
}
function getSystemMonthArr() {
return array_combine(range(1, 12), array_map(fn($m) => sprintf('%02d', $m), range(1, 12)));
}
function getMonthLastDay($year, $month) {
return strtotime("$year-$month-01 +1 month -1 day");
}
function getWeek_SdateAndEdate($timestamp) {
$day = strtotime(date('Y-m-d', $timestamp));
return [
'sdate' => date('Y-m-d', $day - 86400 * (date('N', $day) - 1)),
'edate' => date('Y-m-d', $day + 86400 * (7 - date('N', $day)))
];
}
function dealwithSearchTime($arr = []) {
// 日
$arr['search_time'] = $arr['search_time'] ?? date('Y-m-d', strtotime('-1 day'));
$arr['day']['search_time'] = strtotime($arr['search_time']);
// 週
$arr['searchweek_year'] = $arr['searchweek_year'] ?? date('Y');
$arr['searchweek_month'] = $arr['searchweek_month'] ?? date('m');
$arr['searchweek_week'] = $arr['searchweek_week'] ?? implode('|', getWeek_SdateAndEdate(time()));
// 月
$arr['searchmonth_year'] = $arr['searchmonth_year'] ?? date('Y');
$arr['searchmonth_month'] = $arr['searchmonth_month'] ?? date('m');
return $arr;
}
?>
3. statistics.php - ECharts 圖表資料格式化
<?php
function getStatData_LineLabels($config) {
$config['chart']['type'] = 'line';
$config['colors'] = $config['colors'] ?? ['#058DC7', '#ED561B', '#8bbc21', '#0d233a'];
$config['credits']['enabled'] = false;
$config['exporting']['enabled'] = false;
// 標題、Y軸格式化...
return json_encode($config);
}
function getStatData_Column2D($config) {
$config['chart']['type'] = 'column';
// 色系指派...
return json_encode($config);
}
function getStatData_Pie($data) {
return json_encode([
'chart' => ['type' => 'pie'],
'credits' => ['enabled' => false],
'title' => ['text' => $data['title']],
'tooltip' => ['pointFormat' => '{series.name}: <b>{point.y}</b>'],
'plotOptions' => ['pie' => ['allowPointSelect' => true, 'cursor' => 'pointer']],
'series' => [[
'name' => $data['name'],
'data' => array_map(fn($v) => [$v['p_name'], $v['allnum']], $data['series'])
]]
]);
}
?>
4. theline.php - 前端整合頁面 (含 ECharts)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>統計圖表</title>
<script src="js/echarts.common.min.js"></script>
<script src="js/jquery.js"></script>
<style>
#search_type, #searchtype_day, #searchtype_week, #searchtype_month { float: left; margin-right: 10px; }
</style>
</head>
<body>
<select id="search_type">
<option value="day">按日統計</option>
<option value="week">按週統計</option>
<option value="month">按月統計</option>
</select>
<div id="searchtype_day">
<input id="stime" name="search_time" type="date" value="<?php echo $search_time; ?>">
</div>
<div id="searchtype_week" style="display:none">
<select name="search_time_year" id="searchweek_year"><!-- 年選項 --></select>
<select name="search_time_month" id="searchweek_mouth"><!-- 月選項 --></select>
<select name="search_time_week" id="searchweek_week"><!-- 週選項 (AJAX 載入) --></select>
</div>
<div id="searchtype_month" style="display:none">
<select name="search_time_year"><!-- 年選項 --></select>
<select name="search_time_month"><!-- 月選項 --></select>
</div>
<div id="line_chart" style="width: 100%; height: 400px; clear: both;"></div>
<script>
// ECharts 初始化
var chart = echarts.init(document.getElementById('line_chart'));
var option = {
title: { text: '未來一週氣溫變化', subtext: '純屬虛構' },
tooltip: { trigger: 'axis' },
legend: { data: ['最高氣溫', '最低氣溫'] },
toolbox: { show: true, feature: { dataZoom: {}, magicType: {type: ['line', 'bar']}, restore: {}, saveAsImage: {} } },
xAxis: { type: 'category', boundaryGap: false, data: ['週一','週二','週三','週四','週五','週六','週日'] },
yAxis: { type: 'value', axisLabel: { formatter: '{value} °C' } },
series: [{
name: '最高氣溫', type: 'line', data: <?php echo json_encode($thearray); ?>,
markPoint: { data: [{type: 'max', name: '最大值'}, {type: 'min', name: '最小值'}] },
markLine: { data: [{type: 'average', name: '平均值'}] }
}, {
name: '最低氣溫', type: 'line', data: [1, 4, 2, 5, 3, 2, 0],
markPoint: { data: [{name: '週最低', value: -2, xAxis: 1, yAxis: -1.5}] },
markLine: { data: [{type: 'average', name: '平均值'}] }
}]
};
chart.setOption(option);
// 模式切換
function showSearchTime() {
var type = $('#search_type').val();
$('[id^="searchtype_"]').hide();
$('#searchtype_' + type).show();
}
$(function() {
showSearchTime();
$('#search_type').change(showSearchTime);
// 年/月變更時重新載入週選單
$('[name="search_time_year"], [name="search_time_month"]').change(function() {
var year = $('[name="search_time_year"]').val();
var month = $('[name="search_time_month"]').val();
$('#searchweek_week').empty();
$.getJSON('php/ajax.php', {y: year, m: month}, function(data) {
$.each(data, function(i, item) {
$('#searchweek_week').append('<option value="' + item.key + '">' + item.val + '</option>');
});
});
});
});
</script>
</body>
</html>
關鍵技術點
| 模組 | 技術要點 |
| 週範圍計算 | 以週一為起始,補齊跨月第一週/最後一週 |
| AJAX 週選單 | 年/月聯動,$.getJSON 異步載入 ajax.php |
| ECharts 整合 | PHP json_encode 直接輸出 JS 陣列至 series.data |
| 模式切換 | CSS float + jQuery show/hide 控制顯示區塊 |
擴充建議
- 加入日期選擇器 (flatpickr, daterangepicker) 替代原生
<input type="date">
- 後端加入快取 (Redis) 減少重複日期計算
- 圖表資料 API 化,前端純 AJAX 取數,支援多圖表儀表板
- 加入匯出圖片/PDF 功能 (ECharts
getDataURL() + 後端生成 PDF)