修复节点无法编辑的错误
Some checks failed
build / build (api, amd64, linux) (push) Failing after -50s
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 10:31:31 +08:00
parent 6e75b7d7d5
commit 98379b21f4
6 changed files with 275 additions and 130 deletions

View File

@@ -761,10 +761,9 @@
const list = payload.list || [];
document.getElementById("thead").innerHTML = `
<tr>
<th>主从关系</th>
<th>用户 ID</th>
<th>主账号</th>
<th>IPv6 账号</th>
<th>套餐</th>
<th>IPv6 套餐</th>
<th>状态</th>
<th>操作</th>
</tr>
@@ -772,26 +771,110 @@
document.getElementById("tbody").innerHTML = list.length
? list
.map(
(item) => `
(item) => {
const isActive = item.is_active || item.status === "active";
const isDisabled = item.status === "disabled";
let actionButtons = "";
if (isActive) {
actionButtons = `
<button class="btn" onclick="ipv6Disable(${item.id})">关闭</button>
<button class="btn" onclick="ipv6SyncPassword(${item.id})">同步密码</button>
`;
} else {
actionButtons = `
<button class="btn btn-primary" onclick="ipv6ShowEnableDialog(${item.id}, '${(item.email || '').replace(/'/g, "\\'")}')">开通</button>
`;
}
if (isDisabled) {
actionButtons = `
<button class="btn btn-primary" onclick="ipv6ShowEnableDialog(${item.id}, '${(item.email || '').replace(/'/g, "\\'")}')">重新开通</button>
` + actionButtons;
}
return `
<tr>
<td>${relationChip(item.id, item.shadow_user_id || "-")}</td>
<td class="mono">${item.id}</td>
<td>${item.email || "-"}</td>
<td class="mono">${item.ipv6_email || "-"}</td>
<td>${item.plan_name || "-"}</td>
<td>${statusBadge(item.status_label || item.status)}</td>
<td>
<div class="actions">
<button class="btn btn-primary" onclick="ipv6Enable(${item.id})">开通并同步</button>
<button class="btn" onclick="ipv6SyncPassword(${item.id})">同步密码</button>
${actionButtons}
</div>
</td>
</tr>`,
</tr>`;
},
)
.join("")
: `<tr><td colspan="6" class="empty">暂无数据</td></tr>`;
: `<tr><td colspan="5" class="empty">暂无数据</td></tr>`;
return payload.pagination || { current: 1, last_page: 1, total: list.length };
}
let ipv6Plans = [];
async function loadIpv6Plans() {
if (ipv6Plans.length > 0) return;
try {
const data = await request(`${apiBase}/plan/fetch`);
ipv6Plans = Array.isArray(data) ? data : (data && data.data ? data.data : []);
} catch (e) {
ipv6Plans = [];
}
}
function ipv6ShowEnableDialog(userId, email) {
loadIpv6Plans().then(() => {
const options = ipv6Plans.map(p => `<option value="${p.id}">${p.name || p.id}</option>`).join("");
const dialogHtml = `
<div id="ipv6-enable-dialog" class="dialog-mask is-open" style="z-index:1000">
<div class="dialog" style="width:min(420px,100%);max-height:none">
<div style="padding:20px">
<h3 style="margin:0 0 8px">开通 IPv6 子账号</h3>
<p style="margin:0 0 16px;color:var(--muted);font-size:14px">用户: <strong>${email || userId}</strong></p>
<label style="display:block;margin-bottom:6px;font-size:13px;font-weight:600">选择 IPv6 套餐</label>
<select id="ipv6-plan-select" class="field" style="width:100%;margin-bottom:20px">
<option value="0">使用默认套餐</option>
${options}
</select>
<div style="display:flex;gap:10px;justify-content:flex-end">
<button class="btn" onclick="ipv6CloseEnableDialog()">取消</button>
<button class="btn btn-primary" onclick="ipv6ConfirmEnable(${userId})">确认开通</button>
</div>
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML("beforeend", dialogHtml);
});
}
function ipv6CloseEnableDialog() {
const dialog = document.getElementById("ipv6-enable-dialog");
if (dialog) dialog.remove();
}
async function ipv6ConfirmEnable(userId) {
const select = document.getElementById("ipv6-plan-select");
const planId = select ? Number(select.value) || 0 : 0;
ipv6CloseEnableDialog();
await request(`${apiBase}/user-add-ipv6-subscription/enable/${userId}`, "POST", { plan_id: planId });
await loadData(state.page);
}
async function ipv6Enable(id) {
await request(`${apiBase}/user-add-ipv6-subscription/enable/${id}`, "POST", {});
await loadData(state.page);
}
async function ipv6Disable(id) {
if (!confirm("确认关闭该用户的 IPv6 子账号?(软禁用,可恢复)")) return;
await request(`${apiBase}/user-add-ipv6-subscription/disable/${id}`, "POST", {});
await loadData(state.page);
}
async function ipv6SyncPassword(id) {
await request(`${apiBase}/user-add-ipv6-subscription/sync-password/${id}`, "POST", {});
await loadData(state.page);
}
async function loadData(page = 1) {
const payload = await request(endpoint(page));
const pagination =
@@ -814,16 +897,6 @@
await loadData(state.page);
}
async function ipv6Enable(id) {
await request(`${apiBase}/user-add-ipv6-subscription/enable/${id}`, "POST", {});
await loadData(state.page);
}
async function ipv6SyncPassword(id) {
await request(`${apiBase}/user-add-ipv6-subscription/sync-password/${id}`, "POST", {});
await loadData(state.page);
}
function openMenuDialog() {
document.getElementById("menu-dialog").classList.add("is-open");
document.getElementById("menu-dialog").setAttribute("aria-hidden", "false");