Files
MC_Report/public/js/pages/export-page.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

108 lines
6.3 KiB
JavaScript

/*
* 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 ExportPage = {
async render() { return '<div class="loading"><i class="fas fa-spinner"></i></div>'; },
mount() {
const ct = document.getElementById('page-content');
document.getElementById('page-title').textContent = '数据导出';
document.getElementById('page-actions').innerHTML = '';
ct.innerHTML = `
<div class="grid-2">
<div class="card"><div class="card-h"><i class="fas fa-file-csv"></i> 导出工单</div><div class="card-b">
<form id="exp-tickets">
<div class="grid-2"><div class="form-group"><label>类型</label><select id="et-type"><option value="">全部</option>${Object.entries(U.TYPE).map(([k,v])=>`<option value="${k}">${v}</option>`).join('')}</select></div>
<div class="form-group"><label>状态</label><select id="et-status"><option value="">全部</option>${Object.entries(U.STATUS).map(([k,v])=>`<option value="${k}">${v}</option>`).join('')}</select></div></div>
<div class="grid-2"><div class="form-group"><label>开始日期</label><input type="date" id="et-start"></div><div class="form-group"><label>结束日期</label><input type="date" id="et-end"></div></div>
<div class="form-group"><label>格式</label><select id="et-fmt"><option value="csv">CSV (Excel)</option><option value="json">JSON</option></select></div>
<button type="submit" class="btn btn-p btn-sm"><i class="fas fa-download"></i> 导出</button>
</form>
</div></div>
<div class="card"><div class="card-h"><i class="fas fa-user-slash"></i> 被举报人统计导出</div><div class="card-b">
<p class="tm mb-4">导出所有被举报玩家列表,含被举报次数、处理结果、常见原因等</p>
<form id="exp-reported">
<div class="form-group"><label>格式</label><select id="er-fmt"><option value="csv">CSV (Excel)</option><option value="json">JSON</option></select></div>
<button type="submit" class="btn btn-w btn-sm"><i class="fas fa-download"></i> 导出被举报人统计</button>
</form>
</div></div>
<div class="card"><div class="card-h"><i class="fas fa-history"></i> 导出操作日志</div><div class="card-b">
<form id="exp-logs">
<div class="grid-2"><div class="form-group"><label>开始日期</label><input type="date" id="el-start"></div><div class="form-group"><label>结束日期</label><input type="date" id="el-end"></div></div>
<div class="form-group"><label>格式</label><select id="el-fmt"><option value="csv">CSV (Excel)</option><option value="json">JSON</option></select></div>
<button type="submit" class="btn btn-i btn-sm"><i class="fas fa-download"></i> 导出</button>
</form>
</div></div>
<div class="card"><div class="card-h"><i class="fas fa-chart-bar"></i> 统计报表</div><div class="card-b">
<p class="tm mb-4">查看系统整体统计和趋势数据</p>
<button class="btn btn-p btn-sm" onclick="ExportPage.viewStats()"><i class="fas fa-chart-simple"></i> 查看统计</button>
</div></div>
</div>
`;
document.getElementById('exp-tickets').onsubmit = async e => {
e.preventDefault();
const p = new URLSearchParams({
format: document.getElementById('et-fmt').value,
type: document.getElementById('et-type').value,
status: document.getElementById('et-status').value,
start_date: document.getElementById('et-start').value,
end_date: document.getElementById('et-end').value,
});
try { await API.download(`/export/tickets?${p}`); } catch (ex) { alert(ex.message); }
};
document.getElementById('exp-reported').onsubmit = async e => {
e.preventDefault();
const p = new URLSearchParams({ format: document.getElementById('er-fmt').value });
try { await API.download(`/export/reported-players?${p}`); } catch (ex) { alert(ex.message); }
};
document.getElementById('exp-logs').onsubmit = async e => {
e.preventDefault();
const p = new URLSearchParams({
format: document.getElementById('el-fmt').value,
start_date: document.getElementById('el-start').value,
end_date: document.getElementById('el-end').value,
});
try { await API.download(`/export/audit-logs?${p}`); } catch (ex) { alert(ex.message); }
};
},
async viewStats() {
try {
const d = await API.get('/export/dashboard');
U.modal('系统统计', `
<div class="detail-section"><h4>概览</h4>
<div class="detail-row"><span class="lbl">工单总数</span><span class="val fb">${d.total}</span></div>
<div class="detail-row"><span class="lbl">今日新增</span><span class="val fb">${d.today}</span></div>
<div class="detail-row"><span class="lbl">用户数</span><span class="val fb">${d.usersTotal}</span></div>
</div>
<div class="detail-section"><h4>状态分布</h4>${(d.byStatus||[]).map(r=>`<div class="detail-row"><span class="lbl">${U.STATUS[r.status]||r.status}</span><span class="val fb">${r.c}</span></div>`).join('')}</div>
<div class="detail-section"><h4>类型分布</h4>${(d.byType||[]).map(r=>`<div class="detail-row"><span class="lbl">${U.TYPE[r.type]||r.type}</span><span class="val fb">${r.c}</span></div>`).join('')}</div>
${d.monthly?.length?`<div class="detail-section"><h4>月度趋势</h4>${d.monthly.map(m=>`<div class="detail-row"><span class="lbl">${m.m}</span><span class="val fb">${m.c} 条</span></div>`).join('')}</div>`:''}
`, '600px');
} catch (e) { alert(e.message); }
}
};