规范化UI JS CONFIG
Some checks failed
build / build (api, amd64, linux) (push) Failing after -51s
build / build (api, arm64, linux) (push) Failing after -52s
build / build (api.exe, amd64, windows) (push) Failing after -51s

This commit is contained in:
CN-JS-HuiBai
2026-04-18 21:55:54 +08:00
parent 9d95a7c650
commit 8cca428d89
5 changed files with 518 additions and 518 deletions

View File

@@ -45,20 +45,20 @@
};
const ROUTE_META = {
overview: { title: "总览", description: "查看收入、用户和流量概况。" },
"dashboard-node": { title: "节点状态", description: "查看节点在线状态、负载和推送情况。" },
"node-manage": { title: "节点管理", description: "管理服务节点、可见性以及父子节点关系。" },
"node-group": { title: "权限组", description: "管理节点权限组和用户分组映射。" },
"node-route": { title: "路由规则", description: "维护节点路由匹配规则。" },
"plan-manage": { title: "套餐管理", description: "维护套餐、流量和价格配置。" },
"order-manage": { title: "订单管理", description: "处理待支付和已支付订单。" },
"coupon-manage": { title: "优惠券", description: "创建和维护优惠券信息。" },
"user-manage": { title: "用户管理", description: "查看用户订阅、流量和封禁状态。" },
"ticket-manage": { title: "工单中心", description: "查看用户工单和处理状态。" },
realname: { title: "实名认证", description: "审核实名记录和同步状态。" },
"user-online-devices": { title: "在线设备", description: "查看用户在线 IP 和设备分布。" },
"user-ipv6-subscription": { title: "IPv6 子账号", description: "管理 IPv6 阴影账号与密码同步。" },
"system-config": { title: "系统设置", description: "编辑站点、订阅和安全参数。" }
overview: { title: '总览', description: '查看收入、用户和流量概况。' },
'dashboard-node': { title: '节点状态', description: '查看节点在线状态、负载和推送情况。' },
'node-manage': { title: '节点管理', description: '管理服务节点、可见性以及父子节点关系。' },
'node-group': { title: '权限组', description: '管理节点权限组和用户分组映射。' },
'node-route': { title: '路由规则', description: '维护节点路由匹配规则。' },
'plan-manage': { title: '套餐管理', description: '维护套餐、流量和价格配置。' },
'order-manage': { title: '订单管理', description: '处理待支付和已支付订单。' },
'coupon-manage': { title: '优惠券', description: '创建和维护优惠券信息。' },
'user-manage': { title: '用户管理', description: '查看用户订阅、流量和封禁状态。' },
'ticket-manage': { title: '工单中心', description: '查看用户工单和处理状态。' },
realname: { title: '实名认证', description: '审核实名记录和同步状态。' },
'user-online-devices': { title: '在线设备', description: '查看用户在线 IP 和设备分布。' },
'user-ipv6-subscription': { title: 'IPv6 子账号', description: '管理 IPv6 阴影账号与密码同步。' },
'system-config': { title: '系统设置', description: '编辑站点、订阅和安全参数。' }
};
state.route = normalizeRoute(readRoute());
@@ -66,14 +66,14 @@
boot();
async function boot() {
window.addEventListener("hashchange", async function () {
window.addEventListener('hashchange', async function () {
state.route = normalizeRoute(readRoute());
state.modal = null;
await hydrateRoute();
});
root.addEventListener("click", onClick);
root.addEventListener("submit", onSubmit);
root.addEventListener('click', onClick);
root.addEventListener('submit', onSubmit);
// Initialize shell and modal containers
root.innerHTML = '<div id="admin-shell-container"></div><div id="admin-modal-container"></div><div id="admin-busy-container"></div>';
@@ -94,7 +94,7 @@
async function loadBootstrap() {
try {
setBusy(true);
const loginCheck = unwrap(await request("/api/v1/user/checkLogin", { method: "GET" }));
const loginCheck = unwrap(await request('/api/v1/user/checkLogin', { method: 'GET' }));
if (!loginCheck || !loginCheck.is_admin) {
clearSession();
return;
@@ -102,15 +102,15 @@
state.user = loginCheck;
const [config, system] = await Promise.all([
request(cfg.api.adminConfig, { method: "GET" }),
request(cfg.api.systemStatus, { method: "GET" })
request(cfg.api.adminConfig, { method: 'GET' }),
request(cfg.api.systemStatus, { method: 'GET' })
]);
state.config = unwrap(config) || {};
state.system = unwrap(system) || {};
} catch (error) {
console.error("bootstrap failed", error);
console.error('bootstrap failed', error);
clearSession();
show(error.message || "管理端初始化失败", "error");
show(error.message || '管理端初始化失败', 'error');
} finally {
setBusy(false);
render();
@@ -127,23 +127,23 @@
setBusy(true);
const page = getCurrentPage();
if (state.route === "overview") {
if (state.route === 'overview') {
state.dashboard = unwrap(await request(cfg.api.dashboardSummary));
} else if (state.route === "dashboard-node") {
} else if (state.route === 'dashboard-node') {
const [dashboard, nodes] = await Promise.all([
request(cfg.api.dashboardSummary),
request(cfg.api.serverNodes)
]);
state.dashboard = unwrap(dashboard) || {};
state.nodes = toArray(unwrap(nodes));
} else if (state.route === "node-manage") {
} else if (state.route === 'node-manage') {
const [nodes, groups] = await Promise.all([
request(cfg.api.serverNodes),
request(cfg.api.serverGroups)
]);
state.nodes = toArray(unwrap(nodes));
state.groups = toArray(unwrap(groups));
} else if (state.route === "node-group") {
} else if (state.route === 'node-group') {
state.groups = toArray(unwrap(await request(cfg.api.serverGroups)));
} else if (state.route === "node-route") {
state.routes = toArray(unwrap(await request(cfg.api.serverRoutes)));

View File

@@ -1,11 +1,11 @@
const settings = window.settings || {};
const assetNonce = window.__ADMIN_ASSET_NONCE__ || String(Date.now());
const securePath = String(settings.secure_path || "admin").replace(/^\/+/, "");
const securePath = String(settings.secure_path || 'admin').replace(/^\/+/, '');
const adminBase = `/api/v2/${securePath}`;
window.ADMIN_APP_CONFIG = {
title: settings.title || "XBoard Admin",
version: settings.version || "1.0.0",
title: settings.title || 'XBoard Admin',
version: settings.version || '1.0.0',
securePath,
baseUrl: settings.base_url || window.location.origin,
api: {
@@ -27,28 +27,28 @@ window.ADMIN_APP_CONFIG = {
},
};
document.documentElement.dataset.adminExecutionMode = "main-app";
document.documentElement.dataset.adminExecutionMode = 'main-app';
function showBootError(error) {
console.error("Failed to boot admin app", error);
const root = document.getElementById("admin-app");
console.error('Failed to boot admin app', error);
const root = document.getElementById('admin-app');
if (root) {
root.innerHTML =
`<div style="padding:24px;font-family:system-ui,sans-serif;color:#b91c1c;">Admin app failed to load.<br>${String(
error && error.message ? error.message : error || "Unknown error",
error && error.message ? error.message : error || 'Unknown error',
)}</div>`;
}
}
window.addEventListener("error", (event) => {
window.addEventListener('error', (event) => {
if (!event || !event.error) {
return;
}
showBootError(event.error);
});
const script = document.createElement("script");
const script = document.createElement('script');
script.src = `/admin-assets/app.js?v=${encodeURIComponent(assetNonce)}`;
script.defer = true;
script.onerror = () => showBootError(new Error("Failed to load /admin-assets/app.js"));
script.onerror = () => showBootError(new Error('Failed to load /admin-assets/app.js'));
document.body.appendChild(script);