feat: add big fish runtime rules entry

This commit is contained in:
2026-04-26 21:41:20 +08:00
parent c81305f2e6
commit 7694ef5723
3 changed files with 104 additions and 3 deletions

View File

@@ -77,4 +77,23 @@ describe('BigFishRuntimeShell', () => {
fireEvent.click(screen.getByRole('button', { name: '退出' }));
expect(onBack).toHaveBeenCalledTimes(1);
});
test('opens and closes the runtime rule modal', () => {
render(
<BigFishRuntimeShell
run={createRun('running')}
onBack={() => {}}
onSubmitInput={() => {}}
/>,
);
fireEvent.click(screen.getByRole('button', { name: '查看规则' }));
expect(screen.getByRole('dialog', { name: '玩法规则' })).toBeTruthy();
expect(screen.getByText('低级或同级野生实体会被收编。')).toBeTruthy();
fireEvent.click(screen.getByRole('button', { name: '关闭' }));
expect(screen.queryByRole('dialog', { name: '玩法规则' })).toBeNull();
});
});

View File

@@ -1,4 +1,4 @@
import { ArrowLeft, Loader2, RotateCcw } from 'lucide-react';
import { ArrowLeft, CircleHelp, Loader2, RotateCcw } from 'lucide-react';
import { type PointerEvent, useEffect, useRef, useState } from 'react';
import type {
@@ -7,6 +7,7 @@ import type {
BigFishRuntimeSnapshotResponse,
SubmitBigFishInputRequest,
} from '../../../packages/shared/src/contracts/bigFish';
import { UnifiedModal } from '../common/UnifiedModal';
import { ResolvedAssetImage } from '../ResolvedAssetImage';
type TouchOrigin = {
@@ -127,6 +128,38 @@ function resolveSettlementCopy(run: BigFishRuntimeSnapshotResponse) {
return null;
}
function BigFishRuleModal({
open,
onClose,
}: {
open: boolean;
onClose: () => void;
}) {
return (
<UnifiedModal
open={open}
title="玩法规则"
onClose={onClose}
size="sm"
zIndexClassName="z-[140]"
panelClassName="rounded-[1.25rem]"
bodyClassName="px-4 py-3 sm:px-5 sm:py-4"
>
<div className="space-y-3 text-sm leading-6 text-[var(--platform-text-base)]">
<div className="rounded-2xl bg-cyan-50 px-4 py-3 text-cyan-950">
</div>
<div className="grid gap-2">
<div></div>
<div></div>
<div>3 </div>
<div></div>
</div>
</div>
</UnifiedModal>
);
}
function BigFishEntityDot({
entity,
run,
@@ -194,6 +227,7 @@ export function BigFishRuntimeShell({
}: BigFishRuntimeShellProps) {
const stageRef = useRef<HTMLDivElement | null>(null);
const [touchOrigin, setTouchOrigin] = useState<TouchOrigin | null>(null);
const [isRuleModalOpen, setIsRuleModalOpen] = useState(false);
const [stick, setStick] = useState({ x: 0, y: 0 });
const stickRef = useRef(stick);
@@ -297,8 +331,19 @@ export function BigFishRuntimeShell({
>
<ArrowLeft className="h-4 w-4" />
</button>
<div className="rounded-full bg-black/28 px-4 py-2 text-xs font-bold backdrop-blur">
Lv.{run.playerLevel}/{run.winLevel} · {statusLabel}
<div className="flex items-center gap-2">
<button
type="button"
aria-label="查看规则"
title="查看规则"
onClick={() => setIsRuleModalOpen(true)}
className="pointer-events-auto inline-flex h-10 w-10 items-center justify-center rounded-full bg-black/28 text-white backdrop-blur"
>
<CircleHelp className="h-4 w-4" />
</button>
<div className="rounded-full bg-black/28 px-4 py-2 text-xs font-bold backdrop-blur">
Lv.{run.playerLevel}/{run.winLevel} · {statusLabel}
</div>
</div>
</div>
@@ -370,6 +415,10 @@ export function BigFishRuntimeShell({
</div>
))}
</div>
<BigFishRuleModal
open={isRuleModalOpen}
onClose={() => setIsRuleModalOpen(false)}
/>
</div>
</div>
);