fix: home page tabs in top bar, single nav layer

This commit is contained in:
2026-07-17 13:21:30 +08:00
parent 8f7c34dd86
commit 9eb8aba371
2 changed files with 41 additions and 68 deletions

View File

@@ -67,7 +67,7 @@ const App = {
} }
if (page === 'install') { this.showPublic('install'); return; } if (page === 'install') { this.showPublic('install'); return; }
if (page === 'home') { this.showPublic('home', param); document.getElementById('top-auth').classList.add('hidden'); return; } if (page === 'home') { this.showPublic('home', param); return; }
if (page === 'login' || page === 'register' || page === 'forgot' || page === 'reset') { this.showPublic(page); return; } if (page === 'login' || page === 'register' || page === 'forgot' || page === 'reset') { this.showPublic(page); return; }
if (!Auth.logged()) { location.hash = '#/login'; return; } if (!Auth.logged()) { location.hash = '#/login'; return; }
@@ -107,7 +107,7 @@ const App = {
document.getElementById('main-layout').classList.add('hidden'); document.getElementById('main-layout').classList.add('hidden');
const pub = document.getElementById('public-page'); const pub = document.getElementById('public-page');
pub.classList.remove('hidden'); pub.classList.remove('hidden');
this.updateTopAuth(); if (page !== 'home') this.updateTopAuth();
const comp = page === 'login' ? LoginPage : page === 'register' ? RegisterPage : page === 'install' ? InstallPage : HomePage; const comp = page === 'login' ? LoginPage : page === 'register' ? RegisterPage : page === 'install' ? InstallPage : HomePage;
comp.render(param).then(html => { pub.innerHTML = html; if (comp.mount) comp.mount(param); }).catch(() => { comp.render(param).then(html => { pub.innerHTML = html; if (comp.mount) comp.mount(param); }).catch(() => {
pub.innerHTML = '<div class="pub-card"><div class="logo"><i class="fas fa-exclamation-triangle" style="color:var(--d)"></i><h2>加载失败</h2><p>请刷新页面重试</p></div></div>'; pub.innerHTML = '<div class="pub-card"><div class="logo"><i class="fas fa-exclamation-triangle" style="color:var(--d)"></i><h2>加载失败</h2><p>请刷新页面重试</p></div></div>';

View File

@@ -1,81 +1,54 @@
const HomePage = { const HomePage = {
async render(tab) { async render() {
const t = tab || 'report'; return `<div id="home-content" style="max-width:800px;margin:0 auto;padding:20px 0"><div id="home-tab"></div></div>`;
return `<div id="home-content" style="max-width:800px;margin:0 auto;padding:30px 0">
<div class="tab-nav">
<button class="${t==='report'?'active':''}" data-tab="report"><i class="fas fa-flag"></i> 举报</button>
<button class="${t==='suggestion'?'active':''}" data-tab="suggestion"><i class="fas fa-lightbulb"></i> 建议</button>
<button class="${t==='appeal'?'active':''}" data-tab="appeal"><i class="fas fa-gavel"></i> 申诉</button>
<button class="${t==='tracking'?'active':''}" data-tab="tracking"><i class="fas fa-search"></i> 追踪</button>
</div>
<div id="home-tab"></div>
</div>`;
}, },
mount(tab) { mount(tab) {
const t = tab || 'report'; const t = tab || 'report';
const tabBtns = document.querySelectorAll('.tab-nav button'); const topAuth = document.getElementById('top-auth');
const tabContent = document.getElementById('home-tab'); topAuth.innerHTML = `<a href="#/login" class="btn btn-o btn-sm"><i class="fas fa-sign-in-alt"></i> 登录</a>
<a href="#/register" class="btn btn-p btn-sm"><i class="fas fa-user-plus"></i> 注册</a>
<span style="color:var(--g300)">|</span>
<button class="btn btn-sm ${t==='report'?'btn-p':'btn-o'}" data-tab="report">举报</button>
<button class="btn btn-sm ${t==='suggestion'?'btn-p':'btn-o'}" data-tab="suggestion">建议</button>
<button class="btn btn-sm ${t==='appeal'?'btn-p':'btn-o'}" data-tab="appeal">申诉</button>
<button class="btn btn-sm ${t==='tracking'?'btn-p':'btn-o'}" data-tab="tracking">追踪</button>`;
topAuth.style.display = 'flex';
function switchContent(type) { topAuth.querySelectorAll('[data-tab]').forEach(b => { b.onclick = () => App.navigate('home', b.dataset.tab); });
if (type === 'tracking') renderTracking(tabContent);
else TicketCreate.render(tabContent, { type, prefill: {}, backLink: null });
}
function renderTracking(ct) { const ct = document.getElementById('home-tab');
const token = document.cookie.split('; ').find(r => r.startsWith('tracking_token='))?.split('=')[1]; if (t === 'tracking') this.renderTracking(ct);
ct.innerHTML = ` else TicketCreate.render(ct, { type: t, prefill: {}, backLink: null });
<div class="card"><div class="card-b"> },
<div class="form-group"><label>追踪标识 (Cookie自动读取)</label>
<input id="track-token" value="${token || ''}" placeholder="粘贴追踪标识">
</div>
<button class="btn btn-p" onclick="HomePage.searchTracking()"><i class="fas fa-search"></i> 查找我的工单</button>
<div id="track-result" class="mt-4"></div>
</div></div>`;
}
tabBtns.forEach(b => b.onclick = () => App.navigate('home', b.dataset.tab)); renderTracking(ct) {
switchContent(t); const token = document.cookie.split('; ').find(r => r.startsWith('tracking_token='))?.split('=')[1];
ct.innerHTML = `<div class="card"><div class="card-b">
<div class="form-group"><label>追踪标识 (Cookie自动读取)</label><input id="track-token" value="${token||''}" placeholder="粘贴追踪标识"></div>
<button class="btn btn-p" id="track-search-btn"><i class="fas fa-search"></i> 查找我的工单</button>
<div id="track-result" class="mt-4"></div>
</div></div>`;
document.getElementById('track-search-btn').onclick = () => this.doSearchTracking();
},
this.searchTracking = async () => { async doSearchTracking() {
const token = document.getElementById('track-token').value.trim(); const token = document.getElementById('track-token').value.trim();
if (!token) return alert('请输入追踪标识'); if (!token) return alert('请输入追踪标识');
const ct = document.getElementById('track-result'); const r = document.getElementById('track-result');
ct.innerHTML = '<div class="loading"><i class="fas fa-spinner"></i></div>'; r.innerHTML = '<div class="loading"><i class="fas fa-spinner"></i></div>';
try { try {
const tickets = await API.get(`/tickets/tracking?token=${token}`); const tickets = await API.get(`/tickets/tracking?token=${token}`);
ct.innerHTML = tickets.length ? ` r.innerHTML = tickets.length ? `<div class="table-wrap"><table><thead><tr><th>#</th><th>类型</th><th>标题</th><th>状态</th><th>时间</th></tr></thead><tbody>${tickets.map(tk=>`<tr><td>${tk.id}</td><td>${U.badge(tk.type,'type')}</td><td>${U.esc(tk.title)}</td><td>${U.badge(tk.status,'status')}</td><td>${U.date(tk.created_at)}</td></tr>`).join('')}</tbody></table></div>` : '<div class="empty"><i class="fas fa-inbox"></i><p>未找到工单</p></div>';
<div class="table-wrap"><table><thead><tr> } catch (e) { r.innerHTML = `<div class="alert alert-e">${e.message}</div>`; }
<th>#</th><th>类型</th><th>标题</th><th>状态</th><th>时间</th><th>操作</th>
</tr></thead><tbody>${tickets.map(tick => `
<tr><td>${tick.id}</td><td>${U.badge(tick.type,'type')}</td><td>${U.esc(tick.title)}</td>
<td>${U.badge(tick.status,'status')}</td><td>${U.date(tick.created_at)}</td>
<td><button class="btn btn-o btn-sm" onclick="App.navigate('home','tracking');HomePage.showTrackDetail(${tick.id},'${U.escJs(token)}')">查看</button></td></tr>
`).join('')}</tbody></table></div>` : '<div class="empty"><i class="fas fa-inbox"></i><p>未找到工单</p></div>';
} catch (ex) { ct.innerHTML = `<div class="alert alert-e">${ex.message}</div>`; }
};
}, },
showTrackDetail(id, token) { showTrackDetail(id, token) {
U.modal(`工单 #${id}`, `<div id="track-detail-content"></div>`, '700px'); U.modal(`工单 #${id}`, `<div id="tkd"></div>`, '700px');
const ct = document.getElementById('track-detail-content');
U.loading(ct);
API.get(`/tickets/tracking?token=${token}`).then(tickets => { API.get(`/tickets/tracking?token=${token}`).then(tickets => {
const t = tickets.find(x => x.id === id); const t = tickets.find(x=>x.id===id);
if (!t) { ct.innerHTML = '<p>未找到</p>'; return; } if(!t) return;
ct.innerHTML = ` document.getElementById('tkd').innerHTML = `<div class="detail-section"><h4>基本信息</h4><div class="detail-row"><span class="lbl">标题</span><span class="val fb">${U.esc(t.title)}</span></div><div class="detail-row"><span class="lbl">类型</span><span class="val">${U.badge(t.type,'type')}</span></div><div class="detail-row"><span class="lbl">状态</span><span class="val">${U.badge(t.status,'status')}</span></div><div class="detail-row"><span class="lbl">提交者</span><span class="val">${U.esc(t.reporter_game_name)} (UID: ${U.esc(t.reporter_game_uid)})</span></div></div><p class="tm ts">如需回复请<a href="#/register" style="color:var(--p)">注册账号</a></p>`;
<div class="detail-section"><h4>基本信息</h4> }).catch(()=>{});
<div class="detail-row"><span class="lbl">标题</span><span class="val fb">${U.esc(t.title)}</span></div>
<div class="detail-row"><span class="lbl">类型</span><span class="val">${U.badge(t.type,'type')}</span></div>
<div class="detail-row"><span class="lbl">状态</span><span class="val">${U.badge(t.status,'status')}</span></div>
<div class="detail-row"><span class="lbl">提交者</span><span class="val">${U.esc(t.reporter_game_name)} (UID: ${U.esc(t.reporter_game_uid)})</span></div>
${t.type==='report'?`
<div class="detail-row"><span class="lbl">被举报人</span><span class="val">${U.esc(t.target_game_name||'?')} (UID: ${U.esc(t.target_game_uid||'?')})</span></div>
<div class="detail-row"><span class="lbl">原因</span><span class="val">${U.esc(t.reason)}</span></div>`:''}
${t.description?`<div class="detail-row"><span class="lbl">详情</span><span class="val">${U.esc(t.description)}</span></div>`:''}
<div class="detail-row"><span class="lbl">时间</span><span class="val">${U.date(t.created_at)}</span></div>
</div>
<p class="tm ts">如需回复,请<a href="#/register" style="color:var(--p)">注册账号</a>后关联此工单。</p>`;
}).catch(e => { ct.innerHTML = `<div class="alert alert-e">${e.message}</div>`; });
} }
}; };