Files
smart-crop-ui/crop-x/src/app/(app)/central-config/user/employee/page.tsx

325 lines
9.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { useState, useEffect } from 'react';
import { toast } from 'sonner';
import { EmployeeManagementHeader } from './components/EmployeeManagementHeader';
import { EmployeeManagementStatsCards } from './components/EmployeeManagementStatsCards';
import { EmployeeManagementFilters } from './components/EmployeeManagementFilters';
import { EmployeeList } from './components/EmployeeList';
import { EmployeeFormDialog } from './components/EmployeeFormDialog';
import { EmployeeDetailDialog } from './components/EmployeeDetailDialog';
import { Employee, Role, EmployeeFilters, EmployeeFormData } from './types';
import {
fetchEmployees,
transformEmployeesList,
PaginationState,
EmployeesQueryParams
} from './components/employeeApi';
export default function EmployeeManagementPage() {
const [employees, setEmployees] = useState<Employee[]>([]);
const [roles, setRoles] = useState<Role[]>([]);
const [loading, setLoading] = useState(false);
const [pagination, setPagination] = useState<PaginationState>({
page: 1,
size: 10,
total: 0,
totalPages: 0,
hasNext: false,
hasPrev: false,
});
const [filters, setFilters] = useState<EmployeeFilters>({
searchKeyword: '',
statusFilter: 'all'
});
const [showForm, setShowForm] = useState(false);
const [showDetailDialog, setShowDetailDialog] = useState(false);
const [editingEmployee, setEditingEmployee] = useState<Employee | null>(null);
const [selectedEmployee, setSelectedEmployee] = useState<Employee | null>(null);
const [formData, setFormData] = useState<EmployeeFormData>({
enterpriseId: 'ent-2',
enterpriseName: '丰收现代农业集团',
status: 'active',
auditStatus: 'pending',
roleIds: [],
idCard: '',
address: '',
});
useEffect(() => {
loadEmployees();
loadRoles();
}, [pagination.page, pagination.size,filters.searchKeyword, filters.statusFilter]);
const loadRoles = () => {
const data = localStorage.getItem('smart_agriculture_roles');
if (data) {
setRoles(JSON.parse(data));
}
};
const loadEmployees = async () => {
setLoading(true);
try {
const queryParams: EmployeesQueryParams = {
page: pagination.page,
size: pagination.size,
sort_order: 'desc'
};
// 如果有搜索关键词,添加到查询参数
if (filters.searchKeyword) {
queryParams.search = filters.searchKeyword;
}
// 如果有状态筛选,添加到查询参数
if (filters.statusFilter !== 'all') {
// 注意API可能不支持直接的状态筛选这里暂时在客户端过滤
}
const response = await fetchEmployees(queryParams);
// 转换数据格式
const transformedEmployees = transformEmployeesList(response.data);
// 应用状态筛选如果API不支持
const filteredEmployees = filters.statusFilter === 'all'
? transformedEmployees
: transformedEmployees.filter(emp => {
const status = emp.isActive ? 'active' : 'frozen';
return status === filters.statusFilter;
});
setEmployees(filteredEmployees);
setPagination({
page: response.page,
size: response.size,
total: response.total,
totalPages: response.total_pages,
hasNext: response.has_next,
hasPrev: response.has_prev,
});
} catch (error) {
console.error('Failed to load employees:', error);
toast.error('加载员工数据失败');
// 如果API失败使用localStorage中的数据
setEmployees([]);
} finally {
setLoading(false);
}
};
// 搜索处理函数
const handleSearch = (searchKeyword: string) => {
setFilters(prev => ({ ...prev, searchKeyword }));
// 重置到第一页
setPagination(prev => ({ ...prev, page: 1 }));
};
// 状态筛选处理函数
const handleStatusFilter = (statusFilter: string) => {
setFilters(prev => ({ ...prev, statusFilter }));
// 重置到第一页
setPagination(prev => ({ ...prev, page: 1 }));
};
// 分页处理函数
const handlePageChange = (page: number) => {
setPagination(prev => ({ ...prev, page }));
};
const handlePageSizeChange = (size: number) => {
setPagination(prev => ({ ...prev, size, page: 1 }));
};
const handleAddEmployee = () => {
setEditingEmployee(null);
setFormData({
enterpriseId: 'ent-2',
enterpriseName: '丰收现代农业集团',
status: 'active',
auditStatus: 'pending',
roleIds: [],
idCard: '',
address: '',
});
setShowForm(true);
};
const handleEdit = (employee: Employee) => {
setEditingEmployee(employee);
setFormData(employee);
setShowForm(true);
};
const handleSave = () => {
if (!formData.username || !formData.name || !formData.phone) {
toast.error('请填写必填项');
return;
}
// 验证角色选择
if (!formData.roleIds || formData.roleIds.length === 0) {
toast.error('请至少选择一个角色');
return;
}
// 根据角色ID设置角色名称
const selectedRoles = roles.filter(r => formData.roleIds?.includes(r.id));
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('员工添加成功');
}
setShowForm(false);
};
const handleDelete = (id: string) => {
if (!confirm('确定要删除该员工吗?')) return;
const updated = employees.filter(emp => emp.id !== id);
setEmployees(updated);
localStorage.setItem('smart_agriculture_employees', JSON.stringify(updated));
toast.success('员工删除成功');
};
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' ? '账户已激活' : '账户已冻结');
};
const handleResetPassword = (employee: Employee) => {
if (!confirm(`确定要重置 ${employee.name} 的密码吗?`)) return;
toast.success('密码已重置为123456');
};
const handleViewDetail = (employee: Employee) => {
setSelectedEmployee(employee);
setShowDetailDialog(true);
};
const handleAudit = (employee: Employee, action: 'approve' | 'reject') => {
if (action === 'approve') {
const updated = employees.map(emp =>
emp.id === employee.id
? {
...emp,
auditStatus: 'approved' as const,
auditTime: new Date().toISOString(),
auditor: '当前用户',
updatedAt: new Date().toISOString(),
}
: emp
);
setEmployees(updated);
localStorage.setItem('smart_agriculture_employees', JSON.stringify(updated));
toast.success('审核通过');
} else {
const reason = prompt('请输入驳回原因:');
if (reason) {
const updated = employees.map(emp =>
emp.id === employee.id
? {
...emp,
auditStatus: 'rejected' as const,
auditReason: reason,
auditTime: new Date().toISOString(),
auditor: '当前用户',
updatedAt: new Date().toISOString(),
}
: emp
);
setEmployees(updated);
localStorage.setItem('smart_agriculture_employees', JSON.stringify(updated));
toast.success('已驳回');
}
}
};
return (
<div className="space-y-6">
<EmployeeManagementHeader
onAddEmployee={handleAddEmployee}
/>
{/* 统计卡片 */}
<EmployeeManagementStatsCards employees={employees} />
{/* 搜索和筛选 */}
<EmployeeManagementFilters
filters={filters}
onSearchChange={handleSearch}
onStatusFilterChange={handleStatusFilter}
/>
{/* 员工列表 */}
<EmployeeList
employees={employees}
loading={loading}
pagination={pagination}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
onViewDetail={handleViewDetail}
onEdit={handleEdit}
onResetPassword={handleResetPassword}
onToggleStatus={handleToggleStatus}
onDelete={handleDelete}
onAudit={handleAudit}
/>
{/* 添加/编辑表单 */}
<EmployeeFormDialog
open={showForm}
onOpenChange={setShowForm}
editingEmployee={editingEmployee}
formData={formData}
onFormDataChange={setFormData}
onSave={handleSave}
roles={roles}
/>
{/* 详情对话框 */}
<EmployeeDetailDialog
open={showDetailDialog}
onOpenChange={setShowDetailDialog}
selectedEmployee={selectedEmployee}
/>
</div>
);
}