摘要:在企业办公场景中,“会议室冲突”、“幽灵会议”(预订了但没人来)以及“设备报修难”是行政管理的三大痛点。本文将带你通过 Python 全栈技术(Django/FastAPI + Vue3),手把手构建一套智能会议室预约与管理系统。不仅解决预订冲突,更引入邮件通知与可视化报表,让行政管理更“Smart”。
关键词:Python, Django, Vue3, 全栈开发, Redis, 智能系统
🚀 一、 项目背景与需求分析
你是否经历过抱着电脑冲进会议室,却发现里面已经有人在开会?或者系统显示满房,实际上很多会议室空空荡荡?
为了解决这些问题,我们需要一个系统满足以下核心需求:
-
冲突检测:毫秒级判断时间段是否被占用。
-
流程闭环:预订 -> 审批(可选) -> 通知 -> 签到 -> 结束/评价。
-
智能释放:预订后15分钟未签到,系统自动释放资源。
-
数据可视化:管理员可查看会议室利用率热力图。
🛠 二、 技术栈选型 (Tech Stack)
作为 Python 全栈项目,我们追求开发效率与系统性能的平衡:
-
后端 (Backend):
-
框架:
Django+Django REST Framework (DRF)(利用其强大的Admin后台和ORM) 或FastAPI(追求高性能异步)。本项目演示采用 Django。 -
异步任务:
Celery+Redis(处理定时释放、邮件发送)。
-
-
前端 (Frontend):
-
框架:
Vue 3+Vite+TypeScript。 -
UI库:
Element Plus(后台管理) +Vant UI(移动端适配)。 -
图表:
ECharts(可视化看板)。
-
-
数据库 (Database):
-
PostgreSQL(推荐) 或MySQL。
-
-
部署 (DevOps):
-
Docker+Nginx+Gunicorn。
-
💾 三、 数据库核心设计 (Schema Design)
核心在于处理“人”、“房间”与“时间”的关系。
1. MeetingRoom (会议室表)
| 字段名 | 类型 | 描述 |
| name | Char | 会议室名称 (e.g., "101 极客厅") |
| capacity | Int | 容纳人数 |
| has_projector | Bool | 是否有投影仪 |
| status | SmallInt | 状态 (可用/维修中) |
2. Booking (预订记录表)
这是系统中最繁忙的表,需要建立合理的索引。
Python
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Booking(models.Model):
STATUS_CHOICES = (
(0, '已取消'),
(1, '已预订'),
(2, '进行中'),
(3, '已完成'),
)
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="预订人")
room = models.ForeignKey('MeetingRoom', on_delete=models.CASCADE, verbose_name="会议室")
start_time = models.DateTimeField(verbose_name="开始时间")
end_time = models.DateTimeField(verbose_name="结束时间")
subject = models.CharField(max_length=100, verbose_name="会议主题")
status = models.SmallIntegerField(choices=STATUS_CHOICES, default=1)
class Meta:
# 联合索引,加速按时间查询会议室
indexes = [
models.Index(fields=['room', 'start_time', 'end_time']),
]
💻 四、 核心功能代码实现
1. 解决最棘手的问题:预订冲突检测
这是面试中最常问的逻辑:如何判断两个时间段是否重叠?
逻辑公式:Max(StartA, StartB) < Min(EndA, EndB) 即为重叠,或者简单理解为 新开始时间 < 已有结束时间 且 新结束时间 > 已有开始时间。
Python
# utils/validators.py
from django.core.exceptions import ValidationError
from django.db.models import Q
from .models import Booking
def check_room_availability(room_id, start_time, end_time, exclude_booking_id=None):
"""
检查会议室在指定时间段是否可用
"""
conflicts = Booking.objects.filter(
room_id=room_id,
status__in=[1, 2], # 只检查已预订和进行中的
start_time__lt=end_time, # 核心逻辑
end_time__gt=start_time # 核心逻辑
)
if exclude_booking_id:
conflicts = conflicts.exclude(id=exclude_booking_id)
if conflicts.exists():
return False, "该时间段已被预订"
return True, "可用"
2. API 视图层 (ViewSet)
在保存预订前,利用事务(Atomic)确保数据一致性。
Python
# views.py
from rest_framework import viewsets, status
from rest_framework.response import Response
from django.db import transaction
from .serializers import BookingSerializer
class BookingViewSet(viewsets.ModelViewSet):
queryset = Booking.objects.all()
serializer_class = BookingSerializer
def create(self, request, *args, **kwargs):
room_id = request.data.get('room')
start = request.data.get('start_time')
end = request.data.get('end_time')
# 1. 校验时间逻辑
if start >= end:
return Response({"error": "结束时间必须晚于开始时间"}, status=400)
# 2. 开启事务与行级锁 (select_for_update) 防止高并发下的超卖
with transaction.atomic():
# 这里可以根据业务量级决定是否锁表,或者使用乐观锁
is_available, msg = check_room_availability(room_id, start, end)
if not is_available:
return Response({"error": msg}, status=409)
# 3. 创建预订
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
# 4. (可选) 触发异步任务:发送邮件通知
# send_confirmation_email.delay(serializer.data['id'])
return Response(serializer.data, status=status.HTTP_201_CREATED)
📊 五、 前端实现与可视化 (Vue3 + ECharts)
在前端,我们需要展示一个直观的“时间轴视图”。
JavaScript
// GanttChart.vue (伪代码思路)
<template>
<div class="schedule-container">
<div v-for="room in rooms" :key="room.id" class="room-row">
<div class="room-name">{{ room.name }}</div>
<div class="time-slots">
<div
v-for="booking in room.bookings"
class="booking-block"
:style="calculateStyle(booking)"
@click="showDetail(booking)"
>
{{ booking.user_name }}
</div>
</div>
</div>
</div>
</template>
<script setup>
// 计算色块的左边距(开始时间)和宽度(持续时长)
const calculateStyle = (booking) => {
const startHour = new Date(booking.start_time).getHours();
const duration = (new Date(booking.end_time) - new Date(booking.start_time)) / 3600000;
return {
left: `${startHour * 4.16}%`, // 假设一天24小时,每小时占4.16%
width: `${duration * 4.16}%`,
backgroundColor: '#409EFF'
}
}
</script>
🌟 六、 进阶功能:让系统变“Smart”
-
二维码签到:
-
每个会议室门口贴一个静态二维码(包含
room_id)。 -
用户到达后扫描,前端获取地理位置(GPS)校验是否在公司范围内,调用后端
/api/checkin/接口。
-
-
智能释放 (Celery Beat):
-
设置定时任务,每5分钟轮询一次。
-
逻辑:如果
当前时间 > 会议开始时间 + 15分钟且status == '已预订'(未变为进行中/已签到),则自动取消会议,并记录违规。
-
📝 七、 总结
通过这个项目,我们不仅复习了 Django 的 ORM 操作和 RestFramework 的 API 设计,还深入处理了时间冲突算法和数据库事务并发等后端难点。同时,前端的时间轴可视化也锻炼了 Vue3 的组件封装能力。
项目代码
945

被折叠的 条评论
为什么被折叠?



