"use client" import { useState, useEffect } from "react" import { useSearchParams, useRouter, usePathname } from "next/navigation" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { Plus, Search, MoreHorizontal, Edit, Eye, Trash } from "lucide-react" import { toast } from "sonner" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Badge } from "@/components/ui/badge" import { PaginationControls } from "@/components/ui/pagination-controls" import { useTabContext } from "@/app/dashboard/layout" import { apiRequest } from "@/lib/api-utils" interface Project { id: number name: string status: number tenantId: number companyId: number memo: string | null userCount: number createTime: string deviceCount: number } export default function ProjectsPage() { const searchParams = useSearchParams() const router = useRouter() const pathname = usePathname() const { addTab } = useTabContext() const [searchTerm, setSearchTerm] = useState("") const [projects, setProjects] = useState([]) const [isLoading, setIsLoading] = useState(true) const [currentPage, setCurrentPage] = useState(parseInt(searchParams.get("page") || "1")) const [totalPages, setTotalPages] = useState(1) const [pageSize, setPageSize] = useState(parseInt(searchParams.get("pageSize") || "10")) const [totalItems, setTotalItems] = useState(0) const [deleteDialogOpen, setDeleteDialogOpen] = useState(false) const [deletingProjectId, setDeletingProjectId] = useState(null) const [isDeleting, setIsDeleting] = useState(false) // 从URL更新状态 useEffect(() => { const page = parseInt(searchParams.get("page") || "1") const size = parseInt(searchParams.get("pageSize") || "10") setCurrentPage(page) setPageSize(size) }, [searchParams]) // 更新URL查询参数 const updateUrlParams = (page: number, size: number) => { const params = new URLSearchParams() params.set("page", page.toString()) params.set("pageSize", size.toString()) if (searchTerm) { params.set("search", searchTerm) } router.replace(`${pathname}?${params.toString()}`) } // 获取项目列表 useEffect(() => { const fetchProjects = async () => { setIsLoading(true) try { const result = await apiRequest(`/company/list?page=${currentPage}&limit=${pageSize}`) if (result.code === 200) { setProjects(result.data.list) setTotalItems(result.data.total) setTotalPages(Math.ceil(result.data.total / pageSize)) } else { toast.error(result.msg || "获取项目列表失败") setProjects([]) setTotalItems(0) setTotalPages(0) } } catch (error) { toast.error("获取项目列表失败") setProjects([]) setTotalItems(0) setTotalPages(0) } finally { setIsLoading(false) } } fetchProjects() // 更新URL参数 updateUrlParams(currentPage, pageSize) }, [currentPage, pageSize, pathname]) // 处理页面大小变化 const handlePageSizeChange = (newSize: number) => { setPageSize(newSize) setCurrentPage(1) updateUrlParams(1, newSize) } // 处理页面变化 const handlePageChange = (newPage: number) => { setCurrentPage(newPage) updateUrlParams(newPage, pageSize) } const handleDeleteClick = (projectId: number) => { setDeletingProjectId(projectId) setDeleteDialogOpen(true) } const handleConfirmDelete = async () => { if (!deletingProjectId) return setIsDeleting(true) try { const result = await apiRequest('/company/delete', 'POST', { id: deletingProjectId }) if (result.code === 200) { toast.success("删除成功") // Fetch projects again after delete const fetchProjects = async () => { setIsLoading(true) try { const result = await apiRequest(`/company/list?page=${currentPage}&limit=${pageSize}`) if (result.code === 200) { setProjects(result.data.list) setTotalItems(result.data.total) setTotalPages(Math.ceil(result.data.total / pageSize)) if (currentPage > Math.ceil(result.data.total / pageSize) && Math.ceil(result.data.total / pageSize) > 0) { setCurrentPage(Math.ceil(result.data.total / pageSize)); } } else { setProjects([]); setTotalItems(0); setTotalPages(0); } } catch (error) { setProjects([]); setTotalItems(0); setTotalPages(0); } finally { setIsLoading(false); } } fetchProjects(); } else { toast.error(result.msg || "删除失败") } } catch (error) { toast.error("网络错误,请稍后重试") } finally { setIsDeleting(false) setDeleteDialogOpen(false) setDeletingProjectId(null) } } // 打开项目详情 const handleViewProject = (project: Project) => { addTab({ label: `项目 #${project.id} - 详情`, path: `/dashboard/projects/${project.id}`, closable: true }); } // 打开编辑项目 const handleEditProject = (project: Project) => { addTab({ label: `项目 #${project.id} - 编辑`, path: `/dashboard/projects/${project.id}/edit`, closable: true }); } // 打开新建项目 const handleNewProject = () => { addTab({ label: "新建项目", path: "/dashboard/projects/new", closable: true }); } return (

项目列表

setSearchTerm(e.target.value)} />
ID 项目名称 状态 用户数量 设备数量 创建时间 操作 {isLoading ? ( 加载中... ) : projects.length > 0 ? ( projects.map((project) => ( {project.id} {project.name} {project.status === 1 ? "启用" : "禁用"} {project.userCount} {project.deviceCount} {project.createTime} handleViewProject(project)}> 查看详情 handleEditProject(project)}> 编辑项目 handleDeleteClick(project.id)} > 删除项目 )) ) : ( 未找到项目 )}
确认删除 删除项目将会删除本项目关联的所有账号,项目删除后不可恢复,是否确认删除?
) }