diff --git a/src/apis/project/personnel-organization.ts b/src/apis/project/personnel-organization.ts new file mode 100644 index 0000000..0d07776 --- /dev/null +++ b/src/apis/project/personnel-organization.ts @@ -0,0 +1,54 @@ +import type * as T from './type' +import http from '@/utils/http' + +const BASE_URL = '/project/personnel-organization' + +/** @desc 获取项目列表 */ +export function getProjectList(query?: T.ProjectQuery) { + return http.get>('/project/list', query) +} + +/** @desc 获取项目人员组织信息 */ +export function getPersonnelOrganization(projectId: string | number) { + return http.get(`${BASE_URL}/${projectId}`) +} + +/** @desc 获取工种列表 */ +export function getWorkTypeList() { + return http.get('/work-type/list') +} + +/** @desc 获取施工人员列表 */ +export function getConstructorList(query: T.ConstructorQuery) { + return http.get>('/constructor/list', query) +} + +/** @desc 获取施工人员技能证书 */ +export function getConstructorCertifications(constructorId: string | number) { + return http.get(`/constructor/${constructorId}/certifications`) +} + +/** @desc 分配施工人员到项目 */ +export function assignConstructorToProject(data: T.AssignConstructorReq) { + return http.post(`${BASE_URL}/assign`, data) +} + +/** @desc 移除项目施工人员 */ +export function removeConstructorFromProject(data: T.RemoveConstructorReq) { + return http.delete(`${BASE_URL}/remove`, data) +} + +/** @desc 更新施工人员分配信息 */ +export function updateConstructorAssignment(data: T.UpdateAssignmentReq) { + return http.put(`${BASE_URL}/update`, data) +} + +/** @desc 获取项目人员统计 */ +export function getPersonnelStats(projectId: string | number) { + return http.get(`${BASE_URL}/${projectId}/stats`) +} + +/** @desc 导出项目人员组织 */ +export function exportPersonnelOrganization(projectId: string | number) { + return http.download(`${BASE_URL}/${projectId}/export`) +} diff --git a/src/apis/project/type.ts b/src/apis/project/type.ts index 5d5f527..7840bcc 100644 --- a/src/apis/project/type.ts +++ b/src/apis/project/type.ts @@ -117,6 +117,86 @@ export interface ProjectKanbanStats { teamLeaderCount: string } +// ==================== 工作组相关类型 ==================== + +/** 工作组类型 */ +export interface WorkGroup { + id: string + name: string + description: string + projectId: string + status: 'ACTIVE' | 'INACTIVE' | 'COMPLETED' + workTypeGroups: WorkTypeGroup[] + memberCount: number + requiredCount: number + members?: WorkGroupMember[] + createTime: string + updateTime?: string +} + +/** 工种分组类型 */ +export interface WorkTypeGroup { + id?: string + name: string + requiredCount: number + priority: 'HIGH' | 'MEDIUM' | 'LOW' + assignedCount?: number +} + +/** 工作组成员类型 */ +export interface WorkGroupMember { + id: string + name: string + role: string + avatar?: string + phone?: string + email?: string + workTypes?: string[] + joinTime?: string +} + +/** 工作组查询参数 */ +export interface WorkGroupQuery { + projectId?: string + name?: string + status?: string + workType?: string +} + +/** 工作组分页查询参数 */ +export interface WorkGroupPageQuery extends WorkGroupQuery, PageQuery {} + +/** 创建工作组请求参数 */ +export interface CreateWorkGroupReq { + name: string + description?: string + projectId: string + workTypeGroups: WorkTypeGroup[] +} + +/** 更新工作组请求参数 */ +export interface UpdateWorkGroupReq { + id: string + name?: string + description?: string + status?: string + workTypeGroups?: WorkTypeGroup[] +} + +/** 分配工人到工作组请求参数 */ +export interface AssignWorkerReq { + workGroupId: string + workerIds: string[] + workTypeName: string +} + +/** 从工作组移除工人请求参数 */ +export interface RemoveWorkerReq { + workGroupId: string + workerId: string + workTypeName: string +} + /** 项目看板数据 */ export interface ProjectKanbanData { inProgressProjects: ProjectCard[] @@ -327,7 +407,137 @@ export interface UpdateRequirementStatusForm { status: 'pending' | 'recruiting' | 'completed' } +// ==================== 人员组织相关类型 ==================== +/** 工种响应 */ +export interface WorkTypeResp { + id: string | number + name: string + code: string + description?: string + requiredCertifications?: string[] + sort?: number +} + +/** 施工人员响应 */ +export interface ConstructorResp { + id: string | number + name: string + phone: string + email?: string + avatar?: string + workTypes: string[] // 工种列表 + certifications: CertificationResp[] + experience: number // 工作经验(年) + status: 'ACTIVE' | 'INACTIVE' | 'BUSY' + rating: number // 评分 + joinDate: string + remark?: string +} + +/** 证书响应 */ +export interface CertificationResp { + id: string | number + name: string + type: string + code: string + issueDate: string + expiryDate: string + issuingAuthority: string + status: 'VALID' | 'EXPIRED' | 'EXPIRING_SOON' + imageUrl?: string +} + +/** 施工人员查询参数 */ +export interface ConstructorQuery extends PageQuery { + name?: string + workType?: string + status?: string + hasCertification?: boolean + experienceMin?: number + experienceMax?: number +} + +/** 人员组织响应 */ +export interface PersonnelOrganizationResp { + projectId: string | number + projectName: string + workTypeAssignments: WorkTypeAssignmentResp[] + totalPersonnel: number + assignedPersonnel: number + availablePersonnel: number +} + +/** 工种分配响应 */ +export interface WorkTypeAssignmentResp { + workTypeId: string | number + workTypeName: string + workTypeCode: string + requiredCount: number + assignedCount: number + constructors: ConstructorAssignmentResp[] +} + +/** 施工人员分配响应 */ +export interface ConstructorAssignmentResp { + constructorId: string | number + constructorName: string + phone: string + avatar?: string + workTypes: string[] + certifications: CertificationResp[] + experience: number + rating: number + assignmentDate: string + status: 'ASSIGNED' | 'WORKING' | 'COMPLETED' + remark?: string +} + +/** 分配施工人员请求 */ +export interface AssignConstructorReq { + projectId: string | number + workTypeId: string | number + constructorIds: (string | number)[] + assignmentDate?: string + remark?: string +} + +/** 移除施工人员请求 */ +export interface RemoveConstructorReq { + projectId: string | number + constructorIds: (string | number)[] + reason?: string +} + +/** 更新分配信息请求 */ +export interface UpdateAssignmentReq { + projectId: string | number + constructorId: string | number + workTypeId?: string | number + status?: string + remark?: string +} + +/** 人员统计响应 */ +export interface PersonnelStatsResp { + totalPersonnel: number + assignedPersonnel: number + availablePersonnel: number + workTypeStats: { + workTypeName: string + requiredCount: number + assignedCount: number + shortageCount: number + }[] + certificationStats: { + certificationType: string + count: number + }[] + experienceStats: { + range: string + count: number + }[] +} /** 分页查询基础参数 */ export interface PageQuery { @@ -341,4 +551,89 @@ export interface PageRes { total: number page: number pageSize: number +} + +// ==================== 工作组相关类型 ==================== + +/** 工作组类型 */ +export interface WorkGroup { + id: string + name: string + description: string + projectId: string + status: 'ACTIVE' | 'INACTIVE' | 'COMPLETED' + workTypeGroups: WorkTypeGroup[] + memberCount: number + requiredCount: number + members?: WorkGroupMember[] + createTime: string + updateTime?: string +} + +/** 工种分组类型 */ +export interface WorkTypeGroup { + id?: string + name: string + requiredCount: number + priority: 'HIGH' | 'MEDIUM' | 'LOW' + assignedCount?: number +} + +/** 工作组成员类型 */ +export interface WorkGroupMember { + id: string + name: string + role: string + avatar?: string + phone?: string + email?: string + workTypes?: string[] + joinTime?: string +} + +/** 工作组查询参数 */ +export interface WorkGroupQuery { + projectId?: string + name?: string + status?: string + workType?: string +} + +/** 工作组分页查询参数 */ +export interface WorkGroupPageQuery extends WorkGroupQuery, PageQuery {} + +/** 创建工作组请求参数 */ +export interface CreateWorkGroupReq { + name: string + description?: string + projectId: string + workTypeGroups: WorkTypeGroup[] +} + +/** 更新工作组请求参数 */ +export interface UpdateWorkGroupReq { + id: string + name?: string + description?: string + status?: string + workTypeGroups?: WorkTypeGroup[] +} + +/** 分配工人到工作组请求参数 */ +export interface AssignWorkerReq { + workGroupId: string + workerIds: string[] + workTypeName: string +} + +/** 从工作组移除工人请求参数 */ +export interface RemoveWorkerReq { + workGroupId: string + workerId: string + workTypeName: string +} + +// 扩展项目类型,包含工作组信息 +export interface ProjectWithWorkGroups extends ProjectResp { + workGroups?: WorkGroup[] } \ No newline at end of file diff --git a/src/apis/project/workGroup.ts b/src/apis/project/workGroup.ts new file mode 100644 index 0000000..3a6985f --- /dev/null +++ b/src/apis/project/workGroup.ts @@ -0,0 +1,81 @@ +import request from '@/utils/http' +import type { + WorkGroup, + WorkTypeGroup, + WorkGroupPageQuery, + CreateWorkGroupReq, + UpdateWorkGroupReq, + AssignWorkerReq, + RemoveWorkerReq, + PageRes +} from './type' + +/** + * 获取工作组列表 + */ +export function getWorkGroupList(params: WorkGroupPageQuery) { + return request.get>('/api/work-groups', params) +} + +/** + * 根据项目ID获取工作组列表 + */ +export function getWorkGroupsByProject(projectId: string) { + return request.get(`/api/projects/${projectId}/work-groups`) +} + +/** + * 获取工作组详情 + */ +export function getWorkGroupDetail(id: string) { + return request.get(`/api/work-groups/${id}`) +} + +/** + * 创建工作组 + */ +export function createWorkGroup(data: CreateWorkGroupReq) { + return request.post('/api/work-groups', data) +} + +/** + * 更新工作组 + */ +export function updateWorkGroup(id: string, data: UpdateWorkGroupReq) { + return request.put(`/api/work-groups/${id}`, data) +} + +/** + * 删除工作组 + */ +export function deleteWorkGroup(id: string) { + return request.del(`/api/work-groups/${id}`) +} + +/** + * 分配工人到工作组 + */ +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 updateWorkGroupStatus(id: string, status: string) { + return request.patch(`/api/work-groups/${id}/status`, { status }) +} + +/** + * 获取工作组统计信息 + */ +export function getWorkGroupStats(projectId?: string) { + return request.get('/api/work-groups/stats', { projectId }) +} diff --git a/src/apis/system/user.ts b/src/apis/system/user.ts index 59257e1..479f7f4 100644 --- a/src/apis/system/user.ts +++ b/src/apis/system/user.ts @@ -63,3 +63,8 @@ export function resetUserPwd(data: any, id: string) { export function updateUserRole(data: { roleIds: string[] }, id: string) { return http.patch(`${BASE_URL}/${id}/role`, data) } + +/** @desc 按姓名模糊搜索用户 */ +export function searchUserByName(name: string) { + return http.get(`${BASE_URL}/searchByName`, { name }) +} diff --git a/src/router/route.ts b/src/router/route.ts index 2ced11f..df04f61 100644 --- a/src/router/route.ts +++ b/src/router/route.ts @@ -816,7 +816,17 @@ export const systemRoutes: RouteRecordRaw[] = [ hidden: false, }, }, - + { + path: '/project-management/projects/personnel-organization', + name: 'PersonnelOrganization', + component: () => import('@/views/project-management/projects/personnel-organization/index.vue'), + meta: { + title: '人员组织', + icon: 'user-group', + hidden: false, + }, + }, + { path: '/project-management/projects/device', name: 'DeviceManagement', diff --git a/src/views/project-management/personnel-dispatch/construction-personnel.vue b/src/views/project-management/personnel-dispatch/construction-personnel.vue index c25741e..ef46a07 100644 --- a/src/views/project-management/personnel-dispatch/construction-personnel.vue +++ b/src/views/project-management/personnel-dispatch/construction-personnel.vue @@ -180,7 +180,17 @@
- +
@@ -304,7 +314,7 @@ \ No newline at end of file diff --git a/src/views/project-management/personnel-dispatch/index.vue b/src/views/project-management/personnel-dispatch/index.vue index 2451c01..a0bcbd8 100644 --- a/src/views/project-management/personnel-dispatch/index.vue +++ b/src/views/project-management/personnel-dispatch/index.vue @@ -79,7 +79,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -215,7 +215,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -351,7 +351,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -487,7 +487,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -623,7 +623,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -759,7 +759,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -895,7 +895,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -1031,7 +1031,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -1180,10 +1180,10 @@ 负责人: {{ project.manager || '未指定' }}
-
- - 团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }} -
+
+ + 团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }} +
项目进度 @@ -1327,7 +1327,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -1474,7 +1474,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -1621,7 +1621,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -1915,7 +1915,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -2062,7 +2062,7 @@ 负责人: {{ project.manager || '未指定' }}
-
+
团队: {{ project.teamSize > 0 ? project.teamSize + '人' : '未设置' }}
@@ -3041,11 +3041,11 @@ const openSiteManagement = (project: any) => { } // 人员管理 -const openPersonnelManagement = () => { - if (currentProject.value && currentProject.value.id) { +const openPersonnelManagement = (project: any) => { + if (project && project.id) { router.push({ path: '/project-management/personnel-dispatch/construction-personnel', - query: { projectId: currentProject.value.id } + query: { projectId: project.id } }) } else { Message.error('项目信息不完整,无法进入团队成员管理') diff --git a/src/views/project-management/projects/personnel-organization/index.vue b/src/views/project-management/projects/personnel-organization/index.vue new file mode 100644 index 0000000..6a42055 --- /dev/null +++ b/src/views/project-management/projects/personnel-organization/index.vue @@ -0,0 +1,1871 @@ + + + + + diff --git a/src/views/project-management/projects/progress/index.vue b/src/views/project-management/projects/progress/index.vue index 812e92c..153b22b 100644 --- a/src/views/project-management/projects/progress/index.vue +++ b/src/views/project-management/projects/progress/index.vue @@ -1,476 +1,1448 @@ - - \ No newline at end of file +