'use client' import { useCallback, useEffect, useState } from 'react' import { useSession } from 'next-auth/react' import { useRouter } from 'next/navigation' import MaterialsHeader from '@/components/board/MaterialsHeader' import DepartmentPermissionsTab from '@/components/DepartmentPermissionsTab' import SuperAdminsTab from '@/components/SuperAdminsTab' import MaterialManagement from '@/components/admin/MaterialManagement' import CategoryManagement from '@/components/admin/CategoryManagement' import DataStatisticsTab from '@/components/admin/DataStatisticsTab' import PublicTrafficTab from '@/components/admin/PublicTrafficTab' // 类型定义 interface Material { id: string previewUrl: string productModel: string categoryName: string sceneName: string materialType: string renderer: string authorName: string createdAt: string videoCoverUrl?: string videoPreviewClipUrl?: string videoPreview540Url?: string user: { username: string } } interface Category { id: string name: string count: number } interface Scene { id: string name: string count: number } interface Platform { id: string name: string count: number } interface ProductCategory { id: string name: string count: number } interface Department { id: string name: string // 阶段三:部门层级结构字段 code?: string | null parentId?: string | null level?: number managerId?: string | null status?: string description?: string | null sortOrder?: number createdAt?: string updatedAt?: string // 关联数据(可选) parent?: Department | null children?: Department[] manager?: { id: string email: string username: string realName?: string | null } | null } export default function AdminPage() { const { data: session, status } = useSession() const router = useRouter() const sessionUser = session?.user as { role?: string managedDepartment?: string | null department?: string | null isSuperAdmin?: boolean email?: string | null } | undefined const currentUserRole = sessionUser?.role || '' const canAccessAdminPage = currentUserRole === 'ADMIN' || currentUserRole === 'SYSTEM_ADMIN' || currentUserRole === 'DEPT_ADMIN' const canManageSystemTabs = currentUserRole === 'ADMIN' || currentUserRole === 'SYSTEM_ADMIN' const departmentScopeName = String(sessionUser?.managedDepartment || sessionUser?.department || '').trim() || null const canSelectDepartmentInStats = canManageSystemTabs // Tab状态 const [activeTab, setActiveTab] = useState<'materials' | 'categories' | 'dataStats' | 'permissions' | 'superAdmins' | 'publicTraffic'>('dataStats') const [loading, setLoading] = useState(true) // 数据状态 const [materials, setMaterials] = useState([]) const [categories, setCategories] = useState([]) const [scenes, setScenes] = useState([]) const [platforms, setPlatforms] = useState([]) const [productCategories, setProductCategories] = useState([]) const [departments, setDepartments] = useState([]) // Toast状态 const [toast, setToast] = useState<{message: string, type: 'success' | 'error'} | null>(null) // 素材管理相关状态 const [selectedMaterials, setSelectedMaterials] = useState>(new Set()) const [showRecycleBin, setShowRecycleBin] = useState(false) const [materialSearchTerm, setMaterialSearchTerm] = useState('') const [displayedMaterialsCount, setDisplayedMaterialsCount] = useState(24) const [currentMaterialsPage, setCurrentMaterialsPage] = useState(1) const [hasMoreMaterials, setHasMoreMaterials] = useState(true) const [isLoadingMoreMaterials, setIsLoadingMoreMaterials] = useState(false) const [totalMaterialsCount, setTotalMaterialsCount] = useState(0) // 素材总数(用于显示) const materialsPageSize = 50 // 增大分页大小,减少请求次数 // Toast自动隐藏 useEffect(() => { if (toast) { const timer = setTimeout(() => setToast(null), 3000) return () => clearTimeout(timer) } }, [toast]) const showToast = useCallback((message: string, type: 'success' | 'error' = 'success') => { setToast({ message, type }) }, []) const fetchDepartments = useCallback(async () => { // 阶段三:获取包含层级关系的部门数据 const response = await fetch('/api/departments?includeHierarchy=true') if (!response.ok) { throw new Error('部门数据加载失败') } const data = await response.json() setDepartments(data) }, []) const fetchData = useCallback(async () => { setLoading(true) try { if (activeTab === 'dataStats' || !canManageSystemTabs) { return } else if (activeTab === 'materials') { setCurrentMaterialsPage(1) setDisplayedMaterialsCount(24) setHasMoreMaterials(true) const url = showRecycleBin ? `/api/materials?page=1&pageSize=${materialsPageSize}&deleted=true` : `/api/materials?page=1&pageSize=${materialsPageSize}` const response = await fetch(url) if (!response.ok) throw new Error('素材数据加载失败') const data = await response.json() const materialsData = data.materials || data setMaterials(materialsData) setDisplayedMaterialsCount(materialsData.length) setCurrentMaterialsPage(1) setHasMoreMaterials(materialsData.length >= materialsPageSize) // 保存总数(用于显示) if (data.totalCount !== undefined) { setTotalMaterialsCount(data.totalCount) } } else if (activeTab === 'categories') { const [categoriesRes, scenesRes, platformsRes, productCategoriesRes] = await Promise.all([ fetch('/api/categories'), fetch('/api/scenes'), fetch('/api/platforms'), fetch('/api/product-categories') ]) if (!categoriesRes.ok || !scenesRes.ok || !platformsRes.ok || !productCategoriesRes.ok) { throw new Error('分类数据加载失败') } setCategories(await categoriesRes.json()) setScenes(await scenesRes.json()) setPlatforms(await platformsRes.json()) setProductCategories(await productCategoriesRes.json()) } else if (activeTab === 'permissions') { await fetchDepartments() } } catch (error) { console.error('Error fetching data:', error) showToast(error instanceof Error ? error.message : '数据加载失败', 'error') } finally { setLoading(false) } }, [activeTab, canManageSystemTabs, fetchDepartments, showRecycleBin, showToast]) // 权限检查 useEffect(() => { if (status === 'unauthenticated') { router.push('/login') return } if (status === 'authenticated' && !canAccessAdminPage) { router.push('/') return } }, [status, canAccessAdminPage, router]) useEffect(() => { if (status === 'authenticated' && !canManageSystemTabs && activeTab !== 'dataStats') { setActiveTab('dataStats') } }, [activeTab, canManageSystemTabs, status]) // 数据加载 useEffect(() => { if (status === 'authenticated') { fetchData() } }, [status, fetchData]) // 切换回收站时清空选中状态和搜索词 useEffect(() => { void showRecycleBin setSelectedMaterials(new Set()) setMaterialSearchTerm('') // 清空搜索词,避免状态混乱 }, [showRecycleBin]) // 加载更多素材 const loadMoreMaterials = useCallback(async () => { if (isLoadingMoreMaterials || !hasMoreMaterials) return if (materialSearchTerm.trim().length > 0) return setIsLoadingMoreMaterials(true) try { const nextPage = currentMaterialsPage + 1 const url = showRecycleBin ? `/api/materials?page=${nextPage}&pageSize=${materialsPageSize}&deleted=true` : `/api/materials?page=${nextPage}&pageSize=${materialsPageSize}` const response = await fetch(url) if (response.ok) { const data = await response.json() const newMaterials = data.materials || data if (newMaterials.length > 0) { // 去重:过滤掉已经存在的素材,并同步更新 displayedMaterialsCount setMaterials(prev => { const existingIds = new Set(prev.map(m => m.id)) const uniqueNewMaterials = newMaterials.filter((m: { id: string }) => !existingIds.has(m.id)) // 同步更新 displayedMaterialsCount(使用实际去重后的数量) setDisplayedMaterialsCount(prev.length + uniqueNewMaterials.length) return [...prev, ...uniqueNewMaterials] }) setCurrentMaterialsPage(nextPage) setHasMoreMaterials(newMaterials.length >= materialsPageSize) } else { setHasMoreMaterials(false) } } } catch (error) { console.error('加载更多素材失败:', error) } finally { setIsLoadingMoreMaterials(false) } }, [isLoadingMoreMaterials, hasMoreMaterials, currentMaterialsPage, showRecycleBin, materialSearchTerm]) // 加载状态 if (status === 'loading' || loading) { return (
加载中...
) } if (!session || !canAccessAdminPage) { return null } return (
{/* Toast通知 */} {toast && (
{toast.message}
)}

治理与设置

{canManageSystemTabs && ( )}
{/* Tabs */}
{canManageSystemTabs && ( <> {sessionUser?.isSuperAdmin && ( <> )} )}
{/* 数据统计 Tab */} {activeTab === 'dataStats' && ( )} {/* 素材管理 Tab */} {canManageSystemTabs && activeTab === 'materials' && ( )} {/* 分类管理 Tab */} {canManageSystemTabs && activeTab === 'categories' && ( )} {/* 部门权限配置 Tab */} {canManageSystemTabs && activeTab === 'permissions' && sessionUser?.isSuperAdmin && ( )} {/* 超级管理员 Tab */} {canManageSystemTabs && activeTab === 'superAdmins' && sessionUser?.isSuperAdmin && ( )} {/* 公网流量 Tab */} {canManageSystemTabs && activeTab === 'publicTraffic' && sessionUser?.isSuperAdmin && ( )}
) }