fix(地下室): 搜索改为 AJAX 原地刷新 + 体验优化(#974) - #1000
Conversation
- 搜索表单 onsubmit 拦截,fetch POST 带 X-Requested-With 头 - 视图检测 AJAX:返回 JSON(cards_html/banner_html/bookable_count/scope) 而非整页 - 新增可复用片段 _room_cards.html(房间卡片) 与 _room_search_banner.html(结果横幅) - JS 仅替换对应区块 .doctor-slider 内部与 .room-search-banner,保留滚动位置,体验丝滑 - 校验错误以 JSON error 返回并在横幅区就地提示;清除按钮清空后 AJAX 还原完整列表 - 非 AJAX 提交仍返回整页(向后兼容)
- 三个区块(功能房/研讨室/俄文楼)搜索彼此独立,由 search_scope 决定只筛选对应列表 - 搜索框增强: 支持按日期、时段(开始-结束)、使用人数组合筛选,含过去时间/超7天/时段/人数校验提示 - 一键展开按钮移入居中 .room-toolbar, 不再紧贴标题 - 展开后隐藏房间图片(.doc-img display:none), 提供居中快速查找输入框, 按房间号/名称实时过滤, 移动端免滑动 - 新增可复用搜索片段 _room_search.html - 清理旧 GET 日期搜索残留的孤儿代码
- 修复上一提交引入的回归:新增的 _room_has_free_slot 被插入到 @identity_check 与 def index 之间,导致装饰器错误地套在辅助函数上, 而 index 视图丢失登录校验(未授权可访问)。现将辅助函数移到装饰器之前。 - 日期搜索的越界提示此前写入 search_code/search_message,但 Appointment/index.html 只渲染 warn_code/warn_message,导致搜索过去日期或 7 天以外时页面静默刷新、无任何反馈,这也是"搜索没作用"体感的一部分。 改为调用 utils.global_messages.wrong 写入 warn_* 字段。
- 日期搜索:选中预约日期后不再跳转 arrange_talk,改为在首页直接按“当天仍有空位” 过滤功能房/研讨室/俄文楼三个房间列表,并显示筛选横幅与“清除筛选”入口。 新增 _room_has_free_slot 辅助函数,复用 web_func.timerange2idlist,判定任一 30 分钟时间块空闲即视为可预约。 - 房间列表一键展开:三个房间区块标题增加“一键展开/收起”按钮,通过 slick unslick + CSS flex-wrap 网格展示全部房间,免去横向滑动。 - 实时人数(Yuanpei-Intelligence#974 第一项)经核查为硬件故障:Room.Rpresent/Rlatest_time 仅由 摄像头 POST 到 cameracheck 写入,无软件估算路径,故未做代码改动。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b35c98dd90
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| @identity_check(redirect_field_name='origin', auth_func=lambda x: True) | ||
| def _room_has_free_slot(room, search_date): |
There was a problem hiding this comment.
Put
identity_check back on index
When an authenticated user submits any nonempty search date, index() calls this decorated helper with a Room as its first argument, so login_required treats the room as a request and raises while accessing request.user. The same misplaced decorator leaves index() itself accessible without the login and underground-permission checks it previously had. Remove the duplicate helper definition and restore this decorator immediately above index.
AGENTS.md reference: AGENTS.md:L306-L313
Useful? React with 👍 / 👎.
| # 处理单人预约 | ||
| if "students" not in contents.keys(): | ||
| contents['students'] = [applicant_id] | ||
| contents['students'] = [contents['Sid']] | ||
| else: | ||
| contents['students'].append(applicant_id) | ||
| contents['students'].append(contents['Sid']) |
There was a problem hiding this comment.
Bind the appointment initiator to the session user
The checked-in checkout form deliberately omits Sid and Sname, so an ordinary submission now raises KeyError here. If a caller supplies Sid manually, _add_appoint() trusts it as major_student, allowing one authenticated account to create appointments whose credit, conflicts, notifications, and ownership are attributed to another participant. Continue using the session-derived applicant and discard any posted identity fields.
AGENTS.md reference: AGENTS.md:L312-L316
Useful? React with 👍 / 👎.
| @identity_check(redirect_field_name='origin') | ||
| def checkout_appoint(request: UserRequest): |
There was a problem hiding this comment.
Restore CSRF protection on appointment checkout
This session-authenticated view creates appointments on POST, but the commit removes its csrf_protect decorator while the project has global CsrfViewMiddleware disabled. Consequently, requests without a valid CSRF token reach the mutation path, permitting cross-site reservation creation whenever the browser sends the user's session cookie. Restore the explicit decorator around this view.
AGENTS.md reference: AGENTS.md:L467-L479
Useful? React with 👍 / 👎.
| start_time = datetime(contents['year'], contents['month'], contents['day'], | ||
| *map(int, contents['starttime'].split(":"))) | ||
| end_time = datetime(contents['year'], contents['month'], contents['day'], | ||
| *map(int, contents['endtime'].split(":"))) |
There was a problem hiding this comment.
Validate the submitted slot against the displayed selection
For a crafted checkout POST, these caller-controlled date and time fields now directly define the appointment instead of being verified against the selected weekday, the current seven-day window, and the server-derived startid/endid. Since create_appoint() only rejects past or conflicting times, a user can reserve far-future dates or hours outside the room slot they selected; missing fields also produce a 500. Restore the removed absolute-date validation and derive times from the validated slot IDs.
AGENTS.md reference: AGENTS.md:L514-L516
Useful? React with 👍 / 👎.
| <div class="room-search"> | ||
| <form method="POST"> | ||
| {% csrf_token %} | ||
| <input type="hidden" name="search_scope" value="{{ scope }}"> |
There was a problem hiding this comment.
Connect the AJAX search UI to the index page
The newly added scoped search partial is never included by index.html, and the reviewed tree contains no fetch handler or server-side partial-response branch. The live page therefore keeps its legacy date-only synchronous POST form, while the new scope, time, capacity, card, and banner fragments are dead code, so the advertised AJAX in-place search is unavailable. Include the partials in each room section and wire submissions to an AJAX response.
Useful? React with 👍 / 👎.
cherry-pick 时误将 upstream/develop 对 _add_appoint/checkout_appoint 的 安全加固(applicant 参数、防御性清除 Sid/Sname、@csrf_protect、 _checkout_slot_fields 时段校验)一并回退,导致 Appointment 测试失败。 现以 upstream/develop 的 views.py 为基底,仅叠加 Yuanpei-Intelligence#974 的地下室搜索: - 新增 _room_has_free_slot 辅助函数(仅一次,修正原重复定义) - index 视图日期搜索改成本地展示可预约地下室,不再跳转 其余加固逻辑保持不变。
地下室预约搜索由整页刷新改为 AJAX 原地过滤(三个区块独立,由 search_scope 决定);新增结果横幅与房间卡片片段;修复 index 视图装饰器位置与日期搜索提示。基于 upstream/develop 重建。