会议室预定

效果:

主要代码:

from django.db import models
from django.contrib.auth.models import AbstractUser


class UserInfo(AbstractUser):
    telephone = models.CharField(max_length=32)

    def __str__(self):
        return self.username


class MeetingRoom(models.Model):
    """
    会议室表
    """
    name = models.CharField(max_length=32)
    num = models.IntegerField()  # 容纳人数

    def __str__(self):
        return self.name


class BookRecord(models.Model):
    """
    会议室预定信息
    """
    time_choices = (
        (1, "8:00"),
        (2, "9:00"),
        (3, "10:00"),
        (4, "11:00"),
        (5, "12:00"),
        (6, "13:00"),
        (7, "14:00"),
        (8, "15:00"),
        (9, "16:00"),
        (10, "17:00"),
        (11, "18:00"),
        (12, "19:00"),
        (13, "20:00"),
    )
    user = models.ForeignKey("UserInfo")
    room = models.ForeignKey(to="MeetingRoom")
    time_id = models.IntegerField(choices=time_choices)
    book_date = models.DateField()

    class Meta:
        unique_together = (
            ("room", "book_date", "time_id"),
        )

    def __str__(self):
        return str(self.user) + "预定了" + str(self.room)
models.py
import json
import datetime
from django.db.models import Q
from django.contrib import auth
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.utils.safestring import mark_safe

from app01 import models


def login(request):
    """
    登录
    :param request:
    :return:
    """
    if request.method == "GET":
        return render(request, "login.html")
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        user = auth.authenticate(username=username, password=password)
        if user:
            auth.login(request, user)
            return redirect("/")
        else:
            return render(request, "login.html")


def log_out(request):
    """
    退出登录
    :param request:
    :return:
    """
    auth.logout(request)
    return redirect("/")

def index(request):
    """
    首页
    :param request:
    :return:
    """
    now = datetime.datetime.now().date()
    book_date = request.GET.get("book_date", now)
    time_choices = models.BookRecord.time_choices
    room_list = models.MeetingRoom.objects.all()
    try:
        book_record_list = models.BookRecord.objects.filter(book_date=book_date)
    except Exception:
        book_record_list = models.BookRecord.objects.filter(book_date=now)
    table_body_html = ""
    for room in room_list:
        table_body_html += "<tr><td>{}({})</td>".format(room.name, room.num)
        for time_choice in time_choices:
            book_flag = False  # 预定标志
            book_record = None
            for book_record in book_record_list:
                if book_record.room.pk == room.pk and book_record.time_id == time_choice[0]:
                    # 判断成立,意味这个单元格已被预定
                    book_flag = True
                    book_record = book_record
                    break
            if book_flag:
                if request.user.pk == book_record.user.pk:
                    table_body_html += "<td class='active-self item' room-id={} time-id={}>{}</td>".format(room.pk, time_choice[0], "")
                else:
                    table_body_html += "<td class='active-others item' room-id={} time-id={}>{}</td>".format(room.pk, time_choice[0], book_record.user.username)
            else:
                table_body_html += "<td class='item' room-id={} time-id={}></td>".format(room.pk, time_choice[0])
        table_body_html += "</tr>"
    data = {
        "time_choices": time_choices,
        "table_body_html": mark_safe(table_body_html)
    }
    return render(request, "index.html", data)


def book_meeting_room(request):
    """
    处理预定
    :param request:
    :return:
    """
    rep = {"code": 1000}
    if not request.user.username:
        rep["code"] = 1001
        return JsonResponse(rep)
    post_data = json.loads(request.POST.get("post_data"))  # {"DEL":{"1":["3","7"]},"ADD":{"2":["1","2"],"3":["1"]}}
    choose_date = request.POST.get("choose_date")
    try:
        # 添加预定
        book_list = []
        for room_id, time_id_list in post_data["ADD"].items():
            for time_id in time_id_list:
                obj = models.BookRecord(user=request.user, room_id=int(room_id), time_id=int(time_id), book_date=choose_date)
                book_list.append(obj)
        models.BookRecord.objects.bulk_create(book_list)
        # 删除预定
        for room_id, time_id_list in post_data["DEL"].items():
            for time_id in time_id_list:
                models.BookRecord.objects.filter(room_id=room_id, user_id=request.user.pk, time_id=int(time_id), book_date=choose_date).delete()
    except Exception:
        rep["code"] = 1002
    return JsonResponse(rep)
views.py
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Index</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/sweetalert/sweetalert.css">
    <link rel="stylesheet" href="/static/datetimepicker/bootstrap-datetimepicker.min.css">
    <style>
        .navbar{
            border-radius: unset;
        }
        .navbar-nav{
            float: right;
        }
        @media (max- 800px){
            .navbar-nav{
                float: none;
            }
        }
        .active-self{
            background-color: #228B22;
            color: white;
        }
        .active-others{
            background-color: #CD3333;
            color: white;
        }
        .active-checked{
            background-color: #87CEFA;
            color: white;
        }
        .input-date{
             206px;
        }
        .form_datetime{
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                    aria-expanded="false" aria-controls="navbar">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <span class="navbar-brand">会议室预定</span>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
                {% with user=request.user.username %}
                    {% if user %}
                        <li><a href="/">{{ user }}</a></li>
                        <li><a href="/logout">注销</a></li>
                    {% else %}
                        <li><a href="/login">登录</a></li>
                        <li><a href="#">注册</a></li>
                    {% endif %}
                {% endwith %}
            </ul>
        </div>
    </div>
</nav>
<div class="container">

    <div class="form_datetime pull-right">
        <div class="input-group input-date">
            <input type="text" class="form-control" id="datetimepicker" autocomplete="off"  placeholder="请选择日期">
            <span class="input-group-addon">
                <span class="glyphicon glyphicon-calendar"></span>
            </span>
        </div>
    </div>

    <table class="table table-bordered table-striped">
        <thead>
        <tr>
            <th id="is-login" user="{{ request.user.username }}">会议室/时间</th>
            {% for time_choice in time_choices %}
                <th>{{ time_choice.1 }}</th>
            {% endfor %}
        </tr>
        </thead>
        <tbody>
            {{ table_body_html }}
        </tbody>
    </table>

    <button class="btn btn-primary pull-right save">保存</button>
    {% csrf_token %}
</div>
<script src="/static/jquery-3.3.1.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script src="/static/sweetalert/sweetalert.min.js"></script>
<script src="/static/datetimepicker/bootstrap-datetimepicker.min.js"></script>
<script src="/static/datetimepicker/bootstrap-datetimepicker.zh-CN.js"></script>
<script src="/static/index.js"></script>
</body>
</html>
index.html
// 用来保存用户提交信息
var POST_DATA = {
    "ADD": {},
    "DEL": {}
};

// 为td绑定单击事件
function ClickTableTd() {
    $(".item").click(function () {
        var isLogin = $("#is-login");
        var user = isLogin.attr("user");
        if (user === "") {
            location.href = "/login/"
        } else {
            var roomId = $(this).attr("room-id");
            var timeId = $(this).attr("time-id");
            // 取消预定
            if ($(this).hasClass("active-self")) {
                $(this).removeClass("active-self").empty();
                if (POST_DATA.DEL[roomId]) {
                    POST_DATA.DEL[roomId].push(timeId);
                } else {
                    POST_DATA.DEL[roomId] = [timeId];
                }
            // 取消临时预定
            } else if ($(this).hasClass("active-checked")) {
                $(this).removeClass("active-checked").empty();
                if (POST_DATA.ADD[roomId].length === 1) {
                    delete POST_DATA.ADD[roomId];
                }
                else {
                    var index = POST_DATA.ADD[roomId].indexOf(timeId);
                    POST_DATA.ADD[roomId].splice(index, 1);
                }
            // 其他
            } else {
                // 他人已预定
                if ($(this).hasClass("active-others")) {
                    swal("该会议室已被他人预定")
                // 添加临时预定
                } else {
                    $(this).addClass("active-checked").text("");
                    if (POST_DATA.ADD[roomId]) {
                        POST_DATA.ADD[roomId].push(timeId);
                    } else {
                        POST_DATA.ADD[roomId] = [timeId];
                    }
                }
            }
        }
        console.log(POST_DATA)
    })
}
ClickTableTd();

// 日期格式化方法
Date.prototype.pd = function (fmt) {
    var o = {
        "M+": this.getMonth() + 1,  //月份
        "d+": this.getDate(),       //"h+": this.getHours(),      //小时
        "m+": this.getMinutes(),    //"s+": this.getSeconds(),    //"q+": Math.floor((this.getMonth() + 3) / 3), //季度
        "S": this.getMilliseconds() //毫秒
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
};

// 日历插件
$("#datetimepicker").datetimepicker({
        minView: "month",
        format: "yyyy-mm-dd",
        language: "zh-CN",
        startDate: new Date(),
        autoclose: true,
        todayBtn: true,
}).on("changeDate", queryBookInfo);
function queryBookInfo(e) {
    CHOOSE_DATE = e.date.pd("yyyy-MM-dd");
    location.href = "/?book_date=" + CHOOSE_DATE;
}

// 日期
if (location.search.slice(11)){
    CHOOSE_DATE = location.search.slice(11)
} else {
    CHOOSE_DATE = new Date().pd("yyyy-MM-dd");
}

// 发送Ajax
$(".save").click(function () {
    $.ajax({
        url:"/book/",
        type:"post",
        data:{
           "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
           "choose_date": CHOOSE_DATE,
           "post_data": JSON.stringify(POST_DATA)
        },
        success: function (rep) {
            if (rep.code === 1000) {
                location.href = "/";
            } else if (rep.code === 1001){
                location.href = "login";
            } else {
                swal("预定的会议室已被他人预定");
                location.href = "/"
            }
        }
    })
});
index.js

完整zip包:

https://files.cnblogs.com/files/believepd/msbr.zip

1

原文地址:https://www.cnblogs.com/believepd/p/10664276.html