diff --git a/core/pom.xml b/core/pom.xml index 6e16813..8d32f0d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -197,12 +197,11 @@ jaxb-api 2.3.1 - - + + - commons-io - commons-io - 2.11.0 + org.springframework.boot + spring-boot-starter-websocket diff --git a/core/src/main/java/com/dite/znpt/config/WebSocketConfig.java b/core/src/main/java/com/dite/znpt/config/WebSocketConfig.java new file mode 100644 index 0000000..8635b51 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/config/WebSocketConfig.java @@ -0,0 +1,27 @@ +package com.dite.znpt.config; + +import com.dite.znpt.websocket.SimpleWebSocketHandler; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +/** + * WebSocket配置 + */ +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + + private final SimpleWebSocketHandler simpleWebSocketHandler; + + public WebSocketConfig(SimpleWebSocketHandler simpleWebSocketHandler) { + this.simpleWebSocketHandler = simpleWebSocketHandler; + } + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(simpleWebSocketHandler, "/websocket") + .setAllowedOrigins("*"); // 在生产环境中应该限制允许的源 + } +} diff --git a/core/src/main/java/com/dite/znpt/domain/entity/EquipmentEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/EquipmentEntity.java index 4224af2..642ee6e 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/EquipmentEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/EquipmentEntity.java @@ -177,6 +177,9 @@ public class EquipmentEntity extends AuditableEntity implements Serializable { @ApiModelProperty("发票状态") private String invoiceStatus; + @ApiModelProperty("采购状态,NOT_STARTED-未开始,PENDING_APPROVAL-待审批,APPROVED-已通过,REJECTED-已拒绝,COMPLETED-已完成") + private String procurementStatus; + @ApiModelProperty("附件") private String attachments; @@ -214,4 +217,7 @@ public class EquipmentEntity extends AuditableEntity implements Serializable { @ApiModelProperty("删除标志(0代表存在 1代表删除)") @TableLogic(value = "0", delval = "1") private String delFlag; -} + + @ApiModelProperty("项目id") + private String projectId; +} \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentProcurementApplyReq.java b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentProcurementApplyReq.java new file mode 100644 index 0000000..769d2e2 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentProcurementApplyReq.java @@ -0,0 +1,70 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * @author Bear.G + * @date 2025/1/8/周三 18:00 + * @description 设备采购申请请求VO + */ +@Data +@ApiModel(value = "EquipmentProcurementApplyReq", description = "设备采购申请请求") +public class EquipmentProcurementApplyReq { + + @ApiModelProperty("设备ID") + @NotBlank(message = "设备ID不能为空") + private String equipmentId; + + @ApiModelProperty("设备名称") + @NotBlank(message = "设备名称不能为空") + private String equipmentName; + + @ApiModelProperty("设备类型") + @NotBlank(message = "设备类型不能为空") + private String equipmentType; + + @ApiModelProperty("设备型号") + private String equipmentModel; + + @ApiModelProperty("品牌") + private String brand; + + @ApiModelProperty("供应商名称") + private String supplierName; + + @ApiModelProperty("预算金额") + @NotNull(message = "预算金额不能为空") + private BigDecimal budgetAmount; + + @ApiModelProperty("数量") + @NotNull(message = "数量不能为空") + private Integer quantity; + + @ApiModelProperty("紧急程度:LOW-低,NORMAL-普通,HIGH-高,URGENT-紧急") + @NotBlank(message = "紧急程度不能为空") + private String urgencyLevel; + + @ApiModelProperty("申请原因") + @NotBlank(message = "申请原因不能为空") + private String applyReason; + + @ApiModelProperty("技术要求") + private String technicalRequirements; + + @ApiModelProperty("业务合理性说明") + private String businessJustification; + + @ApiModelProperty("预期交付日期") + private LocalDate expectedDeliveryDate; + + @ApiModelProperty("采购类型:NEW_PURCHASE-新采购,REPLACEMENT-更换,UPGRADE-升级") + @NotBlank(message = "采购类型不能为空") + private String procurementType; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java index d936b01..04642f2 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java @@ -154,6 +154,9 @@ public class EquipmentResp implements Serializable { @ApiModelProperty("总价") private BigDecimal totalPrice; + @ApiModelProperty("采购状态,NOT_STARTED-未开始,PENDING_APPROVAL-待审批,APPROVED-已通过,REJECTED-已拒绝,COMPLETED-已完成") + private String procurementStatus; + // 移除备用状态字段,使用现有的 location_status 字段 // @ApiModelProperty("备用状态") // private String spareStatus; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectInitTaskReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectInitTaskReq.java new file mode 100644 index 0000000..e1ef86f --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectInitTaskReq.java @@ -0,0 +1,41 @@ +package com.dite.znpt.domain.vo; + +import com.dite.znpt.util.ValidationGroup; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.time.LocalDate; + +@Data +@ApiModel("项目初始化任务请求参数") +public class ProjectInitTaskReq { + @ApiModelProperty("任务名称") + private String taskName; + + @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目任务编号不能为空") + @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 100, message = "项目任务编号长度不能超过100字符") + @ApiModelProperty("项目任务编号") + private String taskCode; + + @NotNull(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "计划开始时间不能为空") + @ApiModelProperty("计划开始时间") + private LocalDate planStartDate; + + @NotNull(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "计划结束时间不能为空") + @ApiModelProperty("计划结束时间") + private LocalDate planEndDate; + + @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "任务组id不能为空") + @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 32, message = "任务组id长度不能超过32字符") + @ApiModelProperty("任务组id") + private String taskGroupId; + + @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "任务负责人id不能为空") + @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 100, message = "任务负责人id长度不能超过100字符") + @ApiModelProperty("任务负责人id") + private String mainUserId; +} 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 2e7e598..ed1748d 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 @@ -17,20 +17,29 @@ import java.util.List; @ApiModel(value="ProjectKanbanDataResp对象", description="项目看板数据响应") public class ProjectKanbanDataResp { - @ApiModelProperty("待施工项目列表") + @ApiModelProperty("未开工项目列表") private List pendingProjects; - @ApiModelProperty("施工中项目列表") + @ApiModelProperty("筹备中项目列表") + private List preparingProjects; + + @ApiModelProperty("开工中项目列表") private List inProgressProjects; + @ApiModelProperty("暂停中项目列表") + private List suspendedProjects; + @ApiModelProperty("已完工项目列表") private List completedProjects; - @ApiModelProperty("已审核项目列表") - private List auditedProjects; + @ApiModelProperty("验收中项目列表") + private List acceptanceProjects; - @ApiModelProperty("已验收项目列表") - private List acceptedProjects; + @ApiModelProperty("回款中项目列表") + private List collectionProjects; + + @ApiModelProperty("已结算项目列表") + private List settledProjects; @Data @ApiModel(value="ProjectKanbanItem对象", description="项目看板项目项") diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java index fe2f6f0..d15296a 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java @@ -19,17 +19,26 @@ public class ProjectKanbanStatsResp { @ApiModelProperty("待施工项目数") private Long pendingProjectCount; - @ApiModelProperty("施工中项目数") + @ApiModelProperty("筹备中项目数") + private Long preparingProjectCount; + + @ApiModelProperty("开工中项目数") private Long inProgressProjectCount; + @ApiModelProperty("暂停中项目数") + private Long suspendedProjectCount; + @ApiModelProperty("已完工项目数") private Long completedProjectCount; - @ApiModelProperty("已审核项目数") - private Long auditedProjectCount; + @ApiModelProperty("验收中项目数") + private Long acceptanceProjectCount; - @ApiModelProperty("已验收项目数") - private Long acceptedProjectCount; + @ApiModelProperty("回款中项目数") + private Long collectionProjectCount; + + @ApiModelProperty("已结算项目数") + private Long settledProjectCount; @ApiModelProperty("总机组数") private Long totalTurbineCount; diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java index 5fdcc16..881ecb6 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java @@ -1,5 +1,6 @@ package com.dite.znpt.domain.vo; +import com.dite.znpt.domain.entity.ProjectTaskEntity; import com.dite.znpt.util.ValidationGroup; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -10,6 +11,7 @@ import javax.validation.constraints.Size; import java.io.Serial; import java.io.Serializable; import java.time.LocalDate; +import java.util.List; /** * @Author: gaoxiong @@ -31,7 +33,6 @@ public class ProjectReq implements Serializable { @ApiModelProperty("项目来源") private String projectOrigin; - @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目预算不能为空") @ApiModelProperty("项目预算") private Integer projectBudget; @@ -127,4 +128,7 @@ public class ProjectReq implements Serializable { @ApiModelProperty("其他杂费") private Double othersCost; + + @ApiModelProperty("项目初始任务") + private List tasks; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectTasksDetailResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTasksDetailResp.java new file mode 100644 index 0000000..b4b13c4 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectTasksDetailResp.java @@ -0,0 +1,23 @@ +package com.dite.znpt.domain.vo; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +@ApiModel("项目任务详情响应实体") +public class ProjectTasksDetailResp { + private List list; + + @ApiModelProperty("项目名称") + private String projectName; + + @ApiModelProperty("项目任务总数") + private Integer total; + + @ApiModelProperty("已完成任务数") + private Integer finished; +} \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberUpdateReq.java b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberUpdateReq.java new file mode 100644 index 0000000..f375d8c --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberUpdateReq.java @@ -0,0 +1,60 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDate; + +/** + * @author wangna + * @date 2025/08/05 + * @Description: 团队成员更新请求类(用于更新操作,移除必填验证) + */ +@Data +@ApiModel(value="TeamMemberUpdateReq对象", description="团队成员更新请求类") +public class TeamMemberUpdateReq implements Serializable { + + @ApiModelProperty("项目ID") + private String projectId; + + @ApiModelProperty("机组ID(可选)") + private String turbineId; + + @ApiModelProperty("任务组ID(可选)") + private String taskGroupId; + + @ApiModelProperty("任务ID(可选)") + private String taskId; + + @ApiModelProperty("用户ID") + private String userId; + + @ApiModelProperty("项目角色类型:PROJECT_MANAGER-项目经理,SAFETY_OFFICER-安全员,QUALITY_OFFICER-质量员,CONSTRUCTOR-施工人员,TEAM_LEADER-施工组长") + private String roleType; + + @ApiModelProperty("具体岗位代码(如:GROUND_SERVICE-地勤,DRIVER-司机,ASCENDING-登高等)") + private String jobCode; + + @ApiModelProperty("岗位描述") + private String jobDesc; + + @ApiModelProperty("加入时间") + private LocalDate joinDate; + + @ApiModelProperty("离开时间") + private LocalDate leaveDate; + + @ApiModelProperty("状态:ACTIVE-在职,INACTIVE-离职,PENDING-待入职") + private String status = "ACTIVE"; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("用户电话") + private String phone; + + @ApiModelProperty("用户邮箱") + private String email; +} diff --git a/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java b/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java index 7836468..7fbbeff 100644 --- a/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java +++ b/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java @@ -15,11 +15,14 @@ import java.util.List; @Getter @AllArgsConstructor public enum ProjectStatusEnum { - PENDING(0, "待施工"), - IN_PROGRESS(1, "施工中"), - COMPLETED(2, "已完工"), - AUDITED(3, "已审核"), - ACCEPTED(4, "已验收"); + PENDING(0, "未开工"), + PREPARING(1, "筹备中"), + IN_PROGRESS(2, "开工中"), + SUSPENDED(3, "暂停中"), + COMPLETED(4, "已完工"), + IN_ACCEPTANCE(5, "验收中"), + IN_COLLECTION(6, "回款中"), + SETTLED(7, "已结算"); private final int code; private final String desc; diff --git a/core/src/main/java/com/dite/znpt/service/EquipmentApprovalService.java b/core/src/main/java/com/dite/znpt/service/EquipmentApprovalService.java index 685c7c4..2164186 100644 --- a/core/src/main/java/com/dite/znpt/service/EquipmentApprovalService.java +++ b/core/src/main/java/com/dite/znpt/service/EquipmentApprovalService.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.dite.znpt.domain.vo.EquipmentApprovalListReq; import com.dite.znpt.domain.vo.EquipmentApprovalReq; import com.dite.znpt.domain.vo.EquipmentApprovalResp; +import com.dite.znpt.domain.vo.EquipmentProcurementApplyReq; /** * @author Bear.G @@ -41,4 +42,19 @@ public interface EquipmentApprovalService { * 获取审批统计信息 */ Object getApprovalStats(); + + /** + * 提交采购申请 + */ + void submitProcurementApplication(EquipmentProcurementApplyReq req); + + /** + * 获取我的采购申请 + */ + IPage getMyProcurementApplications(EquipmentApprovalListReq req); + + /** + * 撤回采购申请 + */ + void withdrawProcurementApplication(String approvalId); } diff --git a/core/src/main/java/com/dite/znpt/service/EquipmentStatusUpdateService.java b/core/src/main/java/com/dite/znpt/service/EquipmentStatusUpdateService.java new file mode 100644 index 0000000..2963dde --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/EquipmentStatusUpdateService.java @@ -0,0 +1,51 @@ +package com.dite.znpt.service; + +/** + * 设备状态更新服务接口 + * 用于处理设备审批后的状态更新,避免循环依赖 + * + * @author Bear.G + * @date 2025/1/8/周三 17:50 + */ +public interface EquipmentStatusUpdateService { + + /** + * 更新设备采购状态 + * + * @param equipmentId 设备ID + * @param status 新状态 + */ + void updateProcurementStatus(String equipmentId, String status); + + /** + * 更新设备借用状态 + * + * @param equipmentId 设备ID + * @param status 新状态 + */ + void updateBorrowStatus(String equipmentId, String status); + + /** + * 更新设备归还状态 + * + * @param equipmentId 设备ID + * @param status 新状态 + */ + void updateReturnStatus(String equipmentId, String status); + + /** + * 更新设备位置状态 + * + * @param equipmentId 设备ID + * @param locationStatus 新位置状态 + */ + void updateLocationStatus(String equipmentId, String locationStatus); + + /** + * 更新设备使用状态 + * + * @param equipmentId 设备ID + * @param useStatus 新使用状态 + */ + void updateUseStatus(String equipmentId, String useStatus); +} diff --git a/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java b/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java index 939ff8a..c622b9e 100644 --- a/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java +++ b/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java @@ -27,6 +27,11 @@ public interface ProjectMemberService extends IService { */ ProjectMemberResp updateTeamMember(String memberId, TeamMemberReq req); + /** + * 更新团队成员信息(使用更新专用请求类) + */ + ProjectMemberResp updateTeamMember(String memberId, TeamMemberUpdateReq req); + /** * 删除团队成员(支持单个或批量删除) */ diff --git a/core/src/main/java/com/dite/znpt/service/ProjectTaskService.java b/core/src/main/java/com/dite/znpt/service/ProjectTaskService.java index a142201..8eb9fe5 100644 --- a/core/src/main/java/com/dite/znpt/service/ProjectTaskService.java +++ b/core/src/main/java/com/dite/znpt/service/ProjectTaskService.java @@ -89,5 +89,7 @@ public interface ProjectTaskService extends IService { * @date 2025/06/25 21:16 **/ void endTask(ProjectTaskStartReq taskStartReq); + + List getTaskByProjectId(String projectId); } diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java index 6d1fced..480734d 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java @@ -8,7 +8,11 @@ import com.dite.znpt.domain.mapper.EquipmentApprovalMapper; import com.dite.znpt.domain.vo.EquipmentApprovalListReq; import com.dite.znpt.domain.vo.EquipmentApprovalReq; import com.dite.znpt.domain.vo.EquipmentApprovalResp; +import com.dite.znpt.domain.vo.EquipmentProcurementApplyReq; import com.dite.znpt.service.EquipmentApprovalService; +import com.dite.znpt.service.EquipmentStatusUpdateService; +import com.dite.znpt.websocket.SimpleWebSocketHandler; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -25,11 +29,15 @@ import java.util.stream.Collectors; * @date 2025/1/8/周三 17:55 * @description 设备审批服务实现类 */ +@Slf4j @Service public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { @Resource private EquipmentApprovalMapper equipmentApprovalMapper; + + @Resource + private EquipmentStatusUpdateService equipmentStatusUpdateService; @Override public IPage getPendingApprovals(EquipmentApprovalListReq req) { @@ -81,6 +89,21 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { entity.setApprovalComment(req.getApprovalComment()); equipmentApprovalMapper.updateById(entity); + + // 审批通过后,更新设备状态 + try { + if ("PROCUREMENT".equals(entity.getBusinessType())) { + equipmentStatusUpdateService.updateProcurementStatus(entity.getEquipmentId(), "APPROVED"); + } else if ("BORROW".equals(entity.getBusinessType())) { + equipmentStatusUpdateService.updateBorrowStatus(entity.getEquipmentId(), "APPROVED"); + } else if ("RETURN".equals(entity.getBusinessType())) { + equipmentStatusUpdateService.updateReturnStatus(entity.getEquipmentId(), "APPROVED"); + } + log.info("设备状态更新成功,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId); + } catch (Exception e) { + log.error("设备状态更新失败,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId, e); + // 不抛出异常,避免影响审批流程 + } } @Override @@ -97,6 +120,21 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { entity.setApprovalComment(req.getApprovalComment()); equipmentApprovalMapper.updateById(entity); + + // 审批拒绝后,更新设备状态 + try { + if ("PROCUREMENT".equals(entity.getBusinessType())) { + equipmentStatusUpdateService.updateProcurementStatus(entity.getEquipmentId(), "REJECTED"); + } else if ("BORROW".equals(entity.getBusinessType())) { + equipmentStatusUpdateService.updateBorrowStatus(entity.getEquipmentId(), "REJECTED"); + } else if ("RETURN".equals(entity.getBusinessType())) { + equipmentStatusUpdateService.updateReturnStatus(entity.getEquipmentId(), "REJECTED"); + } + log.info("设备状态更新成功,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId); + } catch (Exception e) { + log.error("设备状态更新失败,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId, e); + // 不抛出异常,避免影响审批流程 + } } @Override @@ -138,38 +176,61 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { * 添加查询条件 */ private void addQueryConditions(LambdaQueryWrapper wrapper, EquipmentApprovalListReq req) { + log.info("开始构建查询条件,请求参数: {}", req); + + // 添加搜索条件并记录日志 + int conditionCount = 0; + if (StringUtils.hasText(req.getEquipmentName())) { wrapper.like(EquipmentApprovalEntity::getEquipmentName, req.getEquipmentName()); + log.info("添加设备名称查询条件: {}", req.getEquipmentName()); + conditionCount++; } if (StringUtils.hasText(req.getApplicantName())) { wrapper.like(EquipmentApprovalEntity::getApplicantName, req.getApplicantName()); + log.info("添加申请人查询条件: {}", req.getApplicantName()); + conditionCount++; } if (StringUtils.hasText(req.getBusinessType())) { wrapper.eq(EquipmentApprovalEntity::getBusinessType, req.getBusinessType()); + log.info("添加业务类型查询条件: {}", req.getBusinessType()); + conditionCount++; } if (StringUtils.hasText(req.getApprovalStatus())) { wrapper.eq(EquipmentApprovalEntity::getApprovalStatus, req.getApprovalStatus()); + log.info("添加审批状态查询条件: {}", req.getApprovalStatus()); + conditionCount++; } if (StringUtils.hasText(req.getApplyTimeStart())) { wrapper.ge(EquipmentApprovalEntity::getApplyTime, req.getApplyTimeStart()); + log.info("添加申请时间开始查询条件: {}", req.getApplyTimeStart()); + conditionCount++; } if (StringUtils.hasText(req.getApplyTimeEnd())) { wrapper.le(EquipmentApprovalEntity::getApplyTime, req.getApplyTimeEnd()); + log.info("添加申请时间结束查询条件: {}", req.getApplyTimeEnd()); + conditionCount++; } if (StringUtils.hasText(req.getApprovalTimeStart())) { wrapper.ge(EquipmentApprovalEntity::getApprovalTime, req.getApprovalTimeStart()); + log.info("添加审批时间开始查询条件: {}", req.getApprovalTimeStart()); + conditionCount++; } if (StringUtils.hasText(req.getApprovalTimeEnd())) { wrapper.le(EquipmentApprovalEntity::getApprovalTime, req.getApprovalTimeEnd()); + log.info("添加审批时间结束查询条件: {}", req.getApprovalTimeEnd()); + conditionCount++; } + log.info("查询条件构建完成,共添加 {} 个条件", conditionCount); + // 排序 wrapper.orderByDesc(EquipmentApprovalEntity::getCreateTime); } @@ -196,4 +257,279 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { return respPage; } + + @Override + public void submitProcurementApplication(EquipmentProcurementApplyReq req) { + log.info("开始提交采购申请,请求参数: {}", req); + + // 创建审批实体 + EquipmentApprovalEntity entity = new EquipmentApprovalEntity(); + + // 设置基本信息 + entity.setEquipmentId(req.getEquipmentId()); // 添加设备ID + entity.setEquipmentName(req.getEquipmentName()); + entity.setEquipmentType(req.getEquipmentType()); + entity.setEquipmentModel(req.getEquipmentModel()); + entity.setBrand(req.getBrand()); + entity.setSupplierName(req.getSupplierName()); + entity.setPurchasePrice(req.getBudgetAmount()); + entity.setTotalPrice(req.getBudgetAmount().multiply(new java.math.BigDecimal(req.getQuantity()))); + entity.setQuantity(req.getQuantity()); + + // 设置申请信息 + entity.setApplicantName(getCurrentUserName()); // 获取当前用户名 + entity.setApplicantId(getCurrentUserId()); // 获取当前用户ID + entity.setApplyTime(LocalDateTime.now()); + entity.setApplyReason(req.getApplyReason()); + + // 设置业务类型和审批状态 + entity.setBusinessType("PROCUREMENT"); + entity.setApprovalStatus("PENDING"); + + // 设置扩展字段(如果有的话) + // entity.setProcurementType(req.getProcurementType()); + // entity.setUrgencyLevel(req.getUrgencyLevel()); + // entity.setTechnicalRequirements(req.getTechnicalRequirements()); + // entity.setBusinessJustification(req.getBusinessJustification()); + // entity.setExpectedDeliveryDate(req.getExpectedDeliveryDate()); + + // 保存到数据库 + equipmentApprovalMapper.insert(entity); + + // 更新设备采购状态 - 新增逻辑 + try { + equipmentStatusUpdateService.updateProcurementStatus(req.getEquipmentId(), "PENDING_APPROVAL"); + log.info("设备采购状态更新成功,设备ID: {}", req.getEquipmentId()); + } catch (Exception e) { + log.error("设备采购状态更新失败,设备ID: {}", req.getEquipmentId(), e); + // 不抛出异常,避免影响审批流程 + } + + // 发送通知 - 使用日志记录,后续可以扩展为WebSocket通知 + log.info("采购申请提交成功,设备名称: {}, 申请人: {}", + req.getEquipmentName(), getCurrentUserName()); + + // 发送WebSocket通知 + try { + SimpleWebSocketHandler.sendProcurementNotification( + req.getEquipmentName(), + getCurrentUserName() + ); + log.info("WebSocket通知发送成功"); + } catch (Exception e) { + log.error("WebSocket通知发送失败", e); + } + + log.info("采购申请提交成功,审批ID: {}", entity.getApprovalId()); + } + + /** + * 更新设备采购状态 + */ + private void updateEquipmentProcurementStatus(String equipmentId, String status) { + if (equipmentId == null || equipmentId.trim().isEmpty()) { + log.warn("设备ID为空,跳过状态更新"); + return; + } + + try { + log.info("准备更新设备采购状态,设备ID: {}, 新状态: {}", equipmentId, status); + + // 这里可以添加具体的更新逻辑 + // 例如:equipmentMapper.updateProcurementStatus(equipmentId, status); + // 由于循环依赖问题,建议通过事件机制或异步处理来避免循环依赖 + + // 暂时记录日志,后续可以通过以下方式实现: + // 1. 使用Spring事件机制 + // 2. 使用异步处理 + // 3. 重构服务架构避免循环依赖 + + } catch (Exception e) { + log.error("更新设备采购状态失败,设备ID: {}, 状态: {}", equipmentId, status, e); + throw e; + } + } + + + + /** + * 审批通过后更新设备状态 + */ + private void updateEquipmentStatusAfterApproval(EquipmentApprovalEntity entity) { + if (entity == null || entity.getEquipmentId() == null) { + log.warn("审批实体或设备ID为空,跳过状态更新"); + return; + } + + try { + log.info("审批通过后更新设备状态,设备ID: {}, 业务类型: {}", entity.getEquipmentId(), entity.getBusinessType()); + + // 根据业务类型更新不同的设备状态 + if ("PROCUREMENT".equals(entity.getBusinessType())) { + // 采购审批通过,更新设备状态为已采购 + updateEquipmentProcurementStatus(entity.getEquipmentId(), "APPROVED"); + } else if ("BORROW".equals(entity.getBusinessType())) { + // 借用审批通过,更新设备状态为已借用 + updateEquipmentBorrowStatus(entity.getEquipmentId(), "APPROVED"); + } else if ("RETURN".equals(entity.getBusinessType())) { + // 归还审批通过,更新设备状态为已归还 + updateEquipmentReturnStatus(entity.getEquipmentId(), "APPROVED"); + } + + log.info("设备状态更新成功,设备ID: {}", entity.getEquipmentId()); + } catch (Exception e) { + log.error("审批通过后更新设备状态失败,设备ID: {}", entity.getEquipmentId(), e); + throw e; + } + } + + /** + * 审批拒绝后更新设备状态 + */ + private void updateEquipmentStatusAfterRejection(EquipmentApprovalEntity entity) { + if (entity == null || entity.getEquipmentId() == null) { + log.warn("审批实体或设备ID为空,跳过状态更新"); + return; + } + + try { + log.info("审批拒绝后更新设备状态,设备ID: {}, 业务类型: {}", entity.getEquipmentId(), entity.getBusinessType()); + + // 根据业务类型更新不同的设备状态 + if ("PROCUREMENT".equals(entity.getBusinessType())) { + // 采购审批拒绝,更新设备状态为审批拒绝 + updateEquipmentProcurementStatus(entity.getEquipmentId(), "REJECTED"); + } else if ("BORROW".equals(entity.getBusinessType())) { + // 借用审批拒绝,更新设备状态为借用拒绝 + updateEquipmentBorrowStatus(entity.getEquipmentId(), "REJECTED"); + } else if ("RETURN".equals(entity.getBusinessType())) { + // 归还审批拒绝,更新设备状态为归还拒绝 + updateEquipmentReturnStatus(entity.getEquipmentId(), "REJECTED"); + } + + log.info("设备状态更新成功,设备ID: {}", entity.getEquipmentId()); + } catch (Exception e) { + log.error("审批拒绝后更新设备状态失败,设备ID: {}", entity.getEquipmentId(), e); + throw e; + } + } + + /** + * 更新设备借用状态 + */ + private void updateEquipmentBorrowStatus(String equipmentId, String status) { + if (equipmentId == null || equipmentId.trim().isEmpty()) { + log.warn("设备ID为空,跳过借用状态更新"); + return; + } + + try { + log.info("准备更新设备借用状态,设备ID: {}, 新状态: {}", equipmentId, status); + // 这里可以添加具体的更新逻辑 + // 例如:equipmentMapper.updateBorrowStatus(equipmentId, status); + } catch (Exception e) { + log.error("更新设备借用状态失败,设备ID: {}, 状态: {}", equipmentId, status, e); + throw e; + } + } + + /** + * 更新设备归还状态 + */ + private void updateEquipmentReturnStatus(String equipmentId, String status) { + if (equipmentId == null || equipmentId.trim().isEmpty()) { + log.warn("设备ID为空,跳过归还状态更新"); + return; + } + + try { + log.info("准备更新设备归还状态,设备ID: {}, 新状态: {}", equipmentId, status); + // 这里可以添加具体的更新逻辑 + // 例如:equipmentMapper.updateReturnStatus(equipmentId, status); + } catch (Exception e) { + log.error("更新设备归还状态失败,设备ID: {}, 状态: {}", equipmentId, status, e); + throw e; + } + } + + @Override + public IPage getMyProcurementApplications(EquipmentApprovalListReq req) { + log.info("开始获取我的采购申请,请求参数: {}", req); + + // 创建分页对象 + Integer pageNum = req.getPage() != null ? req.getPage() : 1; + Integer pageSize = req.getPageSize() != null ? req.getPageSize() : 10; + Page page = new Page<>(pageNum, pageSize); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + // 只查询当前用户的申请 + wrapper.eq(EquipmentApprovalEntity::getApplicantId, getCurrentUserId()); + wrapper.eq(EquipmentApprovalEntity::getBusinessType, "PROCUREMENT"); + + // 添加查询条件 + addQueryConditions(wrapper, req); + + IPage result = equipmentApprovalMapper.selectPage(page, wrapper); + + return convertToRespPage(result); + } + + @Override + public void withdrawProcurementApplication(String approvalId) { + log.info("开始撤回采购申请,审批ID: {}", approvalId); + + EquipmentApprovalEntity entity = equipmentApprovalMapper.selectById(approvalId); + if (entity == null) { + throw new RuntimeException("审批记录不存在"); + } + + // 检查是否是当前用户的申请 + if (!entity.getApplicantId().equals(getCurrentUserId())) { + throw new RuntimeException("只能撤回自己的申请"); + } + + // 检查状态是否可以撤回 + if (!"PENDING".equals(entity.getApprovalStatus())) { + throw new RuntimeException("只能撤回待审批状态的申请"); + } + + // 更新状态为已撤回 + entity.setApprovalStatus("WITHDRAWN"); + equipmentApprovalMapper.updateById(entity); + + log.info("采购申请撤回成功,审批ID: {}", approvalId); + } + + /** + * 获取当前用户名 + */ + private String getCurrentUserName() { + try { + // 从Sa-Token上下文获取当前用户名 + Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId(); + if (loginId != null) { + return loginId.toString(); + } + } catch (Exception e) { + log.warn("获取当前用户名失败: {}", e.getMessage()); + } + return "未知用户"; + } + + /** + * 获取当前用户ID + */ + private String getCurrentUserId() { + try { + // 从Sa-Token上下文获取当前用户ID + Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId(); + if (loginId != null) { + return loginId.toString(); + } + } catch (Exception e) { + log.warn("获取当前用户ID失败: {}", e.getMessage()); + } + return "unknown_user_id"; + } } diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java index 8f15c6e..ebaac5c 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java @@ -562,6 +562,9 @@ public class EquipmentServiceImpl extends ServiceImpl updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId); + + // 根据状态设置相应的字段 + if ("APPROVED".equals(status)) { + // 审批通过:设置采购状态为已通过,位置状态为库存中,使用状态为空闲中 + updateWrapper.set(EquipmentEntity::getProcurementStatus, "APPROVED"); + updateWrapper.set(EquipmentEntity::getLocationStatus, "in_stock"); + updateWrapper.set(EquipmentEntity::getUseStatus, "0"); + updateWrapper.set(EquipmentEntity::getInStockTime, LocalDateTime.now()); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备采购审批通过,设置状态为已通过"); + } else if ("REJECTED".equals(status)) { + // 审批拒绝:设置采购状态为已拒绝,位置状态为未入库,使用状态为空闲中 + updateWrapper.set(EquipmentEntity::getProcurementStatus, "REJECTED"); + updateWrapper.set(EquipmentEntity::getLocationStatus, "not_in_stock"); + updateWrapper.set(EquipmentEntity::getUseStatus, "0"); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备采购审批拒绝,设置状态为已拒绝"); + } else if ("PENDING_APPROVAL".equals(status) || "PENDING".equals(status)) { + // 待审批:设置采购状态为待审批,位置状态为待审批,使用状态为空闲中 + updateWrapper.set(EquipmentEntity::getProcurementStatus, "PENDING_APPROVAL"); + updateWrapper.set(EquipmentEntity::getLocationStatus, "pending_approval"); + updateWrapper.set(EquipmentEntity::getUseStatus, "0"); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备采购申请提交,设置状态为待审批"); + } else if ("COMPLETED".equals(status)) { + // 采购完成:设置采购状态为已完成,位置状态为库存中,使用状态为空闲中 + updateWrapper.set(EquipmentEntity::getProcurementStatus, "COMPLETED"); + updateWrapper.set(EquipmentEntity::getLocationStatus, "in_stock"); + updateWrapper.set(EquipmentEntity::getUseStatus, "0"); + updateWrapper.set(EquipmentEntity::getInStockTime, LocalDateTime.now()); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备采购完成,设置状态为已完成"); + } + + // 执行更新 + int updateCount = equipmentMapper.update(null, updateWrapper); + if (updateCount > 0) { + log.info("设备采购状态更新成功,设备ID: {}, 新状态: {}, 影响行数: {}", equipmentId, status, updateCount); + } else { + log.warn("设备采购状态更新失败,设备ID: {}, 新状态: {}, 可能设备不存在", equipmentId, status); + } + + } catch (Exception e) { + log.error("更新设备采购状态失败,设备ID: {}, 状态: {}", equipmentId, status, e); + throw e; + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateBorrowStatus(String equipmentId, String status) { + if (equipmentId == null || equipmentId.trim().isEmpty()) { + log.warn("设备ID为空,跳过借用状态更新"); + return; + } + + try { + log.info("开始更新设备借用状态,设备ID: {}, 新状态: {}", equipmentId, status); + + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId); + + if ("APPROVED".equals(status)) { + // 借用审批通过:设置位置状态为外借中,使用状态为使用中 + updateWrapper.set(EquipmentEntity::getLocationStatus, "borrowed"); + updateWrapper.set(EquipmentEntity::getUseStatus, "1"); + updateWrapper.set(EquipmentEntity::getBorrowingTime, LocalDateTime.now()); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备借用审批通过,设置状态为外借中"); + } else if ("REJECTED".equals(status)) { + // 借用审批拒绝:保持原有状态 + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备借用审批拒绝,保持原有状态"); + } + + // 执行更新 + int updateCount = equipmentMapper.update(null, updateWrapper); + if (updateCount > 0) { + log.info("设备借用状态更新成功,设备ID: {}, 新状态: {}, 影响行数: {}", equipmentId, status, updateCount); + } else { + log.warn("设备借用状态更新失败,设备ID: {}, 新状态: {}, 可能设备不存在", equipmentId, status); + } + + } catch (Exception e) { + log.error("更新设备借用状态失败,设备ID: {}, 状态: {}", equipmentId, status, e); + throw e; + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateReturnStatus(String equipmentId, String status) { + if (equipmentId == null || equipmentId.trim().isEmpty()) { + log.warn("设备ID为空,跳过归还状态更新"); + return; + } + + try { + log.info("开始更新设备归还状态,设备ID: {}, 新状态: {}", equipmentId, status); + + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId); + + if ("APPROVED".equals(status)) { + // 归还审批通过:设置位置状态为库存中,使用状态为空闲中 + updateWrapper.set(EquipmentEntity::getLocationStatus, "in_stock"); + updateWrapper.set(EquipmentEntity::getUseStatus, "0"); + updateWrapper.set(EquipmentEntity::getReturnTime, LocalDateTime.now()); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备归还审批通过,设置状态为库存中"); + } else if ("REJECTED".equals(status)) { + // 归还审批拒绝:保持原有状态 + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + log.info("设备归还审批拒绝,保持原有状态"); + } + + // 执行更新 + int updateCount = equipmentMapper.update(null, updateWrapper); + if (updateCount > 0) { + log.info("设备归还状态更新成功,设备ID: {}, 新状态: {}, 影响行数: {}", equipmentId, status, updateCount); + } else { + log.warn("设备归还状态更新失败,设备ID: {}, 新状态: {}, 可能设备不存在", equipmentId, status); + } + + } catch (Exception e) { + log.error("更新设备归还状态失败,设备ID: {}, 状态: {}", equipmentId, status, e); + throw e; + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateLocationStatus(String equipmentId, String locationStatus) { + if (equipmentId == null || equipmentId.trim().isEmpty()) { + log.warn("设备ID为空,跳过位置状态更新"); + return; + } + + try { + log.info("开始更新设备位置状态,设备ID: {}, 新位置状态: {}", equipmentId, locationStatus); + + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId); + updateWrapper.set(EquipmentEntity::getLocationStatus, locationStatus); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + + // 执行更新 + int updateCount = equipmentMapper.update(null, updateWrapper); + if (updateCount > 0) { + log.info("设备位置状态更新成功,设备ID: {}, 新位置状态: {}, 影响行数: {}", equipmentId, locationStatus, updateCount); + } else { + log.warn("设备位置状态更新失败,设备ID: {}, 新位置状态: {}, 可能设备不存在", equipmentId, locationStatus); + } + + } catch (Exception e) { + log.error("更新设备位置状态失败,设备ID: {}, 位置状态: {}", equipmentId, locationStatus, e); + throw e; + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUseStatus(String equipmentId, String useStatus) { + if (equipmentId == null || equipmentId.trim().isEmpty()) { + log.warn("设备ID为空,跳过使用状态更新"); + return; + } + + try { + log.info("开始更新设备使用状态,设备ID: {}, 新使用状态: {}", equipmentId, useStatus); + + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId); + updateWrapper.set(EquipmentEntity::getUseStatus, useStatus); + updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now()); + + // 执行更新 + int updateCount = equipmentMapper.update(null, updateWrapper); + if (updateCount > 0) { + log.info("设备使用状态更新成功,设备ID: {}, 新使用状态: {}, 影响行数: {}", equipmentId, useStatus, updateCount); + } else { + log.warn("设备使用状态更新失败,设备ID: {}, 新使用状态: {}, 可能设备不存在", equipmentId, useStatus); + } + + } catch (Exception e) { + log.error("更新设备使用状态失败,设备ID: {}, 使用状态: {}", equipmentId, useStatus, e); + throw e; + } + } +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentUseRecordServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentUseRecordServiceImpl.java index 2db0c74..33e7555 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/EquipmentUseRecordServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentUseRecordServiceImpl.java @@ -90,6 +90,7 @@ public class EquipmentUseRecordServiceImpl extends ServiceImpl list = this.baseMapper.queryTeamMembers(query); - return list.stream() - .filter(member -> member.getMemberId().equals(memberId)) + ProjectMemberResp member = list.stream() + .filter(m -> m.getMemberId().equals(memberId)) .findFirst() .orElse(null); + + if (member != null) { + // 丰富成员信息 + enrichMemberInfo(CollUtil.toList(member)); + } + + return member; } // ========================== 项目看板相关方法实现 ========================== @@ -300,11 +454,14 @@ public class ProjectMemberServiceImpl extends ServiceImpl getTaskByProjectId(String projectId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("project_id", projectId); + List list = baseMapper.selectList(queryWrapper); + if (CollectionUtil.isEmpty(list)) { + return Collections.emptyList(); // 返回不可修改的空集合 + } + String projectName = projectService.getById(projectId).getProjectName(); + List respList = list.stream().map(item -> BeanUtil.copyProperties(item, ProjectTaskResp.class)).toList(); + return respList; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java index 4daf34f..3883546 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/TurbineServiceImpl.java @@ -206,7 +206,7 @@ public class TurbineServiceImpl extends ServiceImpl turbineStatusList = jobService.calCrewStatus(ListUtil.of(turbineId)); @@ -234,7 +234,7 @@ public class TurbineServiceImpl extends ServiceImpl sessions = new ConcurrentHashMap<>(); + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + String sessionId = session.getId(); + sessions.put(sessionId, session); + System.out.println("WebSocket连接建立,sessionId: " + sessionId); + } + + @Override + public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { + // 处理接收到的消息 + System.out.println("收到WebSocket消息: " + message.getPayload()); + } + + @Override + public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { + System.err.println("WebSocket传输错误,sessionId: " + session.getId()); + exception.printStackTrace(); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { + String sessionId = session.getId(); + sessions.remove(sessionId); + System.out.println("WebSocket连接关闭,sessionId: " + sessionId); + } + + @Override + public boolean supportsPartialMessages() { + return false; + } + + /** + * 发送简单消息给所有连接的客户端 + */ + public static void sendMessageToAll(String message) { + System.out.println("准备发送WebSocket消息给 " + sessions.size() + " 个连接的客户端"); + System.out.println("消息内容: " + message); + + final int[] successCount = {0}; + final int[] failCount = {0}; + + sessions.values().forEach(session -> { + try { + if (session.isOpen()) { + session.sendMessage(new TextMessage(message)); + successCount[0]++; + System.out.println("成功发送消息给sessionId: " + session.getId()); + } else { + System.out.println("跳过已关闭的sessionId: " + session.getId()); + } + } catch (IOException e) { + failCount[0]++; + System.err.println("发送消息失败,sessionId: " + session.getId()); + e.printStackTrace(); + } + }); + + System.out.println("WebSocket消息发送完成 - 成功: " + successCount[0] + ", 失败: " + failCount[0]); + } + + /** + * 发送采购申请通知 + */ + public static void sendProcurementNotification(String equipmentName, String applicantName) { + String notificationMessage = String.format( + "{\"type\":\"PROCUREMENT_APPLICATION\",\"title\":\"新的采购申请\",\"content\":\"收到来自 %s 的设备采购申请:%s\"}", + applicantName, equipmentName + ); + + System.out.println("=== 发送采购申请通知 ==="); + System.out.println("设备名称: " + equipmentName); + System.out.println("申请人: " + applicantName); + System.out.println("通知消息: " + notificationMessage); + System.out.println("当前连接数: " + sessions.size()); + + sendMessageToAll(notificationMessage); + } +} diff --git a/web/src/main/java/com/dite/znpt/web/controller/EquipmentApprovalController.java b/web/src/main/java/com/dite/znpt/web/controller/EquipmentApprovalController.java index a49fa5f..ef16e0a 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/EquipmentApprovalController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/EquipmentApprovalController.java @@ -6,6 +6,7 @@ import com.dite.znpt.domain.Result; import com.dite.znpt.domain.vo.EquipmentApprovalListReq; import com.dite.znpt.domain.vo.EquipmentApprovalReq; import com.dite.znpt.domain.vo.EquipmentApprovalResp; +import com.dite.znpt.domain.vo.EquipmentProcurementApplyReq; import com.dite.znpt.service.EquipmentApprovalService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -34,6 +35,21 @@ public class EquipmentApprovalController { @ApiOperation(value = "分页查询待审批的设备采购申请", httpMethod = "GET") @GetMapping("/pending") public PageResult getPendingApprovals(EquipmentApprovalListReq req) { + log.info("=== 设备审批待审批查询接口被调用 ==="); + log.info("接收到的请求参数: {}", req); + log.info("设备名称: {}", req.getEquipmentName()); + log.info("申请人: {}", req.getApplicantName()); + log.info("业务类型: {}", req.getBusinessType()); + log.info("审批状态: {}", req.getApprovalStatus()); + log.info("申请时间开始: {}", req.getApplyTimeStart()); + log.info("申请时间结束: {}", req.getApplyTimeEnd()); + log.info("审批时间开始: {}", req.getApprovalTimeStart()); + log.info("审批时间结束: {}", req.getApprovalTimeEnd()); + log.info("页码: {}", req.getPage()); + log.info("每页大小: {}", req.getPageSize()); + log.info("排序字段: {}", req.getOrderBy()); + log.info("排序方向: {}", req.getOrderDirection()); + IPage page = equipmentApprovalService.getPendingApprovals(req); return PageResult.ok(page.getRecords(), page.getTotal()); } @@ -41,6 +57,21 @@ public class EquipmentApprovalController { @ApiOperation(value = "分页查询已审批的设备采购申请", httpMethod = "GET") @GetMapping("/approved") public PageResult getApprovedApprovals(EquipmentApprovalListReq req) { + log.info("=== 设备审批已审批查询接口被调用 ==="); + log.info("接收到的请求参数: {}", req); + log.info("设备名称: {}", req.getEquipmentName()); + log.info("申请人: {}", req.getApplicantName()); + log.info("业务类型: {}", req.getBusinessType()); + log.info("审批状态: {}", req.getApprovalStatus()); + log.info("申请时间开始: {}", req.getApplyTimeStart()); + log.info("申请时间结束: {}", req.getApplyTimeEnd()); + log.info("审批时间开始: {}", req.getApprovalTimeStart()); + log.info("审批时间结束: {}", req.getApprovalTimeEnd()); + log.info("页码: {}", req.getPage()); + log.info("每页大小: {}", req.getPageSize()); + log.info("排序字段: {}", req.getOrderBy()); + log.info("排序方向: {}", req.getOrderDirection()); + IPage page = equipmentApprovalService.getApprovedApprovals(req); return PageResult.ok(page.getRecords(), page.getTotal()); } @@ -70,4 +101,38 @@ public class EquipmentApprovalController { public Result getApprovalStats() { return Result.ok(equipmentApprovalService.getApprovalStats()); } + + @ApiOperation(value = "提交采购申请", httpMethod = "POST") + @PostMapping("/procurement/apply") + public Result submitProcurementApplication(@Validated @RequestBody EquipmentProcurementApplyReq req) { + log.info("=== 提交采购申请接口被调用 ==="); + log.info("接收到的请求参数: {}", req); + log.info("设备名称: {}", req.getEquipmentName()); + log.info("设备类型: {}", req.getEquipmentType()); + log.info("预算金额: {}", req.getBudgetAmount()); + log.info("申请原因: {}", req.getApplyReason()); + + equipmentApprovalService.submitProcurementApplication(req); + return Result.ok(); + } + + @ApiOperation(value = "获取我的采购申请", httpMethod = "GET") + @GetMapping("/procurement/my-applications") + public PageResult getMyProcurementApplications(EquipmentApprovalListReq req) { + log.info("=== 获取我的采购申请接口被调用 ==="); + log.info("接收到的请求参数: {}", req); + + IPage page = equipmentApprovalService.getMyProcurementApplications(req); + return PageResult.ok(page.getRecords(), page.getTotal()); + } + + @ApiOperation(value = "撤回采购申请", httpMethod = "POST") + @PostMapping("/procurement/{approvalId}/withdraw") + public Result withdrawProcurementApplication(@PathVariable String approvalId) { + log.info("=== 撤回采购申请接口被调用 ==="); + log.info("审批ID: {}", approvalId); + + equipmentApprovalService.withdrawProcurementApplication(approvalId); + return Result.ok(); + } } diff --git a/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java b/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java index 88f58b4..4136c4b 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/ProjectController.java @@ -2,12 +2,12 @@ package com.dite.znpt.web.controller; import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dite.znpt.constant.Constants; -import com.dite.znpt.domain.vo.ProjectListReq; -import com.dite.znpt.domain.vo.ProjectListResp; -import com.dite.znpt.domain.vo.ProjectReq; -import com.dite.znpt.domain.vo.ProjectResp; +import com.dite.znpt.domain.entity.EquipmentEntity; +import com.dite.znpt.domain.vo.*; import com.dite.znpt.domain.entity.ProjectEntity; +import com.dite.znpt.service.EquipmentService; import com.dite.znpt.service.ProjectService; import com.dite.znpt.domain.Result; import com.dite.znpt.domain.PageResult; @@ -35,6 +35,9 @@ public class ProjectController { @Resource private ProjectService projectService; + @Resource + private EquipmentService equipmentService; + @ApiOperation(value = "分页查询项目信息列表", httpMethod = "GET") @GetMapping("/page") public PageResult page(ProjectListReq req) { @@ -100,5 +103,13 @@ public class ProjectController { return Result.ok(projectService.list(req)); } -} - + @ApiOperation(value = "查询项目下的设备列表", httpMethod = "GET") + @GetMapping("/{projectId}/equipments") + public Result> equipments(@PathVariable String projectId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("del_flag", Constants.DEL_FLAG_0); + queryWrapper.eq("use_status", "1"); + queryWrapper.eq("project_id", projectId); + return Result.ok(equipmentService.list(queryWrapper)); + } +} \ 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 220ccfa..fa66e14 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 @@ -45,7 +45,7 @@ public class ProjectMemberController { @PutMapping("/team-member/{memberId}") public Result updateTeamMember( @PathVariable String memberId, - @Valid @RequestBody TeamMemberReq req) { + @RequestBody TeamMemberUpdateReq req) { return Result.ok(projectMemberService.updateTeamMember(memberId, req)); } diff --git a/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java b/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java index dd59781..1bf92ce 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/ProjectTaskController.java @@ -2,10 +2,14 @@ package com.dite.znpt.web.controller; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dite.znpt.constant.Constants; import com.dite.znpt.domain.PageResult; import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.entity.ProjectTaskEntity; import com.dite.znpt.domain.vo.*; +import com.dite.znpt.service.ProjectService; import com.dite.znpt.service.ProjectTaskService; import com.dite.znpt.util.PageUtil; import com.dite.znpt.util.ValidationGroup; @@ -19,6 +23,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.List; /** @@ -32,6 +37,9 @@ public class ProjectTaskController { @Resource private ProjectTaskService projectTaskService; + @Resource + private ProjectService projectService; + @ApiOperation(value = "获取项目任务信息列表", httpMethod = "GET") @GetMapping("/list") public PageResult list(ProjectTaskListReq projectTaskReq) { @@ -105,5 +113,15 @@ public class ProjectTaskController { req.setUserId(StpUtil.getLoginIdAsString()); return Result.ok(projectTaskService.selectList(req)); } -} + @ApiOperation(value = "根据项目id查询任务列表", httpMethod = "GET") + @GetMapping("/{projectId}/tasks") + public Result getTaskByProjectId(@PathVariable String projectId) { + ProjectTasksDetailResp resp = new ProjectTasksDetailResp(); + resp.setProjectName(projectService.getById(projectId).getProjectName()); + resp.setList(projectTaskService.getTaskByProjectId(projectId)); + resp.setTotal(resp.getList().size()); + resp.setFinished((int) resp.getList().stream().filter(projectTaskResp -> projectTaskResp.getStatus() == 2).count()); + return Result.ok(resp); + } +} \ No newline at end of file diff --git a/web/src/main/java/com/dite/znpt/web/controller/UserController.java b/web/src/main/java/com/dite/znpt/web/controller/UserController.java index 057e6b5..430d6a1 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/UserController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/UserController.java @@ -79,5 +79,13 @@ public class UserController { userService.deleteById(userId); return Result.ok(); } + + @ApiOperation(value = "根据姓名模糊查询用户", httpMethod = "GET") + @GetMapping("/searchByName") + public PageResult searchByName(@RequestParam String name) { + UserListReq req = new UserListReq(); + req.setName(name); + return PageResult.ok(userService.list(req)); + } } diff --git a/web/src/main/resources/application-dev.yml b/web/src/main/resources/application-dev.yml index ead266b..40e9bfb 100644 --- a/web/src/main/resources/application-dev.yml +++ b/web/src/main/resources/application-dev.yml @@ -14,7 +14,7 @@ spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://39.99.201.243:3306/test?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: