生产管理系统 - 员工管理、企业信息联调完毕以及一些页面上的样式修改
This commit is contained in:
@@ -9,10 +9,28 @@ import { EmployeeManagementFilters } from './components/EmployeeManagementFilter
|
||||
import { EmployeeList } from './components/EmployeeList';
|
||||
import { EmployeeFormDialog } from './components/EmployeeFormDialog';
|
||||
import { EmployeeDetailDialog } from './components/EmployeeDetailDialog';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { Employee, Role, EmployeeFilters, EmployeeFormData } from './types';
|
||||
import {
|
||||
fetchEmployees,
|
||||
transformEmployeesList,
|
||||
createEmployee,
|
||||
updateEmployee,
|
||||
activateUser,
|
||||
deactivateUser,
|
||||
deleteUser,
|
||||
CreateEmployeeRequest,
|
||||
UpdateEmployeeRequest,
|
||||
PaginationState,
|
||||
EmployeesQueryParams
|
||||
} from './components/employeeApi';
|
||||
@@ -21,6 +39,15 @@ export default function EmployeeManagementPage() {
|
||||
const [employees, setEmployees] = useState<Employee[]>([]);
|
||||
const [roles, setRoles] = useState<Role[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [updating, setUpdating] = useState(false);
|
||||
const [toggling, setToggling] = useState<string | null>(null); // 记录正在操作的用户ID
|
||||
|
||||
// 确认对话框状态
|
||||
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
|
||||
const [userToDelete, setUserToDelete] = useState<Employee | null>(null);
|
||||
const [deactivateConfirmOpen, setDeactivateConfirmOpen] = useState(false);
|
||||
const [userToDeactivate, setUserToDeactivate] = useState<Employee | null>(null);
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
page: 1,
|
||||
size: 10,
|
||||
@@ -35,6 +62,7 @@ export default function EmployeeManagementPage() {
|
||||
});
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
const [showDetailDialog, setShowDetailDialog] = useState(false);
|
||||
const [formKey, setFormKey] = useState(0); // 添加key来强制重新渲染表单
|
||||
const [editingEmployee, setEditingEmployee] = useState<Employee | null>(null);
|
||||
const [selectedEmployee, setSelectedEmployee] = useState<Employee | null>(null);
|
||||
const [formData, setFormData] = useState<EmployeeFormData>({
|
||||
@@ -135,16 +163,36 @@ export default function EmployeeManagementPage() {
|
||||
|
||||
const handleAddEmployee = () => {
|
||||
setEditingEmployee(null);
|
||||
setFormData({
|
||||
clearForm();
|
||||
setFormKey(prev => prev + 1); // 增加key强制重新渲染
|
||||
setShowForm(true);
|
||||
};
|
||||
|
||||
const clearForm = () => {
|
||||
// 先设置一个空的表单对象
|
||||
const emptyForm = {
|
||||
enterpriseId: 'ent-2',
|
||||
enterpriseName: '丰收现代农业集团',
|
||||
status: 'active',
|
||||
auditStatus: 'pending',
|
||||
status: 'active' as const,
|
||||
auditStatus: 'pending' as const,
|
||||
roleIds: [],
|
||||
idCard: '',
|
||||
address: '',
|
||||
});
|
||||
setShowForm(true);
|
||||
username: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
department: '',
|
||||
position: '',
|
||||
};
|
||||
|
||||
// 强制清空表单
|
||||
setFormData(emptyForm);
|
||||
|
||||
// 使用setTimeout确保状态更新完成
|
||||
setTimeout(() => {
|
||||
setFormData({...emptyForm});
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const handleEdit = (employee: Employee) => {
|
||||
@@ -153,7 +201,7 @@ export default function EmployeeManagementPage() {
|
||||
setShowForm(true);
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
const handleSave = async () => {
|
||||
if (!formData.username || !formData.name || !formData.phone) {
|
||||
toast.error('请填写必填项');
|
||||
return;
|
||||
@@ -170,58 +218,195 @@ export default function EmployeeManagementPage() {
|
||||
const roleNames = selectedRoles.map(r => r.name);
|
||||
|
||||
if (editingEmployee) {
|
||||
// 更新
|
||||
const updated = employees.map(emp =>
|
||||
emp.id === editingEmployee.id
|
||||
? {
|
||||
...emp,
|
||||
...formData,
|
||||
roles: roleNames,
|
||||
updatedAt: new Date().toISOString(),
|
||||
}
|
||||
: emp
|
||||
);
|
||||
setEmployees(updated);
|
||||
localStorage.setItem('smart_agriculture_employees', JSON.stringify(updated));
|
||||
toast.success('员工信息更新成功');
|
||||
} else {
|
||||
// 新增
|
||||
const newEmployee: Employee = {
|
||||
id: `emp-${Date.now()}`,
|
||||
...formData as Employee,
|
||||
roles: roleNames,
|
||||
auditStatus: 'pending',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
const updated = [...employees, newEmployee];
|
||||
setEmployees(updated);
|
||||
localStorage.setItem('smart_agriculture_employees', JSON.stringify(updated));
|
||||
toast.success('员工添加成功');
|
||||
}
|
||||
// 更新 - 调用API
|
||||
setUpdating(true);
|
||||
try {
|
||||
// 构建API请求参数
|
||||
const updateRequest: UpdateEmployeeRequest = {
|
||||
email: formData.email || '',
|
||||
username: formData.username,
|
||||
full_name: formData.name,
|
||||
phone: formData.phone,
|
||||
password: '', // 编辑时不传密码
|
||||
tenant_id: formData.enterpriseId,
|
||||
scope: 'tenant',
|
||||
department_id: formData.departmentId || '',
|
||||
is_superuser: formData.isSuperuser || false,
|
||||
};
|
||||
|
||||
setShowForm(false);
|
||||
// 调用API更新用户
|
||||
const updatedEmployee = await updateEmployee(editingEmployee.id, updateRequest);
|
||||
|
||||
// 更新本地列表中的员工数据
|
||||
const updated = employees.map(emp =>
|
||||
emp.id === editingEmployee.id
|
||||
? {
|
||||
...emp,
|
||||
...updatedEmployee,
|
||||
roles: roleNames,
|
||||
updatedAt: new Date().toISOString(),
|
||||
}
|
||||
: emp
|
||||
);
|
||||
setEmployees(updated);
|
||||
|
||||
toast.success('员工信息更新成功');
|
||||
setShowForm(false);
|
||||
clearForm();
|
||||
|
||||
// 刷新员工列表数据
|
||||
await loadEmployees();
|
||||
} catch (error) {
|
||||
console.error('更新员工失败:', error);
|
||||
|
||||
// 处理错误,显示具体的错误消息
|
||||
const errorMessage = error instanceof Error ? error.message : '员工信息更新失败';
|
||||
toast.error(errorMessage);
|
||||
} finally {
|
||||
setUpdating(false);
|
||||
}
|
||||
} else {
|
||||
// 新增 - 调用API
|
||||
setCreating(true);
|
||||
try {
|
||||
// 构建API请求参数
|
||||
const createRequest: CreateEmployeeRequest = {
|
||||
email: formData.email || '', // 没有邮箱就传空字符串
|
||||
username: formData.username,
|
||||
full_name: formData.name,
|
||||
phone: formData.phone,
|
||||
password: '', // 传递空字符串给后端
|
||||
tenant_id: formData.enterpriseId,
|
||||
scope: 'tenant',
|
||||
department_id: formData.departmentId || '',
|
||||
is_superuser: formData.isSuperuser || false,
|
||||
};
|
||||
|
||||
// 调用API创建用户
|
||||
const newEmployee = await createEmployee(createRequest);
|
||||
|
||||
// 将新员工添加到列表
|
||||
const updated = [newEmployee, ...employees];
|
||||
setEmployees(updated);
|
||||
|
||||
toast.success('员工添加成功');
|
||||
setShowForm(false);
|
||||
clearForm();
|
||||
|
||||
// 刷新员工列表数据
|
||||
await loadEmployees();
|
||||
} catch (error) {
|
||||
console.error('创建员工失败:', error);
|
||||
|
||||
// 处理错误,显示具体的错误消息
|
||||
const errorMessage = error instanceof Error ? error.message : '员工添加失败';
|
||||
toast.error(errorMessage);
|
||||
} finally {
|
||||
setCreating(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
if (!confirm('确定要删除该员工吗?')) return;
|
||||
const handleDelete = (userId: string) => {
|
||||
// 防止重复操作
|
||||
if (toggling) {
|
||||
toast.warning('操作进行中,请稍候...');
|
||||
return;
|
||||
}
|
||||
|
||||
const updated = employees.filter(emp => emp.id !== id);
|
||||
setEmployees(updated);
|
||||
localStorage.setItem('smart_agriculture_employees', JSON.stringify(updated));
|
||||
toast.success('员工删除成功');
|
||||
// 查找要删除的员工信息
|
||||
const employeeToDelete = employees.find(emp => emp.id === userId);
|
||||
if (!employeeToDelete) {
|
||||
toast.error('未找到要删除的用户');
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置要删除的用户并显示确认对话框
|
||||
setUserToDelete(employeeToDelete);
|
||||
setDeleteConfirmOpen(true);
|
||||
};
|
||||
|
||||
const executeDelete = async (userId: string) => {
|
||||
setToggling(userId);
|
||||
|
||||
try {
|
||||
// 调用API删除用户
|
||||
await deleteUser(userId);
|
||||
|
||||
// 成功后从本地列表中移除
|
||||
const updated = employees.filter(emp => emp.id !== userId);
|
||||
setEmployees(updated);
|
||||
|
||||
toast.success('用户删除成功');
|
||||
|
||||
// 刷新列表确保数据同步
|
||||
await loadEmployees();
|
||||
|
||||
// 关闭确认对话框
|
||||
setDeleteConfirmOpen(false);
|
||||
setUserToDelete(null);
|
||||
} catch (error) {
|
||||
console.error('删除用户失败:', error);
|
||||
|
||||
// 处理错误,显示具体的错误消息
|
||||
const errorMessage = error instanceof Error ? error.message : '删除失败,请稍后重试';
|
||||
toast.error(errorMessage);
|
||||
|
||||
// 失败时不关闭确认对话框,用户可以重试
|
||||
} finally {
|
||||
setToggling(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleStatus = (employee: Employee) => {
|
||||
const newStatus = employee.status === 'active' ? 'frozen' : 'active';
|
||||
const updated = employees.map(emp =>
|
||||
emp.id === employee.id
|
||||
? { ...emp, status: newStatus, updatedAt: new Date().toISOString() }
|
||||
: emp
|
||||
);
|
||||
setEmployees(updated);
|
||||
localStorage.setItem('smart_agriculture_employees', JSON.stringify(updated));
|
||||
toast.success(newStatus === 'active' ? '账户已激活' : '账户已冻结');
|
||||
if (toggling) {
|
||||
toast.warning('操作进行中,请稍候...');
|
||||
return;
|
||||
}
|
||||
|
||||
if (employee.isActive) {
|
||||
// 当前是激活状态,进行停用操作,需要二次确认
|
||||
setUserToDeactivate(employee);
|
||||
setDeactivateConfirmOpen(true);
|
||||
} else {
|
||||
// 当前是停用状态,进行激活操作(不需要确认)
|
||||
executeToggleStatus(employee);
|
||||
}
|
||||
};
|
||||
|
||||
const executeToggleStatus = async (employee: Employee) => {
|
||||
setToggling(employee.id);
|
||||
|
||||
try {
|
||||
if (employee.isActive) {
|
||||
// 当前是激活状态,进行停用操作
|
||||
await deactivateUser(employee.id);
|
||||
toast.success('账户已停用');
|
||||
} else {
|
||||
// 当前是停用状态,进行激活操作
|
||||
await activateUser(employee.id);
|
||||
toast.success('账户已激活');
|
||||
}
|
||||
|
||||
// 成功后刷新列表
|
||||
await loadEmployees();
|
||||
|
||||
// 关闭停用确认对话框
|
||||
if (deactivateConfirmOpen) {
|
||||
setDeactivateConfirmOpen(false);
|
||||
setUserToDeactivate(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('切换用户状态失败:', error);
|
||||
|
||||
// 处理错误,显示具体的错误消息
|
||||
const errorMessage = error instanceof Error ? error.message : '操作失败,请稍后重试';
|
||||
toast.error(errorMessage);
|
||||
|
||||
// 失败时不关闭确认对话框,用户可以重试
|
||||
} finally {
|
||||
setToggling(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleResetPassword = (employee: Employee) => {
|
||||
@@ -301,10 +486,12 @@ export default function EmployeeManagementPage() {
|
||||
onToggleStatus={handleToggleStatus}
|
||||
onDelete={handleDelete}
|
||||
onAudit={handleAudit}
|
||||
togglingId={toggling}
|
||||
/>
|
||||
|
||||
{/* 添加/编辑表单 */}
|
||||
<EmployeeFormDialog
|
||||
key={formKey} // 使用key强制重新渲染,清除浏览器缓存
|
||||
open={showForm}
|
||||
onOpenChange={setShowForm}
|
||||
editingEmployee={editingEmployee}
|
||||
@@ -312,6 +499,9 @@ export default function EmployeeManagementPage() {
|
||||
onFormDataChange={setFormData}
|
||||
onSave={handleSave}
|
||||
roles={roles}
|
||||
creating={creating}
|
||||
updating={updating}
|
||||
onClearForm={clearForm}
|
||||
/>
|
||||
|
||||
{/* 详情对话框 */}
|
||||
@@ -320,6 +510,74 @@ export default function EmployeeManagementPage() {
|
||||
onOpenChange={setShowDetailDialog}
|
||||
selectedEmployee={selectedEmployee}
|
||||
/>
|
||||
|
||||
{/* 删除确认对话框 */}
|
||||
<AlertDialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>确认删除用户</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
确定要删除用户 "
|
||||
{userToDelete?.displayName || userToDelete?.fullName || userToDelete?.username || ''}
|
||||
" 吗?
|
||||
<br /><br />
|
||||
<span className="text-red-600 font-semibold">
|
||||
删除后该用户将无法恢复,所有相关数据将被清除。
|
||||
</span>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel disabled={toggling !== null}>
|
||||
取消
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={() => {
|
||||
if (userToDelete) {
|
||||
executeDelete(userToDelete.id);
|
||||
}
|
||||
}}
|
||||
disabled={toggling !== null}
|
||||
className="bg-red-600 hover:bg-red-700"
|
||||
>
|
||||
{toggling ? '删除中...' : '确认删除'}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
{/* 停用确认对话框 */}
|
||||
<AlertDialog open={deactivateConfirmOpen} onOpenChange={setDeactivateConfirmOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>确认停用用户</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
确定要停用用户 "
|
||||
{userToDeactivate?.displayName || userToDeactivate?.fullName || userToDeactivate?.username || ''}
|
||||
" 吗?
|
||||
<br /><br />
|
||||
<span className="text-orange-600 font-semibold">
|
||||
停用后,该用户将无法登录系统。
|
||||
</span>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel disabled={toggling !== null}>
|
||||
取消
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={() => {
|
||||
if (userToDeactivate) {
|
||||
executeToggleStatus(userToDeactivate);
|
||||
}
|
||||
}}
|
||||
disabled={toggling !== null}
|
||||
className="bg-orange-600 hover:bg-orange-700"
|
||||
>
|
||||
{toggling ? '停用中...' : '确认停用'}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user