60 lines
3.5 KiB
JavaScript
60 lines
3.5 KiB
JavaScript
/* API 客户端与格式化工具 */
|
|
window.VpsApi = (function () {
|
|
const CFG = window.APP_CONFIG || { appName: 'VPS 资产管理系统' };
|
|
|
|
function getApiKey() { return localStorage.getItem('vps_api_key') || ''; }
|
|
function setApiKey(k) { localStorage.setItem('vps_api_key', k || ''); }
|
|
|
|
async function request(path, options = {}) {
|
|
const headers = { 'Content-Type': 'application/json' };
|
|
const key = getApiKey();
|
|
if (key) headers['X-API-Key'] = key;
|
|
const res = await fetch('/api' + path, { ...options, headers: { ...headers, ...(options.headers || {}) } });
|
|
if (!res.ok) {
|
|
let msg = res.statusText;
|
|
try { const e = await res.json(); msg = (typeof e.detail === 'string' ? e.detail : JSON.stringify(e.detail)) || msg; } catch (_) {}
|
|
throw new Error(msg);
|
|
}
|
|
if (res.status === 204) return null;
|
|
return res.json();
|
|
}
|
|
|
|
return {
|
|
CFG, getApiKey, setApiKey,
|
|
get: (p) => request(p),
|
|
post: (p, body) => request(p, { method: 'POST', body: JSON.stringify(body) }),
|
|
put: (p, body) => request(p, { method: 'PUT', body: JSON.stringify(body) }),
|
|
del: (p) => request(p, { method: 'DELETE' }),
|
|
};
|
|
})();
|
|
|
|
window.VpsFmt = {
|
|
TYPE_LABELS: { vps: 'VPS', domain: '域名', ai_agent: 'AI账号', cloudflare: 'Cloudflare', other: '其他' },
|
|
STATUS_LABELS: { active: '使用中', expired: '已过期', stopped: '已停止', cancelled: '已注销', unknown: '未知' },
|
|
CATEGORY_LABELS: { vps: 'VPS', domain: '域名', ai_agent: 'AI账号', cloudflare: 'Cloudflare', other: '其他' },
|
|
// 平台可提供的服务(综合平台多标签):字段对应 Provider.services 逗号分隔列表
|
|
SERVICES_LABELS: { vps: '云服务器', domain: '域名', ai_agent: 'AI服务', cloudflare: 'Cloudflare', ssl_cert: 'SSL证书', cdn: 'CDN', dns: 'DNS', other: '其他' },
|
|
CYCLE_LABELS: { monthly: '月付', quarterly: '季付', yearly: '年付' },
|
|
typeBadge(t) {
|
|
return { vps: 'bg-blue-500/10 text-blue-600 dark:text-blue-400', domain: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400', ai_agent: 'bg-violet-500/10 text-violet-600 dark:text-violet-400', cloudflare: 'bg-orange-500/10 text-orange-600 dark:text-orange-400', other: 'bg-slate-500/10 text-slate-600 dark:text-slate-400' }[t] || 'bg-slate-500/10 text-slate-500';
|
|
},
|
|
statusBadge(s) {
|
|
return { active: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400', expired: 'bg-red-500/10 text-red-600 dark:text-red-400', stopped: 'bg-slate-500/10 text-slate-500', cancelled: 'bg-slate-500/10 text-slate-400', unknown: 'bg-amber-500/10 text-amber-600 dark:text-amber-400' }[s] || 'bg-slate-500/10 text-slate-500';
|
|
},
|
|
expiryText(d) {
|
|
if (d === null || d === undefined) return 'text-slate-400';
|
|
if (d < 0) return 'text-red-600 dark:text-red-400 font-semibold';
|
|
if (d <= 7) return 'text-red-600 dark:text-red-400 font-semibold';
|
|
if (d <= 30) return 'text-amber-600 dark:text-amber-400';
|
|
return 'text-slate-500 dark:text-slate-400';
|
|
},
|
|
expiryBadge(d) {
|
|
if (d !== null && d !== undefined && d <= 7) return 'bg-red-500/10 text-red-600 dark:text-red-400';
|
|
if (d !== null && d !== undefined && d <= 30) return 'bg-amber-500/10 text-amber-600 dark:text-amber-400';
|
|
return 'bg-slate-500/10 text-slate-500';
|
|
},
|
|
checkBadge(s) {
|
|
return { pass: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400', warn: 'bg-amber-500/10 text-amber-600 dark:text-amber-400', fail: 'bg-red-500/10 text-red-600 dark:text-red-400', unknown: 'bg-slate-500/10 text-slate-500' }[s] || 'bg-slate-500/10 text-slate-500';
|
|
},
|
|
};
|