From 4af2c311bf7a770b563b2d2859c218843d1dbaf7 Mon Sep 17 00:00:00 2001 From: zhx Date: Wed, 17 Jun 2026 12:52:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=BA=E5=99=A8=E4=BA=BA=E6=88=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/rooms/hooks/useRobotRoomsPage.js | 19 ++++++++++++-- src/features/rooms/pages/RoomRobotPage.jsx | 2 +- src/features/rooms/schema.test.ts | 26 +++++++++++++++++++ src/features/rooms/schema.ts | 8 ++++-- 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 src/features/rooms/schema.test.ts diff --git a/src/features/rooms/hooks/useRobotRoomsPage.js b/src/features/rooms/hooks/useRobotRoomsPage.js index a8eb65d..1024c54 100644 --- a/src/features/rooms/hooks/useRobotRoomsPage.js +++ b/src/features/rooms/hooks/useRobotRoomsPage.js @@ -145,12 +145,22 @@ export function useRobotRoomsPage() { }; const selectOwnerRobot = (robot) => { - setForm((current) => ({ ...current, ownerRobotUserId: robot?.userId || "" })); + const ownerRobotUserId = robot?.userId || ""; + setForm((current) => ({ + ...current, + ownerRobotUserId, + candidateRobotUserIds: (current.candidateRobotUserIds || []).filter((userId) => String(userId) !== String(ownerRobotUserId)), + })); }; const selectCandidateRobots = (robots) => { setCandidatesTouched(true); - setForm((current) => ({ ...current, candidateRobotUserIds: robots.map((robot) => robot.userId).filter(Boolean) })); + setForm((current) => ({ + ...current, + candidateRobotUserIds: robots + .map((robot) => robot.userId) + .filter((userId) => userId && String(userId) !== String(current.ownerRobotUserId)), + })); }; const selectGiftIds = (key, gifts) => { @@ -177,6 +187,10 @@ export function useRobotRoomsPage() { const selected = new Set((form.candidateRobotUserIds || []).map(String)); return availableRobotsState.options.filter((item) => selected.has(String(item.userId))); }, [availableRobotsState.options, form.candidateRobotUserIds]); + const candidateRobotOptions = useMemo( + () => availableRobotsState.options.filter((item) => String(item.userId) !== String(form.ownerRobotUserId)), + [availableRobotsState.options, form.ownerRobotUserId], + ); const selectedGiftOptions = useMemo(() => { const selected = new Set((form.giftIds || []).map(String)); return giftOptionsState.options.filter((item) => selected.has(giftId(item))); @@ -194,6 +208,7 @@ export function useRobotRoomsPage() { availableRobots: availableRobotsState.options, changeStatus, closeAction, + candidateRobotOptions, data, error, form, diff --git a/src/features/rooms/pages/RoomRobotPage.jsx b/src/features/rooms/pages/RoomRobotPage.jsx index 6bc5033..b076797 100644 --- a/src/features/rooms/pages/RoomRobotPage.jsx +++ b/src/features/rooms/pages/RoomRobotPage.jsx @@ -184,7 +184,7 @@ export function RoomRobotPage() { isOptionEqualToValue={(option, value) => option.userId === value.userId} loading={page.availableRobotsLoading} noOptionsText="当前无数据" - options={page.availableRobots} + options={page.candidateRobotOptions} renderInput={(params) => ( { + test("preserves int64 robot user ids as strings", () => { + const payload = parseForm(robotRoomCreateSchema, { + candidateRobotUserIds: ["325455441691676672"], + giftIds: ["84"], + luckyComboMax: "10000", + luckyComboMin: "100", + luckyGiftIds: ["28"], + luckyPauseMaxMs: "20000", + luckyPauseMinMs: "5000", + maxRobotCount: "8", + minRobotCount: "2", + normalGiftIntervalMs: "10000", + ownerRobotUserId: "325379237278126080", + visibleRegionId: 0, + }); + + expect(payload.ownerRobotUserId).toBe("325379237278126080"); + expect(payload.candidateRobotUserIds).toEqual(["325455441691676672"]); + }); +}); diff --git a/src/features/rooms/schema.ts b/src/features/rooms/schema.ts index 1e075d5..cb33d5c 100644 --- a/src/features/rooms/schema.ts +++ b/src/features/rooms/schema.ts @@ -2,6 +2,10 @@ import { z } from "zod"; const optionalText = (max: number, message: string) => z.string().trim().max(max, message).optional().default(""); const roomSeatCandidates = [10, 15, 20, 25, 30] as const; +const robotUserIdSchema = (message: string) => z + .union([z.string(), z.number()]) + .transform((value) => String(value).trim()) + .refine((value) => /^[1-9]\d*$/.test(value), message); const pinTypeSchema = z .string() .trim() @@ -72,7 +76,7 @@ export const roomPinCreateSchema = z export const robotRoomCreateSchema = z .object({ - candidateRobotUserIds: z.array(z.coerce.number().int().positive()).min(1, "请选择候选机器人"), + candidateRobotUserIds: z.array(robotUserIdSchema("请选择候选机器人")).min(1, "请选择候选机器人"), giftIds: z.array(z.string().trim().min(1)).min(1, "请选择普通礼物合集"), luckyComboMax: z.coerce.number().int().min(1, "幸运礼物连击范围不正确"), luckyComboMin: z.coerce.number().int().min(1, "幸运礼物连击范围不正确"), @@ -82,7 +86,7 @@ export const robotRoomCreateSchema = z maxRobotCount: z.coerce.number().int().min(1, "机器人数量范围不正确"), minRobotCount: z.coerce.number().int().min(1, "机器人数量范围不正确"), normalGiftIntervalMs: z.coerce.number().int().min(1000, "普通礼物频次不正确"), - ownerRobotUserId: z.coerce.number().int().positive("请选择房主机器人"), + ownerRobotUserId: robotUserIdSchema("请选择房主机器人"), visibleRegionId: z.coerce.number().int().min(0, "区域 ID 不正确").default(0), }) .refine((value) => value.maxRobotCount >= value.minRobotCount, {