生产管理系统 - 激活、删除的联调

This commit is contained in:
2025-11-12 14:34:34 +08:00
parent 8fefadaf55
commit dcd7ddeb71
16 changed files with 487 additions and 458 deletions

View File

@@ -9,7 +9,6 @@
import { useReducer, useEffect, useState, useCallback, useMemo,useRef } from 'react';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import { Eye, Edit, Trash2, UserX, UserCheck } from 'lucide-react';
import {
AlertDialog,
AlertDialogAction,
@@ -20,6 +19,7 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Eye, Edit, Lock, UserX, UserCheck, Trash2 } from 'lucide-react';
import { UserDetailDialog } from './components/UserDetailDialog';
import { AddUserModal } from './components/AddUserModal';
import { EditUserModal } from './components/EditUserModal';
@@ -45,6 +45,8 @@ interface UserManagementState {
showDetailDialog: boolean;
showAddDialog: boolean;
showEditDialog: boolean;
showDeactivateDialog: boolean;
showDeleteDialog: boolean;
}
type UserManagementAction =
@@ -58,6 +60,8 @@ type UserManagementAction =
| { type: 'TOGGLE_DETAIL_DIALOG'; payload: boolean }
| { type: 'TOGGLE_ADD_DIALOG'; payload: boolean }
| { type: 'TOGGLE_EDIT_DIALOG'; payload: boolean }
| { type: 'TOGGLE_DEACTIVATE_DIALOG'; payload: boolean }
| { type: 'TOGGLE_DELETE_DIALOG'; payload: boolean }
| { type: 'REFRESH_DATA' };
const userManagementReducer = (state: UserManagementState, action: UserManagementAction): UserManagementState => {
@@ -88,6 +92,10 @@ const userManagementReducer = (state: UserManagementState, action: UserManagemen
return { ...state, showAddDialog: !state.showAddDialog };
case 'TOGGLE_EDIT_DIALOG':
return { ...state, showEditDialog: !state.showEditDialog };
case 'TOGGLE_DEACTIVATE_DIALOG':
return { ...state, showDeactivateDialog: !state.showDeactivateDialog };
case 'TOGGLE_DELETE_DIALOG':
return { ...state, showDeleteDialog: !state.showDeleteDialog };
case 'REFRESH_DATA':
return { ...state, error: null };
default:
@@ -118,17 +126,13 @@ const initialState: UserManagementState = {
showDetailDialog: false,
showAddDialog: false,
showEditDialog: false,
showDeactivateDialog: false,
showDeleteDialog: false,
};
export default function TenantUserManagementPage() {
const [state, dispatch] = useReducer(userManagementReducer, initialState);
// 弹窗状态管理
const [statusDialogOpen, setStatusDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [actionUser, setActionUser] = useState<User | null>(null);
const [actionType, setActionType] = useState<'activate' | 'deactivate'>('activate');
// 搜索字段配置
const searchFields: SearchFieldConfig[] = useMemo(() => [
{
@@ -279,7 +283,7 @@ export default function TenantUserManagementPage() {
variant="ghost"
size="sm"
onClick={() => handleToggleStatus(user)}
title={user.isActive ? "冻结用户" : "激活用户"}
title={user.isActive ? "停用用户" : "激活用户"}
>
{user.isActive ? (
<UserX className="w-4 h-4 text-orange-600" />
@@ -290,9 +294,9 @@ export default function TenantUserManagementPage() {
<Button
variant="ghost"
size="sm"
onClick={() => handleDeleteUser(user)}
onClick={() => handleDelete(user)}
title="删除用户"
className="text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-950"
className="text-red-600 hover:text-red-700 hover:bg-red-50"
>
<Trash2 className="w-4 h-4" />
</Button>
@@ -504,62 +508,60 @@ export default function TenantUserManagementPage() {
loadUsers({});
}, [loadUsers]);
// 切换用户状态 - 打开确认弹窗
// 切换用户状态
const handleToggleStatus = (user: User) => {
const newStatus = !user.isActive;
setActionUser(user);
setActionType(newStatus ? 'activate' : 'deactivate');
setStatusDialogOpen(true);
dispatch({ type: 'SET_SELECTED_USER', payload: user });
dispatch({ type: 'TOGGLE_DEACTIVATE_DIALOG', payload: true });
};
// 执行状态切换
const handleStatusConfirm = async () => {
if (!actionUser) return;
// 删除用户
const handleDelete = (user: User) => {
dispatch({ type: 'SET_SELECTED_USER', payload: user });
dispatch({ type: 'TOGGLE_DELETE_DIALOG', payload: true });
};
// 确认切换用户状态
const confirmToggleStatus = async () => {
if (!state.selectedUser) return;
try {
if (actionType === 'activate') {
await activateUser(actionUser.id);
toast.success(`用户 ${actionUser.fullName || actionUser.username} 已激活`);
const user = state.selectedUser;
if (user.isActive) {
await deactivateUser(user.id);
toast.success(`用户 ${user.fullName || user.username} 已停用`);
} else {
await deactivateUser(actionUser.id);
toast.success(`用户 ${actionUser.fullName || actionUser.username}停用`);
await activateUser(user.id);
toast.success(`用户 ${user.fullName || user.username}激活`);
}
// 刷新数据
// 关闭对话框并刷新列表
dispatch({ type: 'TOGGLE_DEACTIVATE_DIALOG', payload: false });
dispatch({ type: 'SET_SELECTED_USER', payload: null });
refreshData();
} catch (error) {
console.error(`${actionType === 'activate' ? '激活' : '停用'}用户失败:`, error);
const errorMessage = error instanceof Error ? error.message : `${actionType === 'activate' ? '激活' : '停用'}用户失败,请重试`;
console.error('切换用户状态失败:', error);
const errorMessage = error instanceof Error ? error.message : '操作失败,请重试';
toast.error(errorMessage);
} finally {
setStatusDialogOpen(false);
setActionUser(null);
}
};
// 删除用户 - 打开确认弹窗
const handleDeleteUser = (user: User) => {
setActionUser(user);
setDeleteDialogOpen(true);
};
// 执行删除用户
const handleDeleteConfirm = async () => {
if (!actionUser) return;
// 确认删除用户
const confirmDelete = async () => {
if (!state.selectedUser) return;
try {
await deleteUser(actionUser.id);
toast.success(`用户 ${actionUser.fullName || actionUser.username} 已删除`);
const user = state.selectedUser;
await deleteUser(user.id);
toast.success(`用户 ${user.fullName || user.username} 已删除`);
// 刷新数据
// 关闭对话框并刷新列表
dispatch({ type: 'TOGGLE_DELETE_DIALOG', payload: false });
dispatch({ type: 'SET_SELECTED_USER', payload: null });
refreshData();
} catch (error) {
console.error('删除用户失败:', error);
const errorMessage = error instanceof Error ? error.message : '删除用户失败,请重试';
const errorMessage = error instanceof Error ? error.message : '删除失败,请重试';
toast.error(errorMessage);
} finally {
setDeleteDialogOpen(false);
setActionUser(null);
}
};
@@ -652,54 +654,55 @@ export default function TenantUserManagementPage() {
onSuccess={refreshData}
/>
{/* 状态切换确认对话框 */}
<AlertDialog open={statusDialogOpen} onOpenChange={setStatusDialogOpen}>
{/* 停用/激活用户确认对话框 */}
<AlertDialog open={state.showDeactivateDialog} onOpenChange={(open) => dispatch({ type: 'TOGGLE_DEACTIVATE_DIALOG', payload: open })}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
{actionType === 'activate' ? '激活用户' : '停用用户'}
{state.selectedUser?.isActive ? '停用用户' : '激活用户'}
</AlertDialogTitle>
<AlertDialogDescription>
{actionType === 'activate' ? '激活' : '停用'}
<span className="font-semibold">
{actionUser?.fullName || actionUser?.username}
</span>
{state.selectedUser?.isActive ? '停用' : '激活'} <strong>{state.selectedUser?.fullName || state.selectedUser?.username}</strong>
{state.selectedUser?.isActive && (
<span className="block mt-2 text-amber-600 dark:text-amber-400">
</span>
)}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel></AlertDialogCancel>
<AlertDialogAction
onClick={handleStatusConfirm}
className={actionType === 'activate' ? 'bg-green-600 hover:bg-green-700' : 'bg-orange-600 hover:bg-orange-700'}
<Button
onClick={confirmToggleStatus}
className={state.selectedUser?.isActive ? 'bg-orange-600 hover:bg-orange-700' : 'bg-green-600 hover:bg-green-700'}
>
{actionType === 'activate' ? '激活' : '停用'}
</AlertDialogAction>
{state.selectedUser?.isActive ? '停用' : '激活'}
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
{/* 删除用户确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
<AlertDialog open={state.showDeleteDialog} onOpenChange={(open) => dispatch({ type: 'TOGGLE_DELETE_DIALOG', payload: open })}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle className="text-red-600"></AlertDialogTitle>
<AlertDialogDescription>
<span className="font-semibold text-red-600">
{actionUser?.fullName || actionUser?.username}
<strong>{state.selectedUser?.fullName || state.selectedUser?.username}</strong>
<span className="block mt-2 text-red-600 dark:text-red-400">
</span>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel></AlertDialogCancel>
<AlertDialogAction
onClick={handleDeleteConfirm}
<Button
onClick={confirmDelete}
className="bg-red-600 hover:bg-red-700"
variant="destructive"
>
</AlertDialogAction>
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>