From 2efceee37fea48925263a201be7245e172a6f787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E8=AF=97=E6=95=8F?= <3130004661@qq.com> Date: Fri, 15 Aug 2025 14:46:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=BA=E5=91=98=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E6=8E=A5=E5=8F=A3=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project/personnel-organization-types.ts | 486 ++++++++++++++++++ src/apis/project/personnel-organization.ts | 312 +++++++++-- 2 files changed, 765 insertions(+), 33 deletions(-) create mode 100644 src/apis/project/personnel-organization-types.ts diff --git a/src/apis/project/personnel-organization-types.ts b/src/apis/project/personnel-organization-types.ts new file mode 100644 index 0000000..7f52b20 --- /dev/null +++ b/src/apis/project/personnel-organization-types.ts @@ -0,0 +1,486 @@ +// ==================== 人员组织管理专用类型定义 ==================== + +import type { + ProjectResp, + ConstructorResp, + CertificationResp, + WorkGroup, + WorkTypeGroup, + WorkGroupMember +} from './type' + +// ==================== 项目相关类型 ==================== + +/** + * 扩展项目类型,包含工作组信息 + */ +export interface ProjectWithWorkGroups extends ProjectResp { + workGroups?: WorkGroup[] + // 添加一些前端显示需要的字段 + statusLabel?: string // 状态标签文本 + workGroupCount?: number // 工作组数量 + totalRequiredWorkers?: number // 总需求工人数 + totalAssignedWorkers?: number // 总已分配工人数 +} + +/** + * 项目选择器查询参数 + */ +export interface ProjectSelectorQuery { + status?: number + projectName?: string + projectCode?: string + farmName?: string + hasWorkGroups?: boolean // 是否包含工作组 + page?: number + pageSize?: number +} + +// ==================== 工作组表单类型 ==================== + +/** + * 工作组创建表单 + */ +export interface WorkGroupFormData { + id?: string // 工作组ID(编辑时使用) + name: string + description: string + projectId: string + workTypeGroups: WorkTypeGroupForm[] +} + +/** + * 工种分组表单 + */ +export interface WorkTypeGroupForm { + id?: string + name: string + requiredCount: number + priority: 'HIGH' | 'MEDIUM' | 'LOW' + assignedCount?: number + workers?: ConstructorResp[] // 已分配的工人 +} + +/** + * 工作组创建请求 + */ +export interface CreateWorkGroupRequest { + name: string + description: string + projectId: string + workTypeGroups: Array<{ + name: string + requiredCount: number + priority: 'HIGH' | 'MEDIUM' | 'LOW' + }> +} + +// ==================== 工人筛选和分配类型 ==================== + +/** + * 工人筛选表单 + */ +export interface WorkerFilterForm { + workTypes: string[] + certificateKeyword: string + experienceMin?: number + experienceMax?: number + status?: string + ratingMin?: number + ratingMax?: number +} + +/** + * 工人分配数据 + */ +export interface WorkerAssignment { + workTypeName: string + workers: ConstructorResp[] + requiredCount: number + assignedCount: number +} + +/** + * 工人分配映射 + */ +export interface WorkerAssignmentMap { + [workTypeName: string]: ConstructorResp[] +} + +/** + * 拖拽分配事件数据 + */ +export interface DragAssignmentEvent { + worker: ConstructorResp + fromWorkType?: string + toWorkType: string + workGroupId: string +} + +// ==================== 证书查看类型 ==================== + +/** + * 工人证书查看数据 + */ +export interface WorkerCertificateView { + worker: ConstructorResp + certificates: CertificationResp[] +} + +/** + * 证书状态显示 + */ +export interface CertificateStatusDisplay { + status: string + color: string + text: string + icon?: string +} + +// ==================== 工作组详情类型 ==================== + +/** + * 工作组详情显示 + */ +export interface WorkGroupDetailView { + workGroup: WorkGroup + project: ProjectWithWorkGroups + memberDetails: WorkGroupMemberDetail[] + statistics: WorkGroupStatistics +} + +/** + * 工作组成员详情 + */ +export interface WorkGroupMemberDetail extends WorkGroupMember { + workTypes: string[] + certifications: CertificationResp[] + experience: number + // rating: number // 已注销 + joinDate: string + lastActiveDate?: string +} + +/** + * 工作组统计信息 + */ +export interface WorkGroupStatistics { + totalMembers: number + totalRequired: number + completionRate: number + workTypeDistribution: Array<{ + workTypeName: string + requiredCount: number + assignedCount: number + completionRate: number + }> + skillCoverage: Array<{ + skillName: string + memberCount: number + coverageRate: number + }> +} + +// ==================== 工作流步骤类型 ==================== + +/** + * 人员组织工作流步骤 + */ +export interface PersonnelWorkflowStep { + step: number + name: string + description: string + icon: string + status: 'pending' | 'in-progress' | 'completed' | 'error' + message?: string + canProceed: boolean + canGoBack: boolean +} + +/** + * 工作流状态 + */ +export interface PersonnelWorkflowStatus { + currentStep: number + steps: PersonnelWorkflowStep[] + projectId: string + lastUpdated: string +} + +// ==================== 统计和报表类型 ==================== + +/** + * 人员组织统计概览 + */ +export interface PersonnelOrganizationOverview { + totalProjects: number + activeProjects: number + totalWorkGroups: number + totalWorkers: number + assignedWorkers: number + availableWorkers: number + overallCompletionRate: number +} + +/** + * 项目人员统计 + */ +export interface ProjectPersonnelStats { + projectId: string + projectName: string + workGroupCount: number + totalRequiredWorkers: number + totalAssignedWorkers: number + completionRate: number + workTypeStats: Array<{ + workTypeName: string + requiredCount: number + assignedCount: number + shortageCount: number + priority: 'HIGH' | 'MEDIUM' | 'LOW' + }> +} + +/** + * 工人技能统计 + */ +export interface WorkerSkillStats { + skillName: string + totalWorkers: number + availableWorkers: number + assignedWorkers: number + averageExperience: number + // averageRating: number // 已注销 + certificationCount: number +} + +// ==================== 导入导出类型 ==================== + +/** + * 工人数据导入模板 + */ +export interface WorkerImportTemplate { + headers: string[] + requiredFields: string[] + optionalFields: string[] + sampleData: string[][] + validationRules: Array<{ + field: string + rule: string + message: string + }> +} + +/** + * 导入结果详情 + */ +export interface ImportResultDetail { + row: number + data: Record + status: 'success' | 'error' | 'warning' + message: string + field?: string +} + +/** + * 导入统计 + */ +export interface ImportStatistics { + totalRows: number + successRows: number + errorRows: number + warningRows: number + skippedRows: number + details: ImportResultDetail[] +} + +// ==================== 通知和提醒类型 ==================== + +/** + * 人员分配通知 + */ +export interface PersonnelAssignmentNotification { + id: string + type: 'email' | 'sms' | 'system' | 'push' + title: string + message: string + recipients: string[] + workGroupId: string + workGroupName: string + projectId: string + projectName: string + status: 'pending' | 'sent' | 'delivered' | 'failed' + sendTime?: string + deliveryTime?: string + readTime?: string +} + +/** + * 通知模板 + */ +export interface NotificationTemplate { + id: string + name: string + type: 'email' | 'sms' | 'system' + title: string + content: string + variables: string[] + isDefault: boolean +} + +// ==================== 权限和角色类型 ==================== + +/** + * 人员组织操作权限 + */ +export interface PersonnelOrganizationPermissions { + canViewProjects: boolean + canCreateWorkGroups: boolean + canEditWorkGroups: boolean + canDeleteWorkGroups: boolean + canAssignWorkers: boolean + canRemoveWorkers: boolean + canViewWorkerDetails: boolean + canExportData: boolean + canImportData: boolean + canSendNotifications: boolean +} + +/** + * 用户角色权限 + */ +export interface UserRolePermissions { + roleId: string + roleName: string + permissions: PersonnelOrganizationPermissions + projectScope: 'all' | 'assigned' | 'managed' + dataScope: 'all' | 'department' | 'project' +} + +// ==================== 搜索和查询类型 ==================== + +/** + * 高级搜索条件 + */ +export interface AdvancedSearchCriteria { + projectCriteria: { + status?: number[] + farmName?: string + startDate?: string + endDate?: string + projectManager?: string + } + workerCriteria: { + workTypes?: string[] + experienceRange?: [number, number] + // ratingRange?: [number, number] // 已注销 + certificationTypes?: string[] + status?: string[] + } + workGroupCriteria: { + status?: string[] + memberCountRange?: [number, number] + createdDateRange?: [string, string] + } +} + +/** + * 搜索结果 + */ +export interface PersonnelSearchResult { + projects: ProjectWithWorkGroups[] + workers: ConstructorResp[] + workGroups: WorkGroup[] + totalCount: number + searchTime: string + searchCriteria: AdvancedSearchCriteria +} + +// ==================== 响应和错误类型 ==================== + +/** + * API响应包装 + */ +export interface ApiResponse { + success: boolean + data?: T + message?: string + code?: string | number + timestamp: string +} + +/** + * 分页响应包装 + */ +export interface PaginatedResponse { + list: T[] + total: number + page: number + pageSize: number + totalPages: number + hasNext: boolean + hasPrev: boolean +} + +/** + * 错误响应 + */ +export interface ErrorResponse { + success: false + error: { + code: string | number + message: string + details?: any + timestamp: string + } +} + +// ==================== 工具类型 ==================== + +/** + * 状态映射配置 + */ +export interface StatusMapping { + [key: string]: T +} + +/** + * 颜色映射配置 + */ +export interface ColorMapping { + [key: string]: string +} + +/** + * 图标映射配置 + */ +export interface IconMapping { + [key: string]: string +} + +/** + * 表单验证规则 + */ +export interface ValidationRule { + required?: boolean + min?: number + max?: number + pattern?: RegExp + message?: string + validator?: (value: any) => boolean | string +} + +/** + * 表单字段配置 + */ +export interface FormFieldConfig { + name: string + label: string + type: 'input' | 'select' | 'textarea' | 'number' | 'date' | 'checkbox' | 'radio' + required?: boolean + placeholder?: string + options?: Array<{ label: string; value: any }> + validation?: ValidationRule[] + disabled?: boolean + hidden?: boolean +} diff --git a/src/apis/project/personnel-organization.ts b/src/apis/project/personnel-organization.ts index 0d07776..80d85c0 100644 --- a/src/apis/project/personnel-organization.ts +++ b/src/apis/project/personnel-organization.ts @@ -1,54 +1,300 @@ -import type * as T from './type' -import http from '@/utils/http' +import request from '@/utils/http' +import type { + ProjectWithWorkGroups, + ConstructorResp, + CertificationResp, + WorkGroup, + WorkTypeGroup, + CreateWorkGroupReq, + AssignWorkerReq, + RemoveWorkerReq, + PageRes, + PageQuery +} from './type' -const BASE_URL = '/project/personnel-organization' +// ==================== 项目相关接口 ==================== -/** @desc 获取项目列表 */ -export function getProjectList(query?: T.ProjectQuery) { - return http.get>('/project/list', query) +/** + * 获取项目列表(包含工作组信息) + */ +export function getProjectsWithWorkGroups(params?: { + status?: number + projectName?: string + projectCode?: string + farmName?: string +}) { + return request.get('/api/projects/with-work-groups', params) } -/** @desc 获取项目人员组织信息 */ -export function getPersonnelOrganization(projectId: string | number) { - return http.get(`${BASE_URL}/${projectId}`) +/** + * 获取项目详情(包含工作组信息) + */ +export function getProjectWithWorkGroups(projectId: string) { + return request.get(`/api/projects/${projectId}/with-work-groups`) } -/** @desc 获取工种列表 */ -export function getWorkTypeList() { - return http.get('/work-type/list') +// ==================== 工作组管理接口 ==================== + +/** + * 创建工作组 + */ +export function createWorkGroup(data: CreateWorkGroupReq) { + return request.post('/api/work-groups', data) } -/** @desc 获取施工人员列表 */ -export function getConstructorList(query: T.ConstructorQuery) { - return http.get>('/constructor/list', query) +/** + * 获取项目的工作组列表 + */ +export function getWorkGroupsByProject(projectId: string) { + return request.get(`/api/projects/${projectId}/work-groups`) } -/** @desc 获取施工人员技能证书 */ -export function getConstructorCertifications(constructorId: string | number) { - return http.get(`/constructor/${constructorId}/certifications`) +/** + * 更新工作组 + */ +export function updateWorkGroup(id: string, data: Partial) { + return request.put(`/api/work-groups/${id}`, data) } -/** @desc 分配施工人员到项目 */ -export function assignConstructorToProject(data: T.AssignConstructorReq) { - return http.post(`${BASE_URL}/assign`, data) +/** + * 删除工作组 + */ +export function deleteWorkGroup(id: string) { + return request.del(`/api/work-groups/${id}`) } -/** @desc 移除项目施工人员 */ -export function removeConstructorFromProject(data: T.RemoveConstructorReq) { - return http.delete(`${BASE_URL}/remove`, data) +/** + * 获取工作组详情 + */ +export function getWorkGroupDetail(id: string) { + return request.get(`/api/work-groups/${id}`) } -/** @desc 更新施工人员分配信息 */ -export function updateConstructorAssignment(data: T.UpdateAssignmentReq) { - return http.put(`${BASE_URL}/update`, data) +// ==================== 工人管理接口 ==================== + +/** + * 获取工人列表(支持筛选) + */ +export function getWorkers(params?: { + workTypes?: string[] + certificateKeyword?: string + status?: string + experienceMin?: number + experienceMax?: number + page?: number + pageSize?: number +}) { + return request.get>('/api/workers', params) } -/** @desc 获取项目人员统计 */ -export function getPersonnelStats(projectId: string | number) { - return http.get(`${BASE_URL}/${projectId}/stats`) +/** + * 获取所有工人(不分页,用于分配) + */ +export function getAllWorkers(params?: { + workTypes?: string[] + certificateKeyword?: string + status?: string + experienceMin?: number + experienceMax?: number +}) { + return request.get('/api/workers/all', params) } -/** @desc 导出项目人员组织 */ -export function exportPersonnelOrganization(projectId: string | number) { - return http.download(`${BASE_URL}/${projectId}/export`) +/** + * 获取工人详情 + */ +export function getWorkerDetail(id: string) { + return request.get(`/api/workers/${id}`) +} + +/** + * 获取工人证书列表 + */ +export function getWorkerCertifications(workerId: string) { + return request.get(`/api/workers/${workerId}/certifications`) +} + +// ==================== 工人分配接口 ==================== + +/** + * 分配工人到工作组 + */ +export function assignWorkerToGroup(data: AssignWorkerReq) { + return request.post('/api/work-groups/assign-worker', data) +} + +/** + * 从工作组移除工人 + */ +export function removeWorkerFromGroup(data: RemoveWorkerReq) { + return request.post('/api/work-groups/remove-worker', data) +} + +/** + * 批量分配工人到工作组 + */ +export function batchAssignWorkers(data: { + workGroupId: string + assignments: Array<{ + workTypeName: string + workerIds: string[] + }> +}) { + return request.post('/api/work-groups/batch-assign', data) +} + +/** + * 获取工作组的工人分配情况 + */ +export function getWorkGroupAssignments(workGroupId: string) { + return request.get<{ + workTypeName: string + workers: ConstructorResp[] + requiredCount: number + assignedCount: number + }[]>(`/api/work-groups/${workGroupId}/assignments`) +} + +// ==================== 统计和查询接口 ==================== + +/** + * 获取项目人员组织统计 + */ +export function getProjectPersonnelStats(projectId: string) { + return request.get<{ + totalWorkers: number + assignedWorkers: number + availableWorkers: number + workTypeStats: Array<{ + workTypeName: string + requiredCount: number + assignedCount: number + shortageCount: number + }> + }>(`/api/projects/${projectId}/personnel-stats`) +} + +/** + * 获取工种统计信息 + */ +export function getWorkTypeStats() { + return request.get>('/api/work-types/stats') +} + +/** + * 搜索工人(支持姓名、工种、证书等关键词搜索) + */ +export function searchWorkers(keyword: string, params?: { + workTypes?: string[] + status?: string + limit?: number +}) { + return request.get('/api/workers/search', { + keyword, + ...params + }) +} + +// ==================== 导入导出接口 ==================== + +/** + * 导出项目人员组织数据 + */ +export function exportProjectPersonnel(projectId: string, format: 'excel' | 'pdf' = 'excel') { + return request.get(`/api/projects/${projectId}/personnel-export`, { + format + }, { + responseType: 'blob' + }) +} + +/** + * 导入工人数据 + */ +export function importWorkers(file: File, projectId?: string) { + const formData = new FormData() + formData.append('file', file) + if (projectId) { + formData.append('projectId', projectId) + } + + return request.post<{ + success: boolean + totalCount: number + successCount: number + failCount: number + errors?: Array<{ + row: number + message: string + }> + }>('/api/workers/import', formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +// ==================== 工作流相关接口 ==================== + +/** + * 获取人员组织工作流状态 + */ +export function getPersonnelWorkflowStatus(projectId: string) { + return request.get<{ + currentStep: number + steps: Array<{ + step: number + name: string + status: 'pending' | 'in-progress' | 'completed' | 'error' + message?: string + }> + }>(`/api/projects/${projectId}/personnel-workflow`) +} + +/** + * 更新工作流步骤状态 + */ +export function updateWorkflowStep(projectId: string, step: number, status: string, message?: string) { + return request.patch(`/api/projects/${projectId}/personnel-workflow/step`, { + step, + status, + message + }) +} + +// ==================== 通知和提醒接口 ==================== + +/** + * 发送人员分配通知 + */ +export function sendAssignmentNotification(data: { + workGroupId: string + workerIds: string[] + message: string + type: 'email' | 'sms' | 'system' +}) { + return request.post('/api/notifications/assignment', data) +} + +/** + * 获取人员分配通知历史 + */ +export function getAssignmentNotifications(workGroupId?: string, params?: PageQuery) { + return request.get>('/api/notifications/assignment', { + workGroupId, + ...params + }) }