import { api } from "../../../services/api"; import { getCurrentUser } from "../../../services/authState"; import type { ManagedUser, UserListResponse, UserRole } from "../../../types"; import { confirmDialog, formDialog, notify, notifyError } from "../../../ui/dialogs"; import { escapeHtml } from "../../../utils/format"; type UserFormMode = "create" | "edit"; let users: ManagedUser[] = []; let editingUserId: number | null = null; export async function openUserManager() { await refreshUsers(); editingUserId = null; await formDialog({ title: "人员权限管理", width: 980, height: 560, body: `
账号列表 维护人员角色、启停状态和授权到期时间
用户 角色 状态 授权到期 更新时间 操作
${userRowsHtml()}
`, onOpen: bindUserManagerEvents, onSubmit: () => true }); } async function refreshUsers() { const result = await api("/api/users"); users = result.users; } function userRowsHtml() { return users.map(userRowHtml).join("") || `
暂无人员
`; } function userRowHtml(user: ManagedUser) { const currentUser = getCurrentUser(); const locked = currentUser?.id === user.id; const expired = isExpired(user.expires_at); const statusClass = user.enabled ? (expired ? "is-expired" : "is-enabled") : "is-disabled"; const statusText = user.enabled ? (expired ? "已过期" : "启用") : "禁用"; return `
${escapeHtml(user.username)} ${locked ? `当前账号` : ""} ${roleText(user.role)} ${statusText} ${formatDate(user.expires_at) || "长期有效"} ${formatDate(user.updated_at)}
`; } function bindUserManagerEvents() { document.querySelector("#addUserBtn")?.addEventListener("click", () => { renderUserEditor("create"); }); bindUserRowEvents(); bindUserEditorEvents(); } function bindUserRowEvents() { document.querySelectorAll(".user-table-body button").forEach((button) => { button.addEventListener("click", async () => { try { const id = Number(button.dataset.id); if (button.dataset.action === "edit") renderUserEditor("edit", id); if (button.dataset.action === "delete") await deleteUser(id); } catch (error) { notifyError(error); } }); }); } function renderUserEditor(mode: UserFormMode, id?: number) { editingUserId = mode === "edit" ? id ?? null : null; const user = id ? users.find((item) => item.id === id) : undefined; const isCreate = mode === "create"; const host = document.querySelector("#userEditorHost"); if (!host) return; host.innerHTML = `
${isCreate ? "新增人员" : "编辑权限"} ${isCreate ? "创建账号并设置初始权限" : "调整角色、状态和授权期限"}
`; bindUserEditorEvents(); } function userEditorEmptyHtml() { return `
选择人员 点击新增或编辑后,在这里维护账号权限。
`; } function bindUserEditorEvents() { document.querySelector("#saveUserBtn")?.addEventListener("click", async () => { try { await saveUserEditor(); } catch (error) { notifyError(error); } }); document.querySelector("#cancelUserEditBtn")?.addEventListener("click", () => { editingUserId = null; const host = document.querySelector("#userEditorHost"); if (host) host.innerHTML = userEditorEmptyHtml(); }); } async function saveUserEditor() { const formElement = document.querySelector("#userEditorForm"); if (!formElement) return; const form = new FormData(formElement); const isCreate = formElement.dataset.mode === "create"; const password = String(form.get("password") ?? "").trim(); const result = { username: String(form.get("username") ?? "").trim(), password, role: String(form.get("role") ?? "user") as UserRole, enabled: String(form.get("enabled") ?? "true") === "true", expiresAt: String(form.get("expiresAt") ?? "") || null }; if (isCreate && !result.username) throw new Error("用户名不能为空"); if (isCreate && result.password.length < 6) throw new Error("初始密码至少 6 位"); if (!isCreate && result.password && result.password.length < 6) throw new Error("重置密码至少 6 位"); if (isCreate) { await api("/api/users", { method: "POST", body: JSON.stringify(result) }); notify("新增成功"); } else { if (!editingUserId) throw new Error("请选择要编辑的用户"); await api(`/api/users/${editingUserId}`, { method: "PUT", body: JSON.stringify({ role: result.role, enabled: result.enabled, expiresAt: result.expiresAt, ...(result.password ? { password: result.password } : {}) }) }); notify("保存成功"); } await rerenderUserRows(); if (isCreate) { const host = document.querySelector("#userEditorHost"); if (host) host.innerHTML = userEditorEmptyHtml(); } } async function deleteUser(id: number) { const user = users.find((item) => item.id === id); if (!user) return; const confirmed = await confirmDialog(`确认删除用户「${user.username}」?`); if (!confirmed) return; await api(`/api/users/${id}`, { method: "DELETE" }); notify("删除成功"); await rerenderUserRows(); } async function rerenderUserRows() { await refreshUsers(); const body = document.querySelector("#userTableBody"); if (!body) return; body.innerHTML = userRowsHtml(); bindUserRowEvents(); if (editingUserId) { renderUserEditor("edit", editingUserId); } } function roleText(role: UserRole) { return role === "admin" ? "管理员" : "普通用户"; } function isExpired(value: string | null) { return Boolean(value && new Date(value).getTime() < Date.now()); } function formatDate(value: string | null) { if (!value) return ""; return value.slice(0, 10); } function dateInputValue(value: string | null | undefined) { return value ? value.slice(0, 10) : ""; }