This repository has been archived on 2026-06-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
wsh5485 2c0e7cbb5f style: 将容器最大宽度从1200px调整为1400px
统一修改多个页面容器的最大宽度,以提供更宽敞的布局空间
2025-12-12 16:56:04 +08:00

542 lines
21 KiB
PHP

<?php
// 公告页面 - 显示今日待处理的洗车预约
// 包含数据库连接
require_once 'db_connect.php';
// 设置页面标题
$page_title = '待办列表 - 洗车预约系统';
// 设置默认时区为北京时间
date_default_timezone_set('Asia/Shanghai');
// 获取选择的日期,默认为当前日期
$selected_date = isset($_GET['selected_date']) ? $_GET['selected_date'] : date('Y-m-d');
// 验证日期格式
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $selected_date)) {
$selected_date = date('Y-m-d');
}
// 获取选择日期的开始和结束时间
$day_start = $selected_date . ' 00:00:00';
$day_end = $selected_date . ' 23:59:59';
// 查询选择日期的预约(不包括已取消的)
try {
$stmt = $pdo->prepare("SELECT b.*, p.package_name, p.services
FROM bookings b
LEFT JOIN packages p ON b.package_id = p.id
WHERE b.start_time BETWEEN :day_start AND :day_end
AND b.status != '已取消'
ORDER BY b.start_time ASC");
$stmt->execute(['day_start' => $day_start, 'day_end' => $day_end]);
$today_bookings = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 计算今日待处理和已完成的数量
$pending_count = 0;
$completed_count = 0;
foreach ($today_bookings as $booking) {
if ($booking['status'] == '已完成') {
$completed_count++;
} else {
$pending_count++;
}
}
} catch (PDOException $e) {
$error_message = '获取今日预约失败: ' . $e->getMessage();
$today_bookings = [];
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="format-detection" content="telephone=no">
<meta name="description" content="今日洗车待办列表,直观展示今日需要处理的洗车预约">
<meta name="keywords" content="公告,今日待办,预约列表,洗车管理">
<title>张老师撸车(私家车库)工作室</title>
<link rel="stylesheet" href="style.css">
<script src="mobile-nav.js" defer></script>
<style>
/* 公告页面特有样式 */
.announcement-container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
.page-header {
background: linear-gradient(135deg, #4ECDC4 0%, #44A08D 100%);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 30px;
text-align: center;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
}
.page-header h1 {
margin: 0;
font-size: 2.5rem;
font-weight: 700;
}
.page-header .subtitle {
margin-top: 10px;
font-size: 1.2rem;
opacity: 0.9;
}
.stats-card {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
display: flex;
justify-content: space-around;
flex-wrap: wrap;
gap: 20px;
}
.stat-item {
text-align: center;
flex: 1;
min-width: 120px;
padding: 15px;
border-radius: 8px;
background: #f8f9fa;
transition: transform 0.3s ease;
}
.stat-item:hover {
transform: translateY(-3px);
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.stat-number {
font-size: 2rem;
font-weight: bold;
margin: 10px 0;
}
.stat-pending .stat-number {
color: #ff9800;
}
.stat-completed .stat-number {
color: #4caf50;
}
.stat-total .stat-number {
color: #2196f3;
}
.booking-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 20px;
margin-top: 20px;
}
.booking-card {
background: white;
border-radius: 10px;
padding: 25px;
box-shadow: 0 2px 15px rgba(0,0,0,0.08);
transition: all 0.3s ease;
border-left: 5px solid #2196f3;
}
.booking-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.12);
}
.booking-card.urgent {
border-left-color: #ff9800;
}
.booking-card.completed {
border-left-color: #4caf50;
opacity: 0.8;
}
.booking-time {
font-size: 1.1rem;
font-weight: 600;
color: #333;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid #f0f0f0;
}
.booking-details {
margin-bottom: 20px;
}
.detail-row {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
padding: 5px 0;
}
.detail-label {
font-weight: 600;
color: #666;
min-width: 80px;
}
.detail-value {
color: #333;
text-align: right;
flex: 1;
}
.booking-status {
display: inline-block;
padding: 5px 15px;
border-radius: 20px;
font-size: 0.9rem;
font-weight: 600;
margin-top: 10px;
}
.status-pending {
background: #fff3cd;
color: #856404;
}
.status-confirmed {
background: #d1ecf1;
color: #0c5460;
}
.status-processing {
background: #cce7ff;
color: #004085;
}
.status-completed {
background: #d4edda;
color: #155724;
}
.services-list {
background: #f8f9fa;
padding: 10px;
border-radius: 5px;
margin-top: 10px;
}
.services-list h4 {
margin: 0 0 8px 0;
font-size: 0.9rem;
color: #666;
}
.services-list ul {
margin: 0;
padding-left: 20px;
font-size: 0.9rem;
}
/* 客服备注样式 */
.service-notes {
margin-top: 12px;
padding: 12px;
background-color: #f8f9fa;
border-left: 4px solid #007bff;
border-radius: 4px;
}
.service-notes h4 {
margin-top: 0;
margin-bottom: 8px;
font-size: 14px;
color: #007bff;
}
.service-notes p {
margin: 0;
font-size: 13px;
color: #495057;
line-height: 1.5;
}
.no-bookings {
text-align: center;
padding: 60px 20px;
background: white;
border-radius: 10px;
color: #666;
font-size: 1.2rem;
}
@media (max-width: 768px) {
.booking-list {
grid-template-columns: 1fr;
}
.detail-row {
flex-direction: column;
gap: 5px;
}
.detail-value {
text-align: left;
font-weight: 500;
}
}
</style>
</head>
<body>
<div class="container">
<header class="header">
<button class="mobile-menu-toggle" onclick="toggleMobileMenu()">
<span></span>
<span></span>
<span></span>
</button>
<h1>🚗 张老师撸车工作室 - 今日待办</h1>
<nav class="nav">
<a href="index.php" class="nav-link">预约洗车</a>
<a href="bookings.php" class="nav-link">预约管理</a>
<a href="pending_bookings.php" class="nav-link">待处理预约</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link">VIP管理</a>
<a href="announcement.php" class="nav-link active">今日待办</a>
</nav>
</header>
<!-- 移动端导航菜单 -->
<div class="mobile-nav-overlay" onclick="closeMobileMenu()"></div>
<nav class="mobile-nav">
<a href="index.php" class="nav-link">预约洗车</a>
<a href="bookings.php" class="nav-link">预约管理</a>
<a href="pending_bookings.php" class="nav-link">待处理预约</a>
<a href="packages.php" class="nav-link">套餐管理</a>
<a href="vip.php" class="nav-link">VIP管理</a>
<a href="announcement.php" class="nav-link active">今日待办</a>
</nav>
<div class="announcement-container">
<!-- 页面标题区 -->
<div class="page-header enhanced-card">
<h1>📋 待办列表</h1>
<div class="subtitle"><?php echo date('Y年m月d日', strtotime($selected_date)); ?> - <?php echo date('l', strtotime($selected_date)); ?></div>
</div>
<!-- 日期选择器 -->
<div class="enhanced-card" style="text-align: center; padding: 20px; margin-bottom: 30px;">
<form method="GET" style="display: flex; justify-content: center; align-items: center; gap: 15px; flex-wrap: wrap;">
<label for="selected_date" style="font-weight: 600; color: #333;">选择日期:</label>
<input type="date" id="selected_date" name="selected_date" value="<?php echo $selected_date; ?>" style="padding: 10px 15px; border: 2px solid #e0e0e0; border-radius: 5px; font-size: 1rem; width: 200px; transition: border-color 0.3s ease;">
<button type="submit" class="btn btn-primary" style="padding: 10px 25px; font-size: 1rem;">查看预约</button>
</form>
</div>
<!-- 统计信息卡片 -->
<div class="stats-card enhanced-card">
<div class="stat-item stat-pending">
<div class="stat-label">待处理</div>
<div class="stat-number"><?php echo $pending_count; ?></div>
</div>
<div class="stat-item stat-completed">
<div class="stat-label">已完成</div>
<div class="stat-number"><?php echo $completed_count; ?></div>
</div>
<div class="stat-item stat-total">
<div class="stat-label">总计</div>
<div class="stat-number"><?php echo count($today_bookings); ?></div>
</div>
</div>
<!-- 错误提示 -->
<?php if (isset($error_message)): ?>
<div class="error-message"><?php echo $error_message; ?></div>
<?php endif; ?>
<!-- 预约列表 -->
<?php if (empty($today_bookings)): ?>
<div class="no-bookings">
<div style="font-size: 3rem; margin-bottom: 20px;">🎉</div>
<div>今日暂无预约</div>
</div>
<?php else: ?>
<div class="booking-list">
<?php foreach ($today_bookings as $booking): ?>
<?php
// 确定卡片类型
$card_class = '';
if ($booking['status'] == '已完成') {
$card_class = 'completed';
} else {
// 检查是否紧急(15分钟内开始的预约)
$now = new DateTime();
$start_time = new DateTime($booking['start_time']);
$interval = $now->diff($start_time);
$minutes_diff = $interval->days * 24 * 60 + $interval->h * 60 + $interval->i;
if ($minutes_diff >= 0 && $minutes_diff <= 15 && $booking['status'] != '进行中') {
$card_class = 'urgent';
}
}
// 格式化服务项目列表
$services = [];
if (!empty($booking['services'])) {
$services = explode(',', $booking['services']);
}
?>
<div class="enhanced-card booking-card <?php echo $card_class; ?>">
<div class="booking-time">
🕒 <?php echo date('H:i', strtotime($booking['start_time'])); ?> - <?php echo date('H:i', strtotime($booking['end_time'])); ?>
<span class="status-badge status-<?php echo strtolower($booking['status']); ?>">
<?php echo $booking['status']; ?>
</span>
</div>
<div class="booking-details details-grid">
<div class="detail-item">
<span class="detail-label">客户姓名</span>
<span class="detail-value"><?php echo htmlspecialchars($booking['customer_name']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">联系电话</span>
<span class="detail-value"><?php echo htmlspecialchars($booking['phone']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">车型</span>
<span class="detail-value"><?php echo htmlspecialchars($booking['car_model']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">车牌号</span>
<span class="detail-value"><?php echo htmlspecialchars($booking['car_number']); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">套餐</span>
<span class="detail-value"><?php echo htmlspecialchars($booking['package_name'] ?: '自定义套餐'); ?></span>
</div>
<div class="detail-item">
<span class="detail-label">时长</span>
<span class="detail-value"><?php echo $booking['duration']; ?> 分钟</span>
</div>
<div class="detail-item">
<span class="detail-label">价格</span>
<span class="detail-value">¥<?php echo $booking['total_price']; ?></span>
</div>
<div class="detail-item">
<span class="detail-label">会员类型</span>
<span class="detail-value"><?php echo $booking['member_type']; ?></span>
</div>
<!-- 服务项目列表 -->
<?php if (!empty($services)): ?>
<div class="services-list">
<h4>服务项目:</h4>
<ul>
<?php foreach ($services as $service): ?>
<li><?php echo trim(htmlspecialchars($service)); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<!-- 客服备注 -->
<?php if (!empty($booking['custom_services'])): ?>
<div class="service-notes">
<h4>客服备注:</h4>
<p><?php echo htmlspecialchars($booking['custom_services']); ?></p>
</div>
<?php endif; ?>
<!-- 备注信息 -->
<?php if (!empty($booking['notes'])): ?>
<div class="detail-row">
<span class="detail-label">客户备注</span>
<span class="detail-value"><?php echo htmlspecialchars($booking['notes']); ?></span>
</div>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<script>
// 移动端优化脚本
document.addEventListener('DOMContentLoaded', function() {
// 为按钮添加触摸反馈
var buttons = document.querySelectorAll('.btn');
for (var i = 0; i < buttons.length; i++) {
var btn = buttons[i];
btn.addEventListener('touchstart', function() {
this.style.transform = 'translateY(1px)';
});
btn.addEventListener('touchend', function() {
this.style.transform = 'translateY(-2px)';
});
}
// 检测设备类型
var isMobile = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
if (isMobile) {
document.body.classList.add('mobile-device');
}
// 自动刷新功能(默认开启,每5分钟刷新一次)
setInterval(function() {
window.location.reload();
}, 5 * 60 * 1000);
// 将倒计时添加到页面标题旁边
var pageHeader = document.querySelector('.page-header');
var refreshInfo = document.createElement('div');
refreshInfo.style.cssText = 'font-size:0.9rem;color:#666;margin-top:5px;';
if (pageHeader) {
pageHeader.appendChild(refreshInfo);
} else {
// 如果找不到header,就添加到body
refreshInfo.style.cssText = 'font-size:0.9rem;color:#333;background:#fff;padding:8px 12px;border-radius:4px;box-shadow:0 2px 6px rgba(0,0,0,0.2);border:1px solid #ddd;margin:20px;';
document.body.appendChild(refreshInfo);
}
// 显示北京时间及距离下次刷新倒计时
function updateBeijingTime() {
var now = new Date();
var beijingTime = new Date(now.getTime() + 8 * 60 * 60 * 1000); // 转为北京时间
var hours = String(beijingTime.getUTCHours()).padStart(2, '0');
var minutes = String(beijingTime.getUTCMinutes()).padStart(2, '0');
var seconds = String(beijingTime.getUTCSeconds()).padStart(2, '0');
// 计算距离下次刷新的剩余时间
var refreshInterval = 5 * 60 * 1000; // 5分钟
var elapsed = now.getTime() % refreshInterval;
var remaining = refreshInterval - elapsed;
var remMinutes = Math.floor(remaining / 60000);
var remSeconds = Math.floor((remaining % 60000) / 1000);
// 更新显示
if (refreshInfo) {
refreshInfo.textContent = '北京时间 ' + hours + ':' + minutes + ':' + seconds + ' | 下次刷新 ' + remMinutes + '分' + remSeconds + '秒';
}
}
// 每秒更新一次
setInterval(updateBeijingTime, 1000);
updateBeijingTime(); // 初始化显示
});
</script>
</body>
</html>