task-report/generate_report.php
2025-04-14 00:33:31 +08:00

643 lines
20 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 定期报告生成脚本
*
* 此脚本生成任务报告并保存到服务器
* 可以通过群晖的计划任务定期执行
*/
// 设置错误报告
ini_set('display_errors', 1);
error_reporting(E_ALL);
// 启用网页输出模式
header('Content-Type: text/html; charset=utf-8');
// 配置信息
$config = [
// 数据库配置
'db_host' => '192.168.2.4',
'db_port' => 3307,
'db_name' => 'task_reporter',
'db_user' => 'task_reporter',
'db_pass' => 'Pass12349ers!',
// 报告生成选项
'author' => 'CGNICO Task Reporter', // 报告作者
// 报告配置
'report_days' => 7, // 报告包含的天数例如7表示过去一周
'report_title' => 'CGNICO工具使用报告', // 报告标题
];
// 根据报告天数设置标题
if (isset($_GET['days'])) {
$config['report_days'] = intval($_GET['days']);
// 根据天数调整报告标题
if ($config['report_days'] == 7) {
$config['report_title'] = 'CGNICO工具使用周报';
} elseif ($config['report_days'] == 30) {
$config['report_title'] = 'CGNICO工具使用月报';
} elseif ($config['report_days'] == 90) {
$config['report_title'] = 'CGNICO工具使用季报';
} elseif ($config['report_days'] == 365) {
$config['report_title'] = 'CGNICO工具使用年报';
}
}
// 创建数据库连接
try {
$pdo = new PDO(
"mysql:host={$config['db_host']};port={$config['db_port']};dbname={$config['db_name']}",
$config['db_user'],
$config['db_pass']
);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec("SET NAMES utf8");
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
// 生成报告
function generate_report($pdo, $days) {
$report = [];
// 获取日期范围
$end_date = date('Y-m-d');
$start_date = date('Y-m-d', strtotime("-{$days} days"));
// 1. 总体统计
$stmt = $pdo->prepare("
SELECT
COUNT(*) as total_tasks,
SUM(time_saved) as total_time_saved,
COUNT(DISTINCT username) as total_users,
COUNT(DISTINCT tool_name) as total_tools
FROM task
WHERE timestamp BETWEEN :start_date AND :end_date
AND tool_name NOT LIKE '%(Debug)%'
");
$stmt->bindParam(':start_date', $start_date);
$stmt->bindParam(':end_date', $end_date);
$stmt->execute();
$report['summary'] = $stmt->fetch(PDO::FETCH_ASSOC);
// 2. 工具使用统计
$stmt = $pdo->prepare("
SELECT
tool_name,
COUNT(*) as usage_count,
SUM(time_saved) as time_saved
FROM task
WHERE timestamp BETWEEN :start_date AND :end_date
AND tool_name NOT LIKE '%(Debug)%'
GROUP BY tool_name
ORDER BY usage_count DESC
LIMIT 10
");
$stmt->bindParam(':start_date', $start_date);
$stmt->bindParam(':end_date', $end_date);
$stmt->execute();
$report['tools'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 3. 用户使用统计
$stmt = $pdo->prepare("
SELECT
username,
COUNT(*) as usage_count,
SUM(time_saved) as time_saved
FROM task
WHERE timestamp BETWEEN :start_date AND :end_date
AND tool_name NOT LIKE '%(Debug)%'
GROUP BY username
ORDER BY usage_count DESC
LIMIT 10
");
$stmt->bindParam(':start_date', $start_date);
$stmt->bindParam(':end_date', $end_date);
$stmt->execute();
$report['users'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 4. 每日使用趋势
$stmt = $pdo->prepare("
SELECT
DATE(timestamp) as date,
COUNT(*) as usage_count,
SUM(time_saved) as time_saved
FROM task
WHERE timestamp BETWEEN :start_date AND :end_date
AND tool_name NOT LIKE '%(Debug)%'
GROUP BY DATE(timestamp)
ORDER BY date
");
$stmt->bindParam(':start_date', $start_date);
$stmt->bindParam(':end_date', $end_date);
$stmt->execute();
$report['daily'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
return [
'report' => $report,
'start_date' => $start_date,
'end_date' => $end_date
];
}
// 生成HTML报告
function generate_html_report($report_data) {
$report = $report_data['report'];
$start_date = $report_data['start_date'];
$end_date = $report_data['end_date'];
$html = '
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CGNICO工具使用报告</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1, h2, h3 {
color: #0066cc;
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
th, td {
padding: 10px;
border: 1px solid #ddd;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
.summary {
background-color: #f0f7ff;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
.highlight {
color: #0066cc;
font-weight: bold;
}
</style>
</head>
<body>
<h1>CGNICO工具使用报告</h1>
<p>报告时间范围: ' . $start_date . ' 至 ' . $end_date . '</p>
<div class="summary">
<h2>总体统计</h2>
<p>在过去的 ' . round((strtotime($end_date) - strtotime($start_date)) / 86400) . ' 天中:</p>
<ul>
<li>总任务数: <span class="highlight">' . number_format($report['summary']['total_tasks']) . '</span></li>
<li>总节省时间: <span class="highlight">' . number_format($report['summary']['total_time_saved'], 2) . ' 小时</span></li>
<li>活跃用户数: <span class="highlight">' . $report['summary']['total_users'] . '</span></li>
<li>使用的工具数: <span class="highlight">' . $report['summary']['total_tools'] . '</span></li>
</ul>
</div>
<h2>工具使用排名</h2>
<table>
<tr>
<th>排名</th>
<th>工具名称</th>
<th>使用次数</th>
<th>节省时间 (小时)</th>
</tr>';
$rank = 1;
foreach ($report['tools'] as $tool) {
$html .= '
<tr>
<td>' . $rank++ . '</td>
<td>' . htmlspecialchars($tool['tool_name']) . '</td>
<td>' . number_format($tool['usage_count']) . '</td>
<td>' . number_format($tool['time_saved'], 2) . '</td>
</tr>';
}
$html .= '
</table>
<h2>用户使用排名</h2>
<table>
<tr>
<th>排名</th>
<th>用户名</th>
<th>使用次数</th>
<th>节省时间 (小时)</th>
</tr>';
$rank = 1;
foreach ($report['users'] as $user) {
$html .= '
<tr>
<td>' . $rank++ . '</td>
<td>' . htmlspecialchars($user['username']) . '</td>
<td>' . number_format($user['usage_count']) . '</td>
<td>' . number_format($user['time_saved'], 2) . '</td>
</tr>';
}
$html .= '
</table>
<h2>每日使用趋势</h2>
<table>
<tr>
<th>日期</th>
<th>使用次数</th>
<th>节省时间 (小时)</th>
</tr>';
foreach ($report['daily'] as $day) {
$html .= '
<tr>
<td>' . $day['date'] . '</td>
<td>' . number_format($day['usage_count']) . '</td>
<td>' . number_format($day['time_saved'], 2) . '</td>
</tr>';
}
$html .= '
</table>
<div style="margin-top: 30px; color: #666; font-size: 12px; text-align: center;">
<p>此报告由CGNICO Task Reporter自动生成于 ' . date('Y-m-d H:i:s') . '</p>
</div>
</body>
</html>';
return $html;
}
// 记录日志
function log_message($message) {
$log_dir = __DIR__ . '/logs';
if (!is_dir($log_dir)) {
mkdir($log_dir, 0755, true);
}
$log_file = $log_dir . '/report_' . date('Y-m-d') . '.log';
$time = date('Y-m-d H:i:s');
file_put_contents($log_file, "[$time] $message\n", FILE_APPEND);
}
// 主程序
try {
// 创建报告目录(如果不存在)
$report_dir = __DIR__ . '/reports/';
if (!is_dir($report_dir)) {
mkdir($report_dir, 0755, true);
}
// 检查是否需要生成新报告
$generate_new_report = false;
$report_file = $report_dir . 'report_' . date('Y-m-d') . '.html';
if (isset($_GET['generate']) && $_GET['generate'] == '1') {
$generate_new_report = true;
} elseif (!file_exists($report_file)) {
// 如果今天的报告不存在,自动生成
$generate_new_report = true;
}
if ($generate_new_report) {
log_message('===== 开始执行报告生成脚本 =====');
// 生成报告数据
log_message('开始生成报告数据...');
$days = $config['report_days'];
$report_data = generate_report($pdo, $days);
log_message('报告数据生成完成');
// 生成HTML报告
log_message('生成HTML报告...');
$html_report = generate_html_report($report_data);
log_message('HTML报告生成完成');
// 保存报告到文件
file_put_contents($report_file, $html_report);
log_message('报告已保存到: ' . $report_file);
}
// 开始HTML输出
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CGNICO工具使用报告生成器</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 1000px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
h1 {
color: #ff8c00;
text-align: center;
margin-bottom: 30px;
}
h3 {
color: #555;
margin-top: 0;
}
.success-message {
background-color: #dff0d8;
border: 1px solid #d6e9c6;
color: #3c763d;
border-radius: 4px;
padding: 15px;
margin-bottom: 20px;
}
.action-buttons {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.btn {
display: inline-block;
padding: 10px 15px;
text-decoration: none;
border-radius: 4px;
font-weight: 500;
cursor: pointer;
border: none;
transition: background-color 0.3s;
}
.btn-primary {
background-color: #337ab7;
color: white;
}
.btn-primary:hover {
background-color: #286090;
}
.btn-success {
background-color: #4CAF50;
color: white;
}
.btn-success:hover {
background-color: #3d8b40;
}
.btn-secondary {
background-color: #6c757d;
color: white;
}
.btn-secondary:hover {
background-color: #5a6268;
}
.panel {
background-color: #f5f5f5;
border: 1px solid #e3e3e3;
border-radius: 4px;
padding: 15px;
margin-bottom: 20px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: inline-block;
margin-bottom: 5px;
font-weight: bold;
}
select {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
width: 100%;
max-width: 300px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th, td {
padding: 10px;
border: 1px solid #ddd;
text-align: left;
}
th {
background-color: #f0f0f0;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
tr:hover {
background-color: #f1f1f1;
}
.table-actions {
text-align: center;
}
.footer {
text-align: center;
margin-top: 30px;
padding-top: 15px;
border-top: 1px solid #eee;
color: #777;
font-size: 0.9em;
}
</style>
</head>
<body>
<div class="container">
<h1>CGNICO工具使用报告生成器</h1>
<?php if ($generate_new_report): ?>
<div class="success-message">
<p><strong>报告已生成成功!</strong></p>
<p>报告时间范围: 过去<?php echo $config['report_days']; ?>天 (<?php echo date('Y-m-d', strtotime("-{$config['report_days']} days")); ?> 至 <?php echo date('Y-m-d'); ?>)</p>
</div>
<?php endif; ?>
<div class="action-buttons">
<a href="reports/report_<?php echo date('Y-m-d'); ?>.html" target="_blank" class="btn btn-primary">查看最新报告</a>
<a href="reports/report_<?php echo date('Y-m-d'); ?>.html" download class="btn btn-success">下载最新报告</a>
<a href="index.php" class="btn btn-secondary">返回首页</a>
</div>
<div class="panel">
<h3>生成新报告</h3>
<form method="get" action="">
<div class="form-group">
<label for="days">报告时间范围:</label>
<select name="days" id="days">
<option value="7" <?php echo ($config['report_days'] == 7) ? 'selected' : ''; ?>>过去7天 (一周)</option>
<option value="30" <?php echo ($config['report_days'] == 30) ? 'selected' : ''; ?>>过去30天 (一个月)</option>
<option value="90" <?php echo ($config['report_days'] == 90) ? 'selected' : ''; ?>>过去90天 (一季度)</option>
<option value="365" <?php echo ($config['report_days'] == 365) ? 'selected' : ''; ?>>过去365天 (一年)</option>
</select>
</div>
<input type="hidden" name="generate" value="1">
<button type="submit" class="btn btn-primary">生成报告</button>
</form>
</div>
<?php
// 历史报告列表
$reports_dir = __DIR__ . '/reports/';
if (is_dir($reports_dir)) {
$reports = glob($reports_dir . 'report_*.html');
if (!empty($reports)) {
echo "<div class=\"panel\">\n";
echo "<h3>历史报告</h3>\n";
echo "<table>\n";
echo "<tr>\n";
echo "<th>报告日期</th>\n";
echo "<th>报告类型</th>\n";
echo "<th>操作</th>\n";
echo "</tr>\n";
rsort($reports); // 按日期降序排序
foreach (array_slice($reports, 0, 10) as $report) { // 只显示最近10个
$filename = basename($report);
$date = substr($filename, 7, 10); // 从 report_YYYY-MM-DD.html 提取日期
// 尝试确定报告类型
$report_type = "常规报告";
$file_content = file_get_contents($report);
if (strpos($file_content, "工具使用周报") !== false) {
$report_type = "周报";
} elseif (strpos($file_content, "工具使用月报") !== false) {
$report_type = "月报";
} elseif (strpos($file_content, "工具使用季报") !== false) {
$report_type = "季报";
} elseif (strpos($file_content, "工具使用年报") !== false) {
$report_type = "年报";
}
echo "<tr>\n";
echo "<td>{$date}</td>\n";
echo "<td>{$report_type}</td>\n";
echo "<td class=\"table-actions\">\n";
echo "<a href='reports/{$filename}' target='_blank' class='btn btn-primary' style='padding: 5px 10px; margin-right: 5px;'>查看</a>\n";
echo "<a href='reports/{$filename}' download class='btn btn-success' style='padding: 5px 10px;'>下载</a>\n";
echo "</td>\n";
echo "</tr>\n";
}
echo "</table>\n";
echo "</div>\n";
}
}
?>
<div class="footer">
<p>CGNICO Task Report System &copy; <?php echo date('Y'); ?> | 联系方式: <a href="mailto:jeffreytsai1004@gmail.com">jeffreytsai1004@gmail.com</a></p>
</div>
</div>
</body>
</html>
<?php
} catch (Exception $e) {
log_message('错误: ' . $e->getMessage());
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>错误 - CGNICO工具使用报告生成器</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
h1 {
color: #d9534f;
}
.error-message {
background-color: #f2dede;
border: 1px solid #ebccd1;
color: #a94442;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
}
.btn {
display: inline-block;
padding: 10px 15px;
background-color: #6c757d;
color: white;
text-decoration: none;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="container">
<h1>发生错误</h1>
<div class="error-message">
<p><strong>错误:</strong> <?php echo $e->getMessage(); ?></p>
</div>
<a href="index.php" class="btn">返回首页</a>
</div>
</body>
</html>
<?php
}
?>