我来帮你创建一个简单的PHP工时管理系统,这个系统将包含员工登录、工时打卡、工时记录和统计功能。

完整PHP工时管理系统
数据库结构
-- 创建数据库
CREATE DATABASE IF NOT EXISTS work_time_system;
USE work_time_system;
-- 员工表
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
employee_code VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(50) NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
department VARCHAR(50),
position VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 打卡记录表
CREATE TABLE time_records (
id INT PRIMARY KEY AUTO_INCREMENT,
employee_id INT,
work_date DATE NOT NULL,
check_in TIMESTAMP NOT NULL,
check_out TIMESTAMP,
work_hours DECIMAL(5,2),
status ENUM('正常', '迟到', '早退', '缺卡') DEFAULT '正常',
overtime_hours DECIMAL(5,2) DEFAULT 0,
remark TEXT,
FOREIGN KEY (employee_id) REFERENCES employees(id)
);
-- 请假记录表
CREATE TABLE leave_requests (
id INT PRIMARY KEY AUTO_INCREMENT,
employee_id INT,
leave_type ENUM('事假', '病假', '年假', '调休') NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
reason TEXT,
status ENUM('待审批', '已批准', '已驳回') DEFAULT '待审批',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (employee_id) REFERENCES employees(id)
);
配置文件 (config.php)
<?php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'work_time_system');
// 数据库连接
function db_connect() {
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
$conn->set_charset("utf8mb4");
return $conn;
}
// 会话管理
session_start();
// 检查登录状态
function is_logged_in() {
return isset($_SESSION['employee_id']);
}
function require_login() {
if (!is_logged_in()) {
header('Location: login.php');
exit;
}
}
// 辅助函数
function redirect($url) {
header("Location: $url");
exit;
}
function sanitize($data) {
return htmlspecialchars(strip_tags(trim($data)));
}
?>
登录页面 (login.php)
<?php
require_once 'config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$employee_code = sanitize($_POST['employee_code']);
$password = $_POST['password'];
$conn = db_connect();
// 准备SQL语句
$stmt = $conn->prepare("SELECT id, employee_code, name, password FROM employees WHERE employee_code = ?");
$stmt->bind_param("s", $employee_code);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 1) {
$user = $result->fetch_assoc();
if (password_verify($password, $user['password'])) {
$_SESSION['employee_id'] = $user['id'];
$_SESSION['employee_name'] = $user['name'];
$_SESSION['employee_code'] = $user['employee_code'];
redirect('dashboard.php');
} else {
$error = "密码错误";
}
} else {
$error = "员工号不存在";
}
$stmt->close();
$conn->close();
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">员工登录 - 工时系统</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Microsoft YaHei', sans-serif; background: #f5f5f5; display: flex; justify-content: center; align-items: center; height: 100vh; }
.login-container { background: white; padding: 40px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); width: 100%; max-width: 400px; }
h1 { text-align: center; margin-bottom: 30px; color: #333; }
.form-group { margin-bottom: 20px; }
label { display: block; margin-bottom: 5px; color: #555; }
input[type="text"], input[type="password"] { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; }
button { width: 100%; padding: 12px; background: #4CAF50; color: white; border: none; border-radius: 5px; font-size: 16px; cursor: pointer; }
button:hover { background: #45a049; }
.error { background: #f44336; color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; text-align: center; }
.register-link { text-align: center; margin-top: 15px; }
.register-link a { color: #4CAF50; text-decoration: none; }
</style>
</head>
<body>
<div class="login-container">
<h1>员工工时系统</h1>
<?php if (isset($error)): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST" action="">
<div class="form-group">
<label>员工号</label>
<input type="text" name="employee_code" required>
</div>
<div class="form-group">
<label>密码</label>
<input type="password" name="password" required>
</div>
<button type="submit">登 录</button>
<div class="register-link">
<a href="register.php">还没有账号?注册</a>
</div>
</form>
</div>
</body>
</html>
主页面 (dashboard.php)
<?php
require_once 'config.php';
require_login();
$conn = db_connect();
$employee_id = $_SESSION['employee_id'];
// 处理打卡操作
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$action = $_POST['action'];
$today = date('Y-m-d');
if ($action === 'check_in') {
// 检查今天是否已经打卡
$check_sql = "SELECT id FROM time_records WHERE employee_id = ? AND work_date = ?";
$check_stmt = $conn->prepare($check_sql);
$check_stmt->bind_param("is", $employee_id, $today);
$check_stmt->execute();
$check_result = $check_stmt->get_result();
if ($check_result->num_rows === 0) {
// 正常上班时间为9:00
$check_in_time = date('Y-m-d H:i:s');
$hours = date('H');
$minutes = date('i');
$status = '正常';
if ($hours > 9 || ($hours == 9 && $minutes > 30)) {
$status = '迟到';
}
$insert_sql = "INSERT INTO time_records (employee_id, work_date, check_in, status) VALUES (?, ?, ?, ?)";
$insert_stmt = $conn->prepare($insert_sql);
$insert_stmt->bind_param("isss", $employee_id, $today, $check_in_time, $status);
$insert_stmt->execute();
$message = "上班打卡成功!";
} else {
$message = "今天已经打过卡了";
}
} elseif ($action === 'check_out') {
// 更新下班时间
$update_sql = "UPDATE time_records
SET check_out = ?,
work_hours = TIMESTAMPDIFF(MINUTE, check_in, NOW()) / 60
WHERE employee_id = ? AND work_date = ? AND check_out IS NULL";
$update_stmt = $conn->prepare($update_sql);
$check_out_time = date('Y-m-d H:i:s');
$update_stmt->bind_param("sis", $check_out_time, $employee_id, $today);
$update_stmt->execute();
if ($update_stmt->affected_rows > 0) {
$message = "下班打卡成功!";
} else {
$message = "没有找到有效的打卡记录";
}
}
}
// 获取今日打卡状态
$today = date('Y-m-d');
$today_record = null;
$sql = "SELECT * FROM time_records WHERE employee_id = ? AND work_date = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("is", $employee_id, $today);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$today_record = $result->fetch_assoc();
}
// 获取本月工时统计
$month_start = date('Y-m-01');
$month_end = date('Y-m-t');
$stats_sql = "SELECT
COUNT(*) as total_days,
SUM(work_hours) as total_hours,
AVG(work_hours) as avg_hours,
SUM(overtime_hours) as total_overtime,
SUM(status = '迟到') as late_days
FROM time_records
WHERE employee_id = ? AND work_date BETWEEN ? AND ?";
$stats_stmt = $conn->prepare($stats_sql);
$stats_stmt->bind_param("iss", $employee_id, $month_start, $month_end);
$stats_stmt->execute();
$stats = $stats_stmt->get_result()->fetch_assoc();
// 获取最近7天的记录
$week_sql = "SELECT * FROM time_records
WHERE employee_id = ? AND work_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
ORDER BY work_date DESC";
$week_stmt = $conn->prepare($week_sql);
$week_stmt->bind_param("i", $employee_id);
$week_stmt->execute();
$week_records = $week_stmt->get_result();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">工时管理系统 - 首页</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Microsoft YaHei', sans-serif; background: #f5f5f5; }
.header { background: #333; color: white; padding: 15px 30px; display: flex; justify-content: space-between; align-items: center; }
.header h2 { font-size: 20px; }
.header .user-info { display: flex; align-items: center; }
.header .user-info span { margin-right: 20px; }
.header a, .header button { background: #4CAF50; color: white; padding: 8px 15px; border: none; border-radius: 4px; cursor: pointer; text-decoration: none; font-size: 14px; }
.header a:hover { background: #45a049; }
.container { margin: 20px auto; max-width: 1200px; padding: 0 20px; }
.welcome { background: #e3f2fd; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
.card { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.card h3 { margin-bottom: 15px; color: #333; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; }
.stat-item { background: #f9f9f9; padding: 15px; border-radius: 8px; text-align: center; }
.stat-item .value { font-size: 24px; font-weight: bold; color: #333; }
.stat-item .label { color: #666; margin-top: 5px; }
.btn { padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; margin: 10px; }
.btn-green { background: #4CAF50; color: white; }
.btn-orange { background: #FF9800; color: white; }
.btn:hover { opacity: 0.9; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
th { background: #f2f2f2; }
.date-display { color: #666; margin-bottom: 20px; }
.message { background: #4CAF50; color: white; padding: 10px; border-radius: 5px; margin-bottom: 20px; text-align: center; }
.time-display { font-size: 24px; text-align: center; margin: 20px 0; }
.logout-btn { background: #f44336; margin-right: 10px; }
</style>
</head>
<body>
<div class="header">
<h2>工时管理系统</h2>
<div class="user-info">
<span>欢迎,<?php echo htmlspecialchars($_SESSION['employee_name']); ?></span>
<a href="logout.php" class="logout-btn">退出登录</a>
</div>
</div>
<div class="container">
<?php if (isset($message)): ?>
<div class="message"><?php echo $message; ?></div>
<?php endif; ?>
<div class="welcome">
<div class="time-display" id="current-time"></div>
<div class="date-display" id="current-date"></div>
<!-- 打卡区域 -->
<div style="text-align: center; margin-top: 20px;">
<?php if (!$today_record || empty($today_record['check_in'])): ?>
<form method="POST" action="" style="display: inline;">
<input type="hidden" name="action" value="check_in">
<button type="submit" class="btn btn-green">上班打卡</button>
</form>
<?php else: ?>
<p>✓ 今日已上班打卡:<?php echo date('Y-m-d H:i:s', strtotime($today_record['check_in'])); ?></p>
<?php if (empty($today_record['check_out'])): ?>
<form method="POST" action="" style="display: inline; margin-top: 10px;">
<input type="hidden" name="action" value="check_out">
<button type="submit" class="btn btn-orange">下班打卡</button>
</form>
<?php else: ?>
<p>✓ 今日已下班打卡:<?php echo date('Y-m-d H:i:s', strtotime($today_record['check_out'])); ?></p>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<!-- 本月统计 -->
<div class="card">
<h3>📊 本月统计</h3>
<div class="stats-grid">
<div class="stat-item">
<div class="value"><?php echo $stats['total_days'] ?? 0; ?></div>
<div class="label">工作天数</div>
</div>
<div class="stat-item">
<div class="value"><?php echo number_format(($stats['total_hours'] ?? 0), 2); ?>h</div>
<div class="label">总工时</div>
</div>
<div class="stat-item">
<div class="value"><?php echo number_format(($stats['avg_hours'] ?? 0), 2); ?>h</div>
<div class="label">平均工时</div>
</div>
<div class="stat-item">
<div class="value"><?php echo number_format(($stats['total_overtime'] ?? 0), 2); ?>h</div>
<div class="label">加班时间</div>
</div>
<div class="stat-item">
<div class="value"><?php echo $stats['late_days'] ?? 0; ?></div>
<div class="label">迟到次数</div>
</div>
</div>
</div>
<!-- 近7天记录 -->
<div class="card">
<h3>📋 最近7天打卡记录</h3>
<table>
<thead>
<tr>
<th>日期</th>
<th>上班时间</th>
<th>下班时间</th>
<th>工作时长</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<?php while ($record = $week_records->fetch_assoc()): ?>
<tr>
<td><?php echo $record['work_date']; ?></td>
<td><?php echo $record['check_in'] ? date('H:i:s', strtotime($record['check_in'])) : '--'; ?></td>
<td><?php echo $record['check_out'] ? date('H:i:s', strtotime($record['check_out'])) : '--'; ?></td>
<td><?php echo $record['work_hours'] ? round($record['work_hours'], 2) . 'h' : '--'; ?></td>
<td>
<?php
$status_color = $record['status'] == '正常' ? 'green' : 'orange';
echo "<span style='color: $status_color;'>{$record['status']}</span>";
?>
</td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
</div>
<!-- 功能链接 -->
<div class="card">
<h3>🔧 快捷操作</h3>
<div style="display: flex; flex-wrap: wrap; gap: 10px;">
<a href="leave_request.php" class="btn btn-green">申请请假</a>
<a href="attendance_report.php" class="btn btn-orange">考勤报表</a>
<a href="profile.php" class="btn" style="background: #2196F3; color: white;">个人信息</a>
</div>
</div>
</div>
<!-- JavaScript -->
<script>
// 实时时间显示
function updateTime() {
const now = new Date();
const timeElement = document.getElementById('current-time');
const dateElement = document.getElementById('current-date');
timeElement.textContent = now.toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
dateElement.textContent = now.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
});
}
// 每秒更新时间
setInterval(updateTime, 1000);
updateTime();
</script>
</body>
</html>
退出登录 (logout.php)
<?php
session_start();
session_unset();
session_destroy();
header('Location: login.php');
exit;
?>
注册页面 (register.php)
<?php
require_once 'config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$employee_code = sanitize($_POST['employee_code']);
$name = sanitize($_POST['name']);
$password = $_POST['password'];
$confirm_password = $_POST['confirm_password'];
$email = sanitize($_POST['email']);
$department = sanitize($_POST['department']);
// 密码验证
if ($password !== $confirm_password) {
$error = "两次输入的密码不一致";
} elseif (strlen($password) < 6) {
$error = "密码长度至少6位";
} else {
$conn = db_connect();
// 检查员工号是否已存在
$check_sql = "SELECT id FROM employees WHERE employee_code = ?";
$check_stmt = $conn->prepare($check_sql);
$check_stmt->bind_param("s", $employee_code);
$check_stmt->execute();
$check_result = $check_stmt->get_result();
if ($check_result->num_rows > 0) {
$error = "员工号已存在";
} else {
// 密码加密
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
// 插入新员工
$insert_sql = "INSERT INTO employees (employee_code, name, password, email, department)
VALUES (?, ?, ?, ?, ?)";
$insert_stmt = $conn->prepare($insert_sql);
$insert_stmt->bind_param("sssss", $employee_code, $name, $hashed_password, $email, $department);
if ($insert_stmt->execute()) {
$_SESSION['registration_success'] = true;
redirect('login.php');
} else {
$error = "注册失败,请稍后重试";
}
}
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">员工注册 - 工时系统</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Microsoft YaHei', sans-serif; background: #f5f5f5; display: flex; justify-content: center; align-items: center; min-height: 100vh; }
.register-container { background: white; padding: 40px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); width: 100%; max-width: 500px; margin: 20px; }
h1 { text-align: center; margin-bottom: 30px; color: #333; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; color: #555; }
input[type="text"], input[type="password"], input[type="email"] { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; }
button { width: 100%; padding: 12px; background: #4CAF50; color: white; border: none; border-radius: 5px; font-size: 16px; cursor: pointer; }
button:hover { background: #45a049; }
.error { background: #f44336; color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; text-align: center; }
.back-link { text-align: center; margin-top: 15px; display: block; color: #4CAF50; text-decoration: none; }
</style>
</head>
<body>
<div class="register-container">
<h1>员工注册</h1>
<?php if (isset($error)): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST" action="">
<div class="form-group">
<label>员工号 *</label>
<input type="text" name="employee_code" required>
</div>
<div class="form-group">
<label>姓名 *</label>
<input type="text" name="name" required>
</div>
<div class="form-group">
<label>密码 * (至少6位)</label>
<input type="password" name="password" required minlength="6">
</div>
<div class="form-group">
<label>确认密码 *</label>
<input type="password" name="confirm_password" required>
</div>
<div class="form-group">
<label>邮箱</label>
<input type="email" name="email">
</div>
<div class="form-group">
<label>部门</label>
<input type="text" name="department" placeholder="如:技术部、市场部等">
</div>
<button type="submit">注 册</button>
<a href="login.php" class="back-link" style="color: #4CAF50;">已注册?返回登录</a>
</form>
</div>
</body>
</html>
请假申请页面 (leave_request.php)
<?php
require_once 'config.php';
require_login();
$conn = db_connect();
$employee_id = $_SESSION['employee_id'];
// 处理请假申请
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$leave_type = sanitize($_POST['leave_type']);
$start_date = sanitize($_POST['start_date']);
$end_date = sanitize($_POST['end_date']);
$reason = sanitize($_POST['reason']);
// 检查日期有效性
if ($start_date > $end_date) {
$error = "开始日期不能大于结束日期";
} else {
$insert_sql = "INSERT INTO leave_requests (employee_id, leave_type, start_date, end_date, reason)
VALUES (?, ?, ?, ?, ?)";
$stmt = $conn->prepare($insert_sql);
$stmt->bind_param("issss", $employee_id, $leave_type, $start_date, $end_date, $reason);
if ($stmt->execute()) {
$success = "请假申请已提交,等待审批";
} else {
$error = "提交失败,请稍后重试";
}
}
}
// 获取我的请假记录
$leave_sql = "SELECT * FROM leave_requests WHERE employee_id = ? ORDER BY created_at DESC";
$leave_stmt = $conn->prepare($leave_sql);
$leave_stmt->bind_param("i", $employee_id);
$leave_stmt->execute();
$leave_records = $leave_stmt->get_result();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">请假申请 - 工时系统</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Microsoft YaHei', sans-serif; background: #f5f5f5; }
.header { background: #333; color: white; padding: 15px 30px; display: flex; justify-content: space-between; align-items: center; }
.header a { color: white; text-decoration: none; }
.container { margin: 20px auto; max-width: 1200px; padding: 0 20px; }
.card { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; color: #555; }
input[type="text"], input[type="date"], select, textarea { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; }
textarea { height: 100px; }
button { padding: 12px 24px; background: #4CAF50; color: white; border: none; border-radius: 5px; font-size: 16px; cursor: pointer; }
button:hover { background: #45a049; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
th { background: #f2f2f2; }
.success { background: #4CAF50; color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; }
.error { background: #f44336; color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; }
.back-btn { display: inline-block; background: #333; color: white; padding: 10px 20px; border-radius: 5px; text-decoration: none; }
.status-pending { color: orange; }
.status-approved { color: green; }
.status-rejected { color: red; }
</style>
</head>
<body>
<div class="header">
<h2>请假管理</h2>
<a href="dashboard.php">← 返回首页</a>
</div>
<div class="container">
<?php if (isset($success)): ?>
<div class="success"><?php echo $success; ?></div>
<?php endif; ?>
<?php if (isset($error)): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<!-- 请假申请表单 -->
<div class="card">
<h3>📝 申请请假</h3>
<form method="POST" action="">
<div class="form-group">
<label>请假类型</label>
<select name="leave_type" required>
<option value="">请选择类型</option>
<option value="事假">事假</option>
<option value="病假">病假</option>
<option value="年假">年假</option>
<option value="调休">调休</option>
</select>
</div>
<div class="form-group">
<label>开始日期</label>
<input type="date" name="start_date" required>
</div>
<div class="form-group">
<label>结束日期</label>
<input type="date" name="end_date" required>
</div>
<div class="form-group">
<label>请假原因</label>
<textarea name="reason" required></textarea>
</div>
<button type="submit">提交申请</button>
</form>
</div>
<!-- 我的请假记录 -->
<div class="card">
<h3>📋 我的请假记录</h3>
<table>
<thead>
<tr>
<th>类型</th>
<th>开始日期</th>
<th>结束日期</th>
<th>原因</th>
<th>状态</th>
<th>申请时间</th>
</tr>
</thead>
<tbody>
<?php while ($record = $leave_records->fetch_assoc()): ?>
<tr>
<td><?php echo $record['leave_type']; ?></td>
<td><?php echo $record['start_date']; ?></td>
<td><?php echo $record['end_date']; ?></td>
<td><?php echo htmlspecialchars($record['reason']); ?></td>
<td>
<?php
$status_class = strtolower($record['status']);
echo "<span class='status-$status_class'>{$record['status']}</span>";
?>
</td>
<td><?php echo $record['created_at']; ?></td>
</tr>
<?php endwhile; ?>
<?php if ($leave_records->num_rows === 0): ?>
<tr>
<td colspan="6" style="text-align: center; color: #999;">暂无请假记录</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</body>
</html>
考勤报表页面 (attendance_report.php)
<?php
require_once 'config.php';
require_login();
$conn = db_connect();
$employee_id = $_SESSION['employee_id'];
// 处理日期筛选
$selected_month = isset($_GET['month']) ? $_GET['month'] : date('Y-m');
$month_start = $selected_month . '-01';
$month_end = date('Y-m-t', strtotime($selected_month));
// 获取报表数据
$sql = "SELECT
work_date,
check_in,
check_out,
work_hours,
status,
overtime_hours
FROM time_records
WHERE employee_id = ? AND work_date BETWEEN ? AND ?
ORDER BY work_date DESC";
$stmt = $conn->prepare($sql);
$stmt->bind_param("iss", $employee_id, $month_start, $month_end);
$stmt->execute();
$records = $stmt->get_result();
// 汇总统计
$summary_sql = "SELECT
COUNT(*) as total_days,
SUM(work_hours) as total_work_hours,
SUM(overtime_hours) as total_overtime,
AVG(work_hours) as avg_work_hours,
SUM(status = '迟到') as late_count,
SUM(status = '早退') as early_count
FROM time_records
WHERE employee_id = ? AND work_date BETWEEN ? AND ?";
$summary_stmt = $conn->prepare($summary_sql);
$summary_stmt->bind_param("iss", $employee_id, $month_start, $month_end);
$summary_stmt->execute();
$summary = $summary_stmt->get_result()->fetch_assoc();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">考勤报表 - 工时系统</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Microsoft YaHei', sans-serif; background: #f5f5f5; }
.header { background: #333; color: white; padding: 15px 30px; display: flex; justify-content: space-between; align-items: center; }
.header a { color: white; text-decoration: none; }
.container { margin: 20px auto; max-width: 1400px; padding: 0 20px; }
.card { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.month-selector { margin-bottom: 20px; }
select, button { padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 14px; }
button { background: #4CAF50; color: white; border: none; cursor: pointer; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit,