- 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
66 lines
2.4 KiB
JavaScript
66 lines
2.4 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 API = {
|
|
base: '/api',
|
|
_key: window.__API_KEY__ || '',
|
|
|
|
async req(method, path, data) {
|
|
const token = Auth.token();
|
|
const headers = {};
|
|
if (token) headers['Authorization'] = `Bearer ${token}`;
|
|
if (this._key) headers['x-api-key'] = this._key;
|
|
const opts = { method, headers };
|
|
if (data instanceof FormData) opts.body = data;
|
|
else if (data && method !== 'GET') { headers['Content-Type'] = 'application/json'; opts.body = JSON.stringify(data); }
|
|
opts.headers = headers;
|
|
const res = await fetch(this.base + path, opts);
|
|
const ct = res.headers.get('content-type');
|
|
if (ct && ct.includes('application/json')) {
|
|
const json = await res.json();
|
|
if (!res.ok) throw new Error(json.error || '请求失败');
|
|
return json;
|
|
}
|
|
if (!res.ok) throw new Error('请求失败');
|
|
return res;
|
|
},
|
|
|
|
get(p) { return this.req('GET', p); },
|
|
post(p, d) { return this.req('POST', p, d); },
|
|
put(p, d) { return this.req('PUT', p, d); },
|
|
delete(p) { return this.req('DELETE', p); },
|
|
|
|
async download(path) {
|
|
const token = Auth.token();
|
|
const h = {};
|
|
if (token) h['Authorization'] = `Bearer ${token}`;
|
|
if (this._key) h['x-api-key'] = this._key;
|
|
const res = await fetch(this.base + path, { headers: h });
|
|
if (!res.ok) throw new Error('下载失败');
|
|
const blob = await res.blob();
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
const disp = res.headers.get('content-disposition');
|
|
a.download = disp?.match(/filename=(.+)/)?.[1] || 'export.csv';
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
}
|
|
};
|