starraid/star-raid/index.html
JOJO ab403f4cc7 后端化:账号系统+排行榜+图鉴收集同步+飞行员大厅(零依赖Node+SQLite)
- server/:node:http+node:sqlite 零依赖后端(users/sessions/user_stats/codex_unlocks/runs 五表)
- 安全:scrypt密码哈希/服务端session/全prepared statement/输入白名单/限流/CSP等安全头/静态白名单防穿越
- 前端:o-auth登陆注册 + o-home飞行员大厅(排行榜Top100三排序+图鉴展柜背景:随机3主3副2僚机+刷怪巡游)
- 图鉴改为收集点亮制(未收集=剪影+???),服务端codex_unlocks与本地并集同步
- 修复:回标题/大厅后背景卡在上场残影——render按battleUI门控+离场G=null;空闲=星空
- 结算上报:endRun/rush胜利两处submitRun,Boss击杀计数入排行榜
- playwright全流程验证通过(注册/登陆/游戏/结算/图鉴/安全注入/限流);游戏视觉未验收(用户亲自)
2026-08-06 04:20:25 +08:00

192 lines
8.7 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="icon" href="data:,">
<title>星尘突击队 STAR RAID</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="wrap">
<canvas id="game" width="240" height="320"></canvas>
<div id="scan"></div><div id="vig"></div>
<!-- 登陆/注册 -->
<div class="ovl" id="o-auth">
<div class="tag">PIXEL ROGUELIKE SHMUP</div>
<h1 class="logo">STAR<br>RAID</h1>
<div class="logo-cn">星尘突击队</div>
<div class="panel" style="width:min(92%,340px)">
<div class="row" style="gap:6px">
<button class="btn primary" id="tab-login" style="min-width:0;flex:1">登 陆</button>
<button class="btn" id="tab-reg" style="min-width:0;flex:1">注 册</button>
</div>
<form class="auth-f" id="f-login">
<input id="li-id" placeholder="用户名 / 邮箱" maxlength="64" autocomplete="username" required>
<input id="li-pw" type="password" placeholder="密码" maxlength="72" autocomplete="current-password" required>
<button class="btn primary" type="submit">进入星域 ▶</button>
</form>
<form class="auth-f hide" id="f-reg">
<input id="rg-name" placeholder="用户名2-16位" maxlength="16" autocomplete="off" required>
<input id="rg-email" type="email" placeholder="邮箱" maxlength="64" autocomplete="off" required>
<input id="rg-pw" type="password" placeholder="密码至少8位" maxlength="72" autocomplete="new-password" required>
<input id="rg-pw2" type="password" placeholder="确认密码" maxlength="72" autocomplete="new-password" required>
<button class="btn primary" type="submit">创建飞行员档案</button>
</form>
<div class="h3" id="auth-err" style="color:var(--red)"> </div>
</div>
<div class="small">账号数据保存在服务器 · 排行榜与全服飞行员同台竞技</div>
</div>
<!-- 飞行员大厅(排行榜主页) -->
<div class="ovl hide" id="o-home">
<div class="h2" style="margin-top:2%">— 飞行员大厅 —</div>
<div class="h3" id="home-stats"> </div>
<div class="row">
<button class="btn primary" id="b-base" style="min-width:min(56vw,200px)">▶ 进入基地</button>
<button class="btn" id="b-logout" style="min-width:0">登出</button>
</div>
<div class="lb">
<div class="h3" style="color:var(--cyan);letter-spacing:3px">— 全服排行榜 TOP 100 —</div>
<div class="lb-tabs">
<button data-s="endless" class="on">无尽最高分</button>
<button data-s="boss">击坠Boss</button>
<button data-s="codex">图鉴收集</button>
</div>
<div class="lb-row lb-head"><span>#</span><span>飞行员</span><span>击坠</span><span>图鉴</span><span>无尽最高</span></div>
<div class="lb-list" id="lb-list"></div>
</div>
</div>
<!-- 标题 -->
<div class="ovl hide" id="o-title">
<div class="tag">PIXEL ROGUELIKE SHMUP</div>
<h1 class="logo">STAR<br>RAID</h1>
<div class="logo-cn">星尘突击队</div>
<div class="h3" id="best-line">BEST -- </div>
<div class="h3" id="pilot-line" style="color:var(--cyan)"> </div>
<div class="col" style="margin-top:6px">
<button class="btn primary" id="b-go">▶ 出击</button>
<button class="btn gold" id="b-hangar">✦ 机库强化</button>
<button class="btn" id="b-codex">❖ 军械图鉴</button>
<button class="btn danger" id="b-rush">☠ BOSS 挑战</button>
<button class="btn" id="b-lobby" style="min-width:min(48vw,180px)">⌂ 飞行员大厅</button>
</div>
<div class="small" style="margin-top:8px">键盘 WASD/方向键 移动 · 自动射击 · 超频充满自动暴走<br>SHIFT 精密移动 · P 暂停 · M 音乐</div>
</div>
<!-- 出击准备 -->
<div class="ovl hide" id="o-setup">
<div class="h2">— 出击准备 —</div>
<div class="h3">选择模式</div>
<div class="pick" id="mode-pick">
<div class="pcard sel" data-m="stage"><div class="nm" style="margin-top:2px">闯关模式</div><div class="ds">6 大关卡<br>击破母巢核心<br>即获胜利</div></div>
<div class="pcard" data-m="endless"><div class="nm" style="margin-top:2px">无尽模式</div><div class="ds">无限波次<br>突变词缀<br>冲击最高分</div></div>
</div>
<div class="h3">选择机体</div>
<div class="pick" id="ship-pick"></div>
<div class="h3">难度</div>
<div class="row" id="diff-pick">
<button class="btn sel-diff primary" data-d="0" style="min-width:110px;padding:8px 14px">普通</button>
<button class="btn sel-diff danger" data-d="1" style="min-width:110px;padding:8px 14px">困难</button>
</div>
<div class="row" style="margin-top:6px">
<button class="btn primary" id="b-start">开始出击 ▶</button>
<button class="btn" id="b-back1">返回</button>
</div>
</div>
<!-- Boss 挑战 -->
<div class="ovl hide" id="o-rush">
<div class="h2">— BOSS 挑战 —</div>
<div class="h3">随机武装3主武Lv3 · 3副武Lv3 · 2僚机Lv2 · 击破计时</div>
<div class="togrow"><label><input type="checkbox" id="rush-anim"> 老虎机抽奖动画</label></div>
<div class="pick" id="rush-pick"></div>
<button class="btn" id="b-back6" style="margin-top:6px">返回</button>
</div>
<!-- 武装抽取(老虎机) -->
<div class="ovl hide" id="o-slot">
<div class="h2">— 武装抽取 —</div>
<div class="slotrow" id="slot-row"></div>
<div class="h3" id="slot-hint"> </div>
</div>
<!-- 机库 -->
<div class="ovl hide" id="o-hangar">
<div class="h2">— 机库 · 永久强化 —</div>
<div class="wallet">星币 ✦ <span id="wallet">0</span></div>
<div class="shop" id="shop"></div>
<button class="btn" id="b-back2" style="margin-top:6px">返回</button>
</div>
<!-- 升级三选一 -->
<div class="ovl hide" id="o-cards">
<div class="h2 blink">▲ LEVEL UP ▲</div>
<div class="h3">选择一项强化(按 1 / 2 / 3</div>
<div id="cards"></div>
</div>
<!-- 暂停 -->
<div class="ovl hide" id="o-pause">
<div class="h2">‖ 暂停 · 军械配置</div>
<div id="loadout" style="width:100%;max-height:52%;overflow-y:auto"></div>
<div class="col">
<button class="btn primary" id="b-resume">继续战斗</button>
<button class="btn" id="b-restart">重新开始</button>
<button class="btn danger" id="b-quit">放弃任务</button>
</div>
</div>
<!-- 图鉴 -->
<div class="ovl hide" id="o-codex">
<div class="h2">— 军械图鉴 —</div>
<div class="h3">已收集 <span id="codex-n">0</span>/<span id="codex-t">0</span> · 点击可实时演示</div>
<div id="codex" style="overflow-y:auto;max-height:72%;width:100%;display:flex;flex-direction:column;align-items:center"></div>
<button class="btn" id="b-back4">返回</button>
</div>
<!-- 武器演示(全屏实战模拟,透明覆盖层不挡画布) -->
<div class="ovl hide" id="o-demo" style="background:transparent;pointer-events:none;justify-content:space-between;overflow:hidden">
<div style="margin-top:3%">
<div class="h2" id="demo-name">演示</div>
<div class="h3" id="demo-ds" style="max-width:88%;margin:0 auto"></div>
<div class="h3" style="color:var(--dim);margin-top:4px">实战模拟 · 自动驾驶 · 触屏/方向键可接管</div>
</div>
<button class="btn" id="b-back5" style="pointer-events:auto;margin-bottom:4%">返回图鉴</button>
</div>
<!-- 结算 -->
<div class="ovl hide" id="o-over">
<div class="h2" id="over-title">任务失败</div>
<div class="panel"><div class="stat-grid" id="over-stats"></div></div>
<div class="wallet">获得星币 ✦ <span id="over-coins">0</span></div>
<div class="col">
<button class="btn primary" id="b-again">再来一局</button>
<button class="btn" id="b-home">返回基地</button>
</div>
</div>
<button id="tb-pause" style="display:none">| |</button>
</div>
<script src="js/config.js"></script>
<script src="js/audio.js"></script>
<script src="js/sprites.js"></script>
<script src="js/data.js"></script>
<script src="js/core.js"></script>
<script src="js/enemies.js"></script>
<script src="js/combat.js"></script>
<script src="js/render.js"></script>
<script src="js/boss_art.js"></script>
<script src="js/net.js"></script>
<script src="js/ui.js"></script>
<script src="js/auth.js"></script>
<script src="js/home.js"></script>
</body>
</html>