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: