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
+78
View File
@@ -0,0 +1,78 @@
import { describe, expect, it } from 'vitest'
import { World } from '../src/renderer/game/engine/world'
import { computeUrgency } from '../src/renderer/game/core/urgency'
import { computeGuide, GUIDE_STEPS, guideAdvance } from '../src/renderer/game/core/guide'
import { fmt } from '../src/renderer/game/core/format'
function baseWorld(seed: string): World {
return World.create({ seed, surname: '舒', familyName: '舒家', motto: 'm', difficulty: 'normal' })
}
describe('急事徽章 derivedStateurgent', () => {
it('可突破≥1 时 badge 出现', () => {
const w = baseWorld('urge-a')
const c = w.state.members['x3']
c.realmProgress = 100
const u = computeUrgency(w)
expect(u.blockedCount).toBeGreaterThanOrEqual(1)
})
it('重伤 count 反映', () => {
const w = baseWorld('urge-b')
const c = w.state.members['x3']
c.health = 15
const u = computeUrgency(w)
expect(u.injuredCount).toBeGreaterThanOrEqual(1)
})
it('在外队伍 count 反映', () => {
const w = baseWorld('urge-c')
w.state.missions.push({ id: 'm1', defId: 'm-anmoku', memberIds: ['x3'], startYear: 1, startMonth: 1, stage: 0, stageMonth: 0, log: [], done: false })
const u = computeUrgency(w)
expect(u.missionCount).toBeGreaterThanOrEqual(1)
})
it('无继承人次条(危险信号)', () => {
const w = baseWorld('urge-d')
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)
})
})
describe('引导任务的 state machine', () => {
it('开局处于第 1 步', () => {
const w = baseWorld('guide-a')
expect(computeGuide(w).step).toBe(0)
expect(GUIDE_STEPS.length).toBe(4)
})
it('完成任务推进且可跳步(不强制)', () => {
const w = baseWorld('guide-b')
expect(guideAdvance(w, 2)).toBe(2) // 跳到第 3 步(index 2
})
it('所有目标挂到状态', () => {
for (let i = 0; i < 4; i++) {
expect(GUIDE_STEPS[i].title.length).toBeGreaterThan(1)
expect(GUIDE_STEPS[i].hint.length).toBeGreaterThan(1)
}
})
})
describe('数字格式化', () => {
it.each([[1234, '1.2千'], [56789, '5.7万'], [123456, '12.3万'], [7890123, '789.0万']])('%i → %s', (n, s) => {
expect(fmt(n)).toBe(s)
})
})
describe('0.1.11 编译 smoke', () => {
it('engine 加载并推进数月无异常', () => {
const w = baseWorld('smoke-011')
for (let i = 0; i < 24; i++) w.advanceMonth()
expect(w.state.year).toBeGreaterThan(1)
})
})