feat: dedicated server groups management page in sidebar

This commit is contained in:
2026-07-16 03:56:09 +08:00
parent 8ecefdcb19
commit abf747e3af
3 changed files with 60 additions and 0 deletions

View File

@@ -70,6 +70,7 @@
<script src="js/pages/settings-page.js"></script>
<script src="js/pages/export-page.js"></script>
<script src="js/pages/polls.js"></script>
<script src="js/pages/servers.js"></script>
<script src="js/pages/features.js"></script>
<script src="js/app.js"></script>
</body>

View File

@@ -11,6 +11,7 @@ const App = {
{ id: 'export', label: '数据导出', icon: 'fa-download', roles: ['owner'] },
{ id: 'polls', label: '投票', icon: 'fa-poll', roles: ['owner','admin','player'] },
{ id: 'features', label: '更新内容', icon: 'fa-lightbulb', roles: ['owner','admin','player'] },
{ id: 'servers', label: '服务器管理', icon: 'fa-server', roles: ['owner','admin'] },
],
async init() {
@@ -93,6 +94,7 @@ const App = {
case 'export': this.renderMain('数据导出', ExportPage, param); break;
case 'polls': this.renderMain('投票', PollsPage, param); break;
case 'features': this.renderMain('更新内容', FeaturesPage, param); break;
case 'servers': this.renderMain('服务器管理', ServersPage, param); break;
default: this.renderMain('控制台', Dashboard, param);
}
},
@@ -170,6 +172,7 @@ window.SettingsPage = SettingsPage;
window.ExportPage = ExportPage;
window.PollsPage = PollsPage;
window.FeaturesPage = FeaturesPage;
window.ServersPage = ServersPage;
window.LoginPage = LoginPage;
window.RegisterPage = RegisterPage;
window.HomePage = HomePage;

View File

@@ -0,0 +1,56 @@
const ServersPage = {
async render() { return '<div class="loading"><i class="fas fa-spinner"></i></div>'; },
async mount() {
document.getElementById('page-title').textContent = '服务器管理';
document.getElementById('page-actions').innerHTML = Auth.isOwner()
? '<button class="btn btn-p btn-sm" id="btn-add-srv"><i class="fas fa-plus"></i> 添加</button>'
: '';
document.getElementById('btn-add-srv').onclick = () => this.showAdd();
await this.load();
},
async load() {
const ct = document.getElementById('page-content');
try {
const groups = await API.get('/polls/groups');
const grouped = {};
for (const g of groups) {
if (!grouped[g.group_name]) grouped[g.group_name] = [];
grouped[g.group_name].push(g);
}
ct.innerHTML = Object.keys(grouped).length === 0
? '<div class="empty"><i class="fas fa-server"></i><p>暂无服务器分组</p></div>'
: Object.entries(grouped).map(([group, servers]) => `
<div class="card">
<div class="card-h"><i class="fas fa-folder"></i> ${U.esc(group)} <span class="ts tm">${servers.length} 个子服</span></div>
<div class="card-b">
<div style="display:flex;flex-wrap:wrap;gap:8px">
${servers.map(s => `
<div style="display:flex;align-items:center;gap:6px;background:var(--g1);padding:6px 12px;border-radius:var(--r);font-size:13px">
<i class="fas fa-server ts tm"></i> ${U.esc(s.server_name)}
${Auth.isOwner() ? `<button class="btn btn-d btn-sm" style="padding:2px 6px;font-size:10px" onclick="ServersPage.del(${s.id})"><i class="fas fa-times"></i></button>` : ''}
</div>
`).join('')}
</div>
</div>
</div>`).join('');
} catch (e) { ct.innerHTML = `<div class="alert alert-e">${e.message}</div>`; }
},
showAdd() {
U.modal('添加服务器', `
<form id="add-srv-form">
<div class="grid-2"><div class="form-group"><label>分组名 *</label><input id="as-group" required placeholder="如:生存服"></div>
<div class="form-group"><label>子服名 *</label><input id="as-server" required placeholder="如:一区"></div></div>
<div class="modal-f"><button type="button" class="btn btn-o" data-action="App:closeModal">取消</button><button type="submit" class="btn btn-p">添加</button></div>
</form>
`);
document.getElementById('add-srv-form').onsubmit = async e => {
e.preventDefault();
try { await API.post('/polls/groups', { group_name: document.getElementById('as-group').value, server_name: document.getElementById('as-server').value }); App.closeModal(); this.load(); } catch(ex){alert(ex.message);}
};
},
async del(id) { if (!await U.confirm('确认删除?')) return; try { await API.req('DELETE', '/polls/groups/'+id); this.load(); } catch(ex){alert(ex.message);} }
};