"use client" import { useCallback, useEffect, useState } from "react" import { KeyRoundIcon, RefreshCwIcon, RouteIcon, SearchIcon } from "lucide-react" import { toast } from "sonner" import { fetchPermissions, type AdminPermission, type PageResult, } from "@/lib/api/admin" import { Status, StatusLabels } from "@/lib/generated/enums" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { ListPagination } from "@/components/list-pagination" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" const listStatusOptions = [ { value: "all", label: "全部状态" }, { value: String(Status.Ok), label: StatusLabels[Status.Ok] }, { value: String(Status.Disabled), label: StatusLabels[Status.Disabled] }, { value: String(Status.Deleted), label: StatusLabels[Status.Deleted] }, ] as const function getStatusLabel( value: string, options: ReadonlyArray<{ value: string; label: string }> ) { return options.find((item) => item.value === value)?.label ?? "请选择状态" } export default function DashboardPermissionsPage() { const [keywordInput, setKeywordInput] = useState("") const [groupNameInput, setGroupNameInput] = useState("") const [statusFilterInput, setStatusFilterInput] = useState("all") const [keyword, setKeyword] = useState("") const [groupName, setGroupName] = useState("") const [statusFilter, setStatusFilter] = useState("all") const [page, setPage] = useState(1) const [limit, setLimit] = useState(20) const [loading, setLoading] = useState(true) const [result, setResult] = useState>({ results: [], page: { page: 1, limit: 20, total: 0 }, }) const loadData = useCallback(async () => { setLoading(true) try { const data = await fetchPermissions({ keyword: keyword.trim() || undefined, groupName: groupName.trim() || undefined, status: statusFilter === "all" ? undefined : statusFilter, page, limit, }) setResult(data) } catch (error) { toast.error(error instanceof Error ? error.message : "加载权限失败") } finally { setLoading(false) } }, [groupName, keyword, limit, page, statusFilter]) useEffect(() => { void loadData() }, [loadData]) function handleStatusFilterChange(value: string | null) { setStatusFilterInput(value ?? "all") } function applyFilters() { setKeyword(keywordInput) setGroupName(groupNameInput) setStatusFilter(statusFilterInput) setPage(1) } function handleFilterKeyDown(event: React.KeyboardEvent) { if (event.key !== "Enter") { return } event.preventDefault() applyFilters() } function handlePageChange(nextPage: number) { if (nextPage < 1 || nextPage === page) { return } setPage(nextPage) } return (
setKeywordInput(event.target.value)} onKeyDown={handleFilterKeyDown} placeholder="按权限名称/编码筛选" className="pl-9" />
setGroupNameInput(event.target.value)} onKeyDown={handleFilterKeyDown} placeholder="按分组筛选" className="w-full xl:w-48" />
权限 编码 分组 接口 状态 {result.results.map((item) => (
{item.name}
{item.type}
{item.code} {item.groupName}
{item.method || "ANY"}
{item.apiPath || "-"}
{StatusLabels[item.status as Status] ?? String(item.status)}
))} {!loading && result.results.length === 0 ? ( 没有匹配的权限数据 ) : null}
{ setLimit(nextLimit) setPage(1) }} />
) }