修复账号禁用及队列场次状态规则

问题与需求:后台禁用员工后旧会话仍可继续访问;实时队列跨天误读昨日场次;项目暂停后需禁止取号但允许叫号。

修复思路:账号权限变更时撤销会话并同步前端登录态;实时查询统一按项目时区当天场次过滤;拆分取号与叫号的状态校验,并补充前后端及 PostgreSQL 回归测试。
This commit is contained in:
brother7 committed 2026-07-30 12:02:05 +08:00
1 parent 0e1ac400dc
commit 17d296263c
14 files changed
+752 -54

No files matched your search

+19 -3
View File
@@ -2,6 +2,8 @@ import { act, fireEvent, render, screen, waitFor, within } from "@testing-librar
import { beforeEach, describe, expect, it, vi } from "vitest";
import { MemoryRouter } from "react-router-dom";
const staffPageTestState = vi.hoisted(() => ({ projectStatus: "RUNNING" }));
vi.mock("../components/AppShell", () => ({
AppShell: ({ children, variant }: { children: React.ReactNode; variant?: string }) => (
<div data-testid="app-shell" data-variant={variant}>{children}</div>
@@ -11,7 +13,7 @@ vi.mock("../hooks/usePollingResource", () => ({
usePollingResource: (_load: unknown, options: { intervalMs: number }) => options.intervalMs === 60_000
? {
data: { projects: [
{ id: "project-1", name: "东门观光车", status: "RUNNING", batch_size: 2, call_mode: "BOTH", default_call_ticket_count: 2, max_call_ticket_count: 20, default_call_people_count: 5, max_call_people_count: 30, min_party_size: 1, max_party_size: 8 },
{ id: "project-1", name: "东门观光车", status: staffPageTestState.projectStatus, batch_size: 2, call_mode: "BOTH", default_call_ticket_count: 2, max_call_ticket_count: 20, default_call_people_count: 5, max_call_people_count: 30, min_party_size: 1, max_party_size: 8 },
{ id: "project-2", name: "西门观光车", status: "RUNNING", batch_size: 2, call_mode: "BOTH", default_call_ticket_count: 2, max_call_ticket_count: 20, default_call_people_count: 5, max_call_people_count: 30, min_party_size: 1, max_party_size: 8 },
] },
loading: false,
@@ -23,7 +25,7 @@ vi.mock("../hooks/usePollingResource", () => ({
}
: {
data: {
project: { id: "project-1", name: "东门观光车", status: "RUNNING", batch_size: 2, call_mode: "BOTH", default_call_ticket_count: 2, max_call_ticket_count: 20, default_call_people_count: 5, max_call_people_count: 30, min_party_size: 1, max_party_size: 8 },
project: { id: "project-1", name: "东门观光车", status: staffPageTestState.projectStatus, batch_size: 2, call_mode: "BOTH", default_call_ticket_count: 2, max_call_ticket_count: 20, default_call_people_count: 5, max_call_people_count: 30, min_party_size: 1, max_party_size: 8 },
revision: 8,
waiting: Array.from({ length: 25 }, (_, index) => ({
id: `waiting-${index + 1}`,
@@ -82,7 +84,21 @@ function renderScene(path: string) {
}
describe("StaffPage scene-focused H5", () => {
beforeEach(() => sessionStorage.setItem("scenic-current-project", "project-1"));
beforeEach(() => {
staffPageTestState.projectStatus = "RUNNING";
sessionStorage.setItem("scenic-current-project", "project-1");
});
it("allows calling but blocks ticket creation while the project is paused", () => {
staffPageTestState.projectStatus = "PAUSED";
renderScene("/staff");
expect(screen.getByRole("button", { name: "快速叫下一个号" })).toBeEnabled();
expect(screen.queryByText("当前项目未开放叫号")).not.toBeInTheDocument();
fireEvent.click(screen.getByRole("link", { name: "取号" }));
expect(screen.getByRole("button", { name: "创建排队号码" })).toBeDisabled();
expect(screen.getByText("当前不可取号")).toBeInTheDocument();
});
it("keeps the call scene focused on the active batch and the primary call action", () => {
renderScene("/staff");