diff --git a/core/src/main/java/com/dite/znpt/domain/entity/PostEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/PostEntity.java index 4d93834..6bb6771 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/PostEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/PostEntity.java @@ -32,6 +32,10 @@ public class PostEntity extends AuditableEntity implements Serializable { @TableId(value = "post_id", type = IdType.ASSIGN_UUID) private String postId; + @ApiModelProperty("部门id") + @TableField("dept_id") + private String deptId; + @ApiModelProperty("岗位名称") @TableField("post_name") private String postName; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/PostListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/PostListReq.java new file mode 100644 index 0000000..8425a4e --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/PostListReq.java @@ -0,0 +1,29 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author Bear.G + * @date 2025/8/6/周三 14:37 + * @description + */ +@Data +@ApiModel("项目预算信息列表请求实体") +public class PostListReq implements Serializable { + @Serial + private static final long serialVersionUID = -3911963210474319099L; + + @ApiModelProperty("岗位名称") + private String postName; + + @ApiModelProperty("部门id") + private String deptId; + + @ApiModelProperty("是否包含部门子节点") + private Boolean includeDeptChildren; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/PostReq.java b/core/src/main/java/com/dite/znpt/domain/vo/PostReq.java index c752cb8..624615f 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/PostReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/PostReq.java @@ -22,6 +22,10 @@ public class PostReq implements Serializable { @Serial private static final long serialVersionUID = -149328762675637911L; + @ApiModelProperty("部门id") + @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "部门id不能为空") + private String deptId; + @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "岗位名称不能为空") @Size(max = 30, groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "岗位名称长度不能超过30个字符") @ApiModelProperty("岗位名称") diff --git a/core/src/main/java/com/dite/znpt/domain/vo/PostResp.java b/core/src/main/java/com/dite/znpt/domain/vo/PostResp.java index 3012937..0e08189 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/PostResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/PostResp.java @@ -24,6 +24,12 @@ public class PostResp implements Serializable { @ApiModelProperty("岗位id") private String postId; + @ApiModelProperty("部门id") + private String deptId; + + @ApiModelProperty("部门名称") + private String deptName; + @ApiModelProperty("岗位名称") private String postName; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectDetailResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectDetailResp.java index 2266301..d92ce3a 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectDetailResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectDetailResp.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @@ -70,12 +71,31 @@ public class ProjectDetailResp { @ApiModelProperty("结束时间") private LocalDate endDate; + @ApiModelProperty("计划开始时间") + private LocalDate plannedStartDate; + @ApiModelProperty("创建时间") private String createTime; @ApiModelProperty("更新时间") private String updateTime; + // 新增字段 - 对应前端ProjectCard接口 + @ApiModelProperty("项目预算(万元)") + private BigDecimal budget; + + @ApiModelProperty("项目经理") + private String manager; + + @ApiModelProperty("团队规模") + private Integer teamSize; + + @ApiModelProperty("准备进度百分比") + private Integer preparationProgress; + + @ApiModelProperty("项目进度百分比") + private Integer progress; + // 项目人员信息(从新关联表获取) @ApiModelProperty("项目人员列表") private List projectMembers; @@ -152,9 +172,6 @@ public class ProjectDetailResp { @ApiModelProperty("预算名称") private String budgetName; - @ApiModelProperty("预算类型") - private String budgetType; - @ApiModelProperty("预算金额(万元)") private Double budgetAmount; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java index f80c696..2e7e598 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @@ -71,6 +72,9 @@ public class ProjectKanbanDataResp { @ApiModelProperty("结束时间") private LocalDate endDate; + @ApiModelProperty("计划开始时间") + private LocalDate plannedStartDate; + @ApiModelProperty("项目经理") private String projectManagerName; @@ -103,5 +107,67 @@ public class ProjectKanbanDataResp { @ApiModelProperty("更新时间") private String updateTime; + + // 新增字段 - 对应前端ProjectCard接口 + @ApiModelProperty("项目预算(万元)") + private BigDecimal budget; + + @ApiModelProperty("项目经理") + private String manager; + + @ApiModelProperty("团队规模") + private Integer teamSize; + + @ApiModelProperty("准备进度百分比") + private Integer preparationProgress; + + @ApiModelProperty("项目进度百分比") + private Integer progress; + + @ApiModelProperty("团队成员列表") + private List teamMembers; + + @Data + @ApiModel(value="TeamMemberResp对象", description="团队成员响应") + public static class TeamMemberResp { + @ApiModelProperty("成员ID") + private String memberId; + + @ApiModelProperty("用户ID") + private String userId; + + @ApiModelProperty("用户姓名") + private String userName; + + @ApiModelProperty("用户账号") + private String userAccount; + + @ApiModelProperty("用户头像") + private String userAvatar; + + @ApiModelProperty("角色类型") + private String roleType; + + @ApiModelProperty("角色类型描述") + private String roleTypeDesc; + + @ApiModelProperty("岗位代码") + private String jobCode; + + @ApiModelProperty("岗位代码描述") + private String jobCodeDesc; + + @ApiModelProperty("岗位描述") + private String jobDesc; + + @ApiModelProperty("加入时间") + private LocalDate joinDate; + + @ApiModelProperty("离开时间") + private LocalDate leaveDate; + + @ApiModelProperty("状态") + private String status; + } } } \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/mapper/PostMapper.java b/core/src/main/java/com/dite/znpt/mapper/PostMapper.java index b98dc56..4737b42 100644 --- a/core/src/main/java/com/dite/znpt/mapper/PostMapper.java +++ b/core/src/main/java/com/dite/znpt/mapper/PostMapper.java @@ -2,6 +2,10 @@ package com.dite.znpt.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dite.znpt.domain.entity.PostEntity; +import com.dite.znpt.domain.vo.PostListReq; +import com.dite.znpt.domain.vo.PostResp; + +import java.util.List; /** * @author Bear.G @@ -9,4 +13,6 @@ import com.dite.znpt.domain.entity.PostEntity; * @description */ public interface PostMapper extends BaseMapper { + + List selectPostResp(PostListReq req); } diff --git a/core/src/main/java/com/dite/znpt/service/PostService.java b/core/src/main/java/com/dite/znpt/service/PostService.java index 3a27134..ef9e246 100644 --- a/core/src/main/java/com/dite/znpt/service/PostService.java +++ b/core/src/main/java/com/dite/znpt/service/PostService.java @@ -2,6 +2,7 @@ package com.dite.znpt.service; import com.baomidou.mybatisplus.extension.service.IService; import com.dite.znpt.domain.entity.PostEntity; +import com.dite.znpt.domain.vo.PostListReq; import com.dite.znpt.domain.vo.PostReq; import com.dite.znpt.domain.vo.PostResp; @@ -14,9 +15,9 @@ import java.util.List; */ public interface PostService extends IService { - List page(String postName); + List page(PostListReq req); - List list(String postName); + List list(PostListReq req); PostResp detail(String postId); diff --git a/core/src/main/java/com/dite/znpt/service/impl/PostServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/PostServiceImpl.java index b735355..468fdaf 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/PostServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/PostServiceImpl.java @@ -5,16 +5,20 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dite.znpt.constant.Message; import com.dite.znpt.converts.Converts; +import com.dite.znpt.domain.entity.DeptEntity; import com.dite.znpt.domain.entity.PostEntity; +import com.dite.znpt.domain.vo.PostListReq; import com.dite.znpt.domain.vo.PostReq; import com.dite.znpt.domain.vo.PostResp; import com.dite.znpt.exception.ServiceException; +import com.dite.znpt.mapper.DeptMapper; import com.dite.znpt.mapper.PostMapper; import com.dite.znpt.service.PostService; import com.dite.znpt.util.PageUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; import java.util.List; /** @@ -25,15 +29,18 @@ import java.util.List; @Service public class PostServiceImpl extends ServiceImpl implements PostService { + @Resource + private DeptMapper deptMapper; + @Override - public List page(String postName) { + public List page(PostListReq req) { PageUtil.startPage(); - return this.list(postName); + return this.list(req); } @Override - public List list(String postName) { - return Converts.INSTANCE.toPostResp(this.list(Wrappers.lambdaQuery(PostEntity.class).like(StrUtil.isNotBlank(postName), PostEntity::getPostName, postName))); + public List list(PostListReq req) { + return this.baseMapper.selectPostResp(req); } @Override diff --git a/core/src/main/java/com/dite/znpt/service/impl/ProjectMemberServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ProjectMemberServiceImpl.java index 8c51d1d..9ee100e 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/ProjectMemberServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/ProjectMemberServiceImpl.java @@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -293,7 +294,51 @@ public class ProjectMemberServiceImpl extends ServiceImpl projectMembers = selectByProjectId(projectId); + resp.setProjectMembers(projectMembers); + + // 计算团队规模 + resp.setTeamSize(projectMembers.size()); + + // 获取项目经理信息 + String managerName = projectMembers.stream() + .filter(member -> "PROJECT_MANAGER".equals(member.getRoleType())) + .map(ProjectMemberResp::getUserName) + .findFirst() + .orElse(""); + resp.setManager(managerName); + + // 计算项目预算(从预算信息中汇总) + List budgets = projectBudgetInfoService.lambdaQuery() + .eq(ProjectBudgetInfoEntity::getProjectId, projectId) + .list(); + BigDecimal totalBudget = budgets.stream() + .map(budget -> BigDecimal.valueOf(budget.getBudgetAmount())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + resp.setBudget(totalBudget); + + // 计算项目进度 + List tasks = projectTaskService.lambdaQuery() + .eq(ProjectTaskEntity::getProjectId, projectId) + .list(); + if (!tasks.isEmpty()) { + long completedTasks = tasks.stream() + .filter(task -> task.getStatus() != null && task.getStatus() == 2) + .count(); + resp.setProgress((int) (completedTasks * 100 / tasks.size())); + } else { + resp.setProgress(0); + } + + // 计算准备进度(基于任务状态) + if (!tasks.isEmpty()) { + long preparedTasks = tasks.stream() + .filter(task -> task.getStatus() != null && task.getStatus() >= 1) + .count(); + resp.setPreparationProgress((int) (preparedTasks * 100 / tasks.size())); + } else { + resp.setPreparationProgress(0); + } // 获取项目机组信息 List turbines = turbineService.lambdaQuery() @@ -307,9 +352,6 @@ public class ProjectMemberServiceImpl extends ServiceImpl tasks = projectTaskService.lambdaQuery() - .eq(ProjectTaskEntity::getProjectId, projectId) - .list(); resp.setTasks(tasks.stream().map(task -> { ProjectDetailResp.TaskInfo info = new ProjectDetailResp.TaskInfo(); BeanUtil.copyProperties(task, info); @@ -318,9 +360,6 @@ public class ProjectMemberServiceImpl extends ServiceImpl budgets = projectBudgetInfoService.lambdaQuery() - .eq(ProjectBudgetInfoEntity::getProjectId, projectId) - .list(); resp.setBudgets(budgets.stream().map(budget -> { ProjectDetailResp.BudgetInfo info = new ProjectDetailResp.BudgetInfo(); BeanUtil.copyProperties(budget, info); @@ -381,6 +420,22 @@ public class ProjectMemberServiceImpl extends ServiceImpl teamMembers = members.stream() + .map(member -> { + ProjectKanbanDataResp.ProjectKanbanItem.TeamMemberResp teamMember = new ProjectKanbanDataResp.ProjectKanbanItem.TeamMemberResp(); + BeanUtil.copyProperties(member, teamMember); + return teamMember; + }) + .collect(Collectors.toList()); + item.setTeamMembers(teamMembers); + // 统计机组数量 Long turbineCount = turbineService.lambdaQuery() .eq(TurbineEntity::getProjectId, project.getProjectId()) @@ -403,10 +458,32 @@ public class ProjectMemberServiceImpl extends ServiceImpl 0) { item.setProgressPercentage((int) (completedTaskCount * 100 / taskCount)); + item.setProgress((int) (completedTaskCount * 100 / taskCount)); } else { item.setProgressPercentage(0); + item.setProgress(0); } + // 计算准备进度(基于任务状态) + if (taskCount > 0) { + Long preparedTasks = projectTaskService.lambdaQuery() + .eq(ProjectTaskEntity::getProjectId, project.getProjectId()) + .ge(ProjectTaskEntity::getStatus, 1) + .count(); + item.setPreparationProgress((int) (preparedTasks * 100 / taskCount)); + } else { + item.setPreparationProgress(0); + } + + // 计算项目预算(从预算信息中汇总) + List budgets = projectBudgetInfoService.lambdaQuery() + .eq(ProjectBudgetInfoEntity::getProjectId, project.getProjectId()) + .list(); + BigDecimal totalBudget = budgets.stream() + .map(budget -> BigDecimal.valueOf(budget.getBudgetAmount())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + item.setBudget(totalBudget); + return item; }).collect(Collectors.toList()); } diff --git a/core/src/main/resources/mapper/PostMapper.xml b/core/src/main/resources/mapper/PostMapper.xml index c770671..a9ec082 100644 --- a/core/src/main/resources/mapper/PostMapper.xml +++ b/core/src/main/resources/mapper/PostMapper.xml @@ -2,4 +2,30 @@ + \ No newline at end of file diff --git a/web/src/main/java/com/dite/znpt/web/controller/ProjectMemberController.java b/web/src/main/java/com/dite/znpt/web/controller/ProjectMemberController.java index 85d786a..ae95fb8 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/ProjectMemberController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/ProjectMemberController.java @@ -24,6 +24,7 @@ import java.util.List; * @date 2025/08/05 * @Description: 项目人员管理Controller */ + @Api(tags = "项目人员管理") @RestController @RequestMapping("/project-member") diff --git a/web/src/main/resources/application-dev.yml b/web/src/main/resources/application-dev.yml index 748a800..678614a 100644 --- a/web/src/main/resources/application-dev.yml +++ b/web/src/main/resources/application-dev.yml @@ -30,7 +30,7 @@ spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://39.99.201.243:3306/test01?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + url: jdbc:mysql://39.99.201.243:3306/znpt_dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: BUw8YW6%@^8q druid: