130 lines
4.1 KiB
JavaScript
130 lines
4.1 KiB
JavaScript
(function () {
|
|
const body = document.body;
|
|
const statusEl = document.getElementById('status');
|
|
const leaderboardList = document.getElementById('leaderboard-list');
|
|
const searchForm = document.getElementById('search-form');
|
|
const searchInput = document.getElementById('search-input');
|
|
const searchResults = document.getElementById('search-results');
|
|
|
|
const setStatus = (text) => {
|
|
statusEl.textContent = text || '';
|
|
};
|
|
|
|
const getJson = async (url) => {
|
|
const res = await fetch(url);
|
|
return res.json();
|
|
};
|
|
|
|
const renderLeaderboard = (rows) => {
|
|
if (!leaderboardList) return;
|
|
if (!rows.length) {
|
|
leaderboardList.textContent = '暂无排行数据';
|
|
return;
|
|
}
|
|
const table = document.createElement('table');
|
|
table.className = 'admin-table';
|
|
const thead = document.createElement('thead');
|
|
const headRow = document.createElement('tr');
|
|
['排名', '用户名', '胜场', '参与局', '胜率', '总回合'].forEach((text) => {
|
|
const th = document.createElement('th');
|
|
th.textContent = text;
|
|
headRow.appendChild(th);
|
|
});
|
|
thead.appendChild(headRow);
|
|
table.appendChild(thead);
|
|
const tbody = document.createElement('tbody');
|
|
|
|
rows.forEach((row) => {
|
|
const tr = document.createElement('tr');
|
|
|
|
const tdRank = document.createElement('td');
|
|
tdRank.textContent = `#${row.rank || '-'}`;
|
|
tr.appendChild(tdRank);
|
|
|
|
const tdUser = document.createElement('td');
|
|
const link = document.createElement('a');
|
|
link.href = `/users/${encodeURIComponent(row.username || '')}`;
|
|
link.textContent = row.username || '匿名';
|
|
tdUser.appendChild(link);
|
|
tr.appendChild(tdUser);
|
|
|
|
const tdWins = document.createElement('td');
|
|
tdWins.textContent = String(row.wins || 0);
|
|
tr.appendChild(tdWins);
|
|
|
|
const tdGames = document.createElement('td');
|
|
tdGames.textContent = String(row.played_games || 0);
|
|
tr.appendChild(tdGames);
|
|
|
|
const tdRate = document.createElement('td');
|
|
tdRate.textContent = `${Number(row.win_rate || 0).toFixed(1)}%`;
|
|
tr.appendChild(tdRate);
|
|
|
|
const tdRounds = document.createElement('td');
|
|
tdRounds.textContent = String(row.total_rounds || 0);
|
|
tr.appendChild(tdRounds);
|
|
|
|
tbody.appendChild(tr);
|
|
});
|
|
table.appendChild(tbody);
|
|
leaderboardList.textContent = '';
|
|
leaderboardList.appendChild(table);
|
|
};
|
|
|
|
const renderSearch = (rows) => {
|
|
searchResults.textContent = '';
|
|
if (!rows.length) {
|
|
const li = document.createElement('li');
|
|
li.textContent = '没有匹配用户';
|
|
searchResults.appendChild(li);
|
|
return;
|
|
}
|
|
rows.forEach((row) => {
|
|
const li = document.createElement('li');
|
|
const online = row.presence?.is_online ? '在线' : '离线';
|
|
const rank = row.stats?.rank ? `#${row.stats.rank}` : '-';
|
|
const link = document.createElement('a');
|
|
link.href = `/users/${encodeURIComponent(row.username || '')}`;
|
|
link.textContent = row.username || '匿名';
|
|
li.appendChild(link);
|
|
const text = document.createElement('span');
|
|
text.textContent = ` · ${online} · 排名 ${rank} · 胜场 ${row.stats?.wins || 0}`;
|
|
li.appendChild(text);
|
|
searchResults.appendChild(li);
|
|
});
|
|
};
|
|
|
|
const loadLeaderboard = async () => {
|
|
const data = await getJson('/api/leaderboard?limit=100');
|
|
if (!data.ok) {
|
|
setStatus(data.error || '加载排行榜失败');
|
|
return;
|
|
}
|
|
renderLeaderboard(data.leaderboard || []);
|
|
};
|
|
|
|
const searchUsers = async (q) => {
|
|
const data = await getJson(`/api/users/search?q=${encodeURIComponent(q || '')}&limit=20`);
|
|
if (!data.ok) {
|
|
setStatus(data.error || '搜索失败');
|
|
return;
|
|
}
|
|
renderSearch(data.users || []);
|
|
};
|
|
|
|
if (searchForm) {
|
|
searchForm.addEventListener('submit', async (event) => {
|
|
event.preventDefault();
|
|
try {
|
|
await searchUsers(searchInput?.value || '');
|
|
} catch (error) {
|
|
setStatus(`网络错误: ${error}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
loadLeaderboard()
|
|
.then(() => searchUsers(''))
|
|
.catch((error) => setStatus(`网络错误: ${error}`));
|
|
})();
|