启动器 UI 改用仓库新源码,不上传本机旧 UI

This commit is contained in:
hanfuit committed 2026-11-04 19:24:41 +08:00
1 parent 70b3c5a6dc
commit 56236496a0
1 file changed
+24 -82
+24 -82
View File
@@ -89,17 +89,8 @@ function gmConfirm(title, message, confirmText, onConfirm) {
// 视图切换
// ============================================================
function showLauncher() {
if (window.shellGo) { window.shellGo('start'); return; }
$('launcherView').classList.remove('hidden');
const gm = $('gmView'); if (gm) gm.classList.add('hidden');
}
function showGm() {
if (window.shellGo) { window.shellGo('gm'); return; }
$('launcherView').classList.add('hidden');
const gm = $('gmView'); if (gm) gm.classList.remove('hidden');
if (!gmInited) initGm();
renderGmPage(gmCurrentPage);
$('gmView').classList.add('hidden');
}
// ============================================================
@@ -285,7 +276,7 @@ const GM_PAGES = {
inventory: ['背包装备', '/ 查看背包'],
auction: ['拍卖行', '/ 挂单上下架'],
quests: ['任务管理', '/ 任务查询'],
dungeons: ['副本控制', '/ 副本状态'],
dungeons: ['魔改中心', '/ 副本状态'],
wallet: ['钱包点券', '/ 钱包与黑钻'],
wipe: ['删档管理', '/ 删除角色与账号'],
settings: ['连接设置', '/ 数据源切换'],
@@ -442,10 +433,13 @@ function initGm() {
loadAccounts().then(() => loadCharacters());
renderGmPage(gmCurrentPage);
});
// 「返回启动器」:单窗口内切回开始页
// 「返回启动器」:单窗口模式下回到启动器首页并恢复窗口
$('btnBackLauncher').addEventListener('click', () => {
if (window.shellGo) { window.shellGo('start'); return; }
showLauncher();
if (typeof window.shellExitGm === 'function') {
window.shellExitGm();
} else {
showLauncher();
}
});
// 预加载账号/角色,供所有页面联动
loadAccounts().then(() => loadCharacters());
@@ -626,8 +620,6 @@ async function openCharDetail(charId) {
try {
const r = await api('/api/character?id=' + encodeURIComponent(charId));
const ch = r.data || {};
const fat = await api('/api/character/fatigue?id=' + encodeURIComponent(charId) + '&mode=query');
const fatInfo = fat.data || {};
content.innerHTML = `
<div class="gm-card">
<div class="gm-card-title"><span class="dot"></span>角色:${escapeHtml(ch.name || charId)}</div>
@@ -657,23 +649,6 @@ async function openCharDetail(charId) {
<div class="gm-card-title" style="margin-top:8px"><span class="dot"></span>职业 / 转职</div>
<div id="careerPanel" style="margin-bottom:10px"><div class="gm-hint">正在加载职业信息…</div></div>
<div class="gm-card-title" style="margin-top:8px"><span class="dot"></span>疲劳值(无限疲劳)</div>
<div class="gm-form-row" style="margin-bottom:10px">
<div class="gm-field">
<label>当前疲劳</label>
<input class="gm-input" id="editFatigue" type="number" value="${fmt(fatInfo.fatigue)}">
</div>
<div class="gm-field">
<label>疲劳上限</label>
<input class="gm-input" id="editFatigueLimit" type="number" value="${fmt(fatInfo.fatigue_limit)}">
</div>
</div>
<div class="gm-toolbar">
<button class="gm-btn gm-btn-sm" onclick="saveFatigue()">保存疲劳</button>
<button class="gm-btn gm-btn-sm gm-btn-primary" onclick="maxFatigue()">⚡ 一键无限疲劳</button>
<span class="gm-hint">疲劳每日 6 点重置回上限;无限疲劳 = 把疲劳和上限都设成超大值</span>
</div>
</div>
<div class="gm-card gm-danger-zone">
@@ -785,20 +760,6 @@ async function saveGold() {
if (r.ok) gmToast('金币已更新', 'ok'); else gmToast('失败:' + (r.error || ''), 'err');
}
async function saveFatigue() {
const fatigue = $('editFatigue').value;
const limit = $('editFatigueLimit').value;
const r = await post('/api/character/fatigue', { id: currentCharId, fatigue: parseInt(fatigue), fatigue_limit: parseInt(limit) });
if (r.ok) { gmToast('疲劳值已更新', 'ok'); openCharDetail(currentCharId); }
else gmToast('失败:' + (r.error || ''), 'err');
}
async function maxFatigue() {
const r = await post('/api/character/fatigue', { id: currentCharId, fatigue: 999999, fatigue_limit: 999999 });
if (r.ok) { gmToast('已设置无限疲劳(999999)', 'ok'); openCharDetail(currentCharId); }
else gmToast('失败:' + (r.error || ''), 'err');
}
async function deleteCurrentChar() {
gmConfirm('删除角色', '确定要删除该角色的全部数据吗?<br>此操作<b style="color:#ff5d6c">不可恢复</b>,且需先停止服务端。', 'DELETE', async () => {
const r = await post('/api/character/delete', { id: currentCharId, confirm: 'DELETE' });
@@ -1423,12 +1384,12 @@ async function renderAuction(content) {
<input class="gm-input" id="auction-unit-price" type="number" min="1" placeholder="单价">
</div>
<div class="gm-field">
<label>一口价(每件,留空=单价)</label>
<input class="gm-input" id="auction-buyout" type="number" min="0" placeholder="可空">
<label>一口价</label>
<div class="gm-hint" style="padding-top:8px">本服为单一价格模式,一口价自动等于单价</div>
</div>
<div class="gm-field">
<label>起拍价(每件,留空=不设竞拍)</label>
<input class="gm-input" id="auction-start" type="number" min="0" placeholder="可空">
<label>起拍价</label>
<div class="gm-hint" style="padding-top:8px">本服不设竞拍,按一口价(=单价)直接成交</div>
</div>
<div class="gm-field">
<label>挂单时长(小时)</label>
@@ -1551,19 +1512,20 @@ async function auctionList() {
const itemId = $('auction-item-id').value;
const count = parseInt($('auction-count').value || '0', 10);
const unitPrice = parseInt($('auction-unit-price').value || '0', 10);
const buyoutRaw = $('auction-buyout').value.trim();
const startRaw = $('auction-start').value.trim();
if (!seller) { gmToast('请选择卖家角色', 'err'); return; }
if (!itemId) { gmToast('请填写物品 ID', 'err'); return; }
if (!count || count <= 0) { gmToast('数量必须大于 0', 'err'); return; }
if (!unitPrice || unitPrice <= 0) { gmToast('单价必须大于 0', 'err'); return; }
// 本服拍卖行只支持「一口价 = 单价」的单一价格模式(服务端 unit_price 即唯一定价,
// 客户端只展示这一个价)。这里强制对齐:一口价=单价、起拍价=-1(buyout-only),
// 避免提交后被服务端英文校验(buyout_price must equal unit_price)拒绝。
const body = {
seller_id: seller,
item_id: parseInt(itemId, 10),
count,
unit_price: unitPrice,
start_price: startRaw === '' ? null : parseInt(startRaw, 10),
buyout_price: buyoutRaw === '' ? null : parseInt(buyoutRaw, 10),
start_price: -1,
buyout_price: unitPrice,
duration_hours: parseInt($('auction-duration').value || '24', 10),
grant_if_missing: !!$('auction-grant-missing').checked,
};
@@ -1797,7 +1759,7 @@ async function renderDungeons(content) {
<div class="gm-search-row" style="margin-bottom:10px">
<span class="gm-hint">当前爆率:</span>
<span class="gm-tag gm-tag-purple" id="hell-current">—</span>
<input class="gm-input" id="hell-input" type="number" min="0" max="100" step="1" placeholder="百分比" style="width:140px">
<input class="gm-input" id="hell-input" type="number" min="0" max="15000" step="1" placeholder="百分比" style="width:140px">
<span class="gm-hint">%</span>
<button class="gm-btn gm-btn-primary" onclick="applyHellRate()">应用</button>
<span class="gm-hint" id="hell-range"></span>
@@ -1993,7 +1955,7 @@ async function renderWallet(content) {
</div>
</div>
<button class="gm-btn gm-btn-primary" onclick="activateBlackDiamond()">💎 开启黑钻</button>
<div class="gm-hint" style="margin-top:8px">黑钻提升疲劳上限、额外翻牌等权益;角色需离线(下次登录生效)。</div>
<div class="gm-hint" style="margin-top:8px">黑钻提升疲劳上限、额外翻牌等权益;在线角色回城后即时生效,无需离线。</div>
</div>`;
fillCharSelect($('wallet-char'));
fillAccountSelect($('cera-account'));
@@ -2071,7 +2033,7 @@ async function activateBlackDiamond() {
const id = $('bd-char').value;
const days = parseInt($('bd-days').value) || 30;
if (!id) { gmToast('请选择角色', 'err'); return; }
gmConfirm('开启黑钻', '确定要为所选角色开启黑钻 ' + days + ' 天吗?<br>角色需处于<b style="color:#ff5d6c">离线状态</b>,下次登录生效。', '开启黑钻', async () => {
gmConfirm('开启黑钻', '确定要为所选角色开启黑钻 ' + days + ' 天吗?<br>在线角色回城后即时生效。', '开启黑钻', async () => {
const r = await post('/api/black-diamond/activate', { id, days });
if (r.ok) { gmToast('黑钻已开启 ' + days + ' 天', 'ok'); queryBlackDiamond(); }
else gmToast('开启失败:' + (r.error || ''), 'err');
@@ -2247,32 +2209,19 @@ function initTitlebar() {
// ============================================================
// 初始化
// ============================================================
function isGmWindow() {
// 独立 GM 窗口通过 /gm 路径打开
return window.location.pathname.endsWith('/gm');
}
function init() {
initTitlebar();
// 独立 GM 窗口:直接显示 GM 视图
if (isGmWindow()) {
showLauncher = function() {}; // 降级模式下的返回按钮已处理
$('launcherView').classList.add('hidden');
$('gmView').classList.remove('hidden');
initGm();
renderGmPage('dashboard');
refreshGmHealth();
return;
}
// 启动器按钮
$('btnStart').addEventListener('click', () => {
appendLog('▶ 开始游戏…');
action('start');
});
$('btnGm').addEventListener('click', () => {
showGm();
// GM 工具现为单窗口内嵌页面,通过 shell 导航切换
if (typeof window.shellGo === 'function') {
window.shellGo('gm');
}
});
$('btnStop').addEventListener('click', () => {
appendLog('■ 关闭服务…');
@@ -2308,8 +2257,6 @@ function init() {
window.openCharDetail = openCharDetail;
window.saveLevel = saveLevel;
window.saveGold = saveGold;
window.saveFatigue = saveFatigue;
window.maxFatigue = maxFatigue;
window.deleteCurrentChar = deleteCurrentChar;
window.doGrant = doGrant;
window.loadInventory = loadInventory;
@@ -2338,10 +2285,5 @@ window.wipeCharSelected = wipeCharSelected;
window.wipeAccountSelected = wipeAccountSelected;
window.queryWallet = queryWallet;
window.setCera = setCera;
window.applyFatigueMode = applyFatigueMode;
window.refillFatigue = refillFatigue;
window.toggleBurning = toggleBurning;
window.initGm = initGm;
window.renderGmPage = renderGmPage;
init();