117 lines
8.2 KiB
JavaScript
117 lines
8.2 KiB
JavaScript
const UsersPage = {
|
|
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 = '<button class="btn btn-p btn-sm" data-action="UsersPage:createUser"><i class="fas fa-user-plus"></i> 添加用户</button>';
|
|
await this.load();
|
|
},
|
|
|
|
async load() {
|
|
const ct = document.getElementById('page-content');
|
|
try {
|
|
const users = await API.get('/users');
|
|
const srcLabel = { netease:'网易', skin:'皮肤站' };
|
|
ct.innerHTML = `
|
|
<div class="card table-wrap"><table><thead><tr>
|
|
<th>#</th><th>用户名</th><th>邮箱</th><th>游戏名</th><th>游戏UID</th><th>来源</th><th>角色</th><th>状态</th><th>时间</th><th>操作</th>
|
|
</tr></thead><tbody>${users.map(u => `
|
|
<tr>
|
|
<td>${u.id}</td><td>${U.esc(u.username)}</td><td>${U.esc(u.email)}</td>
|
|
<td>${U.esc(u.game_name)}</td><td>${U.esc(u.game_uid)}</td>
|
|
<td>${srcLabel[u.source] || u.source || '网易'}</td>
|
|
<td>${U.badge(u.role,'role')}</td>
|
|
<td>${u.active ? '<span class="badge bg-resolved">启用</span>' : '<span class="badge bg-rejected">禁用</span>'}</td>
|
|
<td class="ts">${U.date(u.created_at)}</td>
|
|
<td><button class="btn btn-o btn-sm" data-action="UsersPage:editUser:${u.id}:${U.escJs(u.username)}:${U.escJs(u.email)}:${U.escJs(u.game_name)}:${U.escJs(u.game_uid)}:${u.role}:${u.active}:${u.source||'netease'}"><i class="fas fa-edit"></i></button></td>
|
|
</tr>`).join('')}</tbody></table></div>
|
|
`;
|
|
} catch (e) { ct.innerHTML = `<div class="alert alert-e">${e.message}</div>`; }
|
|
},
|
|
|
|
createUser() {
|
|
this.loadServersForCreate();
|
|
},
|
|
|
|
async loadServersForCreate() {
|
|
let groups = [];
|
|
try { groups = await API.get('/polls/groups'); } catch {}
|
|
const checks = groups.map(g => {
|
|
return `<label style="display:inline-flex;align-items:center;gap:4px;margin:2px 8px 2px 0;font-size:12px;white-space:nowrap"><input type="checkbox" value="${g.group_name}::${g.server_name}" class="cu-srv"> ${g.group_name}/${g.server_name}</label>`;
|
|
}).join('');
|
|
|
|
U.modal('添加用户', `
|
|
<form id="cu-form">
|
|
<div class="grid-2"><div class="form-group"><label>用户名 *</label><input id="cu-u" required></div><div class="form-group"><label>密码 *</label><input type="password" id="cu-p" required minlength="6"></div></div>
|
|
<div class="grid-2"><div class="form-group"><label>邮箱 *</label><input type="email" id="cu-e" required></div><div class="form-group"><label>来源</label><select id="cu-s"><option value="netease">网易端</option><option value="skin">皮肤站</option></select></div></div>
|
|
<div class="grid-2"><div class="form-group"><label>角色 *</label><select id="cu-r" onchange="UsersPage.toggleCreateServers()">${req.user.role==='owner'?'<option value="owner">服主</option>':''}<option value="admin">管理员</option><option value="player">玩家</option></select></div></div>
|
|
<div class="grid-2"><div class="form-group"><label>游戏名 *</label><input id="cu-gn" required></div><div class="form-group"><label>游戏UID *</label><input id="cu-gu" required></div></div>
|
|
<div class="form-group hidden" id="cu-servers"><label>管辖子服务器</label><div style="max-height:120px;overflow-y:auto;border:1px solid var(--g200);border-radius:var(--r);padding:8px">${checks||'<span class="tm">暂无可选服务器</span>'}</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('cu-form').onsubmit = async e => {
|
|
e.preventDefault();
|
|
const servers = [];
|
|
document.querySelectorAll('.cu-srv:checked').forEach(cb => { const [g,s] = cb.value.split('::'); servers.push({group_name:g,server_name:s}); });
|
|
try {
|
|
await API.post('/users', {
|
|
username: document.getElementById('cu-u').value, password: document.getElementById('cu-p').value,
|
|
email: document.getElementById('cu-e').value, role: document.getElementById('cu-r').value,
|
|
game_name: document.getElementById('cu-gn').value, game_uid: document.getElementById('cu-gu').value,
|
|
source: document.getElementById('cu-s').value,
|
|
admin_servers: servers,
|
|
});
|
|
App.closeModal(); this.load();
|
|
} catch (ex) { alert(ex.message); }
|
|
};
|
|
setTimeout(() => UsersPage.toggleCreateServers(), 50);
|
|
},
|
|
|
|
toggleCreateServers() {
|
|
const role = document.getElementById('cu-r').value;
|
|
const div = document.getElementById('cu-servers');
|
|
div.classList.toggle('hidden', role === 'player');
|
|
},
|
|
|
|
editUser(id, username, email, gameName, gameUid, role, active, source) {
|
|
this.loadUserServers(id, username, email, gameName, gameUid, role, active, source);
|
|
},
|
|
|
|
async loadUserServers(id, username, email, gameName, gameUid, role, active, source) {
|
|
let groups = [], userServers = [];
|
|
try { groups = await API.get('/polls/groups'); } catch {}
|
|
try { userServers = await API.get('/users/'+id+'/servers'); } catch {}
|
|
const checks = groups.map(g => {
|
|
const key = g.group_name+'::'+g.server_name;
|
|
const has = userServers.some(s => s.group_name===g.group_name && s.server_name===g.server_name);
|
|
return `<label style="display:inline-flex;align-items:center;gap:4px;margin:2px 8px 2px 0;font-size:12px;white-space:nowrap"><input type="checkbox" value="${key}" class="eu-srv" ${has?'checked':''}> ${g.group_name}/${g.server_name}</label>`;
|
|
}).join('');
|
|
|
|
U.modal('编辑用户', `
|
|
<form id="eu-form">
|
|
<div class="form-group"><label>用户名</label><input value="${username}" disabled style="background:var(--g100)"></div>
|
|
<div class="grid-2"><div class="form-group"><label>邮箱</label><input type="email" id="eu-e" value="${email}"></div><div class="form-group"><label>来源</label><select id="eu-s"><option value="netease" ${source==='netease'?'selected':''}>网易端</option><option value="skin" ${source==='skin'?'selected':''}>皮肤站</option></select></div></div>
|
|
<div class="grid-2"><div class="form-group"><label>角色</label><select id="eu-r">${['owner','admin','player'].map(r=>`<option value="${r}" ${r===role?'selected':''}>${U.ROLE[r]}</option>`).join('')}</select></div></div>
|
|
<div class="grid-2"><div class="form-group"><label>游戏名</label><input id="eu-gn" value="${gameName}"></div><div class="form-group"><label>游戏UID</label><input id="eu-gu" value="${gameUid}"></div></div>
|
|
<div class="form-group"><label>管辖子服务器</label><div style="max-height:120px;overflow-y:auto;border:1px solid var(--g200);border-radius:var(--r);padding:8px">${checks||'<span class="tm">无可用服务器(先在投票→分组管理中添加)</span>'}</div></div>
|
|
<div class="grid-2"><div class="form-group"><label>新密码(留空不变)</label><input type="password" id="eu-p"></div><div class="form-group"><label>状态</label><select id="eu-a"><option value="1" ${active?'selected':''}>启用</option><option value="0" ${!active?'selected':''}>禁用</option></select></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('eu-form').onsubmit = async e => {
|
|
e.preventDefault();
|
|
const servers = [];
|
|
document.querySelectorAll('.eu-srv:checked').forEach(cb => { const [g,s] = cb.value.split('::'); servers.push({group_name:g,server_name:s}); });
|
|
const data = {
|
|
email: document.getElementById('eu-e').value, role: document.getElementById('eu-r').value,
|
|
game_name: document.getElementById('eu-gn').value, game_uid: document.getElementById('eu-gu').value,
|
|
active: document.getElementById('eu-a').value === '1', source: document.getElementById('eu-s').value,
|
|
admin_servers: servers,
|
|
};
|
|
const pw = document.getElementById('eu-p').value; if (pw) data.password = pw;
|
|
try { await API.put('/users/'+id, data); App.closeModal(); this.load(); } catch (ex) { alert(ex.message); }
|
|
};
|
|
}
|
|
};
|