/** * useUserOperations Hook * * 用户操作Hook * 统一管理用户相关的操作(更新、删除、切换状态等) * 包括:更新用户、删除用户、切换下载权限、切换激活状态、设置角色、转移最高权限 * * @created 2025-01-XX(从 page.tsx 提取) * @hook */ 'use client' import { useCallback } from 'react' import type { User, Department, ApiSuccessResponse } from '../_components/types' import { parseErrorResponse } from '../_utils/api' import type { ToastFn } from '../_components/types' interface UseUserOperationsOptions { users: User[] setUsers: React.Dispatch> showToast: ToastFn fetchData: () => Promise findDepartmentManagers: (departmentName: string | null | undefined) => User[] | null } export function useUserOperations({ users, setUsers, showToast, fetchData, findDepartmentManagers, }: UseUserOperationsOptions) { const updateUser = useCallback( async (user: User, payload: { username: string; department: string }) => { const { username, department } = payload const usernameChanged = username !== user.username const departmentChanged = department !== (user.department || '') if (!usernameChanged && !departmentChanged) { showToast('未做任何修改', 'error') return false } try { let materialsUpdated = false let parentIdToSet: string | null = null if (departmentChanged && department) { const managers = findDepartmentManagers(department) || [] if (managers.length > 0) { const firstManager = managers.find((manager) => manager.id !== user.id) || managers[0] parentIdToSet = firstManager.id } } if (usernameChanged || departmentChanged) { const response = await fetch('/api/admin/users/update', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ userId: user.id, username, department, }), }) if (!response.ok) { const errorData = await parseErrorResponse(response) showToast(errorData.error || '更新失败', 'error') return false } const successData = (await response.json()) as ApiSuccessResponse<{ materialsUpdated?: boolean }> materialsUpdated = Boolean(successData.materialsUpdated) if (departmentChanged && parentIdToSet) { const hierarchyResponse = await fetch('/api/admin/users/update-hierarchy', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ userId: user.id, parentId: parentIdToSet, }), }) if (!hierarchyResponse.ok) { const errorData = await parseErrorResponse(hierarchyResponse) showToast(errorData.error || '调整上下级失败', 'error') return false } } } await fetchData() showToast(materialsUpdated ? '用户信息已更新,素材信息已同步' : '用户信息已更新') return true } catch (error) { console.error('Update user error:', error) showToast('更新失败,请稍后重试', 'error') return false } }, [showToast, fetchData, findDepartmentManagers] ) const deleteUser = useCallback( async (id: string) => { try { const response = await fetch(`/api/admin/users?id=${id}`, { method: 'DELETE', }) if (response.ok) { setUsers((prevUsers) => prevUsers.filter((u) => u.id !== id)) showToast('删除成功') return true } const errorData = await parseErrorResponse(response) showToast(errorData.error || '删除失败', 'error') return false } catch (error) { console.error('Error deleting user:', error) showToast('删除失败', 'error') return false } }, [setUsers, showToast] ) const toggleDownload = useCallback( async (userId: string, currentCanDownload: boolean) => { const action = currentCanDownload ? '关闭' : '开启' try { const response = await fetch('/api/admin/users/toggle-download', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ userId }), }) if (response.ok) { // 直接更新本地状态,避免重新加载整个列表 setUsers((prevUsers) => prevUsers.map((user) => user.id === userId ? { ...user, canDownload: !currentCanDownload } : user ) ) showToast(`下载权限已${action}`) } else { const errorData = await parseErrorResponse(response) showToast(errorData.error || '操作失败', 'error') } } catch (error) { console.error('Error toggling download permission:', error) showToast('操作失败', 'error') } }, [setUsers, showToast] ) const toggleActive = useCallback( async (userId: string, currentStatus: boolean) => { const action = currentStatus ? '禁用' : '激活' try { const response = await fetch('/api/admin/users/toggle-active', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ userId, isActive: !currentStatus, }), }) if (response.ok) { // 直接更新本地状态 setUsers((prevUsers) => prevUsers.map((user) => (user.id === userId ? { ...user, isActive: !currentStatus } : user)) ) showToast(`${action}成功`) } else { const errorData = await parseErrorResponse(response) showToast(errorData.error || `${action}失败`, 'error') } } catch (error) { console.error('Toggle active error:', error) showToast(`${action}失败`, 'error') } }, [setUsers, showToast] ) const setRole = useCallback( async (userId: string, currentRole: string) => { const newRole = currentRole === 'ADMIN' ? 'USER' : 'ADMIN' const action = newRole === 'ADMIN' ? '设置为管理员' : '取消管理员权限' try { const response = await fetch('/api/admin/users/set-role', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ userId, role: newRole, }), }) if (response.ok) { // 刷新数据,用户树会同步更新最新的管理员信息 await fetchData() showToast(`${action}成功`) } else { const errorData = await parseErrorResponse(response) showToast(errorData.error || `${action}失败`, 'error') } } catch (error) { console.error('Set role error:', error) showToast(`${action}失败`, 'error') } }, [showToast, fetchData] ) const transferSuperAdmin = useCallback( async (targetEmail: string, password: string) => { try { const res = await fetch('/api/admin/transfer-superadmin', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ targetEmail, password }), }) if (res.ok) { showToast('最高权限已转移') await fetchData() return true } const errorData = await parseErrorResponse(res) showToast(errorData.error || '操作失败', 'error') return false } catch (err) { console.error('transfer super admin error:', err) showToast('操作失败,请稍后重试', 'error') return false } }, [showToast, fetchData] ) return { updateUser, deleteUser, toggleDownload, toggleActive, setRole, transferSuperAdmin, } } export type UseUserOperationsReturn = ReturnType