# UI 改动记录(供后续 Agent 阅读) 本文档汇总 **像素 RPG UI 皮肤化** 相关实现与决策,便于新会话快速接手。更细的命名与规范见同目录上一级的 **`UI_CODING_STANDARD.md`**。 --- ## 1. 相关文件一览 | 路径 | 作用 | | ------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | `UI_CODING_STANDARD.md` | 资源目录约定、9-slice 规则、图标语义、`Icons`/`UI` 命名解读、已知问题(含世界按钮切片) | | `src/uiAssets.ts` | **唯一推荐** 的 UI 资源映射:`UI_CHROME`(9-slice 配置)、`TAB_ICONS`、`WORLD_SELECT_ICONS`、`getNineSliceStyle()` | | `src/components/PixelIcon.tsx` | 小图标 ``,`image-rendering: pixelated` | | `src/index.css` | `.pixel-nine-slice`、`.pixel-root-shell` / `.pixel-app-shell`、tab/按钮布局类、`--ui-scale` | | `src/App.tsx` | 世界选择、角色卡、底部 tab、剧情/背包面板、地图弹窗、`MudMapRoom` | | `src/components/GameCanvas.tsx` | 场景名按钮(9-slice `Title_frame_m`) | | `vite.config.ts` | `root` / `envDir` 指向 `__dirname`,保证 `.env.local` 从项目根加载 | | `public/UI/`、`public/Icons/` | 静态资源(路径以 `/UI/...`、`/Icons/...` 引用) | --- ## 2. 架构要点 ### 2.1 9-slice(禁止整图 `background-size: 100% 100%` 拉框体) - 使用 CSS **`border-image`** + **`fill`**,通过自定义属性注入切片参数。 - 类名:**`pixel-nine-slice`**(定义在 `src/index.css`)。 - 行内样式由 **`getNineSliceStyle(texture, overrides?)`** 生成(`src/uiAssets.ts`),设置 `--frame-src`、`--slice-*`、`--frame-pad-*`、`--frame-repeat`、可选 `--frame-base`(一般仅在图源中心确实透明时使用)。 ### 2.2 响应与缩放 - `:root` 上 **`--ui-scale`**:`clamp`(桌面)+ 小屏媒体查询内固定约 `0.8`。 - 边框宽度 = 切片像素 × `--ui-scale`,与 padding 同逻辑,避免移动端边框比例失控。 ### 2.3 交互 - **`pixel-pressable`**:hover 用 `translateY` + `brightness`,**避免**对像素框体做 `scale()` 以免糊边。 ### 2.4 全局背景 - **根布局**(`App.tsx` 最外层):`pixel-root-shell` + `Background_fill.png` 平铺 + 深色半透明渐变(替代纯 `#050505` 死底)。 - **下半屏内容区** `pixel-app-shell`:同一纹理 + **更轻**的遮罩,让纹理更明显。 - 开局标题区已去掉单独 `bg-zinc-950`,与根背景一致。 --- ## 3. `UI_CHROME` 当前用途(速查) 以下为 `src/uiAssets.ts` 中主要键与界面位置的对应关系(切片数值以文件内为准): | Key | 资源(示例) | 用途 | | ----------------------------------------- | ------------------------------------- | ------------------------------------------ | | `appBackground` | `Background_fill.png` | 根壳 + 下半屏平铺底 | | `worldButtonWuxia` / `worldButtonXianxia` | `1_orange_button` / `1_violet_button` | 开局武侠/仙侠(**条高 28px**,切片见下文) | | `characterCardFrame` | `pick_hero_frame` | 选角卡片 | | `tabActive` / `tabInactive` | `Shop_tab_picked` / `Shop_tab` | 底部「角色 / 冒险 / 背包」 | | `panel` | `Frame_bg_big_2` | 装备区等通用面板 | | `storyPanel` | `Dialogue_frame` | 剧情正文区 | | `inventoryPanel` | `Inventory_bg` | 背包条目 | | `statsPanel` | `Stats_bar` | 角色数值面板 | | `choiceButton` | `Options_bar` | 剧情选项按钮 | | `modalPanel` | `Popup_window` | 地图弹窗外壳 | | `infoPanel` | `Dialogue_frame` | 地图弹窗内「当前地点 / 可前往」信息块 | | `sceneTitle` | `Title_frame_m` | 战斗画布顶部场景名按钮 | | `mapRoomCell` | `Map_frame` | 地图节点卡片(`MudMapRoom`) | | `mapDiagramPanel` | `Frame_bg_big_2` | 地图关系图整体衬底 | 图标路径:`TAB_ICONS`、`WORLD_SELECT_ICONS`、`CHROME_ICONS`;装备槽与背包分类见 `getEquipmentSlotIcon` / `getInventoryCategoryIcon`。 --- ## 4. 已知坑(必读) ### 4.1 世界选择按钮「中间发空」 - 图源 **`1_orange_button.png` / `1_violet_button.png` 为 125×28**。 - 若 **`slice.top + slice.bottom >= 28`**,中间横带高度为 **0**,`border-image` 的 `fill` 异常,看起来像透明/没画上。 - **正确做法**:减小上下切片(当前为 **9+9**),并配合 `repeat: 'stretch'` 竖向拉伸条形成品。 - **不推荐**:用大色块 `baseColor` 糊底(与素材内渐变/内框不一致)。详见 `UI_CODING_STANDARD.md`「已知问题」。 ### 4.2 新增 9-slice 前 先读 PNG **宽高**,保证 **`top+bottom < height`** 且 **`left+right < width`**。 --- ## 5. 环境与运行(与 UI 无关但易踩坑) - LLM:`VITE_LLM_*` 写在项目根 **`.env.local`**;因 `vite.config.ts` 固定 `envDir: __dirname`,从任意 cwd 启动也应能读到。 - 开发:`npm run dev`(默认端口见 `package.json`)。 --- ## 6. 尚未统一成 UI 图、仍用 Tailwind 小块面的区域(可选后续) 若产品要求「全盘无纯色板」,可继续替换,当前仍可能为 `bg-black/20`、`rounded-lg border` 等: - 角色页装备行、属性格子 - 地图弹窗顶栏分隔、关闭按钮外圈 - `GameCanvas` 内血条、名字条等 HUD --- ## 7. 修改清单摘要(按主题) 1. **资源规范**:`UI_CODING_STANDARD.md` + 集中映射 `uiAssets.ts`。 2. **9-slice 系统**:`index.css` + `getNineSliceStyle`。 3. **开局 / 主界面**:世界按钮、选角卡、tab、面板、选项、背包、根与内容区背景纹理。 4. **地图弹窗**:外壳、信息板、节点 `Map_frame`、关系图 `Frame_bg_big_2`。 5. **画布**:场景名 `Title_frame_m`。 6. **世界按钮**:按真实像素尺寸修正切片,去掉错误 `baseColor` 方案。 7. **Vite**:`root`/`envDir` 保证环境变量加载稳定。 --- ## 8. 2026-04-18 / 2026-04-20 账号入口补充记录 - 早期方案曾在 `AuthGate` 层提供右上角全局账号信息条,并在 `GameShellRuntime` 中临时隐藏。 - 2026-04-20 起,这个全局悬浮入口已整体下线,不再区分“平台显示 / 冒险隐藏”。 - 原因是右上角高频观察区不适合承载账号入口,且平台内已经有更明确的页面内入口。 ## 9. 2026-05-08 创作首页通知入口下线 - `CreativeAgentHome` 顶栏右上角不再展示“通知与账户”按钮,避免创作首页把通知入口放在首屏高频区域。 - 2026-05-12 平台入口页同步移除移动端和桌面端右上角通知铃铛;移动端顶栏只保留品牌,未登录时保留登录按钮,桌面端只保留账号入口。 - 账号入口仍保留在侧边栏底部,创作首页顶栏维持左侧菜单、居中品牌的轻量结构。 - 当前账号相关入口统一保留在平台首页受保护动作、个人页、存档页与账号弹窗,不再占用全局悬浮层。 --- ## 9. 2026-04-20 等级 HUD / 冒险布局补充 - 当前运行中的等级 UI 已从 `AdventurePanel` 底部移出,改为放在 `GameShellRuntime` 左上角固定 HUD,避免把主对话区挤短。 - 左上角 HUD 复用 `CharacterInfoShared.tsx` 里的 `PlayerLevelProgress`,角色面板、实体详情、游戏 HUD 使用同一套等级进度表现。 - `AdventurePanel` 不再承担等级条展示,底部交互区只保留队伍 / 背包 / 刷新 / 退出聊天 / 选项 / 自定义输入,并压缩了底部留白与面板间距。 - 角色信息不只在总 HUD 里显示:`CharacterPanel` 的队伍成员卡、角色详情面板,以及 `AdventureEntityModal` 的实体详情头部都会展示角色身份与等级信息。 - 队长展示正式 `Lv.`;同行角色展示“参考 Lv.”;NPC 优先展示运行时 `levelProfile.level`,这样 UI 只负责表现,不在前端虚构额外成长逻辑。 - 左上角等级 HUD 不使用背景框体,仅保留 `Lv`、等级数字与极细经验线,避免遮挡场景背景与移动端视野。 --- ## 10. 2026-04-20 平台亮色主题主 Tab 修正 - `PlatformHomeView.tsx` 的四个主 Tab(首页 / 创作 / 存档 / 我的)现在统一挂在 `platform-remap-surface` 下,让亮色主题能接管历史遗留的 `text-zinc-*`、`bg-black/*`、`border-white/*` 组合。 - 平台首页卡片覆层不要在组件里继续写死深色 `rgba(8,10,14,...)` 渐变;这次已收口为 `--platform-card-overlay-soft`、`--platform-card-overlay-strong`、`--platform-card-overlay-deep`,明暗主题都从 token 走。 - 平台桌面顶栏里的账号头像、移动端底部主 Tab 分隔线,也不要保留暗色主题时留下的固定蓝色渐变和深色边线,应直接使用平台主题变量(如 `--platform-profile-avatar-fill`、`--platform-line-soft`)。 - 后续如果继续调整平台主 Tab 视觉,优先改 `src/index.css` 的平台主题 token 和 remap 规则;只有 token 无法表达时,再做局部组件样式补丁,避免亮色主题再次出现“页面整体是亮的,但局部卡片仍是暗的”。 - 参考图方向已明确:平台亮色主题应以白色为主底色,粉红只承担背景气氛和重点 CTA,不应让整页主壳继续像深粉底板。 - 移动端底部 `platform-bottom-nav` 的 Tab 激活态必须与默认态使用同一套盒模型;边框要预占位,不能在 onPress / active 时临时增加边框导致按钮尺寸和留白跳变。 - 2026-04-20 第二轮细查补色时,继续把 `PlatformWorldDetailView.tsx`、`PlatformHomeView.tsx`、`PreGameSelectionFlow.tsx` 里落在白底/浅底面板上的标题、说明、次级标签、搜索栏和加载兜底文本显式切回平台亮色 token,避免亮色主题下继续出现浅底白字或过浅灰字。 - 2026-04-20 第三轮修正方向后,平台首页移动端底部 `platform-bottom-nav` 的高度、内边距、按钮圆角、图标尺寸、标签字号统一收口到 `src/index.css` token;`PlatformHomeView.tsx` 只保留结构类,避免 `h-14`、容器 padding、按钮内部内容间距和 active 底座各自维护半套尺寸,导致选中态看起来比 Tab 槽位更矮或更高。 - 2026-04-20 第四轮把平台亮色主题顶部过重的红色收轻:`--platform-body-fill`、`--platform-hero-fill`、`--platform-shell-glow-*` 与 `--platform-surface-glow-*` 改成更接近暖白 + 浅珊瑚的低饱和版本,首页 / 创作页 / 详情页 Hero 覆层统一改走 `--platform-hero-overlay-strong`,避免组件里继续写死高饱和粉红渐变。 --- ## 11. 2026-04-20 创作 Agent 聊天工作台亮色主题补色 - `src/components/custom-world-agent/*` 这一条创作 Agent 工作台链路已统一切回 `platform-subpanel`、`platform-input`、`platform-button`、`platform-banner`、`platform-progress-track`,亮色主题下不再继续裸露 `bg-[#111318]`、`bg-black/*`、`bg-white/*`、`text-white` 这类历史深色残留。 - 聊天线程中的用户气泡、助手气泡、系统消息、推荐回复按钮、流式回复态统一映射到平台 token;后续如果继续调整创作 Agent 聊天视觉,优先改平台 token 或平台 class,不要在组件里再单独写一套聊天色板。 - 顶栏、操作横幅、进度条、输入框的状态色统一复用平台亮暗主题变量,避免再次出现“页面整体已切亮色,但 Agent 局部还是旧暗色弹层”的割裂感。 --- ## 12. 2026-04-20 NPC 聊天退出恢复与文本阅读性修正 - `AdventurePanel.tsx` 的叙事 `storyText` 已取消斜体,改为更大的正文尺寸,避免长段阅读时发飘。 - 冒险面板里的 `actionText` 统一上调到聊天态同级字号;`detailText` 不再默认渲染,保持底部选项区更清爽。 - `npcEncounterActions.ts` 在“退出聊天”后重新续写剧情时,会优先把当前故事里最近一轮已经呈现给玩家的非聊天选项文案并回 `optionCatalog`,避免高好感聊天收束后又退回 NPC 静态 fallback 文案。 --- ## 13. 2026-04-21 创作中心失效草稿恢复兜底 - `src/components/rpg-entry/useRpgEntryLibraryDetail.ts` 现在会识别 `custom-world agent session` 的 `404 NOT_FOUND` 读取失败,不再把这类错误直接冒泡成未捕获 Promise。 - 当用户在创作中心点击“继续创作”命中失效草稿时,前端会主动清空 `customWorldSessionId` 恢复参数,并刷新一次 works 列表,避免刷新页面后反复尝试恢复同一个坏会话。 - 当前交互已收口成平台内可见提示:用户会停留在创作中心,并看到“这份共创草稿已失效,已为你返回创作中心,请重新开始创作。”,而不是卡在空白工作区或只在控制台看到英文异常。 - 这次兜底只处理失效会话恢复,不改变正常草稿继续创作、结果页恢复和已发布作品进入世界的主链。 --- ## 14. 2026-04-24 Agent 工作区恢复指针按用户隔离 - `custom-world agent session` 现在由 `server-rs` Axum 路由接入 SpacetimeDB procedure,模块内按 `owner_user_id + session_id` 查询;前端恢复旧工作区前必须确认本地指针属于当前登录用户,否则旧账号残留会先请求一次 `/api/runtime/custom-world/agent/sessions/:sessionId` 并产生 404。 - `src/services/customWorldAgentUiState.ts` 的 URL 仍只保留 `customWorldSessionId` / `customWorldOperationId`,用户归属只写入 `sessionStorage`,避免把 `userId` 暴露到可分享链接里。 - `src/components/rpg-entry/useRpgCreationSessionController.ts` 在恢复初始工作区时会对比 `ownerUserId`,发现不是当前用户就清空恢复指针并停留在创作入口,不再打后端失效 session。 - 后续新增 Agent 类恢复入口时,同样要区分“可分享的 URL 指针”和“仅本机使用的登录用户归属”,不要只凭 sessionId 自动恢复受保护资源。 --- ## 15. 2026-04-24 多玩法 Agent 聊天顶部文案统一隐藏 - `CreationAgentWorkspace` 已支持在 `title` 与 `assistantSummary` 为空时只展示返回、主操作、进度与锚点区域;各玩法适配层不要再传入“世界共创 / 玩法共创”这类模块标题或引导副文案。 - `custom-world`、`big-fish`、`puzzle` 三条 Agent 聊天工作区现在统一隐藏顶部标题与标题下方说明,避免只有 RPG / 自定义世界生效、其他玩法模板仍残留旧文案。 - 后续新增玩法模板时,聊天页顶部模块应保持清爽:必要状态放进进度、操作横幅或聊天消息,不把功能说明类文案默认写入 UI。 --- ## 16. 2026-04-24 创作结果页亮色主题细节补色 - RPG / 拼图 / 大鱼结果页根容器统一挂 `platform-remap-surface`,让亮色主题能接管遗留的 `text-white`、`text-zinc-*`、`bg-white/*`、`bg-black/*` 和状态色工具类。 - 拼图与大鱼结果页顶部 Hero 只增加 `platform-result-hero` 语义类,不改变整体布局;亮色主题下由 `src/index.css` 统一换成暖白底、轻粉高光和平台主按钮色。 - 地图弹窗新增 `map-modal-overlay`、`map-modal-shell`、`map-modal-backdrop`、`map-modal-shade`、`map-info-panel` 语义类;亮色主题通过这些类降低暗色遮罩、提亮地图背景、统一节点卡与连线颜色。 - 结果页中保存、生成、发布等旧的 `bg-amber-600` / `bg-cyan-600` / `bg-cyan-200` 按钮,在 `platform-remap-surface` 内被映射回 `platform-button--primary` 同款渐变,避免亮色主题下按钮体系割裂。 - 后续继续做结果页 UI 细节时,优先补语义 class + `src/index.css` 的 light remap,不要在每个结果页组件里复制一套亮色配色,也不要调整页面整体布局结构。 --- ## 17. 2026-04-26 创作编辑器关闭确认弹窗亮色主题修正 - `RpgCreationEntityEditorShared.tsx` 的未保存关闭确认统一收口为 `CloseConfirmDialog`,弹窗只保留确认信息和两个动作,不新增说明文案。 - `CloseConfirmDialog` 通过 `platform-close-confirm-dialog` 语义类接入平台主题 token;提示块使用 `--platform-warm-*`,确认按钮使用 `--platform-button-primary-*`,继续编辑按钮使用 `--platform-neutral-*`。 - 后续新增关闭 / 退出确认面板时,不要继续复制 `text-amber-50`、`text-sky-50`、`bg-black/*` 这类深色 Tailwind 组合;优先复用语义类,避免亮色主题出现浅底白字和按钮文字不可读。 --- ## 18. 2026-04-30 资料兑换码弹窗响应式修正 - `RpgEntryHomeView.tsx` 的兑换码弹窗现在抽成同一份 `rewardCodeModal`,桌面与移动端分支都挂载,避免竖屏点击头像右侧“兑换码”后只更新状态但不显示窗口。 - `src/index.css` 已补齐 `platform-modal-backdrop`、`platform-recharge-modal`、`platform-profile-input`、`platform-primary-button`、`platform-modal-close` 与兑换结果提示样式;后续资料类轻量弹窗可以复用这组类接入平台主题背景。 - 兑换码窗口仍只保留输入框、兑换按钮和后端返回提示,不新增规则说明文案。 --- ## 19. 2026-05-12 登录协议与个人页法律入口 - 登录弹窗的法律协议确认应挂在短信 / 密码登录提交按钮上方,法律链接只打开独立 `LegalDocumentModal`,不能顺手勾选同意。 - 法律弹窗通过 portal 挂到 `body` 时必须显式带 `platform-theme--*` 和高于登录遮罩的层级,否则容易丢主题变量或被登录弹窗遮住。 - “我的”页常用功能区固定为 3 列,法律信息区放在设置入口下方;备案号作为外链进入工信部备案站,入口保持轻量,不在页面内展开长文。 --- _文档目的:交接给下一个 Agent 时,优先读本文件 + `UI_CODING_STANDARD.md`,再改 `uiAssets.ts` / `App.tsx` / `index.css`。_