- 5 个解码阈值叙事里程碑(ms_5/12/25/40/60)+ 全屏碎片释放叠层 - loreLayer 已读标记(readLoreLayers + 点击文本标记 + 已读/未读视觉区分) - idleProjectHistory 详情展开(倒序最近 5 条 + 相对时间) - 新建 format.ts formatRelativeTime 工具函数 - 移动端 375px 适配审计(4 组件字号 9→10px + flex-wrap + 响应式 padding) - 严格 4 色全息,lint 零错误,agent-browser 端到端验证通过
7.8 KiB
Executable File
Task ID: 2-b Agent: full-stack-developer Task: v0.16 完善 — loreLayer 已读标记 + idleProjectHistory 详情展开 + 移动端 375px 适配审计
Work Log:
-
必读上下文:worklog v0.15-release 段 + Codex.tsx(v0.15 loreLayers 分层渲染)+ StatsPanel.tsx(v0.15 抽出独立组件)+ types.ts GameState + config.ts FRAGMENTS/loreLayers/isLoreLayerUnlocked + gameStore.ts(actions + persist migrate)+ IdleOperationsPanel.tsx + BeaconPanel.tsx + ExpeditionPanel.tsx
-
子任务 1:loreLayer 已读标记
- 新建
src/lib/game/format.ts导出formatRelativeTime(ts)工具函数(<60s "刚刚" / <60m "X 分钟前" / <24h "X 小时前" / <7d "X 天前" / 否则具体日期) types.ts:GameState 接口新增readLoreLayers: string[](位置:v0.14 idle 字段之后、元字段之前,注释标 v0.16 loreLayer 已读)engine.ts:createInitialState末尾加readLoreLayers: [](在 idleStats 之后)performPrestige返回对象加readLoreLayers: Array.isArray(state.readLoreLayers) ? state.readLoreLayers : [](跨周目永久保留,与 idle 永久字段同一区域)
gameStore.ts:- GameActions 接口加
markLoreLayerRead: (fragmentId: string, layer: 1 | 2) => void(在 tickIdleProjects 之后) - 实现该 action:构造 key
${fragmentId}_L${layer},已存在则 no-op,否则 set 新数组 - persist migrate 函数末尾加
readLoreLayers: Array.isArray(s.readLoreLayers) ? s.readLoreLayers : [](不改 version,仍是 1)
- GameActions 接口加
Codex.tsx:- useShallow 订阅新增
readLoreLayers与markLoreLayerRead - LoreLayerBlock 接收
isRead+onMarkReadprops:- 已读:层标题旁加 muted "✓ 已读" 标记 + 边框从 amber/fuchsia 高亮降级为
border-white/10 - 未读但已解锁:保持 v0.15 高亮 + 标题旁加
animate-pulse脉冲小圆点 + "新" 字提示 - 文本区域包成
<button>元素,点击调用onMarkRead(自然交互,不另设按钮) - 未读时下方加一行 muted "▸ 点击文本标记已读" 引导文字
- 已读:层标题旁加 muted "✓ 已读" 标记 + 边框从 amber/fuchsia 高亮降级为
- 列表卡片标题旁小圆点:未读时
animate-pulse+ glow,已读时bg-*-400/30静态 - 顶部统计从单行"深层叙事 X/Y 已解锁"扩展为两行(移动端 stack / 桌面并排):深层叙事 X/Y 已解锁 + 已读 A/B(A=已读数,B=已解锁层数)
- 弹层 padding 从
p-5改p-4 sm:p-5,标题text-lg改text-base sm:text-lg,外层 backdrop padding 从p-4改p-3 sm:p-4(375px 适配)
- useShallow 订阅新增
- 新建
-
子任务 2:idleProjectHistory 详情展开
StatsPanel.tsx:- useShallow 订阅新增
idleProjectHistory数组与idleProjectSlots(用于详情中潜在"进行中"状态参考) - 删除原"放置工程历史 N 条"的简单行,改为
col-span-2可展开按钮:- 左侧 label + "(最近 5 条可展开)" 提示(仅 historyLen > 0 时显示)
- 右侧 "N 条" + ChevronDown/ChevronUp 图标(lucide-react)
- 展开后渲染
col-span-2卡片:- 空历史 → "暂无放置工程完成记录 · 前往「放置」标签派遣工程"
- 非空 → 倒序最近 5 条:每行 = 工程图标 + 工程名(truncate)+ 相对时间(formatRelativeTime)
- 最近一条用
bg-fuchsia-500/5高亮 - 历史超 5 条时底部加 "仅展示最近 5 条 · 共 N 条历史" 提示
- 展开状态用本地
useState<boolean> - useMemo 派生
recentHistory(避免每次渲染重切)
- useShallow 订阅新增
-
子任务 3:移动端 375px 适配审计
- 审计范围:Codex / IdleOperationsPanel / StatsPanel / BeaconPanel / ExpeditionPanel
- 修复点:
IdleOperationsPanel.tsx:所有text-[9px]→text-[10px](11 处,符合"移动端字号最小 10px"规范)BeaconPanel.tsx:所有text-[9px]→text-[10px](7 处);信标链底部统计行flex items-center justify-between gap-2→flex flex-wrap items-center justify-between gap-x-2 gap-y-1(防 3 组数据在 375px 溢出)Codex.tsx:弹层 padding + 标题字号响应式(见子任务 1);顶部统计区flex flex-col sm:flex-row(移动端纵向堆叠)StatsPanel.tsx:detail 区text-[9px]→text-[10px](2 处)
- 审计通过(无需改):
ExpeditionPanel.tsx:节点路径已用overflow-x-auto自适应窄屏;事件卡 p-3 padding 合理;按钮组flex-1+ abort 收起;能量条文字text-[10px]已达标;路径节点h-9 w-936px 足够小且可横向滚动BeaconPanel.tsx:4 个里程碑节点w-12 h-12(48px)× 4 = 192px + flex-1 分布,375px 下可容纳;日/周挑战卡 padding p-3 合理;周挑战+信标链已用grid-cols-1 lg:grid-cols-2移动单列IdleOperationsPanel.tsx:4 个 section 已用grid-cols-1 sm:grid-cols-N/grid-cols-2 sm:grid-cols-3响应式降级;DispatchCard 槽位按钮h-5 w-7× 3 在单列布局下不溢出Codex.tsx列表grid-cols-2 gap-2:每卡片约 165px 宽,aspect-[4/3] + p-2 + text-[11px]/text-[9px](已升 text-[10px])在 375px 下可读
-
严格 4 色全息:emerald / rose / amber / fuchsia,未引入 blue / indigo
-
useShallow:所有 store 订阅用 useShallow(Codex / StatsPanel 均已用)
-
持久化兼容:persist version 仍为 1,新字段
readLoreLayers靠 migrate 兜底,旧存档加载时自动补[] -
与子代理 A 文件边界:types.ts/engine.ts/gameStore.ts 三个共享文件,A 的
triggeredMilestones/pendingMilestone/dismissMilestone字段已落地,与本子代理的readLoreLayers/markLoreLayerRead完全无冲突(不同字段、不同 action、不同 migrate 行)
Stage Summary:
- ✅ 子任务 1:loreLayer 已读标记完整实现
- 类型 + store + UI 三层联动;点击层文本即可标记已读
- 视觉区分:已读 = muted "✓ 已读" + 边框降级为 border-white/10;未读 = 高亮 + 脉冲小圆点 + "新" 字
- 顶部统计新增"已读 A/B"行(A=已读数 / B=已解锁层数)
- 跨周目永久保留(performPrestige 不重置)
- ✅ 子任务 2:idleProjectHistory 详情展开完整实现
- "放置工程历史" 行可点击展开/收起
- 展开后显示最近 5 条倒序历史(图标 + 工程名 + 相对时间)
- 空态友好提示,超 5 条底部加"仅展示最近 5 条"说明
- ✅ 子任务 3:移动端 375px 适配审计完成
- 审 5 个组件,修 4 个(Codex / IdleOps / StatsPanel / Beacon),ExpeditionPanel 无需改
- 主要修复:text-[9px] → text-[10px](共 20 处,符合"移动端字号最小 10px"规范)
- 信标链底部统计加 flex-wrap 防 3 组数据溢出
- Codex 弹层 padding + 标题字号响应式
- Codex 顶部统计区移动端纵向堆叠
- ✅ 新建文件:
/home/z/my-project/src/lib/game/format.ts - ✅ 修改文件清单(绝对路径):
/home/z/my-project/src/lib/game/types.ts(+readLoreLayers 字段)/home/z/my-project/src/lib/game/engine.ts(createInitialState 默认 + performPrestige 保留)/home/z/my-project/src/store/gameStore.ts(GameActions 签名 + action 实现 + migrate 补全)/home/z/my-project/src/components/game/Codex.tsx(已读标记 + 点击逻辑 + 顶部统计 + 弹层响应式)/home/z/my-project/src/components/game/StatsPanel.tsx(idleHistory 展开 + 相对时间 + 字号升级)/home/z/my-project/src/components/game/IdleOperationsPanel.tsx(字号 9→10px 升级)/home/z/my-project/src/components/game/BeaconPanel.tsx(字号 9→10px 升级 + 信标链底部 flex-wrap)
- ✅ bun run lint 零错误零警告
- ✅ HTTP 200,dev.log 无运行时错误(compile 11ms / render 33ms)
- ✅ 与子代理 A 文件边界完全无冲突(不同字段/action/migrate 行)
- ⚠️ 未做 agent-browser 端到端验证(按工单由主控完成)