启动器:游戏更新拆分为当前/历史双子页,新增关于我们页
- 游戏更新页改为「当前更新 / 历史更新」两个标签页,历史页显示条数 - 更新日志合并仓库 Release 与本地 更新日志.txt,按日期去重、仓库优先;断网时仅用本地记录 - 主导航新增「关于我们」,内容与游戏内控制台关于页一致(四行文案 + 赞助/公众号二维码) - 新增 /qr/<name> 白名单路由读取启动器目录 qr\ 下图片,防止目录穿越 - 二维码支持点击放大(灯箱),图片缺失时显示占位而不是破图 - 打包 spec 补入 qr 三张图,静态响应统一 Cache-Control: no-store
This commit is contained in:
1 parent
1dd3775510
commit
6a4b7e58d3
8 files changed
+311
-36
No files matched your search
+82
-30
@@ -1,13 +1,13 @@
|
||||
/* 90轮回启动器 · 单窗口页面与工具整合 */
|
||||
(function () {
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const pages = ['start','changelog','gm','loadout','gamesettings'];
|
||||
const pages = ['start','changelog','gm','loadout','gamesettings','about'];
|
||||
let shellGmInit = false;
|
||||
let loConfig = null, loPage = 0, loScheme = -1;
|
||||
let loCooldownUntil = 0, loCooldownCharacter = '', loCooldownTimer = null;
|
||||
let hotkeyCapture = false;
|
||||
|
||||
const crumb = {start:'开始 / 本地服务端',changelog:'游戏更新',gm:'GM工具',loadout:'工具 / 一键换装',gamesettings:'工具 / 游戏设置'};
|
||||
const crumb = {start:'开始 / 本地服务端',changelog:'游戏更新',gm:'GM工具',loadout:'工具 / 一键换装',gamesettings:'工具 / 游戏设置',about:'关于我们'};
|
||||
|
||||
function shellGo(page) {
|
||||
if (!pages.includes(page)) page = 'start';
|
||||
@@ -258,43 +258,60 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 更新日志页面:拉取所有 Release 的 changelog
|
||||
async function loadChangelog() {
|
||||
const box = $('changelogBody');
|
||||
if (!box) return;
|
||||
box.innerHTML = '<div class="empty-box">正在获取更新日志…</div>';
|
||||
// 更新日志:当前更新 = 最新一条;历史更新 = 其余。优先 Gitea,断网退回本地 更新日志.txt
|
||||
function updDate(rel) {
|
||||
return rel.published_at ? rel.published_at.replace('T', ' ').slice(0, 16) : '';
|
||||
}
|
||||
|
||||
function updCard(rel, featured) {
|
||||
const badge = rel.prerelease ? '<span class="gm-tag gm-tag-gray">预发布</span>' : '';
|
||||
const body = (rel.body || '').replace(/\r?\n/g, '<br>');
|
||||
const assets = (rel.assets || []).map(a =>
|
||||
`<a class="changelog-asset" href="${escapeHtml(a.download_url)}" target="_blank">⬇ ${escapeHtml(a.name)} (${fmt(a.size)} B)</a>`
|
||||
).join('');
|
||||
const when = updDate(rel);
|
||||
return `<div class="changelog-item${featured ? ' featured' : ''}">
|
||||
<div class="changelog-head">
|
||||
<span class="changelog-tag">${escapeHtml(rel.tag || rel.name || '')}</span>
|
||||
<span class="changelog-name">${escapeHtml(rel.name || '')}</span>
|
||||
${badge}
|
||||
<span class="changelog-time">${escapeHtml(when)}</span>
|
||||
</div>
|
||||
<div class="changelog-body">${body || '<span class="muted">(这次没有填写更新说明)</span>'}</div>
|
||||
${assets ? '<div class="changelog-assets">' + assets + '</div>' : ''}
|
||||
${featured ? `<a class="changelog-link" href="${escapeHtml(rel.html_url)}" target="_blank">在浏览器中查看 ↗</a>` : ''}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
async function loadChangelog(force) {
|
||||
const latestBox = $('updLatest'), historyBox = $('updHistory');
|
||||
if (!latestBox || !historyBox) return;
|
||||
latestBox.innerHTML = '<div class="empty-box">正在获取更新日志…</div>';
|
||||
historyBox.innerHTML = '';
|
||||
try {
|
||||
const r = await api('/api/update/changelog');
|
||||
const r = await api('/api/update/changelog' + (force ? '?force=1' : ''));
|
||||
if (!r.ok) {
|
||||
box.innerHTML = '<div class="empty-box">获取失败:' + escapeHtml(r.error || '未知错误') + '</div>';
|
||||
latestBox.innerHTML = '<div class="empty-box">获取失败:' + escapeHtml(r.error || '未知错误') + '</div>';
|
||||
if ($('updHistoryCount')) $('updHistoryCount').textContent = '';
|
||||
return;
|
||||
}
|
||||
const rels = r.releases || [];
|
||||
if (!rels.length) {
|
||||
box.innerHTML = '<div class="empty-box">暂无发布记录。<br>在 Gitea 仓库「发布 Release」并填写更新说明后,这里会自动显示。</div>';
|
||||
latestBox.innerHTML = '<div class="empty-box">暂无更新记录。<br>在仓库发布 Release,或把「更新日志.txt」放在启动器目录,这里就会显示。</div>';
|
||||
if ($('updHistoryCount')) $('updHistoryCount').textContent = '';
|
||||
return;
|
||||
}
|
||||
box.innerHTML = rels.map(rel => {
|
||||
const badge = rel.prerelease ? '<span class="gm-tag gm-tag-gray">预发布</span>' : '';
|
||||
const body = (rel.body || '').replace(/\r?\n/g, '<br>');
|
||||
const assets = (rel.assets || []).map(a =>
|
||||
`<a class="changelog-asset" href="${escapeHtml(a.download_url)}" target="_blank">⬇ ${escapeHtml(a.name)} (${fmt(a.size)} B)</a>`
|
||||
).join('');
|
||||
const when = rel.published_at ? rel.published_at.replace('T', ' ').slice(0, 16) : '';
|
||||
return `<div class="changelog-item">
|
||||
<div class="changelog-head">
|
||||
<span class="changelog-tag">${escapeHtml(rel.tag || rel.name || '')}</span>
|
||||
<span class="changelog-name">${escapeHtml(rel.name || '')}</span>
|
||||
${badge}
|
||||
<span class="changelog-time">${escapeHtml(when)}</span>
|
||||
</div>
|
||||
<div class="changelog-body">${body}</div>
|
||||
${assets ? '<div class="changelog-assets">' + assets + '</div>' : ''}
|
||||
<a class="changelog-link" href="${escapeHtml(rel.html_url)}" target="_blank">在浏览器中查看 ↗</a>
|
||||
</div>`;
|
||||
}).join('');
|
||||
const source = r.source === 'local'
|
||||
? '<div class="upd-source">未连接更新仓库,以下内容读取自本地「更新日志.txt」。</div>'
|
||||
: '';
|
||||
latestBox.innerHTML = source + updCard(rels[0], true);
|
||||
const rest = rels.slice(1);
|
||||
historyBox.innerHTML = rest.length
|
||||
? rest.map(rel => updCard(rel, false)).join('')
|
||||
: '<div class="empty-box">还没有更早的更新记录。</div>';
|
||||
if ($('updHistoryCount')) $('updHistoryCount').textContent = rest.length ? '(' + rest.length + ')' : '';
|
||||
} catch (e) {
|
||||
box.innerHTML = '<div class="empty-box">获取失败:' + escapeHtml(e && e.message ? e.message : e) + '</div>';
|
||||
latestBox.innerHTML = '<div class="empty-box">获取失败:' + escapeHtml(e && e.message ? e.message : e) + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,6 +762,41 @@
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------- 游戏更新:当前 / 历史 两个子页 ----------------
|
||||
(function bindUpdTabs() {
|
||||
const tabs = document.querySelectorAll('#updTabs .st-tab');
|
||||
tabs.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const which = btn.dataset.upd;
|
||||
tabs.forEach(b => b.classList.toggle('active', b === btn));
|
||||
$('updLatestPane').style.display = which === 'latest' ? '' : 'none';
|
||||
$('updHistoryPane').style.display = which === 'history' ? '' : 'none';
|
||||
});
|
||||
});
|
||||
const refresh = $('updRefresh');
|
||||
if (refresh) refresh.addEventListener('click', () => loadChangelog(true));
|
||||
})();
|
||||
|
||||
// ---------------- 关于我们:二维码放大 ----------------
|
||||
(function bindQrLightbox() {
|
||||
const box = $('qrLightbox'), img = $('qrLightboxImg'), tip = $('qrLightboxTip');
|
||||
if (!box || !img) return;
|
||||
document.querySelectorAll('#page-about .about-qr').forEach(fig => {
|
||||
fig.addEventListener('click', () => {
|
||||
const src = fig.querySelector('img');
|
||||
if (!src) return;
|
||||
img.src = src.getAttribute('src');
|
||||
img.alt = src.getAttribute('alt') || '';
|
||||
tip.textContent = (fig.dataset.qr || '') + ' · 点击任意处关闭';
|
||||
box.classList.remove('hidden');
|
||||
});
|
||||
});
|
||||
box.addEventListener('click', () => box.classList.add('hidden'));
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') box.classList.add('hidden');
|
||||
});
|
||||
})();
|
||||
|
||||
// 兼容旧 GM 页面里的返回
|
||||
window.shellGo = shellGo;
|
||||
loadStart();
|
||||
|
||||
Reference in new issue
Block a user