会议室预定

CRM之会议室预订系统代码

 views

 1 from django.shortcuts import render,redirect,HttpResponse
 2 from book import models
 3 from django.contrib import auth
 4 from django.http import JsonResponse
 5 import datetime,json
 6 from django.db.models import Q
 7 # Create your views here.
 8 
 9 def index(request):
10     today = datetime.datetime.now().date()
11     date = request.GET.get("date",today)
12 
13 
14     res = {"status": 200, }
15     if request.method=="POST":
16 
17         ############添加选中的数据##################
18 
19         post_data = request.POST.get("post_data")
20         data_info = json.loads(post_data)
21         add_data = data_info["ADD"]
22         del_data =data_info["DEL"]
23         choose_date = request.POST.get("choose_date")
24 
25         book_list = []
26         for rid,add_tid_list in add_data.items():
27             for tid in add_tid_list:
28                 book=models.Book(user=request.user,date=choose_date or date,room_id=rid,time_id=tid)
29                 book_list.append(book)
30         if book_list:
31             models.Book.objects.bulk_create(book_list)   #############采用批量添加提高运行效率,逼格稍微好一点
32 
33 
34         ###################删除要取消的数据################
35         # {'DEL': {'1': ['5', '6', '7']}, 'ADD': {}}
36         remove_booking = Q()
37         for rid,del_tid_list in del_data.items():
38             for tid in del_tid_list:
39                 temp=Q()
40                 temp.connector="AND"
41                 temp.children.append(("user_id",request.user.pk,))
42                 temp.children.append(("room_id", rid))
43                 temp.children.append(("time_id", tid))
44                 temp.children.append(("date", choose_date or date))
45                 remove_booking.add(temp,"OR")
46         if remove_booking:
47             models.Book.objects.filter(remove_booking).delete()
48             '''
49             同样是为了增加运行效率,减少与数据的的撞库,
50             先用Q语句将关系构建好,房间与时间,用户id,日期保持且的关系,每个td之间保持或的关系
51             '''
52 
53 
54         return JsonResponse(res)
55 
56 
57     time_list = models.time_choices
58     room_list = models.Room.objects.all()
59     book_list = list(models.Book.objects.filter(date=date).values("time_id","user__username","room_id"))
60 
61     return render(request,"index.html",locals())
62 
63 
64 
65 
66 def login(request):
67     if request.method =="POST":
68         username=request.POST.get("user")
69         pwd=request.POST.get("pwd")
70         user = auth.authenticate(username=username,password=pwd)  ##验证用户名和密码
71 
72         if user:
73             auth.login(request,user)   ##注入session信息
74             return redirect("/index/")
75     else:
76         return render(request,"login.html",locals())
View Code

models

 1 from django.db import models
 2 from django.contrib.auth.models import AbstractUser
 3 # Create your models here.
 4 
 5 time_choices = (
 6     (1, '8:00'),
 7     (2, '9:00'),
 8     (3, '10:00'),
 9     (4, '11:00'),
10     (5, '12:00'),
11     (6, '13:00'),
12     (7, '14:00'),
13     (8, '15:00'),
14     (9, '16:00'),
15     (10, '17:00'),
16     (11, '18:00'),
17     (12, '19:00'),
18     (13, '20:00'),
19 )
20 
21 
22 class UserInfo(AbstractUser):
23     pass
24 '''
25 注意若继承django自带的auth.User表格,需要到settings中更改配置参数为:
26 AUTH_USER_MODEL="book.UserInfo"
27 '''
28 
29 
30 class Room(models.Model):
31     caption = models.CharField(max_length=32)
32     num = models.IntegerField()
33     def __str__(self):  #__str__ 的作用,在调用显示该类时,返回一个友好的,用户可读的字符串作为对象的str(自己命名)
34         return self.caption
35 
36 class Book(models.Model):
37     '''
38     预定记录表
39     '''
40     room = models.ForeignKey(to=Room,on_delete=models.CASCADE)
41     user = models.ForeignKey(to=UserInfo,on_delete=models.CASCADE)
42     date = models.DateField()
43     time_id = models.IntegerField(choices=time_choices)
44     class meta():
45         unique_together = (
46             ('room', 'date', 'time_id'),
47         )
48         '''
49                  unique_together会将以下三个字段关联,防止下面三个字段同时出现重复
50 
51                 '''
52 
53     def __str__(self):
54         return str(self.user)+"已预定"+str(self.room)
View Code

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
     {% csrf_token %}
    <input type="text" name="user">
    <input type="password" name="pwd">
    <input type="submit" value="提交">
</form>

</body>
</html>
View Code

index.html

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>Title</title>
  6      <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
  7     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  8     <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
  9     <script src="/static/datetimepicker/bootstrap-datetimepicker.min.js"></script>
 10     <script src="/static/datetimepicker/bootstrap-datetimepicker.zh-CN.js"></script>
 11 
 12 
 13     <style>
 14         .active{
 15             background-color: darkseagreen!important;
 16             color: white;
 17             text-align: center;
 18         }
 19         .other_active{
 20              background-color: burlywood;
 21             color: white;
 22             text-align: center;
 23         }
 24         .td_active{
 25             background-color: deepskyblue;
 26         }
 27     </style>
 28 </head>
 29 
 30 <body>
 31 <h3>会议室预定</h3>
 32 
 33 {#日历插件#}
 34   <div class="clearfix">
 35         <div class="calender pull-right">
 36             <div class='input-group' style=" 230px;">
 37                 <input type='text' class="form-control" id='datetimepicker11' placeholder="请选择日期"/>
 38             <span class="input-group-addon">
 39                 <span class="glyphicon glyphicon-calendar">
 40                 </span>
 41             </span>
 42 
 43             </div>
 44         </div>
 45   </div>
 46 
 47 
 48     <div class="row">
 49         <div class="col-md-9 col-md-offset-2">
 50             <table class="table table-hover table-bordered">
 51                 <thead>
 52                     <tr>
 53                         <th>会议室/时间</th>
 54                         {% for time in time_list %}
 55                                 <th>{{ time.1 }}</th>
 56                         {% endfor %}
 57                     </tr>
 58                 </thead>
 59                 <tbody>
 60 
 61                       {% for room in room_list %}
 62                         <tr>
 63                             <td>
 64                                  {{ room.caption }}({{ room.num }})
 65                             </td>
 66                             {% for time in time_list %}
 67                                 <td class="item" rid="{{ room.pk  }}" tid="{{ time.0  }}"></td>
 68                             {% endfor %}
 69 
 70                         </tr>
 71                     {% endfor %}
 72 
 73                 </tbody>
 74             </table>
 75             <button class="btn btn-primary pull-right keep">保存</button>
 76         </div>
 77     </div>
 78 
 79 
 80 <script>
 81     book_list= {{ book_list|safe }}
 82 
 83 
 84         //显示已经预定的消息
 85     $.each(book_list,function (i,book_info) {
 86         let rid = book_info["room_id"];
 87         let tid = book_info["time_id"];
 88         let name = book_info["user__username"];
 89 
 90         var c=`[rid=${rid}][tid=${tid}]` ; //取得同时具备rid和tid与循环所得的td
 91         if ("{{ request.user.username }}"===name){
 92              $(c).addClass("active").html(name).removeClass("item");//添加active标签并且注意要移去item属性
 93         }
 94         else{
 95              $(c).addClass("other_active").html(name).removeClass("item");
 96         }
 97     })
 98     // 显示选中的td标签
 99     //采用时间委派,是为了防止取消预订是点击生成新的item无法出发事件
100      $("body").on("click",".item",function () {
101         $(this).toggleClass("td_active")   //toggleClass 用法 当存在td_active属性时去掉,不存在该属性时添加
102 
103     });
104 
105     // 不能预定其他人已经预定房间
106      $(".other_active").click(function () {
107          alert("该房间已被预订")
108      })
109 
110      // 取消预定
111     $(".active").click(function (e) {
112         $(this).removeClass("active").addClass("cancel item").html("");
113         $(this).unbind("click");   //防止事件绑定溢出,取消绑定暂时
114         e.stopPropagation();
115     })
116 
117 
118     //提交选中标签
119     var POST_DATA = {
120                 DEL: {
121                    // 2:[2,3,4]
122                 },
123                 ADD: {
124                    // 1:[1,2,3,4,5]
125                 },
126             };
127 
128     $(".keep").click(function () {
129 
130     //处理添加的数据
131     $(".td_active").each(function () {
132          ///此处是为了防止客户,本来点击取消,而后又撤销而导致重复添加数据,导致报错
133        if($(this).hasClass("cancel")){
134            return
135        }
136 
137         let tid = $(this).attr("tid")
138         let rid = $(this).attr("rid")
139 
140         if (POST_DATA.ADD[rid]) {    ///js取字典的形式需要去了解下,不熟悉
141             POST_DATA.ADD[rid].push(tid)
142         }
143         else {
144             POST_DATA.ADD[rid] = [tid]
145         }
146     })
147 
148      //处理提交取消的数据
149     $(".cancel").each(function () {
150         ///此处是为了防止客户,本来点击取消,而后又撤销而导致提交时把不想删掉的删除掉
151         if($(this).hasClass("td_active")){
152            return
153        }
154 
155         let tid = $(this).attr("tid")
156         let rid = $(this).attr("rid")
157 
158         if(POST_DATA.DEL[rid]){    ///js取字典的形式需要去了解下,不熟悉
159             POST_DATA.DEL[rid].push(tid)
160         }
161         else{
162             POST_DATA.DEL[rid]=[tid]
163         }
164     })
165 
166     //ajax将数据打包付出
167     $.ajax({
168             url:"/index/",
169             type:"post",
170             data:{post_data:JSON.stringify(POST_DATA),
171                   choose_date: location.search.slice(6),
172             },
173             success:function (res) {
174                 if (res["status"]){
175                     location.href="/index/"
176                 }
177             }
178         })
179 
180 
181         })
182 
183 ///添加事件插件
184      $('#datetimepicker11').datetimepicker({
185             minView: "month",
186             language: "zh-CN",
187             sideBySide: true,
188             format: 'yyyy-mm-dd',
189             startDate: new Date(),
190             bootcssVer: 3,
191             autoclose: true,
192         }).on('changeDate', book_query);
193         function book_query(ev) {
194             console.log(ev.date);
195             CHOSEN_DATE = ev.date.Format('yyyy-MM-dd');
196             location.href = "?date=" + CHOSEN_DATE
197 
198         }
199 
200           //  1 构建日期类型
201     // Date.prototype.Format 用于自己构建类方法
202         Date.prototype.Format = function (fmt) { //author: meizz
203             var o = {
204                 "M+": this.getMonth() + 1, //月份
205                 "d+": this.getDate(), //206                 "h+": this.getHours(), //小时
207                 "m+": this.getMinutes(), //208                 "s+": this.getSeconds(), //209                 "q+": Math.floor((this.getMonth() + 3) / 3), //季度
210                 "S": this.getMilliseconds() //毫秒
211             };
212             if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
213             for (var k in o)
214                 if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
215             return fmt;
216         };
217 
218 
219 
220 </script>
221 
222 </body>
223 </html>
View Code
原文地址:https://www.cnblogs.com/Mixtea/p/10447198.html