diff --git a/app/admin/_components/UsersTab.tsx b/app/admin/_components/UsersTab.tsx index fcf06f5..0ddc565 100644 --- a/app/admin/_components/UsersTab.tsx +++ b/app/admin/_components/UsersTab.tsx @@ -337,7 +337,7 @@ export default function UsersTab({ .filter(Boolean) as string[] }, [editingUserDepartment, users]) - const renderStatusBadges = (user: User) => ( + const renderStatusBadges = useCallback((user: User) => ( <> - ) + ), [badgeActive, badgeInactive, badgeNoRole, badgeRole]) const renderActionButtons = useCallback((user: User, options?: { showRoleToggle?: boolean }) => { const allowed = canManageUser(user) @@ -419,7 +419,20 @@ export default function UsersTab({ )} ) - }, [canManageUser, currentIsSuperAdmin, currentUserId, handleEditUser, onToggleActive, onToggleDownload, onSetRole]) + }, [ + canManageUser, + currentIsSuperAdmin, + currentUserId, + handleEditUser, + onToggleActive, + onToggleDownload, + onSetRole, + styles.buttonModifiers.compactXs, + styles.buttonStyles.danger, + styles.buttonStyles.secondary, + styles.buttonStyles.success, + textDesc, + ]) const renderUserRow = useCallback( (user: User, isManager = false) => ( @@ -453,7 +466,7 @@ export default function UsersTab({ {renderActionButtons(user)} ), - [renderActionButtons], + [renderActionButtons, renderStatusBadges, styles.cardStyles.hover, textDesc, textNormal, textSuperAdmin], ) const showSearchResults = Boolean(searchTerm.trim()) diff --git a/app/admin/page.tsx b/app/admin/page.tsx index a666050..467590f 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -79,7 +79,7 @@ const departmentCollator = useMemo(() => getDepartmentCollator(), []) router.push('/') return } - }, [status, session, router]) + }, [status, router, sessionUser?.isSuperAdmin, sessionUser?.role]) const fetchData = useCallback(async () => { const blockUI = !hasLoadedOnceRef.current diff --git a/app/page.tsx b/app/page.tsx index 414ef81..809a282 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -598,41 +598,6 @@ export default function Home() { } }, []) - const fetchMaterialTypes = useCallback(async () => { - try { - const response = await fetch('/api/material-types', { - cache: 'no-store', - }) - if (response.ok) { - const data = await response.json() - console.log('[Home] Fetched material types from API:', data) - console.log('[Home] Data type:', typeof data, 'Is array:', Array.isArray(data), 'Length:', Array.isArray(data) ? data.length : 'N/A') - if (Array.isArray(data) && data.length > 0) { - console.log('[Home] Applying material type list:', data) - console.log('[Home] Custom types in list:', data.filter(t => t.startsWith('template:'))) - applyMaterialTypeList(data) - // 获取每个类型的素材数量 - fetchMaterialTypesCount(data) - return - } - if (Array.isArray(data?.types) && data.types.length > 0) { - console.log('[Home] Applying material type list (nested):', data.types) - applyMaterialTypeList(data.types) - fetchMaterialTypesCount(data.types) - return - } - } - // 接口返回异常或为空时使用兜底 - console.warn('[Home] Material types API returned empty or invalid data, using fallback') - applyMaterialTypeList(FALLBACK_MATERIAL_TYPES) - fetchMaterialTypesCount(FALLBACK_MATERIAL_TYPES) - } catch (error) { - console.error('[Home] Error fetching material types:', error) - applyMaterialTypeList(FALLBACK_MATERIAL_TYPES) - fetchMaterialTypesCount(FALLBACK_MATERIAL_TYPES) - } - }, [applyMaterialTypeList]) - const fetchMaterialTypesCount = useCallback(async (types: string[]) => { try { const counts: Record = {} @@ -667,6 +632,41 @@ export default function Home() { } }, []) + const fetchMaterialTypes = useCallback(async () => { + try { + const response = await fetch('/api/material-types', { + cache: 'no-store', + }) + if (response.ok) { + const data = await response.json() + console.log('[Home] Fetched material types from API:', data) + console.log('[Home] Data type:', typeof data, 'Is array:', Array.isArray(data), 'Length:', Array.isArray(data) ? data.length : 'N/A') + if (Array.isArray(data) && data.length > 0) { + console.log('[Home] Applying material type list:', data) + console.log('[Home] Custom types in list:', data.filter(t => t.startsWith('template:'))) + applyMaterialTypeList(data) + // 获取每个类型的素材数量 + fetchMaterialTypesCount(data) + return + } + if (Array.isArray(data?.types) && data.types.length > 0) { + console.log('[Home] Applying material type list (nested):', data.types) + applyMaterialTypeList(data.types) + fetchMaterialTypesCount(data.types) + return + } + } + // 接口返回异常或为空时使用兜底 + console.warn('[Home] Material types API returned empty or invalid data, using fallback') + applyMaterialTypeList(FALLBACK_MATERIAL_TYPES) + fetchMaterialTypesCount(FALLBACK_MATERIAL_TYPES) + } catch (error) { + console.error('[Home] Error fetching material types:', error) + applyMaterialTypeList(FALLBACK_MATERIAL_TYPES) + fetchMaterialTypesCount(FALLBACK_MATERIAL_TYPES) + } + }, [applyMaterialTypeList, fetchMaterialTypesCount]) + const fetchHomeFilterFields = useCallback(async () => { try { const response = await fetch('/api/home-filter-fields', { @@ -830,7 +830,6 @@ export default function Home() { selectedTemplateId, selectedPlatform, selectedYear, - selectedMonth, selectedYearMonth, sortBy, ] diff --git a/components/MaterialPreviewModal.tsx b/components/MaterialPreviewModal.tsx index f28c2e7..9638b31 100644 --- a/components/MaterialPreviewModal.tsx +++ b/components/MaterialPreviewModal.tsx @@ -262,7 +262,7 @@ export default function MaterialPreviewModal({ } setIsPolling(false) } - }, [isOpen, isVideoMaterial, material?.id]) + }, [isOpen, isVideoMaterial, material?.id, videoStatus]) const modalTitle = material?.productModel || title || '素材预览' const isLongForm = diff --git a/components/UploadModal.tsx b/components/UploadModal.tsx index 1e89ef2..eee374b 100644 --- a/components/UploadModal.tsx +++ b/components/UploadModal.tsx @@ -238,6 +238,7 @@ const isVideoFile = (file: File) => { previewImages, displayImage, zipFile, + uploadComplete, ]) // 清除保存的上传状态 @@ -293,7 +294,7 @@ const isVideoFile = (file: File) => { setShowNewSceneInput(false) setNewCategoryName('') setNewSceneName('') - }, []) + }, [previewUrls]) // 检查是否有未完成的上传 useEffect(() => {