diff --git a/src/api/resources.ts b/src/api/resources.ts index 59b955a..ede7efc 100644 --- a/src/api/resources.ts +++ b/src/api/resources.ts @@ -21,6 +21,8 @@ import type { export const usersApi = { list: () => api.get("/admin/users"), create: (body: Partial) => api.post("/admin/users", body), + update: (id: string, body: Partial) => api.put(`/admin/users/${id}`, body), + remove: (id: string) => api.del<{ ok: boolean }>(`/admin/users/${id}`), setRole: (id: string, body: { role: string; sub_role?: string }) => api.post(`/admin/users/${id}/role`, body), setStatus: (id: string, status: string) => diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx index ecd8fb4..1eb633c 100644 --- a/src/pages/users/index.tsx +++ b/src/pages/users/index.tsx @@ -1,3 +1,4 @@ +import * as React from "react"; import { PageHeader } from "@/components/generic/PageHeader"; import { DataTable, type Column } from "@/components/generic/DataTable"; import { StatusBadge } from "@/components/generic/StatusBadge"; @@ -6,31 +7,85 @@ import { usersApi } from "@/api/resources"; import type { UserRow } from "@/types"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { formatDate } from "@/lib/utils"; -const columns: Column[] = [ - { key: "username", header: "账号", cell: (r) => {r.username} }, - { key: "nickname", header: "昵称", cell: (r) => r.nickname || "-" }, - { key: "role", header: "端口角色", cell: (r) => r.sub_role || r.role || "-" }, - { key: "status", header: "状态", cell: (r) => }, - { key: "created_at", header: "创建时间", cell: (r) => formatDate(r.created_at) }, -]; +const PORT_ROLES = ["operator", "government", "enterprise", "provider", "carrier", "opc_member", "investor"]; +const EMPTY = { username: "", nickname: "", role: "opc_member", sub_role: "" }; export default function UsersPage() { - const { data, loading, error, reload } = useResource(() => usersApi.list()); + const res = useResource(() => usersApi.list()); + const [open, setOpen] = React.useState(false); + const [editing, setEditing] = React.useState(null); + const [form, setForm] = React.useState>(EMPTY); + const [busy, setBusy] = React.useState(false); + + const openCreate = () => { setEditing(null); setForm(EMPTY); setOpen(true); }; + const openEdit = (r: UserRow) => { setEditing(r); setForm({ username: r.username || "", nickname: r.nickname || "", role: r.role || "opc_member", sub_role: r.sub_role || "" }); setOpen(true); }; + + const save = async () => { + setBusy(true); + try { + if (editing) await usersApi.update(editing.id, { nickname: form.nickname, role: form.role, sub_role: form.sub_role || undefined }); + else await usersApi.create({ username: form.username, nickname: form.nickname, password: form.password || "123456", role: form.role, sub_role: form.sub_role || undefined }); + setOpen(false); res.reload(); + } finally { setBusy(false); } + }; + const remove = async (id: string) => { + if (!window.confirm("确认删除该用户?")) return; + await usersApi.remove(id); res.reload(); + }; + const toggle = async (r: UserRow) => { + await usersApi.setStatus(r.id, r.status === "disabled" ? "active" : "disabled"); res.reload(); + }; + + const columns: Column[] = [ + { key: "username", header: "账号", cell: (r) => {r.username} }, + { key: "nickname", header: "昵称", cell: (r) => r.nickname || "-" }, + { key: "role", header: "端口角色", cell: (r) => r.sub_role || r.role || "-" }, + { key: "status", header: "状态", cell: (r) => }, + { key: "created_at", header: "创建时间", cell: (r) => formatDate(r.created_at) }, + { + key: "actions", header: "操作", cell: (r) => ( +
+ + + +
+ ), + }, + ]; + return (
- 刷新} - /> - - - {error ?

{error}

: null} - -
-
+
} /> + + {res.error ?

{res.error}

: null} + +
+ + + + {editing ? "编辑用户" : "新增用户"} +
+
setForm((f) => ({ ...f, username: e.target.value }))} />
+ {!editing &&
setForm((f) => ({ ...f, password: e.target.value }))} />
} +
setForm((f) => ({ ...f, nickname: e.target.value }))} />
+
+ +
+
setForm((f) => ({ ...f, sub_role: e.target.value }))} />
+
+ +
+
); }