123
This commit is contained in:
@@ -1015,6 +1015,67 @@ test('消除成功时会播放消除和掉落过渡动画', async () => {
|
||||
'.puzzle-clear-transition-piece--drop',
|
||||
).length,
|
||||
).toBeGreaterThan(0);
|
||||
expect(
|
||||
screen
|
||||
.getByTestId('puzzle-clear-board')
|
||||
.querySelector('.puzzle-clear-transition-piece--drop')
|
||||
?.getAttribute('style') ?? '',
|
||||
).toContain('--puzzle-clear-drop-delay: 520ms');
|
||||
});
|
||||
|
||||
test('正确局部拼合但未消除时会高光提醒拼合组', async () => {
|
||||
const previousRun = cloneRunWithBoard(createRun(), {
|
||||
rows: 3,
|
||||
cols: 3,
|
||||
cells: [
|
||||
{ row: 0, col: 0, card: createCard(40, 0, 0), lockedGroupId: null },
|
||||
{ row: 0, col: 1, card: createCard(40, 1, 0), lockedGroupId: null },
|
||||
{ row: 0, col: 2, card: createCard(42, 0, 0), lockedGroupId: null },
|
||||
{ row: 1, col: 0, card: createCard(43, 0, 0), lockedGroupId: null },
|
||||
{ row: 1, col: 1, card: createCard(44, 0, 0), lockedGroupId: null },
|
||||
{ row: 1, col: 2, card: createCard(45, 0, 0), lockedGroupId: null },
|
||||
{ row: 2, col: 0, card: createCard(46, 0, 0), lockedGroupId: null },
|
||||
{ row: 2, col: 1, card: createCard(47, 0, 0), lockedGroupId: null },
|
||||
{ row: 2, col: 2, card: createCard(48, 0, 0), lockedGroupId: null },
|
||||
],
|
||||
});
|
||||
const nextRun = cloneRunWithBoard(previousRun, {
|
||||
rows: 3,
|
||||
cols: 3,
|
||||
cells: previousRun.board.cells.map((cell) =>
|
||||
cell.row === 0 && (cell.col === 0 || cell.col === 1)
|
||||
? { ...cell, lockedGroupId: 'group-40' }
|
||||
: cell,
|
||||
),
|
||||
});
|
||||
|
||||
const { rerender } = render(
|
||||
<PuzzleClearRuntimeShell
|
||||
profile={createProfile()}
|
||||
run={previousRun}
|
||||
onSwapCards={vi.fn()}
|
||||
onRetryLevel={vi.fn()}
|
||||
onNextLevel={vi.fn()}
|
||||
onTimeUp={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
rerender(
|
||||
<PuzzleClearRuntimeShell
|
||||
profile={createProfile()}
|
||||
run={nextRun}
|
||||
onSwapCards={vi.fn()}
|
||||
onRetryLevel={vi.fn()}
|
||||
onNextLevel={vi.fn()}
|
||||
onTimeUp={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
screen.getByTestId('puzzle-clear-locked-group-visual').className,
|
||||
).toContain('puzzle-clear-locked-group-visual--highlight'),
|
||||
);
|
||||
});
|
||||
|
||||
test('完成拼接的局部会以连续组面板呈现,而不是单个绿框', () => {
|
||||
@@ -1162,7 +1223,7 @@ test('棋盘继承拼图模板的正方形触控面约束', () => {
|
||||
expect(board.className).toContain('aspect-square');
|
||||
expect(board.className).toContain('touch-none');
|
||||
expect(board.className).toContain('select-none');
|
||||
expect(board.className).toContain('gap-[3px]');
|
||||
expect(board.className).toContain('gap-[1.5px]');
|
||||
expect(board.className).not.toContain('gap-1.5');
|
||||
expect(board.className).not.toContain('h-full');
|
||||
expect(board.className).toContain('relative');
|
||||
|
||||
@@ -113,8 +113,18 @@ type PuzzleClearClearTransitionState = {
|
||||
}>;
|
||||
};
|
||||
|
||||
type PuzzleClearMergeHighlightState = {
|
||||
highlightKey: number;
|
||||
groupIds: string[];
|
||||
};
|
||||
|
||||
type PuzzleClearLockedGroupViewModel = PuzzleClearDragGroupState;
|
||||
|
||||
const PUZZLE_CLEAR_CLEAR_TRANSITION_MS = 1120;
|
||||
const PUZZLE_CLEAR_REFILL_DROP_DELAY_MS = 520;
|
||||
const PUZZLE_CLEAR_DROP_STAGGER_MAX_MS = 180;
|
||||
const PUZZLE_CLEAR_MERGE_HIGHLIGHT_MS = 760;
|
||||
|
||||
function getRun(
|
||||
run: PuzzleClearRuntimeSnapshotResponse | null | undefined,
|
||||
snapshot: PuzzleClearRuntimeSnapshotResponse | null | undefined,
|
||||
@@ -272,6 +282,60 @@ function cloneDragGroupState(
|
||||
};
|
||||
}
|
||||
|
||||
function buildPuzzleClearLockedGroupSignatures(
|
||||
run: PuzzleClearRuntimeSnapshotResponse,
|
||||
) {
|
||||
// 只比较锁定组包含的卡片,避免同一组整体移动时误触发拼合高光。
|
||||
const groupCards = new Map<string, string[]>();
|
||||
for (const cell of run.board.cells) {
|
||||
if (!cell.card || !cell.lockedGroupId) {
|
||||
continue;
|
||||
}
|
||||
const cardIds = groupCards.get(cell.lockedGroupId) ?? [];
|
||||
cardIds.push(cell.card.cardId);
|
||||
groupCards.set(cell.lockedGroupId, cardIds);
|
||||
}
|
||||
|
||||
const signatures = new Map<string, string>();
|
||||
for (const [groupId, cardIds] of groupCards.entries()) {
|
||||
if (cardIds.length <= 1) {
|
||||
continue;
|
||||
}
|
||||
signatures.set(groupId, cardIds.sort().join('|'));
|
||||
}
|
||||
return signatures;
|
||||
}
|
||||
|
||||
function buildPuzzleClearMergeHighlight(
|
||||
previousRun: PuzzleClearRuntimeSnapshotResponse,
|
||||
nextRun: PuzzleClearRuntimeSnapshotResponse,
|
||||
): PuzzleClearMergeHighlightState | null {
|
||||
if (
|
||||
previousRun.runId !== nextRun.runId ||
|
||||
previousRun.clearsDone !== nextRun.clearsDone
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const previousGroups = buildPuzzleClearLockedGroupSignatures(previousRun);
|
||||
const nextGroups = buildPuzzleClearLockedGroupSignatures(nextRun);
|
||||
const groupIds = [...nextGroups.entries()]
|
||||
.filter(([groupId, nextSignature]) => {
|
||||
const previousSignature = previousGroups.get(groupId);
|
||||
return !previousSignature || previousSignature !== nextSignature;
|
||||
})
|
||||
.map(([groupId]) => groupId);
|
||||
|
||||
if (groupIds.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
highlightKey: Date.now(),
|
||||
groupIds,
|
||||
};
|
||||
}
|
||||
|
||||
function buildPuzzleClearClearTransition(
|
||||
previousRun: PuzzleClearRuntimeSnapshotResponse,
|
||||
nextRun: PuzzleClearRuntimeSnapshotResponse,
|
||||
@@ -327,7 +391,12 @@ function buildPuzzleClearClearTransition(
|
||||
col: cell.col,
|
||||
card: cell.card!,
|
||||
distance: movedDistance,
|
||||
delayMs: Math.min(220, Math.max(0, (movedDistance - 1) * 60 + cell.row * 16)),
|
||||
delayMs:
|
||||
PUZZLE_CLEAR_REFILL_DROP_DELAY_MS +
|
||||
Math.min(
|
||||
PUZZLE_CLEAR_DROP_STAGGER_MAX_MS,
|
||||
Math.max(0, (movedDistance - 1) * 52 + cell.row * 14),
|
||||
),
|
||||
hideBoardCell: !previousPosition,
|
||||
};
|
||||
})
|
||||
@@ -383,6 +452,7 @@ export function PuzzleClearRuntimeShell({
|
||||
const swapFlightTimerRef = useRef<number | null>(null);
|
||||
const previousRunRef = useRef<PuzzleClearRuntimeSnapshotResponse | null>(null);
|
||||
const clearTransitionTimerRef = useRef<number | null>(null);
|
||||
const mergeHighlightTimerRef = useRef<number | null>(null);
|
||||
const cellElementRefMap = useRef(new Map<string, HTMLButtonElement>());
|
||||
const [selectedCell, setSelectedCell] = useState<PuzzleClearGridPosition | null>(
|
||||
null,
|
||||
@@ -395,6 +465,8 @@ export function PuzzleClearRuntimeShell({
|
||||
);
|
||||
const [clearTransition, setClearTransition] =
|
||||
useState<PuzzleClearClearTransitionState | null>(null);
|
||||
const [mergeHighlight, setMergeHighlight] =
|
||||
useState<PuzzleClearMergeHighlightState | null>(null);
|
||||
const [showOpeningPhase, setShowOpeningPhase] = useState(Boolean(activeRun));
|
||||
const [secondsLeft, setSecondsLeft] = useState(
|
||||
activeRun?.levelDurationSeconds ?? 600,
|
||||
@@ -460,6 +532,10 @@ export function PuzzleClearRuntimeShell({
|
||||
.filter((group) => group.cells.length > 1)
|
||||
.sort((left, right) => left.groupId.localeCompare(right.groupId));
|
||||
}, [board]);
|
||||
const mergeHighlightGroupIds = useMemo(
|
||||
() => new Set(mergeHighlight?.groupIds ?? []),
|
||||
[mergeHighlight],
|
||||
);
|
||||
const draggedGroup = dragState?.group ?? null;
|
||||
const draggedGroupId = draggedGroup?.groupId ?? null;
|
||||
const draggedGroupCellKeys = useMemo(() => {
|
||||
@@ -580,24 +656,41 @@ export function PuzzleClearRuntimeShell({
|
||||
window.clearTimeout(clearTransitionTimerRef.current);
|
||||
clearTransitionTimerRef.current = null;
|
||||
}
|
||||
if (mergeHighlightTimerRef.current !== null) {
|
||||
window.clearTimeout(mergeHighlightTimerRef.current);
|
||||
mergeHighlightTimerRef.current = null;
|
||||
}
|
||||
if (!activeRun || !previousRun) {
|
||||
setClearTransition(null);
|
||||
setMergeHighlight(null);
|
||||
return;
|
||||
}
|
||||
const transition = buildPuzzleClearClearTransition(previousRun, activeRun);
|
||||
if (!transition) {
|
||||
setClearTransition(null);
|
||||
if (transition) {
|
||||
setDragState(null);
|
||||
setSwapFeedback(null);
|
||||
setSwapFlight(null);
|
||||
setSelectedCell(null);
|
||||
setMergeHighlight(null);
|
||||
setClearTransition(transition);
|
||||
clearTransitionTimerRef.current = window.setTimeout(() => {
|
||||
clearTransitionTimerRef.current = null;
|
||||
setClearTransition(null);
|
||||
}, PUZZLE_CLEAR_CLEAR_TRANSITION_MS);
|
||||
return;
|
||||
}
|
||||
setDragState(null);
|
||||
setSwapFeedback(null);
|
||||
setSwapFlight(null);
|
||||
setSelectedCell(null);
|
||||
setClearTransition(transition);
|
||||
clearTransitionTimerRef.current = window.setTimeout(() => {
|
||||
clearTransitionTimerRef.current = null;
|
||||
setClearTransition(null);
|
||||
}, 640);
|
||||
|
||||
const highlight = buildPuzzleClearMergeHighlight(previousRun, activeRun);
|
||||
setClearTransition(null);
|
||||
if (!highlight) {
|
||||
setMergeHighlight(null);
|
||||
return;
|
||||
}
|
||||
setMergeHighlight(highlight);
|
||||
mergeHighlightTimerRef.current = window.setTimeout(() => {
|
||||
mergeHighlightTimerRef.current = null;
|
||||
setMergeHighlight(null);
|
||||
}, PUZZLE_CLEAR_MERGE_HIGHLIGHT_MS);
|
||||
}, [
|
||||
activeRun,
|
||||
activeRun?.board,
|
||||
@@ -615,7 +708,16 @@ export function PuzzleClearRuntimeShell({
|
||||
setDragState(null);
|
||||
setSwapFeedback(null);
|
||||
setSwapFlight(null);
|
||||
if (clearTransitionTimerRef.current !== null) {
|
||||
window.clearTimeout(clearTransitionTimerRef.current);
|
||||
clearTransitionTimerRef.current = null;
|
||||
}
|
||||
if (mergeHighlightTimerRef.current !== null) {
|
||||
window.clearTimeout(mergeHighlightTimerRef.current);
|
||||
mergeHighlightTimerRef.current = null;
|
||||
}
|
||||
setClearTransition(null);
|
||||
setMergeHighlight(null);
|
||||
}, [activeRun?.levelIndex, activeRun?.status]);
|
||||
|
||||
useEffect(
|
||||
@@ -629,6 +731,12 @@ export function PuzzleClearRuntimeShell({
|
||||
if (swapFlightTimerRef.current !== null) {
|
||||
window.clearTimeout(swapFlightTimerRef.current);
|
||||
}
|
||||
if (clearTransitionTimerRef.current !== null) {
|
||||
window.clearTimeout(clearTransitionTimerRef.current);
|
||||
}
|
||||
if (mergeHighlightTimerRef.current !== null) {
|
||||
window.clearTimeout(mergeHighlightTimerRef.current);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
@@ -964,7 +1072,7 @@ export function PuzzleClearRuntimeShell({
|
||||
<section className="relative mt-2 min-h-0 flex-1 rounded-[1.35rem] border border-white/76 bg-white/50 p-2 shadow-[0_22px_60px_rgba(15,118,110,0.16)] backdrop-blur">
|
||||
<div
|
||||
data-testid="puzzle-clear-board"
|
||||
className="relative mx-auto grid aspect-square w-full max-w-[min(100%,calc(100vh_-_15rem))] touch-none select-none gap-[3px] overflow-hidden rounded-[0.9rem]"
|
||||
className="relative mx-auto grid aspect-square w-full max-w-[min(100%,calc(100vh_-_15rem))] touch-none select-none gap-[1.5px] overflow-hidden rounded-[0.9rem]"
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(${board?.cols ?? 3}, minmax(0, 1fr))`,
|
||||
gridTemplateRows: `repeat(${board?.rows ?? 3}, minmax(0, 1fr))`,
|
||||
@@ -1114,7 +1222,7 @@ export function PuzzleClearRuntimeShell({
|
||||
className="pointer-events-none absolute inset-0 z-20"
|
||||
style={{
|
||||
display: 'grid',
|
||||
gap: '3px',
|
||||
gap: '1.5px',
|
||||
gridTemplateColumns: `repeat(${board?.cols ?? 3}, minmax(0, 1fr))`,
|
||||
gridTemplateRows: `repeat(${board?.rows ?? 3}, minmax(0, 1fr))`,
|
||||
}}
|
||||
@@ -1123,9 +1231,17 @@ export function PuzzleClearRuntimeShell({
|
||||
.filter((group) => group.groupId !== draggedGroupId)
|
||||
.map((group) => (
|
||||
<div
|
||||
key={group.groupId}
|
||||
key={`${group.groupId}:${
|
||||
mergeHighlightGroupIds.has(group.groupId)
|
||||
? (mergeHighlight?.highlightKey ?? 'active')
|
||||
: 'idle'
|
||||
}`}
|
||||
data-testid="puzzle-clear-locked-group-visual"
|
||||
className="puzzle-clear-locked-group-visual overflow-hidden rounded-[0.58rem] border border-white/78 bg-white/56 shadow-[0_10px_24px_rgba(15,23,42,0.08)]"
|
||||
className={`puzzle-clear-locked-group-visual overflow-hidden rounded-[0.58rem] border border-white/78 bg-white/56 shadow-[0_10px_24px_rgba(15,23,42,0.08)] ${
|
||||
mergeHighlightGroupIds.has(group.groupId)
|
||||
? 'puzzle-clear-locked-group-visual--highlight'
|
||||
: ''
|
||||
}`}
|
||||
style={{
|
||||
gridColumn: `${group.minCol + 1} / ${group.minCol + group.colSpan + 1}`,
|
||||
gridRow: `${group.minRow + 1} / ${group.minRow + group.rowSpan + 1}`,
|
||||
@@ -1160,7 +1276,7 @@ export function PuzzleClearRuntimeShell({
|
||||
{clearTransition ? (
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute inset-0 z-30 grid gap-[3px]"
|
||||
className="pointer-events-none absolute inset-0 z-30 grid gap-[1.5px]"
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(${board?.cols ?? 3}, minmax(0, 1fr))`,
|
||||
gridTemplateRows: `repeat(${board?.rows ?? 3}, minmax(0, 1fr))`,
|
||||
|
||||
112
src/index.css
112
src/index.css
@@ -217,21 +217,33 @@ body {
|
||||
|
||||
@keyframes puzzle-clear-transition-clear-pop {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.68);
|
||||
filter: saturate(1.06) brightness(1.04);
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
filter: saturate(1.04) brightness(1.02);
|
||||
}
|
||||
|
||||
32% {
|
||||
28% {
|
||||
opacity: 1;
|
||||
transform: scale(1.06);
|
||||
filter: saturate(1.14) brightness(1.06);
|
||||
transform: scale(1.12);
|
||||
filter: saturate(1.2) brightness(1.08);
|
||||
}
|
||||
|
||||
52% {
|
||||
opacity: 1;
|
||||
transform: scale(1.08);
|
||||
filter: saturate(1.12) brightness(1.04);
|
||||
}
|
||||
|
||||
82% {
|
||||
opacity: 0.42;
|
||||
transform: scale(1.01);
|
||||
filter: saturate(0.96) brightness(1) blur(0.2px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(0.84);
|
||||
filter: saturate(0.92) brightness(1);
|
||||
transform: scale(0.94);
|
||||
filter: saturate(0.88) brightness(0.98) blur(0.8px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,6 +364,28 @@ body {
|
||||
animation: puzzle-clear-locked-group-settle 180ms ease-out both;
|
||||
}
|
||||
|
||||
.puzzle-clear-locked-group-visual--highlight {
|
||||
position: relative;
|
||||
animation: puzzle-clear-locked-group-highlight 760ms ease-out both;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.puzzle-clear-locked-group-visual--highlight::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: -10%;
|
||||
pointer-events: none;
|
||||
background: linear-gradient(
|
||||
105deg,
|
||||
transparent 20%,
|
||||
rgba(255, 255, 255, 0.72) 48%,
|
||||
rgba(255, 255, 255, 0.18) 54%,
|
||||
transparent 76%
|
||||
);
|
||||
mix-blend-mode: screen;
|
||||
animation: puzzle-clear-locked-group-sheen 680ms ease-out both;
|
||||
}
|
||||
|
||||
.puzzle-clear-locked-group-visual--merge {
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.5),
|
||||
@@ -393,13 +427,17 @@ body {
|
||||
}
|
||||
|
||||
.puzzle-clear-transition-piece--clear {
|
||||
animation: puzzle-clear-transition-clear-pop 340ms ease-out both;
|
||||
animation: puzzle-clear-transition-clear-pop 720ms cubic-bezier(0.2, 0.78, 0.2, 1)
|
||||
both;
|
||||
transform-origin: center;
|
||||
will-change: transform, opacity, filter;
|
||||
}
|
||||
|
||||
.puzzle-clear-transition-piece--drop {
|
||||
animation: puzzle-clear-transition-drop 420ms cubic-bezier(0.18, 0.82, 0.24, 1)
|
||||
animation: puzzle-clear-transition-drop 460ms cubic-bezier(0.18, 0.82, 0.24, 1)
|
||||
both;
|
||||
animation-delay: var(--puzzle-clear-drop-delay, 0ms);
|
||||
will-change: transform, opacity, filter;
|
||||
}
|
||||
|
||||
@keyframes puzzle-clear-card-swap-feedback {
|
||||
@@ -461,6 +499,58 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes puzzle-clear-locked-group-highlight {
|
||||
0% {
|
||||
transform: scale(0.992);
|
||||
filter: saturate(1) brightness(1);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.42),
|
||||
0 10px 24px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
22% {
|
||||
transform: scale(1.035);
|
||||
filter: saturate(1.18) brightness(1.06);
|
||||
box-shadow:
|
||||
inset 0 0 0 2px rgba(255, 255, 255, 0.82),
|
||||
0 0 0 3px rgba(52, 211, 153, 0.28),
|
||||
0 18px 34px rgba(15, 23, 42, 0.16);
|
||||
}
|
||||
|
||||
58% {
|
||||
transform: scale(1.012);
|
||||
filter: saturate(1.08) brightness(1.02);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.68),
|
||||
0 0 0 2px rgba(251, 191, 36, 0.18),
|
||||
0 14px 28px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
filter: saturate(1) brightness(1);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.5),
|
||||
0 10px 24px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes puzzle-clear-locked-group-sheen {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-130%) skewX(-14deg);
|
||||
}
|
||||
|
||||
26% {
|
||||
opacity: 0.86;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateX(130%) skewX(-14deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes puzzle-clear-drag-ghost-drop {
|
||||
0% {
|
||||
opacity: 0.98;
|
||||
@@ -492,6 +582,8 @@ body {
|
||||
.puzzle-clear-card--swap-feedback,
|
||||
.puzzle-clear-swap-flight--incoming,
|
||||
.puzzle-clear-locked-group-visual,
|
||||
.puzzle-clear-locked-group-visual--highlight,
|
||||
.puzzle-clear-locked-group-visual--highlight::after,
|
||||
.puzzle-clear-drag-ghost--dropping,
|
||||
.puzzle-clear-drag-ghost--returning,
|
||||
.puzzle-clear-transition-piece--clear,
|
||||
|
||||
@@ -31,6 +31,17 @@ beforeEach(() => {
|
||||
requestJsonMock.mockReset();
|
||||
});
|
||||
|
||||
test('拼消消创作保留足够长的 image2 生成等待窗口', async () => {
|
||||
await import('./puzzleClearClient');
|
||||
|
||||
expect(createCreationAgentClientMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
createSessionTimeoutMs: 40 * 60 * 1000,
|
||||
executeActionTimeoutMs: 40 * 60 * 1000,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('拼消消客户端区分创作详情和公开运行态详情', async () => {
|
||||
const { puzzleClearClient } = await import('./puzzleClearClient');
|
||||
requestJsonMock.mockResolvedValue({
|
||||
|
||||
@@ -28,8 +28,8 @@ import {
|
||||
const PUZZLE_CLEAR_API_BASE = '/api/creation/puzzle-clear/sessions';
|
||||
const PUZZLE_CLEAR_WORKS_API_BASE = '/api/creation/puzzle-clear/works';
|
||||
const PUZZLE_CLEAR_RUNTIME_API_BASE = '/api/runtime/puzzle-clear';
|
||||
// 中文注释:拼消消编译会等待底图、4 张素材工作表、切片、最终 atlas 合成和 OSS 写入,保留长请求窗口。
|
||||
const PUZZLE_CLEAR_GENERATION_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
// 中文注释:拼消消编译要串行等待底图、4 张素材工作表、切片、最终 atlas 合成和 OSS 写入;VectorEngine 偶发单张图可超过 10 分钟。
|
||||
const PUZZLE_CLEAR_GENERATION_TIMEOUT_MS = 40 * 60 * 1000;
|
||||
const PUZZLE_CLEAR_RUNTIME_READ_RETRY: ApiRetryOptions = {
|
||||
maxRetries: 1,
|
||||
baseDelayMs: 120,
|
||||
|
||||
Reference in New Issue
Block a user