diff --git a/web/src/components/layouts/withGame.tsx b/web/src/components/layouts/withGame.tsx index 458f0a8a..a63eaec1 100644 --- a/web/src/components/layouts/withGame.tsx +++ b/web/src/components/layouts/withGame.tsx @@ -40,7 +40,7 @@ export default function withGame(WrappedComponent: React.ComponentType) { flexShrink: 0, }} > - + {game?.title} diff --git a/web/src/components/modals/ChallengeModal.tsx b/web/src/components/modals/ChallengeModal.tsx index 80e7caa9..78e9aab8 100644 --- a/web/src/components/modals/ChallengeModal.tsx +++ b/web/src/components/modals/ChallengeModal.tsx @@ -36,6 +36,8 @@ import { } from "@/utils/notification"; import { useForm } from "@mantine/form"; import { useTeamStore } from "@/stores/team"; +import { useInterval } from "@mantine/hooks"; +import { set } from "zod"; interface ChallengeModalProps extends ModalProps { challenge?: Challenge; @@ -54,7 +56,11 @@ export default function ChallengeModal(props: ChallengeModalProps) { const teamStore = useTeamStore(); const [pod, setPod] = useState(); + const [podTime, setPodTime] = useState(0); + const interval = useInterval(() => setPodTime((s) => s - 1), 1000); const [podCreateLoading, setPodCreateLoading] = useState(false); + const [podRemoveLoading, setPodRemoveLoading] = useState(false); + const [podRenewLoading, setPodRenewLoading] = useState(false); const form = useForm({ mode: "uncontrolled", @@ -108,23 +114,26 @@ export default function ChallengeModal(props: ChallengeModalProps) { } function removePod() { + setPodRemoveLoading(true); podApi .removePod({ id: pod?.id as number, }) - .then((res) => { - const r = res.data; - if (r?.code === 200) { - setPod(undefined); - } + .then((_) => { + setPod(undefined); + setPodTime(0); showSuccessNotification({ title: "操作成功", message: "实例已销毁!", }); + }) + .finally(() => { + setPodRemoveLoading(false); }); } function renewPod() { + setPodRenewLoading(true); podApi .renewPod({ id: pod?.id!, @@ -134,6 +143,9 @@ export default function ChallengeModal(props: ChallengeModalProps) { if (r?.code === 200) { getPod(); } + }) + .finally(() => { + setPodRenewLoading(false); }); } @@ -196,14 +208,31 @@ export default function ChallengeModal(props: ChallengeModalProps) { }); } + useEffect(() => { + if (podTime > 0) { + interval.start(); + return interval.stop; + } + }, [podTime]); + + useEffect(() => { + if (pod) { + setPodTime( + Math.ceil(pod?.removed_at - new Date().getTime() / 1000) + ); + } + }, [pod]); + useEffect(() => { if (challenge?.is_dynamic) { getPod(); } - }, [challenge]); + }, [challenge, modalProps.opened]); useEffect(() => { form.reset(); + setPodTime(0); + setPod(undefined); }, [modalProps.opened]); return ( @@ -238,18 +267,7 @@ export default function ChallengeModal(props: ChallengeModalProps) { }} > - + {challenge?.category?.icon} {challenge?.title} @@ -345,16 +363,7 @@ export default function ChallengeModal(props: ChallengeModalProps) { key={nat?.id} value={nat?.entry} readOnly - sx={{ - input: { - "&:focus": { - borderColor: - challenge?.category - ?.color || - "#3F51B5", - }, - }, - }} + color={challenge?.category?.color} leftSectionWidth={135} leftSection={ - 本题容器时间 {challenge?.duration}s + 本题容器时间{" "} + {podTime || challenge?.duration}s {pod?.id && ( <> @@ -73,7 +88,9 @@ export default function Page() { sx={{ flexGrow: 1, }} + pos={"relative"} > + {games.map((game) => ( >([]); + const [loading, setLoading] = useState(true); + const [createOpened, { open: createOpen, close: createClose }] = useDisclosure(false); @@ -31,6 +41,7 @@ export default function Page() { useDisclosure(false); function getTeams() { + setLoading(true); teamApi .getTeams({ user_id: authStore?.user?.id, @@ -38,6 +49,9 @@ export default function Page() { .then((res) => { const r = res.data; setTeams(r.data); + }) + .finally(() => { + setLoading(false); }); } @@ -68,19 +82,22 @@ export default function Page() { 创建团队 - - {teams?.map((team) => ( - { - editOpen(); - setEditTeam(team); - }} - > - - - ))} - + + + + {teams?.map((team) => ( + { + editOpen(); + setEditTeam(team); + }} + > + + + ))} + + {