From 1a72e3236a7764a073cae323725c2abe9f796012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=94=E9=A6=99=E4=B8=B8=E5=AD=90?= <15518898337@163.com> Date: Mon, 24 Aug 2026 21:12:58 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E9=9A=90=E8=97=8F=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E6=A8=A1=E7=B3=8A=E9=A1=B9=E7=9B=AE=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 首页默认项目状态改为空 移除最近项目标题下的解释性副标题 补充首页视觉规则并更新界面测试 --- .../src/features/app-shell/WorkspaceLauncher.tsx | 2 +- apps/ai-game-creator-shell/src/view/home/index.tsx | 3 --- apps/ai-game-creator-shell/tests/appSurface/home.suite.ts | 2 +- docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md | 1 + 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx b/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx index 14199a02f..e8ca749c5 100644 --- a/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx +++ b/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx @@ -34,7 +34,7 @@ export function WorkspaceLauncherShell({ ProjectSupervisor, }: WorkspaceLauncherShellProps) { const accountWallet = useAccountWallet(currentUser.id); - const [status, setStatus] = useState('请选择项目'); + const [status, setStatus] = useState(''); const recentProjects = useRecentProjects(setStatus); const { recentProjectRows, rememberRecentWorkspace } = recentProjects; const [launcherView, setLauncherView] = useState(initialView); diff --git a/apps/ai-game-creator-shell/src/view/home/index.tsx b/apps/ai-game-creator-shell/src/view/home/index.tsx index f73810e01..00fa69ca7 100644 --- a/apps/ai-game-creator-shell/src/view/home/index.tsx +++ b/apps/ai-game-creator-shell/src/view/home/index.tsx @@ -253,9 +253,6 @@ export default function HomeView({

最近项目

-

- 选择一个项目继续创作 -

- {status ? ( - - {status} - - ) : null}
{ rejectAutomaticProject?.(new Error('自动创建测试结束')); @@ -1522,7 +1523,7 @@ export function registerHomeProjectCreationTests() { await waitFor(() => { expect((createButton as HTMLButtonElement).disabled).toBe(false); }); - expect(screen.getAllByText('自动创建测试结束')).not.toHaveLength(0); + expect(screen.queryByText('自动创建测试结束')).toBeNull(); }); it('refreshes Direct Codex art commits while the turn is still running and after a later failure', async () => { diff --git a/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md b/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md index 6fe0495e6..653d993f3 100644 --- a/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md +++ b/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md @@ -118,7 +118,7 @@ - 客户端正式产品仍只按最小 `1280×720` 横屏合同交付,并保留 `1280×800` 默认窗口与既有基线验收;更窄浏览器样式只负责不崩溃和开发兼容,不改成移动端创作工作台。 - 普通用户界面不默认展示内部错误码或本机绝对路径,也不展示 External Editor Base URL 或 Developer API Key;官方服务地址由客户端构建固定,远端编辑自动使用当前陶泥儿登录态。仅独立 standalone game-chat release 或显式高级自定义模式在隔离配置页维护 External v1 URL/Key,确需诊断的信息进入受控详情或开发模式。 - 创建模式素材画布的“素材名称”是用户可编辑的正式输出名称;“资源用途”是 manifest subtype,不向普通用户开放自由文本。新增资源默认“普通游戏美术”,可从普通游戏美术、统一视觉规范、游戏界面原型、核心美术图集四项中选择。图片精修继承源名称和用途,不显示创建模式保存设置;候选图片只从选中图片的“设为最终图”提交。精修顶栏只保留返回、导入、定位当前最终图、撤销和重做,删除进入图片上下文工具栏,通用 AI 生成只保留给创建模式。图片输出统一使用 PNG;创建模式工具动作与保存设置分层展示,“保存到项目”在 `1280×800` 和窄容器中都必须完整可见。 -- 首页创作输入区与“最近项目”之间默认不展示项目选择占位状态,“最近项目”标题下不追加解释性副标题;进行中或失败等可操作反馈仍按实际状态展示。 +- 首页创作输入区与“最近项目”之间不展示共享项目状态文本,“最近项目”标题下也不追加解释性副标题;默认、成功、进行中或失败状态均不得在该位置形成文字行,项目管理页继续保留自己的状态反馈。 ### 3.8 现有 Godot 项目 -- 2.52.0 From a207928d39c0d50c8b5bac0be74ca063e4be3c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=94=E9=A6=99=E4=B8=B8=E5=AD=90?= <15518898337@163.com> Date: Mon, 24 Aug 2026 21:58:43 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E8=A7=86=E7=AA=97=E6=92=AD=E6=94=BE=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将桌面运行视窗播放按钮移至顶部中间 资源管理点击播放后直接启动本地预览并切换运行视窗 更新播放链路回归测试与工作台规则 --- apps/ai-game-creator-shell/src/App.tsx | 6 +- apps/ai-game-creator-shell/src/styles.css | 14 ++++ .../appSurface/project-development.suite.ts | 64 +++++++++++-------- ...AI游戏创作】项目开发工作台PRD-2026-07-20.md | 1 + 4 files changed, 57 insertions(+), 28 deletions(-) diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index ddf21796e..53dba1e34 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -1141,6 +1141,9 @@ export function App({ const initialProjectOpenedRef = useRef(false); const pendingUiConfirmationActionRef = useRef<(() => void) | null>(null); const queueRunLocalShortcutRef = useRef<() => void>(() => undefined); + const executeRunLocalRef = useRef<(announceToChat: boolean) => void>( + () => undefined, + ); function requestRuntimeConfigOpen() { if (projectSupervisorOnly && !supervisorChatOnly && !gameChatOnly) { @@ -3045,6 +3048,7 @@ export function App({ ]); } queueRunLocalShortcutRef.current = queueRunLocalShortcut; + executeRunLocalRef.current = executeRunLocal; useEffect(() => { const nextProjectPath = localProject?.projectPath; @@ -3062,7 +3066,7 @@ export function App({ } handledPlayRequestRef.current = requestKey; onPlayRequestHandled?.(playRequest.requestId); - queueRunLocalShortcutRef.current(); + void executeRunLocalRef.current(true); }, [ localProject?.projectPath, onPlayRequestHandled, diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 6760b2656..1c531b7ee 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -5087,6 +5087,7 @@ iframe.preview-frame { } .game-workbench-toolbar { + position: relative; display: flex; align-items: center; justify-content: space-between; @@ -5183,6 +5184,9 @@ iframe.preview-frame { } .game-workbench-view-actions .game-workbench-play-button { + position: absolute; + left: 50%; + transform: translateX(-50%); border-color: var(--platform-button-primary-border); background: var(--platform-button-primary-fill); color: var(--platform-button-primary-text); @@ -7377,6 +7381,11 @@ iframe.preview-frame { .game-workbench-view-actions { justify-content: flex-end; } + + .game-workbench-view-actions .game-workbench-play-button { + position: static; + transform: none; + } } @media (max-width: 760px) { @@ -7407,6 +7416,11 @@ iframe.preview-frame { flex-direction: column; } + .game-workbench-view-actions .game-workbench-play-button { + position: static; + transform: none; + } + .game-workbench-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); diff --git a/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts index 683457993..8a4d34cc2 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts @@ -773,7 +773,9 @@ export function registerProjectWorkbenchFoundationTests() { 'workbench-art-viewport-memory', '美术资源视口记忆', ); - const codeTask = manifest.tasks.find((task) => task.id === 'code-prototype'); + const codeTask = manifest.tasks.find( + (task) => task.id === 'code-prototype', + ); expect(codeTask).toBeDefined(); codeTask!.status = 'completed'; manifest.assets = [ @@ -1071,7 +1073,9 @@ export function registerProjectWorkbenchFoundationTests() { ).not.toBeNull(); fireEvent.click(within(outline).getByRole('button', { name: /设计文档/ })); - dispatchPageWheel(screen.getByRole('button', { name: /下一页\s*美术资源/ })); + dispatchPageWheel( + screen.getByRole('button', { name: /下一页\s*美术资源/ }), + ); expect( screen.getByRole('region', { name: '美术资源资源画布' }), ).not.toBeNull(); @@ -1134,9 +1138,7 @@ export function registerProjectWorkbenchFoundationTests() { name: /打开资源详情:设计文档 section\.md/, }), ); - expect( - screen.getByRole('dialog', { name: 'section.md' }), - ).not.toBeNull(); + expect(screen.getByRole('dialog', { name: 'section.md' })).not.toBeNull(); dispatchPageWheel(dependencyCanvas); expect( screen.getByRole('region', { name: '美术资源资源画布' }), @@ -1278,9 +1280,7 @@ export function registerProjectWorkbenchFoundationTests() { }), ); }); - fireEvent.click( - within(outline).getByRole('button', { name: /项目版本/ }), - ); + fireEvent.click(within(outline).getByRole('button', { name: /项目版本/ })); await act(async () => { await new Promise((resolve) => setTimeout(resolve, 220)); }); @@ -1288,9 +1288,7 @@ export function registerProjectWorkbenchFoundationTests() { screen.getByRole('region', { name: '项目版本资源画布' }), ).not.toBeNull(); - fireEvent.click( - within(outline).getByRole('button', { name: /设计文档/ }), - ); + fireEvent.click(within(outline).getByRole('button', { name: /设计文档/ })); act(() => { dependencyCanvas.dispatchEvent( new WheelEvent('wheel', { @@ -3704,10 +3702,7 @@ export function registerProjectWorkbenchFoundationTests() { '[data-resource-viewport]', ); const viewportScale = Number( - viewportElement - ?.getAttribute('data-resource-viewport') - ?.split(',') - .at(2), + viewportElement?.getAttribute('data-resource-viewport')?.split(',').at(2), ); expect(viewportScale).toBeGreaterThan(0); const expectedX = Math.round(12 + (-100 - 20) / viewportScale); @@ -4727,7 +4722,7 @@ export function registerUserSurfaceBoundaryTests() { } export function registerProjectSupervisorSurfaceTests() { - it('routes a top workbench play request into the existing game.run_local confirmation', async () => { + it('runs a top workbench play request without a second confirmation', async () => { const projectPath = '/tmp/top-play-request'; const supervisorHarness = createProjectSupervisorRuntimeHarness({ projectPath, @@ -4745,6 +4740,19 @@ export function registerProjectSupervisorSurfaceTests() { recentRunStopReason: null, }; } + if (command === 'start_local_game_preview') { + return { + url: 'http://127.0.0.1:43127/', + port: 43127, + root: projectPath, + }; + } + if (command === 'get_local_game_manifest') { + return createGameCreationAppManifest( + 'top-play-request', + '顶部播放请求', + ); + } return supervisorHarness.invoke(command, args); }, ); @@ -4764,14 +4772,17 @@ export function registerProjectSupervisorSurfaceTests() { ); expect( - await screen.findByText('game.run_local', {}, { timeout: 3_000 }), + await screen.findByText( + /运行通过,已载入客户端运行视图/, + {}, + { timeout: 3_000 }, + ), ).not.toBeNull(); expect(handled).toHaveBeenCalledWith(7); - expect(screen.getByText(`启动 ${projectPath}/game/`)).not.toBeNull(); - expect(invoke).not.toHaveBeenCalledWith( - 'start_local_game_preview', - expect.anything(), - ); + expect(invoke).toHaveBeenCalledWith('start_local_game_preview', { + projectPath, + }); + expect(screen.queryByText('game.run_local')).toBeNull(); }); it('starts a direct product preview without the legacy Canvas-only static smoke', async () => { @@ -4812,9 +4823,6 @@ export function registerProjectSupervisorSurfaceTests() { }), ); - expect(await screen.findByText('game.run_local')).not.toBeNull(); - fireEvent.click(screen.getByRole('button', { name: '确认' })); - expect( await screen.findByText( '运行通过,已载入客户端运行视图:http://127.0.0.1:43126/', @@ -9961,7 +9969,8 @@ export function registerProjectSupervisorSurfaceTests() { projectPath, }); let directTurnUpdateHandler: - ((event: { payload: Record }) => void) | null = null; + | ((event: { payload: Record }) => void) + | null = null; const listen = vi.fn( async ( eventName: string, @@ -10919,7 +10928,8 @@ export function registerProjectAgentStatusTests() { }, ); let runtimeUpdateHandler: - ((event: { payload: Record }) => void) | null = null; + | ((event: { payload: Record }) => void) + | null = null; const listen = vi.fn( async ( eventName: string, diff --git a/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md b/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md index 653d993f3..a74487190 100644 --- a/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md +++ b/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md @@ -116,6 +116,7 @@ - 资源总览的“资源依赖 / 资源类型”视图切换使用连通的分段按钮组,相邻选项共享边界并保持唯一选中语义。每个分段都必须有清晰的键盘焦点指示,焦点环不得被分段容器的圆角或 `overflow` 裁切。 - 右侧 Supervisor 对话中,用户消息使用右对齐、最大宽度受限的主题暖色气泡,assistant 消息保持左对齐;消息换行不得产生水平溢出,执行过程卡继续占满消息区可用宽度。气泡正文在 light / dark 平台主题下均须满足 WCAG AA 普通文本 `4.5:1` 对比度。 - 客户端正式产品仍只按最小 `1280×720` 横屏合同交付,并保留 `1280×800` 默认窗口与既有基线验收;更窄浏览器样式只负责不崩溃和开发兼容,不改成移动端创作工作台。 +- 工作台顶部播放按钮在桌面视窗中水平居中;资源管理视窗触发播放时直接切换到运行视窗并启动本地预览,不再弹出 `game.run_local` 二次确认。 - 普通用户界面不默认展示内部错误码或本机绝对路径,也不展示 External Editor Base URL 或 Developer API Key;官方服务地址由客户端构建固定,远端编辑自动使用当前陶泥儿登录态。仅独立 standalone game-chat release 或显式高级自定义模式在隔离配置页维护 External v1 URL/Key,确需诊断的信息进入受控详情或开发模式。 - 创建模式素材画布的“素材名称”是用户可编辑的正式输出名称;“资源用途”是 manifest subtype,不向普通用户开放自由文本。新增资源默认“普通游戏美术”,可从普通游戏美术、统一视觉规范、游戏界面原型、核心美术图集四项中选择。图片精修继承源名称和用途,不显示创建模式保存设置;候选图片只从选中图片的“设为最终图”提交。精修顶栏只保留返回、导入、定位当前最终图、撤销和重做,删除进入图片上下文工具栏,通用 AI 生成只保留给创建模式。图片输出统一使用 PNG;创建模式工具动作与保存设置分层展示,“保存到项目”在 `1280×800` 和窄容器中都必须完整可见。 - 首页创作输入区与“最近项目”之间不展示共享项目状态文本,“最近项目”标题下也不追加解释性副标题;默认、成功、进行中或失败状态均不得在该位置形成文字行,项目管理页继续保留自己的状态反馈。 -- 2.52.0 From f103a01857cc1925f5861621fe072f5de0c39f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=94=E9=A6=99=E4=B8=B8=E5=AD=90?= <15518898337@163.com> Date: Mon, 24 Aug 2026 23:05:54 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Agent=20=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E4=B8=8E=E8=BF=90=E8=A1=8C=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化 Agent 消息排版与悬浮输入框 隐藏资源管理搜索框并调整运行入口 恢复运行视窗播放按钮位置与箭头样式 --- .../ProjectSupervisorView.tsx | 11 +- apps/ai-game-creator-shell/src/styles.css | 361 +++++++++++++++++- .../src/view/project-development/index.tsx | 259 ++++++++----- 3 files changed, 524 insertions(+), 107 deletions(-) diff --git a/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx b/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx index f51a37029..0d13a7671 100644 --- a/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx +++ b/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx @@ -1,4 +1,4 @@ -import { Send } from 'lucide-react'; +import { ArrowUp } from 'lucide-react'; import type { ComponentProps, Dispatch, @@ -210,14 +210,7 @@ export function ProjectSupervisorView({ type="submit" disabled={runtimePanelProps.controlBusy || needsUserInput} > -
- - -
@@ -4792,11 +4886,6 @@ export default function ProjectDevelopmentView({ {!uiEditorRoute ? (