Files
echo-nexus/mini-services/leaderboard-service/README.md
T
Super_Z 191434e6ad 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)
2026-06-23 23:57:41 +00:00

3.0 KiB
Raw Blame History

Echo Nexus · 云排行榜 mini-service

回响星核 / Echo Nexus 的 P2 云排行榜服务(v0.8.2 / Task 10-b)。

把信标本机排行榜(localStorage)升级为云端 Top100,玩家间可比。

技术栈

  • 运行时Bun(原生 TypeScript,无需编译)
  • 框架Hono(轻量 web 框架,bun 原生支持)
  • 存储:内存数组,重启清空(够用,符合 P2 规格)
  • 端口:固定 3030Caddy 通过 ?XTransformPort=3030 转发)

目录结构

mini-services/leaderboard-service/
├── package.json    # 独立 bun 项目
├── index.ts        # Hono 入口
└── README.md

API

所有响应自动 CORS 开放,OPTIONS 预检由 Hono 自动处理。

方法 路径 入参 返回
GET / { service, version, ok, uptime } 健康检查
GET /api/leaderboard { entries: BeaconScoreEntry[], total } Top100
POST /api/leaderboard body { entry: BeaconScoreEntry } { entries, total, rank } rank=1..N 或 -1
GET /api/leaderboard/stats { totalSubmissions, uniquePlayers, topScore }

BeaconScoreEntry 结构

{
  timestamp: number,        // 提交时间戳
  dateKey: string,          // YYYY-MM-DD 或 YYYY-Www
  challenge: string,        // decode | expedition | pulse | boss | insight
  difficulty: string,       // routine | anomaly | singular
  progress: number,         // 0-11 = 完成
  score: number,            // 最终得分
  durationSec: number,      // 完成时长(秒)
  isWeekly?: boolean,       // 周挑战记录
  isTimed?: boolean         // 限时挑战记录(预留)
}

存储 & 防刷规则

  • 容量:最多 1000 条,按分数降序;超过自动丢弃尾部。
  • Top 榜API 返回前 100 条。
  • 同分排序:先看用时短,再看提交早。
  • 防刷:同 dateKey + challenge 10 秒内只接受 1 次提交,返回 429

启动

cd mini-services/leaderboard-service
bun run dev
# 等价于 bun --hot index.ts,文件变更自动重启

联调(前端请求规范)

前端必须用相对路径 + ?XTransformPort=3030

// 拉取全球 Top100
const res = await fetch("/api/leaderboard?XTransformPort=3030");
const { entries, total } = await res.json();

// 提交一条记录
const res = await fetch("/api/leaderboard?XTransformPort=3030", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ entry }),
});
const { entries, total, rank } = await res.json();

禁止 fetch("http://localhost:3030/...") —— 不通过 Caddy 网关,会被浏览器同源策略拦截。

部署形态

独立 bun 项目,与主 Next.js 项目解耦:

  • 主项目端口 3000Next.js dev
  • 本服务端口 3030Hono + Bun
  • Caddy 网关端口 81(按 ?XTransformPort=3030 转发到本服务)

服务重启会清空数据,符合 P2 阶段规格(不需要持久化)。