v0.1.11: 全源码审计 + 缺陷歼灭 + UI/UX 打磨

【引擎审计修复】
- P0:大比 once(原整年刷 12 场、奖励通胀);flag 年份键 3 年剪枝(长线膨胀)
- P1:飞升离世累加 feishengCount(飞升之资称号可达);圣者护族接消费(原死代码);
  大比/传薪挂能力卡门控;pending 抢渡劫时不再重设
- P2:version 硬编码统一 0.1.11;yearaxis 飞升归类;MonumentList 挂载

【UI 审计修复】
- P0:已故成员卡显示「已殁」(原秀活动 status);空队迎战禁用+提示(原静默失效)
- P1:指婚候选去截断(滚动列表);终局出口(回卷/主菜单按钮);saveNow 反馈;
  事件来临写入 feed(k-event 使用);遣队「最强 N 人/清空」一键;寻衅确认+联姻原因提示;
  未建建筑视觉 uc 类
- P2:speed 死代码;Modal 分层 z-index;FamilyPanel 在世/先人分隔

【UX 三件套】
- 警讯徽章(瓶颈/重伤/在外/媒缘/孤嗣之忧)顶栏一屏秒答「我该干嘛」
- 首启引导任务条(四步目标 + 完成推进,可跳不强制)
- 顶栏丹药瘦身(4 资源);数字千/万化;瓶颈卡红框高亮

【测试】905→923(urgency/guide/format 三模块 + 审计修复回归 6 项)
金钟罩三档重固化(0.1.11),typecheck/build 通过
This commit is contained in:
2026-08-23 11:30:16 +08:00
parent 586fa643b1
commit 9bcb5d6af8
25 changed files with 417 additions and 28 deletions
+93
View File
@@ -0,0 +1,93 @@
import { describe, expect, it } from 'vitest'
import { World } from '../src/renderer/game/engine/world'
import { applyEventChoice } from '../src/renderer/game/engine/systems/events'
import { computeUrgency } from '../src/renderer/game/core/urgency'
import { monthlyRate } from '../src/renderer/game/engine/systems/cultivation'
import { resetSaveBus, attachLogSink } from './world.helpers'
function baseWorld(seed: string): World {
const w = World.create({ seed, surname: '凌', familyName: '凌家', motto: 'm', difficulty: 'normal' })
resetSaveBus()
attachLogSink(w)
return w
}
describe('0.1.11 审计修复回归', () => {
it('大比 once:一季只触一次(不会整年刷 12 场)', () => {
const w = baseWorld('tourn-once')
w.state.year = 9
w.state.month = 12
w.advanceMonth() // year10 monthly
const seen: string[] = []
for (let i = 0; i < 24; i++) {
if (w.state.pendingEvent) {
if (w.state.pendingEvent.startsWith('ev-tournament-')) seen.push(w.state.pendingEvent)
applyEventChoice(w, w.state.pendingEvent, 0)
w.state.pendingEvent = undefined
}
w.advanceMonth()
}
expect(seen.filter((x) => x === 'ev-tournament-10').length).toBe(1)
})
it('飞升离世累加 feishengCount(可入飞升之资档)', () => {
const w = baseWorld('fs-count')
const c = w.state.members['x4']
c.realm = { major: 'spirit', minor: 1 }
applyEventChoice(w, 'ev-feisheng', 1) // 云游
expect(w.state.stats.feishengCount).toBe(1)
expect(w.state.family.flag['fengFeiBless']).toBe(true)
})
it('圣者护族对幼童有效(hasPatriarch 消费)', () => {
const w = baseWorld('patriarch')
const c = w.state.members['x5']
c.bornYear = 1 // 1 岁
const elder = w.state.members['x4']
elder.bornYear = 1 - 70
elder.realm = { major: 'foundation', minor: 1 }
const rate = monthlyRate(w, c)
expect(rate).toBeGreaterThan(0)
// 幼童本身速率低(<8 → ×0.65),此处只保证不为负
expect(rate).toBeGreaterThanOrEqual(0.1)
})
it('年份 flag 3 年后清理(pruneYearFlags', () => {
const w = baseWorld('prune')
w.state.year = 50
w.state.family.flag['auction-45'] = true
w.state.family.flag['auction-49'] = true
w.advanceMonth()
expect(w.state.family.flag['auction-45']).toBeUndefined()
expect(w.state.family.flag['auction-49']).toBe(true)
})
it('急事徽章 derived 正确(无继承人/重伤/瓶颈)', () => {
const w = baseWorld('urgent')
// 无继承人:除 x2 都死
w.state.members['x1'].alive = false
w.state.members['x3'].alive = false
w.state.members['x5'].alive = false
w.state.members['x4'].alive = false
const u = computeUrgency(w)
expect(u.noHeir).toBe(true)
// 重伤
const w2 = baseWorld('urgent2')
w2.state.members['x3'].health = 20
const u2 = computeUrgency(w2)
expect(u2.injuredCount).toBeGreaterThanOrEqual(1)
// 瓶颈
const w3 = baseWorld('urgent3')
w3.state.members['x3'].realmProgress = 100
const u3 = computeUrgency(w3)
expect(u3.blockedCount).toBeGreaterThanOrEqual(1)
})
it('王座 dead 成员不再显示活动 state(标签层修复)', () => {
const w = baseWorld('deadlabel')
const c = w.state.members['x3']
c.alive = false
// MemberCard 逻辑由 STATE_LABEL['dead'] 处理,引擎侧保证 alive=false 时 state 不变
expect(c.state === 'idle' || c.state === 'wounded' || c.state === 'meditation').toBe(true)
})
})