From 8c23d7e6a7f531f904a273e4e4b9b4e093901da0 Mon Sep 17 00:00:00 2001 From: zhx Date: Tue, 23 Jun 2026 11:53:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A1=A8=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.test.jsx | 2 + src/features/cp-config/pages/CPConfigPage.jsx | 1 - src/features/rooms/hooks/useRobotRoomsPage.js | 42 +- src/features/rooms/pages/RoomRobotPage.jsx | 705 +++++++++--------- src/features/rooms/rooms.module.css | 10 +- 5 files changed, 365 insertions(+), 395 deletions(-) diff --git a/src/App.test.jsx b/src/App.test.jsx index 73c1155..79f54b2 100644 --- a/src/App.test.jsx +++ b/src/App.test.jsx @@ -118,6 +118,8 @@ test("renders cp config route with an authenticated session", async () => { renderWithRoute("/activities/cp-config"); expect((await screen.findAllByText("CP配置")).length).toBeGreaterThan(0); + expect(await screen.findByText("已加载 1 条 · 共 1 条")).toBeInTheDocument(); + expect(screen.queryByText("共 1 条")).not.toBeInTheDocument(); }); test("admin routes declare menu code and permission", () => { diff --git a/src/features/cp-config/pages/CPConfigPage.jsx b/src/features/cp-config/pages/CPConfigPage.jsx index 78f4b2d..20fea3e 100644 --- a/src/features/cp-config/pages/CPConfigPage.jsx +++ b/src/features/cp-config/pages/CPConfigPage.jsx @@ -93,7 +93,6 @@ export function CPConfigPage() { rowKey={(item) => isApplicationsTab ? item.applicationId : item.relationshipId || `${item.userA?.userId}-${item.userB?.userId}` } - total={activePage.total} /> diff --git a/src/features/rooms/hooks/useRobotRoomsPage.js b/src/features/rooms/hooks/useRobotRoomsPage.js index ac3ca34..20ef30a 100644 --- a/src/features/rooms/hooks/useRobotRoomsPage.js +++ b/src/features/rooms/hooks/useRobotRoomsPage.js @@ -82,7 +82,6 @@ export function useRobotRoomsPage() { const { showToast } = useToast(); const [activeAction, setActiveAction] = useState(""); const [availableRobotsState, setAvailableRobotsState] = useState({ error: "", loading: false, options: [] }); - const [candidatesTouched, setCandidatesTouched] = useState(false); const [form, setForm] = useState(emptyForm); const [giftOptionsState, setGiftOptionsState] = useState({ error: "", loading: false, options: [] }); const [humanConfigState, setHumanConfigState] = useState({ config: null, error: "", loading: false }); @@ -151,14 +150,21 @@ export function useRobotRoomsPage() { }, [activeAction]); useEffect(() => { - if (activeAction !== "create" || candidatesTouched) { + if (activeAction !== "create") { return; } - const ids = availableRobotsState.options.map((item) => item.userId).filter(Boolean); - if (ids.length > 0) { - setForm((current) => ({ ...current, candidateRobotUserIds: ids })); - } - }, [activeAction, availableRobotsState.options, candidatesTouched]); + const ownerRobotUserId = String(form.ownerRobotUserId || ""); + const ids = availableRobotsState.options + .map((item) => item.userId) + .filter((userId) => userId && String(userId) !== ownerRobotUserId); + setForm((current) => { + const currentIds = (current.candidateRobotUserIds || []).map(String); + if (currentIds.join(",") === ids.map(String).join(",")) { + return current; + } + return { ...current, candidateRobotUserIds: ids }; + }); + }, [activeAction, availableRobotsState.options, form.ownerRobotUserId]); const changeStatus = (value) => { setStatus(value || "active"); @@ -172,7 +178,6 @@ export function useRobotRoomsPage() { const openCreate = () => { setActiveAction("create"); - setCandidatesTouched(false); setForm(emptyForm()); setAvailableRobotsState({ error: "", loading: false, options: [] }); setGiftOptionsState({ error: "", loading: false, options: [] }); @@ -233,16 +238,6 @@ export function useRobotRoomsPage() { })); }; - const selectCandidateRobots = (robots) => { - setCandidatesTouched(true); - setForm((current) => ({ - ...current, - candidateRobotUserIds: robots - .map((robot) => robot.userId) - .filter((userId) => userId && String(userId) !== String(current.ownerRobotUserId)), - })); - }; - const selectGiftIds = (key, gifts) => { setForm((current) => ({ ...current, [key]: gifts.map(giftId).filter(Boolean) })); }; @@ -313,14 +308,6 @@ export function useRobotRoomsPage() { () => availableRobotsState.options.find((item) => item.userId === String(form.ownerRobotUserId)) || null, [availableRobotsState.options, form.ownerRobotUserId], ); - const selectedCandidateRobots = useMemo(() => { - 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 countryLabels = useMemo( () => Object.fromEntries(countryOptions.map((option) => [option.value, option.label])), [countryOptions], @@ -365,7 +352,6 @@ export function useRobotRoomsPage() { availableRobots: availableRobotsState.options, changeStatus, closeAction, - candidateRobotOptions, countryOptions, data, error, @@ -387,11 +373,9 @@ export function useRobotRoomsPage() { page, reload, resetFilters, - selectCandidateRobots, selectGiftIds, selectHumanGiftIds, selectOwnerRobot, - selectedCandidateRobots, selectedGiftOptions, selectedLuckyGiftOptions, selectedHumanGiftOptions, diff --git a/src/features/rooms/pages/RoomRobotPage.jsx b/src/features/rooms/pages/RoomRobotPage.jsx index 8fe124d..76afd44 100644 --- a/src/features/rooms/pages/RoomRobotPage.jsx +++ b/src/features/rooms/pages/RoomRobotPage.jsx @@ -7,7 +7,12 @@ import MenuItem from "@mui/material/MenuItem"; import TextField from "@mui/material/TextField"; import Tooltip from "@mui/material/Tooltip"; import { Button } from "@/shared/ui/Button.jsx"; -import { AdminFormDialog } from "@/shared/ui/AdminFormDialog.jsx"; +import { + AdminFormAmountField, + AdminFormDialog, + AdminFormFieldGrid, + AdminFormSection, +} from "@/shared/ui/AdminFormDialog.jsx"; import { AdminUserIdentity } from "@/shared/ui/AdminUserIdentity.jsx"; import { DataState } from "@/shared/ui/DataState.jsx"; import { DataTable } from "@/shared/ui/DataTable.jsx"; @@ -190,190 +195,138 @@ export function RoomRobotPage() { onClose={page.closeAction} onSubmit={page.submitCreate} > - option.userId === value.userId} - loading={page.availableRobotsLoading} - noOptionsText="当前无数据" - options={page.availableRobots} - renderInput={(params) => ( - - )} - renderOption={(props, option) => ( -
  • - + option.userId === value.userId} + loading={page.availableRobotsLoading} + noOptionsText="当前无数据" + options={page.availableRobots} + renderInput={(params) => ( + -
  • - )} - size="small" - value={page.selectedOwnerRobot} - onChange={(_, option) => page.selectOwnerRobot(option)} - /> - option.userId === value.userId} - loading={page.availableRobotsLoading} - noOptionsText="当前无数据" - options={page.candidateRobotOptions} - renderInput={(params) => ( - 候选机器人} + )} + renderOption={(props, option) => ( +
  • + +
  • + )} + size="small" + value={page.selectedOwnerRobot} + onChange={(_, option) => page.selectOwnerRobot(option)} + /> + + + + page.setForm({ ...page.form, minRobotCount: value })} /> - )} - renderOption={(props, option) => ( -
  • - -
  • - )} - size="small" - value={page.selectedCandidateRobots} - onChange={(_, options) => page.selectCandidateRobots(options)} - /> -
    - page.setForm({ ...page.form, minRobotCount: event.target.value })} - /> - page.setForm({ ...page.form, maxRobotCount: event.target.value })} - /> -
    - giftId(option) === giftId(value)} - loading={page.giftOptionsLoading} - noOptionsText="当前无数据" - options={page.giftOptions} - renderInput={(params) => ( - 礼物合集} + page.setForm({ ...page.form, maxRobotCount: value })} /> - )} - size="small" - value={page.selectedGiftOptions} - onChange={(_, options) => page.selectGiftIds("giftIds", options)} - /> - page.setForm({ ...page.form, normalGiftIntervalMs: event.target.value })} - /> -
    - + + + page.setForm({ ...page.form, robotStayMinMs: event.target.value })} + value={page.selectedGiftOptions} + onChange={(options) => page.selectGiftIds("giftIds", options)} /> - page.setForm({ ...page.form, robotStayMaxMs: event.target.value })} - /> - page.setForm({ ...page.form, robotReplaceMinMs: event.target.value })} - /> - page.setForm({ ...page.form, robotReplaceMaxMs: event.target.value })} - /> - page.setForm({ ...page.form, maxGiftSenders: event.target.value })} - /> -
    - giftId(option) === giftId(value)} - loading={page.giftOptionsLoading} - noOptionsText="当前无数据" - options={page.giftOptions} - renderInput={(params) => ( - 幸运礼物合集} + + page.setForm({ ...page.form, normalGiftIntervalMs: value })} /> - )} - size="small" - value={page.selectedLuckyGiftOptions} - onChange={(_, options) => page.selectGiftIds("luckyGiftIds", options)} - /> -
    - page.setForm({ ...page.form, robotStayMinMs: value })} + /> + page.setForm({ ...page.form, robotStayMaxMs: value })} + /> + page.setForm({ ...page.form, robotReplaceMinMs: value })} + /> + page.setForm({ ...page.form, robotReplaceMaxMs: value })} + /> + page.setForm({ ...page.form, maxGiftSenders: value })} + /> + + + + page.setForm({ ...page.form, luckyComboMin: event.target.value })} + value={page.selectedLuckyGiftOptions} + onChange={(options) => page.selectGiftIds("luckyGiftIds", options)} /> - page.setForm({ ...page.form, luckyComboMax: event.target.value })} - /> - page.setForm({ ...page.form, luckyPauseMinMs: event.target.value })} - /> - page.setForm({ ...page.form, luckyPauseMaxMs: event.target.value })} - /> -
    + + page.setForm({ ...page.form, luckyComboMin: value })} + /> + page.setForm({ ...page.form, luckyComboMax: value })} + /> + page.setForm({ ...page.form, luckyPauseMinMs: value })} + /> + page.setForm({ ...page.form, luckyPauseMaxMs: value })} + /> + +
    @@ -446,190 +399,199 @@ function HumanConfigDialog({ page }) { onClose={page.closeAction} onSubmit={page.submitHumanConfig} > -
    -
    + } + title="基础规则" + > + + + page.setHumanConfigForm({ + ...page.humanConfigForm, + candidateRoomMaxOnline: value, + }) } /> - - - + page.setHumanConfigForm({ ...page.humanConfigForm, roomTargetMaxOnline: value }) + } + /> + + + + + + + page.setHumanConfigForm({ + ...page.humanConfigForm, + normalGiftIntervalMinMs: value, + }) + } + /> + + page.setHumanConfigForm({ + ...page.humanConfigForm, + normalGiftIntervalMaxMs: value, + }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, robotStayMinMs: value }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, robotStayMaxMs: value }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, robotReplaceMinMs: value }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, robotReplaceMaxMs: value }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, maxGiftSenders: value }) + } + /> + + + + + - page.setHumanConfigForm({ - ...page.humanConfigForm, - candidateRoomMaxOnline: event.target.value, - }) - } + value={page.selectedHumanGiftOptions.giftIds} + onChange={(options) => page.selectHumanGiftIds("giftIds", options)} /> - - page.setHumanConfigForm({ ...page.humanConfigForm, roomTargetMinOnline: event.target.value }) - } + page.selectHumanGiftIds("luckyGiftIds", options)} /> - - page.setHumanConfigForm({ ...page.humanConfigForm, roomTargetMaxOnline: event.target.value }) - } + page.selectHumanGiftIds("superLuckyGiftIds", options)} /> - -
    - - page.setHumanConfigForm({ - ...page.humanConfigForm, - normalGiftIntervalMinMs: event.target.value, - }) - } - /> - - page.setHumanConfigForm({ - ...page.humanConfigForm, - normalGiftIntervalMaxMs: event.target.value, - }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, robotStayMinMs: event.target.value }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, robotStayMaxMs: event.target.value }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, robotReplaceMinMs: event.target.value }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, robotReplaceMaxMs: event.target.value }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, maxGiftSenders: event.target.value }) - } - /> -
    - page.selectHumanGiftIds("giftIds", options)} - /> -
    - - page.setHumanConfigForm({ ...page.humanConfigForm, luckyComboMin: event.target.value }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, luckyComboMax: event.target.value }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, luckyPauseMinMs: event.target.value }) - } - /> - - page.setHumanConfigForm({ ...page.humanConfigForm, luckyPauseMaxMs: event.target.value }) - } - /> -
    - page.selectHumanGiftIds("luckyGiftIds", options)} - /> - page.selectHumanGiftIds("superLuckyGiftIds", options)} - /> - {page.humanConfigForm.countryLimitEnabled ? : null} +
    + + + + + page.setHumanConfigForm({ ...page.humanConfigForm, luckyComboMin: value }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, luckyComboMax: value }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, luckyPauseMinMs: value }) + } + /> + + page.setHumanConfigForm({ ...page.humanConfigForm, luckyPauseMaxMs: value }) + } + /> + + + + + + page.setHumanCountryLimitEnabled(checked)} + /> + + + } + title="国家进房配置" + > + {page.humanConfigForm.countryLimitEnabled ? : null} + +
    机器人池自动获取
    @@ -642,12 +604,26 @@ function HumanConfigDialog({ page }) { ); } +function ConfigNumberField({ label, min = 1, onChange, size, unit, value }) { + const fieldProps = { + label, + required: true, + size, + slotProps: { htmlInput: { min, step: 1 } }, + type: "number", + value, + onChange: (event) => onChange(event.target.value), + }; + + return unit ? : ; +} + function HumanCountryRules({ page }) { const rows = page.humanConfigForm.countryRules || []; return (
    -
    国家进房配置
    +
    按机器人账号国家限制同时进入真人房的房间数量
    ))} - {rows.length === 0 ?
    当前没有国家配置
    : null} + {rows.length === 0 ?
    当前无数据
    : null}
    ); } -function GiftAutocomplete({ label, loading, onChange, options, required = false, value }) { +function GiftAutocomplete({ error = false, helperText = "", label, loading, onChange, options, required = false, value }) { return ( ( - {label} : label} /> + {label} : label} + /> )} size="small" value={value} diff --git a/src/features/rooms/rooms.module.css b/src/features/rooms/rooms.module.css index 3f6d5fc..0e0b2ba 100644 --- a/src/features/rooms/rooms.module.css +++ b/src/features/rooms/rooms.module.css @@ -286,6 +286,13 @@ align-items: center; } +.configSwitchActions { + display: inline-flex; + min-width: 0; + align-items: center; + gap: var(--space-2); +} + .robotAutoPoolNotice { display: grid; gap: var(--space-3); @@ -319,13 +326,14 @@ .countryRuleRow { display: grid; - grid-template-columns: minmax(180px, 1fr) minmax(140px, 0.6fr) auto; + grid-template-columns: minmax(220px, 1fr) minmax(132px, 0.42fr) auto; align-items: center; gap: var(--space-2); } @media (max-width: 720px) { .countryRulesHeader, + .configSwitchActions, .humanConfigActions { align-items: stretch; flex-direction: column;