Files
MC_Report/public/js/pages/servers.js
canglan 8c5ce78fd0 chore: add AGPLv3 copyright header to all source files
- 52 JS files (backend + public/js): header with
  Copyright (C) 2026 Sea Network Technology Studio
  Author: CangLan <admin@sea-studio.top>
  + AGPLv3 notice
- idempotent (skips if header present), all syntax-checked
2026-08-19 20:27:05 +08:00

112 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
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.
/*
* MC Report System
* Copyright (C) 2026 Sea Network Technology Studio
* Author: CangLan <admin@sea-studio.top>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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)}
${s.alias ? `<span class="badge bg-admin" title="外部别名">${U.esc(s.alias)}</span>` : ''}
${Auth.isOwner() ? `<button class="btn btn-o btn-sm" style="padding:2px 6px;font-size:10px" onclick="ServersPage.showEdit(${s.id})"><i class="fas fa-edit"></i></button><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="form-group"><label>外部别名(可选)</label><input id="as-alias" placeholder="如survival —— 供外部API按别名拉取该子服数据"><span class="help">外部 API 可用别名或「分组/子服名」定位此服务器</span></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,
alias: document.getElementById('as-alias').value.trim(),
});
App.closeModal(); this.load();
} catch(ex){alert(ex.message);}
};
},
async showEdit(id) {
try {
const groups = await API.get('/polls/groups');
const s = groups.find(x => x.id === id);
if (!s) return alert('未找到');
U.modal('编辑服务器', `
<form id="edit-srv-form">
<div class="grid-2"><div class="form-group"><label>分组名 *</label><input id="es-group" required value="${U.esc(s.group_name)}"></div>
<div class="form-group"><label>子服名 *</label><input id="es-server" required value="${U.esc(s.server_name)}"></div></div>
<div class="form-group"><label>外部别名(可选)</label><input id="es-alias" value="${U.esc(s.alias||'')}" placeholder="如survival"><span class="help">外部 API 可用别名或「分组/子服名」定位此服务器</span></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('edit-srv-form').onsubmit = async e => {
e.preventDefault();
try {
await API.put(`/polls/groups/${id}`, {
group_name: document.getElementById('es-group').value,
server_name: document.getElementById('es-server').value,
alias: document.getElementById('es-alias').value.trim(),
});
App.closeModal(); this.load();
} catch(ex){alert(ex.message);}
};
} 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);} }
};