v0.1.9: 百年报告 & 发布之窗(报告/迁移/阵型/冬祷/哨兵)

- 百年族史报告:buildReport 纯函数(人口/声望/战力三线、死因榜、突破密度、
  大比战绩、代际长度带)+ 春秋原 SVG 折线视图 + 自动措辞结语
- 存档迁移管线 v2:migrate 链(v1→v2)+ 未来版本拒载(TOO_NEW)+ 导出信封
  带 appId/schemaVersion + 导入全链路迁移校验;saveState 自动写 CURRENT_SCHEMA
- 战斗阵型:锋阵(+10%攻)/雁阵(御5%+溃伤-15%)/蛇阵(溃伤-30%),三处出战接入
  (遣队/大比/劫掠)点将面板下拉 + 战报首行标阵
- 冬至岁祷:每年十一月三选(观星+3声望/祈福全族修为/问卜吉凶)
- 发布准备:scripts/verify-release.mjs 验收哨兵(npm run verify/verify:package)
  + README 全面重写(架构/守护/版本沿革);版本号三处归一
- 测试 861→881(报告四例/迁移五链/阵型六则含胜率统计/冬祷四则);
  金钟罩三指纹零漂移;typecheck/build 通过
This commit is contained in:
2026-08-23 10:11:22 +08:00
parent 3195f67455
commit f5a2c1b68a
18 changed files with 654 additions and 50 deletions
+16 -1
View File
@@ -4,6 +4,7 @@ import { sendMission, recallAll } from '../../game/engine/systems/missions'
import { combatPowerOf } from '../../game/engine/systems/combat'
import { useState } from 'react'
import { describeRealm, MAJOR_ORDER } from '../../game/data/realms'
import { FORMATIONS, FormationId } from '../../game/data/formations'
export default function ExpeditionPanel() {
const world = useGameStore((s) => s.world)
@@ -13,6 +14,7 @@ export default function ExpeditionPanel() {
const revision = useGameStore((s) => s.revision)
void revision
const [squad, setSquad] = useState<string[]>([])
const [formation, setFormation] = useState<FormationId>('vanguard')
if (!world) return null
const w = world
const s = w.state
@@ -78,11 +80,24 @@ export default function ExpeditionPanel() {
))}
{candidates.length === 0 && <span className="dim2"></span>}
</div>
<div className="formation-pick" style={{ marginBottom: 8 }}>
{(Object.keys(FORMATIONS) as FormationId[]).map((fid) => (
<div
key={fid}
className={`tag ${formation === fid ? 'gold-t' : ''}`}
style={{ cursor: 'pointer', padding: '3px 10px' }}
onClick={() => setFormation(fid)}
title={FORMATIONS[fid].desc}
>
{FORMATIONS[fid].name}
</div>
))}
</div>
<button
className="btn btn-primary"
disabled={squad.length < def.minMembers || squad.length > def.maxMembers || active.length >= 3}
onClick={() => {
sendMission(w, def.id, squad)
sendMission(w, def.id, squad, formation)
setSquad([])
bump()
}}