v0.8.2: 工单大清理 - 编年史分页+限时挑战+星潮深化+云排行榜+手写叙事+socket多人星潮+UI打磨

工单 #8 编年史上限+分页:
- engine.ts: slice(-50)→slice(-200)
- ChronicleDialog.tsx: 加分页(每页10条)+上一页/下一页+页码显示

工单 #5 限时挑战 (subagent 10-a):
- beacon.ts: BeaconTimedChallenge + getTimedSlotKey(4h时段) + generateTimedChallenge
- BeaconPanel.tsx: amber主题限时区块 + 倒计时 + <30min紧急状态
- gameStore: trackBeacon 加 timedJustCompleted + claimTimedBeacon action

工单 #3 星潮类型深化 (subagent 10-a):
- starTide.ts: +3种星潮 surge(emerald)/eclipse(rose)/prism(fuchsia)
- TideModifiers: +targetLenBonus/bossWinRateBonus/autoDecodeIntervalMult
- decode.ts: generatePuzzle 加 targetLenBonus 参数
- achievements: ach_tides_all 阈值 6→9

工单 #4/P2 云排行榜 (subagent 10-b):
- mini-services/leaderboard-service/ (端口3030, Hono+bun, 内存1000条)
- API: GET/POST /api/leaderboard + /stats + CORS + 防刷
- beacon.ts: fetchCloudLeaderboard/submitCloudScore
- BeaconPanel: 本地Top20/全球Top100 双tab + YOU徽章高亮

工单 #9 手写叙事 (subagent 10-c):
- chronicle.ts: EPOCH_LORE 5纪元×3节点=15段手写叙事(80-150字/段)
- buildLore 优先手写节点, fallback 模板, 11个变量替换

P3 socket 多人星潮 (subagent 10-c):
- mini-services/star-tide-service/ (端口3031, socket.io)
- 每10-15min广播global-tide, 60s持续, 6种类型权重
- useGlobalTide hook + triggerGlobalTide action
- StarTideIndicator 加 🌐 全球星潮标记

P2 UI打磨:
- page.tsx: CrystalOrb 区加装饰全息环(3层旋转) + 四角标记 + 顶部状态条 + 底部铭文

QA: lint零错误 + dev HTTP200 + VLM 8/10 + 2个mini-service运行中(3030/3031)
This commit is contained in:
2026-06-23 23:57:41 +00:00
parent 6d7c52daa9
commit 191434e6ad
55 changed files with 9026 additions and 129 deletions
+52 -12
View File
@@ -16,12 +16,15 @@ export function StarTideNotifier() {
if (events.length === 0) return;
const items = consume();
for (const ev of items) {
const globalTag = ev.isGlobal ? "🌐 " : "";
if (ev.started) {
const meta = TIDE_EVENTS[ev.started];
sfx("tideStart");
toast({
title: `${meta.icon} 星潮降临${meta.name}`,
description: meta.desc,
title: `${globalTag}${meta.icon} ${ev.isGlobal ? "全球星潮" : "星潮降临"}${meta.name}`,
description: ev.isGlobal
? `全球玩家同步经历 · ${meta.desc}`
: meta.desc,
});
}
if (ev.ended) {
@@ -29,14 +32,16 @@ export function StarTideNotifier() {
if (ev.silenceCompensation && ev.silenceCompensation > 0) {
sfx("techBuy");
toast({
title: `${meta.icon} 寂静期消散`,
title: `${globalTag}${meta.icon} 寂静期消散`,
description: `虚空回赠 ${ev.silenceCompensation} 洞见。`,
});
} else {
sfx("tideEnd");
toast({
title: `${meta.icon} ${meta.name}结束`,
description: "星潮退去,物理法则恢复。",
title: `${globalTag}${meta.icon} ${meta.name}结束`,
description: ev.isGlobal
? "全球星潮退去,物理法则恢复。"
: "星潮退去,物理法则恢复。",
});
}
}
@@ -49,6 +54,7 @@ export function StarTideNotifier() {
/** 顶部星潮指示器(活跃时显示倒计时芯片) */
export function StarTideIndicator() {
const activeTide = useGameStore((s) => s.activeTide);
const globalTide = useGameStore((s) => s.globalTide);
const [, force] = useState(0);
// 每秒刷新倒计时
@@ -62,18 +68,27 @@ export function StarTideIndicator() {
const meta = TIDE_EVENTS[activeTide.type];
const remaining = Math.max(0, activeTide.endsAt - Date.now());
const secs = Math.ceil(remaining / 1000);
const progress = 1 - remaining / TIDE_CONFIG.duration;
// 全球星潮持续 60s,本地 75s —— 用实际 endsAt-startedAt 计算 progress,避免越界
const duration = globalTide
? globalTide.endsAt - globalTide.startedAt
: TIDE_CONFIG.duration;
const progress = Math.min(1, Math.max(0, 1 - remaining / duration));
const isGlobal = !!globalTide;
return (
<div
className="flex items-center gap-1.5 px-2 py-1 rounded-full text-[10px] font-medium relative overflow-hidden"
className={`flex items-center gap-1.5 px-2 py-1 rounded-full text-[10px] font-medium relative overflow-hidden ${
isGlobal ? "ring-1 ring-amber-300/60" : ""
}`}
style={{
background: `${meta.color}1a`,
border: `1px solid ${meta.color}55`,
background: isGlobal
? `linear-gradient(135deg, ${meta.color}26, ${meta.color}11)`
: `${meta.color}1a`,
border: `1px solid ${meta.color}${isGlobal ? "88" : "55"}`,
color: meta.color,
boxShadow: `0 0 10px ${meta.glow}`,
boxShadow: `0 0 ${isGlobal ? "16" : "10"}px ${meta.glow}`,
}}
title={meta.desc}
title={isGlobal ? `🌐 全球星潮 · ${meta.desc}` : meta.desc}
>
{/* 进度环背景 */}
<div
@@ -82,6 +97,14 @@ export function StarTideIndicator() {
background: `linear-gradient(90deg, ${meta.color}40 ${progress * 100}%, transparent ${progress * 100}%)`,
}}
/>
{isGlobal && (
<span
className="relative text-[11px] leading-none animate-pulse"
aria-label="全球星潮标记"
>
🌐
</span>
)}
<span className="relative text-xs leading-none">{meta.icon}</span>
<span className="relative leading-none">{meta.name}</span>
<span className="relative font-mono leading-none opacity-80">{secs}s</span>
@@ -92,8 +115,10 @@ export function StarTideIndicator() {
/** 全屏背景叠层:活跃星潮时给页面罩一层对应色的微光 */
export function StarTideOverlay() {
const activeTide = useGameStore((s) => s.activeTide);
const globalTide = useGameStore((s) => s.globalTide);
if (!activeTide) return null;
const meta = TIDE_EVENTS[activeTide.type];
const isGlobal = !!globalTide;
return (
<div className="fixed inset-0 pointer-events-none z-0 transition-opacity duration-1000">
@@ -115,15 +140,30 @@ export function StarTideOverlay() {
<div
className="absolute inset-0"
style={{
boxShadow: `inset 0 0 120px ${meta.glow}`,
boxShadow: `inset 0 0 ${isGlobal ? "160" : "120"}px ${meta.glow}`,
animation: "tide-breathe 3s ease-in-out infinite",
}}
/>
{/* 全球星潮:顶部多一道琥珀色光带,强化"全球同步"视觉信号 */}
{isGlobal && (
<div
className="absolute top-0 left-0 right-0 h-1 opacity-90"
style={{
background: "linear-gradient(90deg, transparent, #fbbf24, #fcd34d, #fbbf24, transparent)",
boxShadow: "0 0 16px rgba(251,191,36,0.7)",
animation: "global-tide-sweep 2.5s linear infinite",
}}
/>
)}
<style jsx>{`
@keyframes tide-breathe {
0%, 100% { opacity: 0.5; }
50% { opacity: 0.9; }
}
@keyframes global-tide-sweep {
0% { transform: translateX(-30%); }
100% { transform: translateX(30%); }
}
`}</style>
</div>
);