自习室预订系统问题:已预订时段复选框替换为Reserved失效
自习室预订时段锁定问题解决方案
核心问题分析
你的代码思路方向是对的,但大概率卡在这几个关键环节:
- 后端未传递带星期/日期的完整时段信息,导致模板判断和JS逻辑匹配出错
- Flask向JS传递
bookedTimeslots的方式有误,变量未正确注入页面 - localStorage是单浏览器本地存储,无法实现多用户共享状态,这个方案本身不适用多用户预订场景
第一步:修正后端数据库逻辑
首先要确保数据库存储**「星期+时段」的组合数据**,否则周一的07:00和周二的07:00会被判定为同一个时段。示例表结构:
CREATE TABLE booked_slots ( id INTEGER PRIMARY KEY AUTOINCREMENT, day_of_week TEXT NOT NULL, -- 存储'Monday'/'Tuesday'这类星期标识 timeslot TEXT NOT NULL, user_id TEXT NOT NULL -- 可选,记录预订用户的标识 );
Flask视图函数中,查询对应星期的已预订时段,同时传递给模板和JS:
from flask import render_template, request, redirect, json import sqlite3 def get_booked_timeslots(target_day): conn = sqlite3.connect('your_database.db') cursor = conn.cursor() cursor.execute("SELECT timeslot FROM booked_slots WHERE day_of_week = ?", (target_day,)) booked_list = [row[0] for row in cursor.fetchall()] conn.close() return booked_list @app.route('/booking/<day>') def booking_page(day): booked_timeslots = get_booked_timeslots(day) # 把数据转成JSON格式,方便注入JS booked_timeslots_js = json.dumps(booked_timeslots) return render_template('booking.html', day=day, booked_timeslots=booked_timeslots, booked_timeslots_js=booked_timeslots_js)
第二步:修正前端模板渲染
模板中的判断逻辑需要确保booked_timeslots是当前星期的专属列表,同时提交表单时要传递星期信息:
<div id="{{ day }}" class="tabcontent"> <table class="tableAvailability"> <th>Time</th> <th>Availability</th> {% for timeslot in ['07:00 - 08:00', '08:00 - 09:00', '09:00 - 10:00', '10:00 - 11:00', '11:00 - 12:00', '12:00 - 13:00', '13:00 - 14:00','14:00 - 15:00', '15:00 - 16:00'] %} <tr> <td>{{ timeslot }}</td> <td> {% if timeslot in booked_timeslots %} <span style="color: #dc3545;">Reserved</span> {% else %} <input type="checkbox" id="checkbox-{{loop.index}}" name="timeslots" value="{{ timeslot }}" data-day="{{ day }}" data-time="{{ timeslot }}" onclick="displayCheckbox()"> {% endif %} </td> </tr> {% endfor %} </table> <!-- 隐藏字段传递当前星期,提交表单时用 --> <input type="hidden" name="day" value="{{ day }}"> </div>
第三步:修正JavaScript数据注入与逻辑
之前的JS代码中bookedTimeslots变量未被正确赋值,需要在模板中先注入数据:
<!-- 在引入外部JS前,先注入后端传递的已预订列表 --> <script> const bookedTimeslots = {{ booked_timeslots_js|safe }}; </script> <script src="your_script.js"></script>
然后修正JS逻辑,实现复选框替换(如果模板渲染已经处理了初始状态,JS更多用于预订后的动态刷新):
window.onload = function() { const checkboxes = document.querySelectorAll('input[type=checkbox][name=timeslots]'); checkboxes.forEach(checkbox => { const timeslot = checkbox.dataset.time; if (bookedTimeslots.includes(timeslot)) { checkbox.remove(); // 移除复选框 const reservedText = document.createElement('span'); reservedText.textContent = ' Reserved'; reservedText.style.color = '#dc3545'; checkbox.parentNode.appendChild(reservedText); } }); };
第四步:预订提交后的后端处理
用户提交表单时,后端要将星期+时段存入数据库,同时做重复预订校验:
@app.route('/submit-booking', methods=['POST']) def submit_booking(): day = request.form.get('day') selected_timeslots = request.form.getlist('timeslots') conn = sqlite3.connect('your_database.db') cursor = conn.cursor() for slot in selected_timeslots: # 先检查该时段是否已被预订,避免重复插入 cursor.execute("SELECT * FROM booked_slots WHERE day_of_week = ? AND timeslot = ?", (day, slot)) if not cursor.fetchone(): # 用用户IP或登录ID作为user_id,这里示例用IP cursor.execute("INSERT INTO booked_slots (day_of_week, timeslot, user_id) VALUES (?, ?, ?)", (day, slot, request.remote_addr)) conn.commit() conn.close() return redirect(f'/booking/{day}')
关于localStorage的说明
localStorage仅存储在当前用户的浏览器中,其他用户无法获取该数据,完全不适合多用户共享的预订系统,必须使用服务器端数据库(如sqlite3)存储已预订信息,才能保证所有用户看到的时段状态一致。
内容的提问来源于stack exchange,提问作者onuk98
相关产品推荐
相关产品推荐

