修复自查发现的门禁与体验问题:格式、超时态语义、压缩 CPU 边界
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m48s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m3s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m33s
Project CI / Frontend tests (pull_request) Successful in 3m24s
Project CI / Backend tests (pull_request) Successful in 7m29s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m55s
Project CI / Repository checks (pull_request) Successful in 6m33s
Project CI / Native shell tests (pull_request) Successful in 9m0s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m48s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m3s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m33s
Project CI / Frontend tests (pull_request) Successful in 3m24s
Project CI / Backend tests (pull_request) Successful in 7m29s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m55s
Project CI / Repository checks (pull_request) Successful in 6m33s
Project CI / Native shell tests (pull_request) Successful in 9m0s
- 新增 Rust 测试补齐 cargo fmt;ESLint 按仓库约定收口:常量与解析函数拆到 platformGameLoadingSurfaceModel.ts,删除 GAME_PLAY_STARTUP_TIMEOUT_MS 常量别名(测试直接用共享常量) - 共享加载面新增 stalled:宿主判定等待不再推进时停掉进度动画并把 aria-busy 置回 false(去掉与 role=status 重复的 aria-live) - 后台试玩超时时传入 stalled,避免「一边转圈一边说超时」 - Accept-Encoding 权重参数名改为大小写不敏感(RFC 9110 §12.5.3),GZIP;Q=0 视为拒绝并补用例 - 发行资源压缩分级:≥2 MiB 改用 level 1(zlib 端实测约 1/3 耗时、压缩比差约 3%),小文件仍用 level 6 - 文档:主规范补压缩与条件请求契约(并写明 60 秒窗口与撤销窗口不放宽)、nginx README 修正 Pingora 压缩关闭时的口径、pitfalls 补 CPU 边界与措辞修正
This commit is contained in:
@@ -3,13 +3,13 @@
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import { afterEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import { PlatformGameLoadingSurface } from './PlatformGameLoadingSurface';
|
||||
import {
|
||||
PLATFORM_GAME_LOADING_ASSET_PHASE_MS,
|
||||
PLATFORM_GAME_LOADING_ENGINE_PHASE_MS,
|
||||
PLATFORM_GAME_LOADING_SLOW_PHASE_MS,
|
||||
PlatformGameLoadingSurface,
|
||||
resolvePlatformGameLoadingMessage,
|
||||
} from './PlatformGameLoadingSurface';
|
||||
} from './platformGameLoadingSurfaceModel';
|
||||
|
||||
function readMessage() {
|
||||
return screen
|
||||
@@ -84,6 +84,14 @@ describe('PlatformGameLoadingSurface', () => {
|
||||
expect(screen.getByRole('img', { name: '封面' })).toBeTruthy();
|
||||
});
|
||||
|
||||
test('宿主判定停止推进时不再声明 busy,并停掉进度动画', () => {
|
||||
render(<PlatformGameLoadingSurface title="待审版本试玩" stalled />);
|
||||
|
||||
const surface = screen.getByRole('status');
|
||||
expect(surface.getAttribute('aria-busy')).toBe('false');
|
||||
expect(surface.className).toContain('platform-game-loading--stalled');
|
||||
});
|
||||
|
||||
test('没有封面时渲染图标占位而不是空白区块', () => {
|
||||
const { container } = render(
|
||||
<PlatformGameLoadingSurface title="加载中" tone="player" />,
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
import { Gamepad2 } from 'lucide-react';
|
||||
import { useEffect, useState, type ReactNode } from 'react';
|
||||
import { type ReactNode, useEffect, useState } from 'react';
|
||||
|
||||
/** 阶段文案切换点:先「准备」,再「资源」,最后「引擎」。 */
|
||||
export const PLATFORM_GAME_LOADING_ASSET_PHASE_MS = 1_500;
|
||||
export const PLATFORM_GAME_LOADING_ENGINE_PHASE_MS = 6_000;
|
||||
/** 超过这个时长仍未进入游戏,补一行「比平时久」的状态,避免用户以为卡死。 */
|
||||
export const PLATFORM_GAME_LOADING_SLOW_PHASE_MS = 12_000;
|
||||
/**
|
||||
* 发行包首屏加载上限。
|
||||
*
|
||||
* 网页游玩页与后台审核试玩共用同一口径:超过上限就给出显式超时与重试,而不是让
|
||||
* 用户对着加载面无限期等待。
|
||||
*/
|
||||
export const PLATFORM_GAME_LOADING_TIMEOUT_MS = 20_000;
|
||||
import {
|
||||
PLATFORM_GAME_LOADING_SLOW_PHASE_MS,
|
||||
resolvePlatformGameLoadingMessage,
|
||||
} from './platformGameLoadingSurfaceModel';
|
||||
|
||||
export type PlatformGameLoadingSurfaceTone = 'player' | 'panel';
|
||||
|
||||
@@ -30,32 +22,23 @@ export type PlatformGameLoadingSurfaceProps = {
|
||||
message?: string;
|
||||
/** 追加一行提示(例如失败的兜底说明)。 */
|
||||
hint?: string;
|
||||
/**
|
||||
* 宿主已判定这次等待不再推进(例如已经给出超时结论):停掉进度动画并把
|
||||
* `aria-busy` 置回 `false`,避免「一边转圈一边说超时」。
|
||||
*/
|
||||
stalled?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const DEFAULT_COPY_BY_PHASE: Record<'prepare' | 'assets' | 'engine', string> = {
|
||||
prepare: '正在准备游戏…',
|
||||
assets: '正在加载游戏资源…',
|
||||
engine: '正在启动游戏引擎…',
|
||||
};
|
||||
|
||||
/** 按已等待时长给出阶段文案;与 `PlatformGameLoadingSurface` 内的计时同源。 */
|
||||
export function resolvePlatformGameLoadingMessage(elapsedMs: number) {
|
||||
if (elapsedMs >= PLATFORM_GAME_LOADING_ENGINE_PHASE_MS) {
|
||||
return DEFAULT_COPY_BY_PHASE.engine;
|
||||
}
|
||||
if (elapsedMs >= PLATFORM_GAME_LOADING_ASSET_PHASE_MS) {
|
||||
return DEFAULT_COPY_BY_PHASE.assets;
|
||||
}
|
||||
return DEFAULT_COPY_BY_PHASE.prepare;
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台通用「游戏加载面」。
|
||||
*
|
||||
* 发行包(Phaser/Vite 产物)首屏要下完整个引擎与资源,网络稍慢就是好几秒;这段时间
|
||||
* 网页游玩页与后台审核试玩都必须给出**看得见的**加载反馈,而不是近黑面板上的一行小字
|
||||
* 或一片空白。阶段文案由组件自己按时长推进,宿主只负责在真正进入游戏后把它换掉。
|
||||
*
|
||||
* 组件按绝对定位铺满**最近的定位祖先**:宿主必须给它一个 `position: relative` 的容器
|
||||
* (网页游玩页是 `.game-player-shell`,后台试玩是 `.admin-game-review-preview-shell`)。
|
||||
*/
|
||||
export function PlatformGameLoadingSurface({
|
||||
title,
|
||||
@@ -63,6 +46,7 @@ export function PlatformGameLoadingSurface({
|
||||
tone = 'panel',
|
||||
message,
|
||||
hint,
|
||||
stalled = false,
|
||||
className,
|
||||
}: PlatformGameLoadingSurfaceProps) {
|
||||
const [elapsedMs, setElapsedMs] = useState(0);
|
||||
@@ -84,12 +68,12 @@ export function PlatformGameLoadingSurface({
|
||||
return (
|
||||
<div
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-busy="true"
|
||||
aria-busy={stalled ? 'false' : 'true'}
|
||||
aria-label={`${title} ${statusMessage}`}
|
||||
className={[
|
||||
'platform-game-loading',
|
||||
`platform-game-loading--${tone}`,
|
||||
stalled ? 'platform-game-loading--stalled' : null,
|
||||
className,
|
||||
]
|
||||
.filter(Boolean)
|
||||
|
||||
@@ -48,14 +48,14 @@ export type {
|
||||
PlatformGameLoadingSurfaceProps,
|
||||
PlatformGameLoadingSurfaceTone,
|
||||
} from './PlatformGameLoadingSurface';
|
||||
export { PlatformGameLoadingSurface } from './PlatformGameLoadingSurface';
|
||||
export {
|
||||
PLATFORM_GAME_LOADING_ASSET_PHASE_MS,
|
||||
PLATFORM_GAME_LOADING_ENGINE_PHASE_MS,
|
||||
PLATFORM_GAME_LOADING_SLOW_PHASE_MS,
|
||||
PLATFORM_GAME_LOADING_TIMEOUT_MS,
|
||||
PlatformGameLoadingSurface,
|
||||
resolvePlatformGameLoadingMessage,
|
||||
} from './PlatformGameLoadingSurface';
|
||||
} from './platformGameLoadingSurfaceModel';
|
||||
export type {
|
||||
PlatformIconBadgeProps,
|
||||
PlatformIconBadgeShape,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/** 阶段文案切换点:先「准备」,再「资源」,最后「引擎」。 */
|
||||
export const PLATFORM_GAME_LOADING_ASSET_PHASE_MS = 1_500;
|
||||
export const PLATFORM_GAME_LOADING_ENGINE_PHASE_MS = 6_000;
|
||||
/** 超过这个时长仍未进入游戏,补一行「比平时久」的状态,避免用户以为卡死。 */
|
||||
export const PLATFORM_GAME_LOADING_SLOW_PHASE_MS = 12_000;
|
||||
/**
|
||||
* 发行包首屏加载上限。
|
||||
*
|
||||
* 网页游玩页与后台审核试玩共用同一口径:超过上限就给出显式超时与重试,而不是让
|
||||
* 用户对着加载面无限期等待。
|
||||
*/
|
||||
export const PLATFORM_GAME_LOADING_TIMEOUT_MS = 20_000;
|
||||
|
||||
const DEFAULT_COPY_BY_PHASE: Record<'prepare' | 'assets' | 'engine', string> = {
|
||||
prepare: '正在准备游戏…',
|
||||
assets: '正在加载游戏资源…',
|
||||
engine: '正在启动游戏引擎…',
|
||||
};
|
||||
|
||||
/** 按已等待时长给出阶段文案;与 `PlatformGameLoadingSurface` 内的计时同源。 */
|
||||
export function resolvePlatformGameLoadingMessage(elapsedMs: number) {
|
||||
if (elapsedMs >= PLATFORM_GAME_LOADING_ENGINE_PHASE_MS) {
|
||||
return DEFAULT_COPY_BY_PHASE.engine;
|
||||
}
|
||||
if (elapsedMs >= PLATFORM_GAME_LOADING_ASSET_PHASE_MS) {
|
||||
return DEFAULT_COPY_BY_PHASE.assets;
|
||||
}
|
||||
return DEFAULT_COPY_BY_PHASE.prepare;
|
||||
}
|
||||
@@ -1677,6 +1677,14 @@ textarea.genarrative-ui-text-field__control {
|
||||
background: var(--platform-button-primary-fill, #c7653d);
|
||||
}
|
||||
|
||||
/* 宿主已判定这次等待不再推进(例如已经给出超时结论):进度条停下并压暗,
|
||||
避免出现「一边转圈一边说超时」的自相矛盾。 */
|
||||
.platform-game-loading--stalled .platform-game-loading__fill {
|
||||
animation: none;
|
||||
transform: none;
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.platform-game-loading__hint {
|
||||
margin: 0;
|
||||
font-size: 0.72rem;
|
||||
|
||||
Reference in New Issue
Block a user