diff --git a/.gitignore b/.gitignore index 5c11c82..fa488e5 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,10 @@ build/ ### VS Code ### .vscode/ target/ -logs/ \ No newline at end of file +logs/ + +### Maven ### +pom.xml + +### YAML ### +*.yaml diff --git a/core/pom.xml b/core/pom.xml index a1e8bba..8d32f0d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -197,6 +197,12 @@ jaxb-api 2.3.1 + + + + 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/BusinessDataEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/BusinessDataEntity.java index 3bd598e..c769f0a 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/BusinessDataEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/BusinessDataEntity.java @@ -1,38 +1,38 @@ -package com.dite.znpt.domain.entity; - - -import com.baomidou.mybatisplus.annotation.TableName; -import io.swagger.annotations.ApiModel; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Data -@EqualsAndHashCode(callSuper = false) -@TableName("business_data_part") -@ApiModel(value="商务资料文件夹对象") -@AllArgsConstructor -@NoArgsConstructor -public class BusinessDataEntity { - - // 主键 - private Long folderId = null; - // 文件夹名称 - private String folderName = null; - // 父级文件夹 - private Long parentId = null; - // 创建人 - private Long creatorId = null; - // 创建时间 - private LocalDateTime createTime = null; - // 更新时间 - private LocalDateTime updateTime = null; - // 是否删除 - private Boolean isDeleted = false; - // 文件夹路径 - private String folderPath = null; - -} +package com.dite.znpt.domain.entity; + + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("business_data_part") +@ApiModel(value="商务资料文件夹对象") +@AllArgsConstructor +@NoArgsConstructor +public class BusinessDataEntity { + + // 主键 + private Long folderId = null; + // 文件夹名称 + private String folderName = null; + // 父级文件夹 + private Long parentId = null; + // 创建人 + private String creatorId = null; + // 创建时间 + private LocalDateTime createTime = null; + // 更新时间 + private LocalDateTime updateTime = null; + // 是否删除 + private Boolean isDeleted = false; + // 文件夹路径 + private String folderPath = null; + +} diff --git a/core/src/main/java/com/dite/znpt/domain/entity/BusinessDataFileEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/BusinessDataFileEntity.java index 6b14ed8..8daf3cf 100644 --- a/core/src/main/java/com/dite/znpt/domain/entity/BusinessDataFileEntity.java +++ b/core/src/main/java/com/dite/znpt/domain/entity/BusinessDataFileEntity.java @@ -1,37 +1,39 @@ -package com.dite.znpt.domain.entity; - - -import com.baomidou.mybatisplus.annotation.TableName; -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.Date; - -@Data -@EqualsAndHashCode(callSuper = false) -@TableName("business_data_part_file") -@ApiModel(value="商务资料对象") - -public class BusinessDataFileEntity { - - //文件id - private Long fileId = null; - //文件夹id - private Long folderId = null; - //文件名 - private String fileName = null; - //文件路径 - private String filePath = null; - //文件类型 - private String fileType = "unknown"; - //文件大小 - private Long fileSize = null; - //上传时间 - private Date uploadTime = null; - //上传人id - private Long uploaderId = null; - //是否删除 - private Boolean isDeleted = false; - -} +package com.dite.znpt.domain.entity; + + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("business_data_part_file") +@ApiModel(value="商务资料对象") + +public class BusinessDataFileEntity { + + //文件id + private Long fileId = null; + //文件夹id + private Long folderId = null; + //文件名 + private String fileName = null; + //文件路径 + private String filePath = null; + //文件类型 + private String fileType = "unknown"; + //文件大小 + private Long fileSize = null; + //上传时间 + private Date uploadTime = null; + //上传人id + private String uploaderId = null; + //是否删除 + private Boolean isDeleted = false; +// //有效日期 +// private Date validDate = null; + +} diff --git a/core/src/main/java/com/dite/znpt/domain/entity/EquipmentApprovalEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/EquipmentApprovalEntity.java new file mode 100644 index 0000000..69eded6 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/entity/EquipmentApprovalEntity.java @@ -0,0 +1,91 @@ +package com.dite.znpt.domain.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.dite.znpt.domain.AuditableEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author Bear.G + * @date 2025/1/8/周三 17:26 + * @description 设备审批实体 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("equipment_approval") +@ApiModel(value="EquipmentApprovalEntity对象", description="设备审批信息表") +public class EquipmentApprovalEntity extends AuditableEntity implements Serializable { + private static final long serialVersionUID = -6665040704562461286L; + + @ApiModelProperty("审批ID") + @TableId(type = IdType.ASSIGN_ID) + private String approvalId; + + @ApiModelProperty("设备ID") + private String equipmentId; + + @ApiModelProperty("设备名称") + private String equipmentName; + + @ApiModelProperty("设备类型") + private String equipmentType; + + @ApiModelProperty("设备型号") + private String equipmentModel; + + @ApiModelProperty("品牌") + private String brand; + + @ApiModelProperty("供应商名称") + private String supplierName; + + @ApiModelProperty("采购价格") + private BigDecimal purchasePrice; + + @ApiModelProperty("总价") + private BigDecimal totalPrice; + + @ApiModelProperty("数量") + private Integer quantity; + + @ApiModelProperty("申请人") + private String applicantName; + + @ApiModelProperty("申请人ID") + private String applicantId; + + @ApiModelProperty("申请时间") + private LocalDateTime applyTime; + + @ApiModelProperty("申请原因") + private String applyReason; + + @ApiModelProperty("业务类型,PROCUREMENT-采购,BORROW-借用,RETURN-归还") + private String businessType; + + @ApiModelProperty("审批状态,PENDING-待审批,APPROVED-已通过,REJECTED-已拒绝") + private String approvalStatus; + + @ApiModelProperty("审批人") + private String approverName; + + @ApiModelProperty("审批人ID") + private String approverId; + + @ApiModelProperty("审批时间") + private LocalDateTime approvalTime; + + @ApiModelProperty("审批意见") + private String approvalComment; + + @ApiModelProperty("删除标志(0代表存在 1代表删除)") + @TableLogic + private String delFlag; +} 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..e6d836b 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 @@ -214,4 +214,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/mapper/EquipmentApprovalMapper.java b/core/src/main/java/com/dite/znpt/domain/mapper/EquipmentApprovalMapper.java new file mode 100644 index 0000000..92a9818 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/mapper/EquipmentApprovalMapper.java @@ -0,0 +1,14 @@ +package com.dite.znpt.domain.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dite.znpt.domain.entity.EquipmentApprovalEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author Bear.G + * @date 2025/1/8/周三 17:30 + * @description 设备审批Mapper接口 + */ +@Mapper +public interface EquipmentApprovalMapper extends BaseMapper { +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalListReq.java new file mode 100644 index 0000000..39b5833 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalListReq.java @@ -0,0 +1,54 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Bear.G + * @date 2025/1/8/周三 17:45 + * @description 设备审批列表查询请求VO + */ +@Data +@ApiModel(value="EquipmentApprovalListReq对象", description="设备审批列表查询请求") +public class EquipmentApprovalListReq implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("设备名称") + private String equipmentName; + + @ApiModelProperty("申请人") + private String applicantName; + + @ApiModelProperty("业务类型,PROCUREMENT-采购,BORROW-借用,RETURN-归还") + private String businessType; + + @ApiModelProperty("审批状态") + private String approvalStatus; + + @ApiModelProperty("申请时间开始") + private String applyTimeStart; + + @ApiModelProperty("申请时间结束") + private String applyTimeEnd; + + @ApiModelProperty("审批时间开始") + private String approvalTimeStart; + + @ApiModelProperty("审批时间结束") + private String approvalTimeEnd; + + @ApiModelProperty("当前页码") + private Integer page; + + @ApiModelProperty("每页大小") + private Integer pageSize; + + @ApiModelProperty("排序字段") + private String orderBy; + + @ApiModelProperty("排序方向") + private String orderDirection; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalReq.java b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalReq.java new file mode 100644 index 0000000..e1ff546 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalReq.java @@ -0,0 +1,33 @@ +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.io.Serializable; + +/** + * @author Bear.G + * @date 2025/1/8/周三 17:35 + * @description 设备审批请求VO + */ +@Data +@ApiModel(value="EquipmentApprovalReq对象", description="设备审批请求") +public class EquipmentApprovalReq implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("审批意见") + private String approvalComment; + + @ApiModelProperty("审批结果,APPROVED-通过,REJECTED-拒绝") + @NotBlank(message = "审批结果不能为空") + private String approvalResult; + + @ApiModelProperty("审批人") + private String approverName; + + @ApiModelProperty("审批人ID") + private String approverId; +} diff --git a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalResp.java b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalResp.java new file mode 100644 index 0000000..3fc8e50 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalResp.java @@ -0,0 +1,86 @@ +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.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author Bear.G + * @date 2025/1/8/周三 17:40 + * @description 设备审批响应VO + */ +@Data +@ApiModel(value="EquipmentApprovalResp对象", description="设备审批响应") +public class EquipmentApprovalResp implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("审批ID") + private String approvalId; + + @ApiModelProperty("设备ID") + private String equipmentId; + + @ApiModelProperty("设备名称") + private String equipmentName; + + @ApiModelProperty("设备类型") + private String equipmentType; + + @ApiModelProperty("设备型号") + private String equipmentModel; + + @ApiModelProperty("品牌") + private String brand; + + @ApiModelProperty("供应商名称") + private String supplierName; + + @ApiModelProperty("采购价格") + private BigDecimal purchasePrice; + + @ApiModelProperty("总价") + private BigDecimal totalPrice; + + @ApiModelProperty("数量") + private Integer quantity; + + @ApiModelProperty("申请人") + private String applicantName; + + @ApiModelProperty("申请人ID") + private String applicantId; + + @ApiModelProperty("申请时间") + private LocalDateTime applyTime; + + @ApiModelProperty("申请原因") + private String applyReason; + + @ApiModelProperty("业务类型,PROCUREMENT-采购,BORROW-借用,RETURN-归还") + private String businessType; + + @ApiModelProperty("审批状态") + private String approvalStatus; + + @ApiModelProperty("审批人") + private String approverName; + + @ApiModelProperty("审批人ID") + private String approverId; + + @ApiModelProperty("审批时间") + private LocalDateTime approvalTime; + + @ApiModelProperty("审批意见") + private String approvalComment; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + @ApiModelProperty("更新时间") + private LocalDateTime updateTime; +} 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 4aac551..d936b01 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 @@ -1,5 +1,6 @@ package com.dite.znpt.domain.vo; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -29,7 +30,7 @@ public class EquipmentResp implements Serializable { @ApiModelProperty("设备名称") private String equipmentName; - @ApiModelProperty("设备类型") + @ApiModelProperty("类型") private String equipmentType; @ApiModelProperty("设备类型描述") @@ -75,21 +76,27 @@ public class EquipmentResp implements Serializable { private String healthStatusLabel; @ApiModelProperty("采购时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime purchaseTime; @ApiModelProperty("入库时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime inStockTime; @ApiModelProperty("启用时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime activationTime; @ApiModelProperty("预计报废时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime expectedScrapTime; @ApiModelProperty("实际报废时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime actualScrapTime; @ApiModelProperty("状态变更时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime statusChangeTime; @ApiModelProperty("采购订单") @@ -115,12 +122,15 @@ public class EquipmentResp implements Serializable { private BigDecimal salvageValue; @ApiModelProperty("保修截止日期") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime warrantyExpireDate; @ApiModelProperty("上次维护日期") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime lastMaintenanceDate; @ApiModelProperty("下次维护日期") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime nextMaintenanceDate; @ApiModelProperty("维护人员") @@ -168,12 +178,15 @@ public class EquipmentResp implements Serializable { private String usingDepartment; @ApiModelProperty("领用时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime borrowingTime; @ApiModelProperty("归还时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime returnTime; @ApiModelProperty("出库时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime outStockTime; @ApiModelProperty("总使用时间") @@ -234,8 +247,10 @@ public class EquipmentResp implements Serializable { private String name; @ApiModelProperty("创建时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime createTime; @ApiModelProperty("更新时间") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8") private LocalDateTime updateTime; } diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberListReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberListReq.java deleted file mode 100644 index 92eda45..0000000 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberListReq.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dite.znpt.domain.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -/** - * @author wangna - * @date 2025/08/05 - * @Description: 项目人员查询请求VO - */ -@Data -@ApiModel(value="ProjectMemberListReq对象", description="项目人员查询请求") -public class ProjectMemberListReq { - - @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("角色类型") - private String roleType; - - @ApiModelProperty("岗位代码") - private String jobCode; - - @ApiModelProperty("状态") - private String status; - - @ApiModelProperty("用户姓名(模糊查询)") - private String userName; - - @ApiModelProperty("用户账号(模糊查询)") - private String userAccount; -} \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberResp.java index a633545..c69e49c 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberResp.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberResp.java @@ -1,5 +1,6 @@ package com.dite.znpt.domain.vo; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -45,8 +46,34 @@ public class ProjectMemberResp { @ApiModelProperty("用户ID") private String userId; - @ApiModelProperty("用户姓名") - private String userName; + // ========================== 前端需要的字段 ========================== + + @ApiModelProperty("姓名") + private String name; + + @ApiModelProperty("联系电话") + private String phone; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("项目岗位") + private String position; + + @ApiModelProperty("状态") + private String status; + + @ApiModelProperty("技能标签") + private String skills; + + @ApiModelProperty("入职日期") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate joinDate; + + @ApiModelProperty("备注") + private String remark; + + // ========================== 保留的原有字段(用于内部处理) ========================== @ApiModelProperty("用户账号") private String userAccount; @@ -69,15 +96,10 @@ public class ProjectMemberResp { @ApiModelProperty("岗位描述") private String jobDesc; - @ApiModelProperty("加入时间") - private LocalDate joinDate; - @ApiModelProperty("离开时间") + @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate leaveDate; - @ApiModelProperty("状态") - private String status; - - @ApiModelProperty("备注") - private String remark; + @ApiModelProperty("状态描述") + private String statusDesc; } \ No newline at end of file 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/TeamMemberQuery.java b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberQuery.java new file mode 100644 index 0000000..c147e51 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberQuery.java @@ -0,0 +1,39 @@ +package com.dite.znpt.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author wangna + * @date 2025/08/05 + * @Description: 团队成员查询参数(支持筛选、分页、搜索) + */ +@Data +@ApiModel(value="TeamMemberQuery对象", description="团队成员查询参数") +public class TeamMemberQuery { + + @ApiModelProperty("项目ID") + private String projectId; + + @ApiModelProperty("姓名搜索") + private String name; + + @ApiModelProperty("岗位筛选") + private String position; + + @ApiModelProperty("状态筛选") + private String status; + + @ApiModelProperty("当前页码") + private Integer pageNum = 1; + + @ApiModelProperty("每页大小") + private Integer pageSize = 10; + + @ApiModelProperty("排序列") + private String orderByColumn; + + @ApiModelProperty("排序方向") + private String isAsc = "asc"; +} \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberReq.java b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberReq.java similarity index 65% rename from core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberReq.java rename to core/src/main/java/com/dite/znpt/domain/vo/TeamMemberReq.java index d2ffb17..be6af52 100644 --- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectMemberReq.java +++ b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberReq.java @@ -6,19 +6,17 @@ import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import java.io.Serializable; import java.time.LocalDate; /** * @author wangna * @date 2025/08/05 - * @Description: 项目人员请求VO + * @Description: 团队成员请求类(用于创建和更新) */ @Data -@ApiModel(value="ProjectMemberReq对象", description="项目人员请求") -public class ProjectMemberReq { - - @ApiModelProperty("关联ID(更新时必填)") - private String memberId; +@ApiModel(value="TeamMemberReq对象", description="团队成员请求类") +public class TeamMemberReq implements Serializable { @NotBlank(message = "项目ID不能为空") @ApiModelProperty("项目ID") @@ -38,10 +36,10 @@ public class ProjectMemberReq { private String userId; @NotBlank(message = "角色类型不能为空") - @ApiModelProperty("角色类型") + @ApiModelProperty("项目角色类型:PROJECT_MANAGER-项目经理,SAFETY_OFFICER-安全员,QUALITY_OFFICER-质量员,CONSTRUCTOR-施工人员,TEAM_LEADER-施工组长") private String roleType; - @ApiModelProperty("岗位代码") + @ApiModelProperty("具体岗位代码(如:GROUND_SERVICE-地勤,DRIVER-司机,ASCENDING-登高等)") private String jobCode; @ApiModelProperty("岗位描述") @@ -54,9 +52,9 @@ public class ProjectMemberReq { @ApiModelProperty("离开时间") private LocalDate leaveDate; - @ApiModelProperty("状态") - private String status; + @ApiModelProperty("状态:ACTIVE-在职,INACTIVE-离职,PENDING-待入职") + private String status = "ACTIVE"; @ApiModelProperty("备注") private String remark; -} \ No newline at end of file +} \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/mapper/BusinessDataFileMapper.java b/core/src/main/java/com/dite/znpt/mapper/BusinessDataFileMapper.java index 6192769..02d682b 100644 --- a/core/src/main/java/com/dite/znpt/mapper/BusinessDataFileMapper.java +++ b/core/src/main/java/com/dite/znpt/mapper/BusinessDataFileMapper.java @@ -1,20 +1,29 @@ -package com.dite.znpt.mapper; - -import com.dite.znpt.domain.entity.BusinessDataFileEntity; -import io.swagger.annotations.ApiOperation; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -@ApiOperation("商务资料文件对象") -public interface BusinessDataFileMapper { - public List List(@Param("folderId") Long folderId, @Param("fileName") String fileName); - void delete(@Param("fileId") Long fileId,@Param("folderId") Long folderId); - - void add(BusinessDataFileEntity businessDataFileEntity); - - String getPath(Long fileId); - - // 在接口中添加重命名方法 - void reName(@Param("fileId") Long fileId, @Param("newFileName") String newFileName, @Param("newFilePath") String newFilePath); -} +package com.dite.znpt.mapper; + +import com.dite.znpt.domain.entity.BusinessDataFileEntity; +import com.dite.znpt.domain.entity.BusinessDataEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiOperation; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@ApiOperation("商务资料文件对象") +@Mapper +public interface BusinessDataFileMapper { + + // 新增文件预览方法 + + + public List List(@Param("folderId") Long folderId, @Param("fileName") String fileName); + void delete(@Param("fileId") Long fileId,@Param("folderId") Long folderId); + + void add(BusinessDataFileEntity businessDataFileEntity); + + String getPath(Long fileId); + + // 在接口中添加重命名方法 + void reName(@Param("fileId") Long fileId, @Param("newFileName") String newFileName, @Param("newFilePath") String newFilePath); +} diff --git a/core/src/main/java/com/dite/znpt/mapper/BusinessDataMapper.java b/core/src/main/java/com/dite/znpt/mapper/BusinessDataMapper.java index b92887f..b7e4bae 100644 --- a/core/src/main/java/com/dite/znpt/mapper/BusinessDataMapper.java +++ b/core/src/main/java/com/dite/znpt/mapper/BusinessDataMapper.java @@ -1,26 +1,32 @@ -package com.dite.znpt.mapper; - -import com.dite.znpt.domain.entity.BusinessDataEntity; -import io.swagger.annotations.ApiOperation; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - - - - - -@ApiOperation("商务资料文件夹对象") -public interface BusinessDataMapper { - public String getPath(Long parentId); - - public List List(); - - void insert(BusinessDataEntity businessDataEntity); - - void delete(Long folderId); - - void reName(BusinessDataEntity businessDataEntity); - - public List ListWithCondition(@Param("folderName") String folderName); -} +package com.dite.znpt.mapper; + +import com.baomidou.mybatisplus.core.injector.methods.SelectList; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dite.znpt.domain.entity.BusinessDataEntity; +import io.swagger.annotations.ApiOperation; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDateTime; +import java.util.List; + + + + + +@ApiOperation("商务资料文件夹对象") +@Mapper +public interface BusinessDataMapper { + public String getPath(Long parentId); + + public List List(); + + void insert(BusinessDataEntity businessDataEntity); + + void delete(Long folderId); + + void reName(BusinessDataEntity businessDataEntity); + + public List ListWithCondition(@Param("folderName") String folderName); +} diff --git a/core/src/main/java/com/dite/znpt/mapper/ProjectMemberMapper.java b/core/src/main/java/com/dite/znpt/mapper/ProjectMemberMapper.java index d514e90..106a33d 100644 --- a/core/src/main/java/com/dite/znpt/mapper/ProjectMemberMapper.java +++ b/core/src/main/java/com/dite/znpt/mapper/ProjectMemberMapper.java @@ -2,10 +2,9 @@ package com.dite.znpt.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dite.znpt.domain.entity.ProjectMemberEntity; -import com.dite.znpt.domain.vo.ProjectMemberListReq; import com.dite.znpt.domain.vo.ProjectMemberResp; +import com.dite.znpt.domain.vo.TeamMemberQuery; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; import java.util.List; @@ -18,37 +17,7 @@ import java.util.List; public interface ProjectMemberMapper extends BaseMapper { /** - * 根据条件查询项目人员列表 + * 获取项目团队成员列表(支持筛选、分页、搜索) */ - List queryBySelective(ProjectMemberListReq req); - - /** - * 根据项目ID查询项目人员列表 - */ - List queryByProjectId(@Param("projectId") String projectId); - - /** - * 根据机组ID查询机组人员列表 - */ - List queryByTurbineId(@Param("turbineId") String turbineId); - - /** - * 根据任务组ID查询任务组人员列表 - */ - List queryByTaskGroupId(@Param("taskGroupId") String taskGroupId); - - /** - * 根据任务ID查询任务人员列表 - */ - List queryByTaskId(@Param("taskId") String taskId); - - /** - * 根据用户ID查询用户参与的项目列表 - */ - List queryByUserId(@Param("userId") String userId); - - /** - * 根据项目ID和角色类型查询人员列表 - */ - List queryByProjectIdAndRoleType(@Param("projectId") String projectId, @Param("roleType") String roleType); + List queryTeamMembers(TeamMemberQuery query); } \ No newline at end of file diff --git a/core/src/main/java/com/dite/znpt/service/BusinessDataFileService.java b/core/src/main/java/com/dite/znpt/service/BusinessDataFileService.java index 5b8d99c..9eafc83 100644 --- a/core/src/main/java/com/dite/znpt/service/BusinessDataFileService.java +++ b/core/src/main/java/com/dite/znpt/service/BusinessDataFileService.java @@ -1,27 +1,41 @@ -package com.dite.znpt.service; - -import com.dite.znpt.domain.Result; -import com.dite.znpt.domain.entity.BusinessDataFileEntity; -import com.dite.znpt.domain.page.PageBean; -import io.swagger.annotations.ApiOperation; -import org.springframework.stereotype.Service; -import org.springframework.web.bind.annotation.RequestParam; - -@ApiOperation("商务资料文件service") -@Service -public interface BusinessDataFileService { - - PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName); - - Result delete(@RequestParam(value = "fileId", required = false) Long fileId,@RequestParam(value = "foldelId", required = false) Long folderId); - - void add(BusinessDataFileEntity businessDataFileEntity); - - String getPath(Long fileId); - - // 在接口中添加重命名方法 - Result reName(Long fileId, String newFileName); - - // 在接口中添加预览方法 -// Result preview(Long fileId, HttpServletResponse response); -} +package com.dite.znpt.service; + +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.entity.BusinessDataFileEntity; +import com.dite.znpt.domain.page.PageBean; +import io.swagger.annotations.ApiOperation; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; + +@ApiOperation("商务资料文件service") +@Service +public interface BusinessDataFileService { + + @ApiOperation("分页查询文件") + PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName); + + @ApiOperation("删除文件") + Result delete(@RequestParam(value = "fileId", required = false) Long fileId,@RequestParam(value = "foldelId", required = false) Long folderId); + + @ApiOperation("增加数据库文件信息") + void add(BusinessDataFileEntity businessDataFileEntity); + + @ApiOperation("获取文件路径") + String getPath(Long fileId); + + @ApiOperation("删除文件") + // 在接口中添加重命名方法 + Result reName(Long fileId, String newFileName); + + @ApiOperation("下载文件") + void upload(Long fileId, HttpServletResponse response); + + @ApiOperation("上传文件") + Result addfile(MultipartFile file, Long folderId); + + @ApiOperation("预览文件") + void preview(Long fileId, HttpServletResponse response); +} diff --git a/core/src/main/java/com/dite/znpt/service/BusinessDataService.java b/core/src/main/java/com/dite/znpt/service/BusinessDataService.java index ec37987..f4a826c 100644 --- a/core/src/main/java/com/dite/znpt/service/BusinessDataService.java +++ b/core/src/main/java/com/dite/znpt/service/BusinessDataService.java @@ -1,15 +1,18 @@ -package com.dite.znpt.service; - -import com.dite.znpt.domain.Result; -import com.dite.znpt.domain.page.PageBean; -import io.swagger.annotations.ApiOperation; - -@ApiOperation("商务资料文件夹service") -public interface BusinessDataService { - - PageBean pageSelect(Integer page, Integer pageSize, String folderName); - Result createFolder(String folderName, Long parentId); - String getPath(Long parentId); - Result delete(Long folderId); - Result reName(Long folderId, String newName); -} +package com.dite.znpt.service; + +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.page.PageBean; +import io.swagger.annotations.ApiOperation; + +import javax.servlet.http.HttpServletResponse; + +@ApiOperation("商务资料文件夹service") +public interface BusinessDataService { + + PageBean pageSelect(Integer page, Integer pageSize, String folderName); + Result createFolder(String folderName, Long parentId); + String getPath(Long parentId); + Result delete(Long folderId); + Result reName(Long folderId, String newName); + +} diff --git a/core/src/main/java/com/dite/znpt/service/EquipmentApprovalService.java b/core/src/main/java/com/dite/znpt/service/EquipmentApprovalService.java new file mode 100644 index 0000000..2164186 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/EquipmentApprovalService.java @@ -0,0 +1,60 @@ +package com.dite.znpt.service; + +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 + * @date 2025/1/8/周三 17:50 + * @description 设备审批服务接口 + */ +public interface EquipmentApprovalService { + + /** + * 分页查询待审批的设备采购申请 + */ + IPage getPendingApprovals(EquipmentApprovalListReq req); + + /** + * 分页查询已审批的设备采购申请 + */ + IPage getApprovedApprovals(EquipmentApprovalListReq req); + + /** + * 审批通过 + */ + void approve(String approvalId, EquipmentApprovalReq req); + + /** + * 审批拒绝 + */ + void reject(String approvalId, EquipmentApprovalReq req); + + /** + * 获取审批详情 + */ + EquipmentApprovalResp getApprovalDetail(String approvalId); + + /** + * 获取审批统计信息 + */ + 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/ProjectMemberService.java b/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java index 9004093..939ff8a 100644 --- a/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java +++ b/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java @@ -1,11 +1,10 @@ package com.dite.znpt.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.dite.znpt.domain.PageResult; import com.dite.znpt.domain.entity.ProjectMemberEntity; import com.dite.znpt.domain.vo.*; -import java.util.List; - /** * @author wangna * @date 2025/08/05 @@ -14,79 +13,24 @@ import java.util.List; public interface ProjectMemberService extends IService { /** - * 查询项目人员列表 + * 获取项目团队成员列表(支持筛选、分页、搜索) */ - List selectList(ProjectMemberListReq req); + PageResult getProjectTeamMembers(TeamMemberQuery query); /** - * 根据项目ID查询项目人员列表 + * 创建团队成员 */ - List selectByProjectId(String projectId); + ProjectMemberResp createTeamMember(TeamMemberReq req); /** - * 根据机组ID查询机组人员列表 + * 更新团队成员信息 */ - List selectByTurbineId(String turbineId); + ProjectMemberResp updateTeamMember(String memberId, TeamMemberReq req); /** - * 根据任务组ID查询任务组人员列表 + * 删除团队成员(支持单个或批量删除) */ - List selectByTaskGroupId(String taskGroupId); - - /** - * 根据任务ID查询任务人员列表 - */ - List selectByTaskId(String taskId); - - /** - * 根据用户ID查询用户参与的项目列表 - */ - List selectByUserId(String userId); - - /** - * 根据项目ID和角色类型查询人员列表 - */ - List selectByProjectIdAndRoleType(String projectId, String roleType); - - /** - * 新增项目人员 - */ - void saveData(ProjectMemberReq req); - - /** - * 更新项目人员 - */ - void updateData(ProjectMemberReq req); - - /** - * 删除项目人员 - */ - void deleteById(String memberId); - - /** - * 批量添加项目人员 - */ - void batchAddMembers(List reqList); - - /** - * 根据项目ID删除所有项目人员 - */ - void deleteByProjectId(String projectId); - - /** - * 根据机组ID删除所有机组人员 - */ - void deleteByTurbineId(String turbineId); - - /** - * 根据任务组ID删除所有任务组人员 - */ - void deleteByTaskGroupId(String taskGroupId); - - /** - * 根据任务ID删除所有任务人员 - */ - void deleteByTaskId(String taskId); + boolean deleteTeamMembers(String... memberIds); // ========================== 项目看板相关方法 ========================== 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/BusinessDataFileServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/BusinessDataFileServiceImpl.java index 2392b49..660f034 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/BusinessDataFileServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/BusinessDataFileServiceImpl.java @@ -1,163 +1,530 @@ -package com.dite.znpt.service.impl; - - - -import com.dite.znpt.domain.Result; -import com.dite.znpt.domain.entity.BusinessDataFileEntity; -import com.dite.znpt.domain.page.PageBean; -import com.dite.znpt.mapper.BusinessDataFileMapper; -import com.dite.znpt.service.BusinessDataFileService; -import com.github.pagehelper.Page; -import com.github.pagehelper.PageHelper; -import io.swagger.annotations.ApiOperation; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.io.File; -import java.io.IOException; -import java.util.List; - -import static jodd.io.FileUtil.deleteFile; -import static org.apache.tomcat.util.http.fileupload.FileUtils.deleteDirectory; - -@AllArgsConstructor -@Service -@ApiOperation("商务资料文件service实现类") -public class BusinessDataFileServiceImpl implements BusinessDataFileService { - @Resource - private BusinessDataFileMapper businessDataFileMapper; - - - @ApiOperation("分页查询文件") - @Override - public PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName) { - PageHelper.startPage(page, pageSize); - List list = businessDataFileMapper.List(folderId, fileName); - Page p = (Page) list; - PageBean pageBean = new PageBean(p.getTotal(), p.getResult()); - return pageBean; - } - @ApiOperation("删除文件") - public Result delete(Long fileId, Long folderId) { - //删除数据库数据 - if (folderId != null){ - businessDataFileMapper.delete(null,folderId); - System.out.println("888888888走对了"); - - return Result.okM("删除,走对了,成功"); - } - - //删除文件 - String sPath = businessDataFileMapper.getPath(fileId); - - businessDataFileMapper.delete(fileId,null); - - boolean flag = false; - File file = new File(sPath); - // 判断目录或文件是否存在 - if (!file.exists()) { // 不存在返回 false - return Result.error("文件不存在"); - } else { - // 判断是否为文件 - if (file.isFile()) { // 为文件时调用删除文件方法 - try { - deleteFile(file); - } catch (IOException e) { - throw new RuntimeException(e); - } - return Result.okM("删除成功"); - } else { // 为目录时调用删除目录方法 - try { - deleteDirectory(file); - } catch (IOException e) { - throw new RuntimeException(e); - } - return Result.okM("删除成功"); - } - } - - - } - - @ApiOperation("增加文件") - public void add(BusinessDataFileEntity businessDataFileEntity) { - businessDataFileMapper.add(businessDataFileEntity); - } - - @ApiOperation("获取文件路径") - public String getPath(Long fileId) { - return businessDataFileMapper.getPath(fileId); - } - - @ApiOperation("重命名文件") - @Override - public Result reName(Long fileId, String newFileName) { - // 参数校验 - if (fileId == null) { - return Result.error("文件ID不能为空"); - } - if (newFileName == null || newFileName.trim().isEmpty()) { - return Result.error("新文件名不能为空"); - } - if (newFileName.length() > 100) { - return Result.error("文件名过长"); - } - - try { - // 获取原文件信息 - String oldFilePath = businessDataFileMapper.getPath(fileId); - if (oldFilePath == null) { - return Result.error("文件不存在"); - } - - // 创建原文件对象 - File oldFile = new File(oldFilePath); - if (!oldFile.exists()) { - return Result.error("文件不存在"); - } - - // 构建新文件路径 - String parentPath = oldFile.getParent(); - String fileExtension = ""; - String fileNameWithoutExt = newFileName; - - // 获取原文件扩展名 - int lastDotIndex = oldFile.getName().lastIndexOf('.'); - if (lastDotIndex > 0) { - fileExtension = oldFile.getName().substring(lastDotIndex); - } - - // 如果新文件名没有扩展名,则添加原文件扩展名 - if (!newFileName.contains(".")) { - newFileName = newFileName + fileExtension; - } - - // 构建新文件路径 - String newFilePath = parentPath + File.separator + newFileName; - File newFile = new File(newFilePath); - - // 检查新文件名是否已存在 - if (newFile.exists()) { - return Result.error("文件名已存在"); - } - - // 重命名实际文件 - boolean renameSuccess = oldFile.renameTo(newFile); - if (!renameSuccess) { - return Result.error("文件重命名失败"); - } - - // 更新数据库中的文件信息 - businessDataFileMapper.reName(fileId, newFileName, newFilePath); - - return Result.okM("文件重命名成功"); - - } catch (Exception e) { - return Result.error("文件重命名失败: " + e.getMessage()); - } - } - - - -} +package com.dite.znpt.service.impl; + + +import javax.servlet.http.HttpServletResponse; +import java.io.FileInputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.springframework.util.MimeTypeUtils; +import org.springframework.http.MediaType; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import java.util.Base64; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +// +import cn.dev33.satoken.stp.StpUtil; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.entity.BusinessDataFileEntity; +import com.dite.znpt.domain.page.PageBean; +import com.dite.znpt.mapper.BusinessDataFileMapper; +import com.dite.znpt.mapper.BusinessDataMapper; +import com.dite.znpt.service.BusinessDataFileService; +import com.dite.znpt.service.BusinessDataService; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.util.Date; +import java.util.List; + +import static jodd.io.FileUtil.deleteFile; +import static org.apache.tomcat.util.http.fileupload.FileUtils.deleteDirectory; + +@AllArgsConstructor +@Service +@ApiOperation("商务资料文件service实现类") +public class BusinessDataFileServiceImpl implements BusinessDataFileService { + @Resource + private BusinessDataFileMapper businessDataFileMapper; + @Resource + private BusinessDataService businessDataService; + + + @ApiOperation("分页查询文件") + @Override + public PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName) { + PageHelper.startPage(page, pageSize); + List list = businessDataFileMapper.List(folderId, fileName); + Page p = (Page) list; + PageBean pageBean = new PageBean(p.getTotal(), p.getResult()); + return pageBean; + } + @ApiOperation("删除文件") + public Result delete(Long fileId, Long folderId) { + //删除数据库数据 + if (folderId != null){ + businessDataFileMapper.delete(null,folderId); + return Result.okM("删除成功"); + } + + //删除文件 + String sPath = businessDataFileMapper.getPath(fileId); + + businessDataFileMapper.delete(fileId,null); + + boolean flag = false; + File file = new File(sPath); + // 判断目录或文件是否存在 + if (!file.exists()) { // 不存在返回 false + return Result.error("文件不存在"); + } else { + // 判断是否为文件 + if (file.isFile()) { // 为文件时调用删除文件方法 + try { + deleteFile(file); + } catch (IOException e) { + throw new RuntimeException(e); + } + return Result.okM("删除成功"); + } else { // 为目录时调用删除目录方法 + try { + deleteDirectory(file); + } catch (IOException e) { + throw new RuntimeException(e); + } + return Result.okM("删除成功"); + } + } + } + + @ApiOperation("增加文件") + public void add(BusinessDataFileEntity businessDataFileEntity) { + businessDataFileMapper.add(businessDataFileEntity); + } + + @ApiOperation("获取文件路径") + public String getPath(Long fileId) { + return businessDataFileMapper.getPath(fileId); + } + + @ApiOperation("重命名文件") + @Override + public Result reName(Long fileId, String newFileName) { + // 参数校验 + if (fileId == null) { + return Result.error("文件ID不能为空"); + } + if (newFileName == null || newFileName.trim().isEmpty()) { + return Result.error("新文件名不能为空"); + } + if (newFileName.length() > 100) { + return Result.error("文件名过长"); + } + + try { + // 获取原文件信息 + String oldFilePath = businessDataFileMapper.getPath(fileId); + if (oldFilePath == null) { + return Result.error("文件不存在"); + } + + // 创建原文件对象 + File oldFile = new File(oldFilePath); + if (!oldFile.exists()) { + return Result.error("文件不存在"); + } + + // 构建新文件路径 + String parentPath = oldFile.getParent(); + String fileExtension = ""; + String fileNameWithoutExt = newFileName; + + // 获取原文件扩展名 + int lastDotIndex = oldFile.getName().lastIndexOf('.'); + if (lastDotIndex > 0) { + fileExtension = oldFile.getName().substring(lastDotIndex); + } + + // 如果新文件名没有扩展名,则添加原文件扩展名 + if (!newFileName.contains(".")) { + newFileName = newFileName + fileExtension; + } + + // 构建新文件路径 + String newFilePath = parentPath + File.separator + newFileName; + File newFile = new File(newFilePath); + + // 检查新文件名是否已存在 + if (newFile.exists()) { + return Result.error("文件名已存在"); + } + + // 重命名实际文件 + boolean renameSuccess = oldFile.renameTo(newFile); + if (!renameSuccess) { + return Result.error("文件重命名失败"); + } + + // 更新数据库中的文件信息 + businessDataFileMapper.reName(fileId, newFileName, newFilePath); + + return Result.okM("文件重命名成功"); + + } catch (Exception e) { + return Result.error("文件重命名失败: " + e.getMessage()); + } + } + + @ApiOperation("下载文件") + @Override + public void upload(Long fileId, HttpServletResponse response) { + String path = getPath(fileId); + try { + // path是指想要下载的文件的路径 + File file = new File(path); + // 获取文件名 + String filename = file.getName(); + // 获取文件后缀名 + String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase(); + // 将文件写入输入流 + FileInputStream fileInputStream = new FileInputStream(file); + InputStream fis = new BufferedInputStream(fileInputStream); + byte[] buffer = new byte[fis.available()]; + fis.read(buffer); + fis.close(); + + // 清空response + response.reset(); + // 设置response的Header + response.setCharacterEncoding("UTF-8"); + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + // 告知浏览器文件的大小 + response.addHeader("Content-Length", "" + file.length()); + OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); + response.setContentType("application/octet-stream"); + outputStream.write(buffer); + outputStream.flush(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + @ApiOperation("上传文件") + @Override + public Result addfile(MultipartFile file, Long folderId) { + String loginIdAsLong = "未登录用户"; + if(StpUtil.isLogin()){ + loginIdAsLong = StpUtil.getLoginIdAsString(); + } + + if (file.isEmpty()) { + return Result.error("上传文件为空"); + } + // TODO 以后可以优化,就算文件名一样,加个(1),(2)这种 + + try { + byte[] bytes = file.getBytes(); + String uploadDir = businessDataService.getPath(folderId); + + File uploadedFile = new File(uploadDir + "\\" + file.getOriginalFilename()); + if (uploadedFile.exists()) { + return Result.error("文件已存在"); + } + file.transferTo(uploadedFile); + + // 保存文件信息到数据 + BusinessDataFileEntity fileEntity = new BusinessDataFileEntity(); + fileEntity.setFolderId(folderId); + fileEntity.setFileName(file.getOriginalFilename()); + fileEntity.setFilePath(uploadDir + "\\" + file.getOriginalFilename()); + fileEntity.setFileType(file.getContentType()); + fileEntity.setFileSize(file.getSize()/1024); + fileEntity.setUploadTime(new Date()); + fileEntity.setUploaderId(loginIdAsLong); + System.out.println(uploadDir + "\\" + file.getOriginalFilename()); + add(fileEntity); + + return Result.okM("上传成功"); + } catch (IOException e) { + e.printStackTrace(); + return Result.error("上传失败"); + } + } + + + @ApiOperation("文件预览") + public void preview(Long fileId, HttpServletResponse response) { + try { + // 获取文件路径 + String filePath = businessDataFileMapper.getPath(fileId); + if (filePath == null || filePath.isEmpty()) { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"文件不存在\"}"); + return; + } + + File file = new File(filePath); + if (!file.exists()) { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"文件不存在\"}"); + return; + } + + // 获取文件扩展名 + String extension = getFileExtension(filePath); + // ... 后续 switch 语句 + + // 根据文件类型处理预览 + switch (extension) { + case "pdf": + previewPdf(file, response); + break; + case "jpg": + case "jpeg": + case "png": + case "gif": + case "bmp": + case "webp": + previewImage(file, response); + break; + case "txt": + case "md": + case "log": + previewText(file, response); + break; + case "doc": + case "docx": + case "xls": + case "xlsx": + case "ppt": + case "pptx": + previewOffice(file, response); + break; + case "mp4": + case "avi": + case "mov": + case "wmv": + case "flv": + previewVideo(file, response); + break; + case "mp3": + case "wav": + case "flac": + case "aac": + previewAudio(file, response); + break; + default: + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"暂不支持该文件类型的预览\"}"); + } catch (IOException e) { + e.printStackTrace(); + } + break; + } + } catch (Exception e) { + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"文件预览失败: " + e.getMessage() + "\"}"); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + private String getFileExtension(String filePath) { + if (filePath == null || filePath.isEmpty()) { + return ""; + } + // 从路径中提取文件名 + String fileName = new File(filePath).getName(); + int lastDotIndex = fileName.lastIndexOf('.'); + if (lastDotIndex == -1) { + return ""; + } + return fileName.substring(lastDotIndex + 1).toLowerCase(); + } + + private void previewPdf(File file, HttpServletResponse response) { + try { + response.setContentType("application/pdf"); + response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getName(), "UTF-8")); + + try (FileInputStream fis = new FileInputStream(file); + OutputStream os = response.getOutputStream()) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + } + } catch (Exception e) { + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"PDF预览失败: " + e.getMessage() + "\"}"); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + private void previewImage(File file, HttpServletResponse response) { + try { + String contentType = getImageContentType(file.getName()); + response.setContentType(contentType); + response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getName(), "UTF-8")); + + try (FileInputStream fis = new FileInputStream(file); + OutputStream os = response.getOutputStream()) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + } + } catch (Exception e) { + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"图片预览失败: " + e.getMessage() + "\"}"); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + private void previewText(File file, HttpServletResponse response) { + try { + response.setContentType("text/plain; charset=UTF-8"); + response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getName(), "UTF-8")); + + try (FileInputStream fis = new FileInputStream(file); + OutputStream os = response.getOutputStream()) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + } + } catch (Exception e) { + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"文本预览失败: " + e.getMessage() + "\"}"); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + private void previewOffice(File file, HttpServletResponse response) { + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"Office文件预览功能暂未实现,请下载后查看\"}"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void previewVideo(File file, HttpServletResponse response) { + try { + String contentType = getVideoContentType(file.getName()); + response.setContentType(contentType); + response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getName(), "UTF-8")); + + try (FileInputStream fis = new FileInputStream(file); + OutputStream os = response.getOutputStream()) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + } + } catch (Exception e) { + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"视频预览失败: " + e.getMessage() + "\"}"); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + private void previewAudio(File file, HttpServletResponse response) { + try { + String contentType = getAudioContentType(file.getName()); + response.setContentType(contentType); + response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getName(), "UTF-8")); + + try (FileInputStream fis = new FileInputStream(file); + OutputStream os = response.getOutputStream()) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + } + } catch (Exception e) { + try { + response.setContentType("application/json; charset=UTF-8"); + response.getWriter().write("{\"status\":500,\"msg\":\"音频预览失败: " + e.getMessage() + "\"}"); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + private String getImageContentType(String fileName) { + String extension = getFileExtension(fileName); + switch (extension) { + case "jpg": + case "jpeg": + return "image/jpeg"; + case "png": + return "image/png"; + case "gif": + return "image/gif"; + case "bmp": + return "image/bmp"; + case "webp": + return "image/webp"; + default: + return "application/octet-stream"; + } + } + + private String getVideoContentType(String fileName) { + String extension = getFileExtension(fileName); + switch (extension) { + case "mp4": + return "video/mp4"; + case "avi": + return "video/x-msvideo"; + case "mov": + return "video/quicktime"; + case "wmv": + return "video/x-ms-wmv"; + case "flv": + return "video/x-flv"; + default: + return "application/octet-stream"; + } + } + + private String getAudioContentType(String fileName) { + String extension = getFileExtension(fileName); + switch (extension) { + case "mp3": + return "audio/mpeg"; + case "wav": + return "audio/wav"; + case "flac": + return "audio/flac"; + case "aac": + return "audio/aac"; + default: + return "application/octet-stream"; + } + } + +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/BusinessDataServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/BusinessDataServiceImpl.java index 3d74793..2f17a2b 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/BusinessDataServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/BusinessDataServiceImpl.java @@ -1,197 +1,179 @@ -package com.dite.znpt.service.impl; - -import com.dite.znpt.domain.Result; -import com.dite.znpt.domain.entity.BusinessDataEntity; -import com.dite.znpt.domain.page.PageBean; -import com.dite.znpt.mapper.BusinessDataMapper; -import com.dite.znpt.service.BusinessDataFileService; -import com.dite.znpt.service.BusinessDataService; -import com.github.pagehelper.Page; -import com.github.pagehelper.PageHelper; -import io.swagger.annotations.ApiOperation; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.LocalDateTime; -import java.util.Comparator; -import java.util.List; - -/** - * 商务资料文件夹实现类 - */ -@Service -@ApiOperation("商务资料文件夹service实现类") -@AllArgsConstructor -@NoArgsConstructor -public class BusinessDataServiceImpl implements BusinessDataService { - @Resource - private BusinessDataMapper businessDataMapper; - @Resource - private BusinessDataFileService businessDataFileService; - - // 从配置文件中读取基础路径(默认值:D:/upload/businessData) - // ,新建文件夹的时候,如果没指定父文件夹Id,就用这个 - @Value("${file.upload.businessDataPath:D:/upload/businessData}") - private String businessDataPath; - - @ApiOperation(value = "分页查询") - @Override - public PageBean pageSelect(Integer page, Integer pageSize, String folderName) { - PageHelper.startPage(page, pageSize); - List businessDataEntityList = businessDataMapper.ListWithCondition(folderName); - Page p = (Page) businessDataEntityList; - PageBean pageBean = new PageBean(p.getTotal(), p.getResult()); - return pageBean; - } - - @ApiOperation(value = "创建文件夹") - @Override - public Result createFolder(String folderName, Long parentId) { - //获取ID - Long loginIdAsLong = 888L; -// loginIdAsLong = StpUtil.getLoginIdAsLong(); -// - // 文件夹名称不能为空 - //TODO: 添加文件夹名称校验,后续最好更规范些,写个工具类专门校验,用正则表达式 - if (folderName == null || folderName.trim().isEmpty()) { - return Result.error("文件夹名称不能为空"); - } - if (folderName.length() > 50) { - return Result.error("文件夹名称过长"); - } - - // 文件夹名称前置一个/ - String folderName1 = "/" + folderName; - // 目标文件夹 - File targetDir=Paths.get(businessDataPath, folderName1).toFile(); - if(parentId != 0L){ - // 获取父文件夹路径 - targetDir = Paths.get(businessDataMapper.getPath(parentId), folderName1).toFile(); - } - // 创建文件夹和新增文件夹路径 - if (!targetDir.exists()) { - // 创建文件夹 - boolean created = targetDir.mkdirs(); - if (!created) { - throw new RuntimeException("文件夹创建失败: " + targetDir.getAbsolutePath()); - } - //上面是新增文件夹功能,但没有往数据库插入文件夹相关数据,所以下面新增 - // 创建BusinessDataEntity对象并设置属性 - BusinessDataEntity businessDataEntity = new BusinessDataEntity( - null, - folderName, - parentId, - loginIdAsLong, - LocalDateTime.now(), - LocalDateTime.now(), - false, - targetDir.getAbsolutePath() - ); - // 插入到数据库 - businessDataMapper.insert(businessDataEntity); - return Result.okM( "文件夹创建成功"); - } else { - return Result.error("文件夹已存在: "); - } - } - - @ApiOperation("获取文件夹路径") - public String getPath(Long parentId) { - return businessDataMapper.getPath(parentId); - } - -// @ApiOperation("删除文件夹") -// @Override -// public Result delete(Long folderId) { -// // 获取文件夹路径 -// String folderPath = businessDataMapper.getPath(folderId); -// -// // 创建File对象并删除文件夹 -// File folder = new File(folderPath); -// if (folder.exists()) { -// boolean deleted = folder.delete(); -// if (!deleted) { -// // throw new RuntimeException("文件夹删除失败: " + folderPath); -// // TODO: 以后可以用全局异常处理器捕获,或者用try catch捕获 -// return Result.error("文件夹删除失败: " + folderPath); -// } -// //删除数据库中文件夹的数据 -// businessDataMapper.delete(folderId); -// //删除文件夹下文件的数据 -// businessDataFileService.delete(folderId); -// return Result.okM("删除成功"); -// } else { -// // throw new RuntimeException("文件夹不存在: " + folderPath); -// return Result.error("文件夹不存在: " + folderPath); -// } -// } - @ApiOperation("删除文件夹") - @Override - public Result delete(Long folderId) { - // 获取文件夹路径 - String folderPath = businessDataMapper.getPath(folderId); - - // 创建Path对象并删除文件夹 - Path folder = Paths.get(folderPath); - if (Files.exists(folder)) { - try { - // 使用Files.walk获取所有文件和目录,按深度排序后删除 - java.util.stream.Stream filePaths = Files.walk(folder); - filePaths.sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - filePaths.close(); - - //删除数据库中文件夹的数据 - businessDataMapper.delete(folderId); - //删除文件夹下文件的数据 - businessDataFileService.delete(null , folderId); - return Result.okM("删除成功"); - } catch (Exception e) { - return Result.okM("删除成功"); - } - } else { - return Result.error("文件夹不存在: " + folderPath); - } - } - @ApiOperation("重命名文件夹") - @Override - public Result reName(Long folderId, String newName) { - // 获取文件夹路径 - String folderPath = businessDataMapper.getPath(folderId); - String newPath = folderPath.substring(0, folderPath.lastIndexOf('\\'))+"\\" + newName; - System.out.printf("7777777"+newPath); -// -// //想命名的原文件的路径 -// File file = new File("f:/a/a.xlsx"); -// //将原文件更改为f:\a\b.xlsx,其中路径是必要的。注意 -// file.renameTo(new File("f:/a/b.xlsx")); - //想命名的原文件夹的路径 - File file1 = new File(folderPath); - //将原文件夹更改为A,其中路径是必要的。注意 - file1.renameTo(new File(newPath)); - LocalDateTime now = LocalDateTime.now(); - - BusinessDataEntity businessDataEntity = new BusinessDataEntity( - folderId, - newName, - null, - null, - null, - now, - null, - newPath - ); - System.out.println(businessDataEntity); - businessDataMapper.reName(businessDataEntity); - return Result.okM("重命名成功"); - } - -} +package com.dite.znpt.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.entity.BusinessDataEntity; +import com.dite.znpt.domain.page.PageBean; +import com.dite.znpt.mapper.BusinessDataMapper; +import com.dite.znpt.service.BusinessDataFileService; +import com.dite.znpt.service.BusinessDataService; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.util.Comparator; +import java.util.List; + +/** + * 商务资料文件夹实现类 + */ +@Service +@ApiOperation("商务资料文件夹service实现类") +@AllArgsConstructor +@NoArgsConstructor +public class BusinessDataServiceImpl implements BusinessDataService { + @Resource + private BusinessDataMapper businessDataMapper; + @Resource + private BusinessDataFileService businessDataFileService; + + // 从配置文件中读取基础路径(默认值:D:/upload/businessData) + // ,新建文件夹的时候,如果没指定父文件夹Id,就用这个 + @Value("${file.upload.businessDataPath:D:/upload/businessData}") + private String businessDataPath; + + @ApiOperation(value = "分页查询") + @Override + public PageBean pageSelect(Integer page, Integer pageSize, String folderName) { + PageHelper.startPage(page, pageSize); + List businessDataEntityList = businessDataMapper.ListWithCondition(folderName); + Page p = (Page) businessDataEntityList; + PageBean pageBean = new PageBean(p.getTotal(), p.getResult()); + return pageBean; + } + + @ApiOperation(value = "创建文件夹") + @Override + public Result createFolder(String folderName, Long parentId) { + // 获取ID + String loginIdAsLong = "未登录用户"; + if(StpUtil.isLogin()){ + loginIdAsLong = StpUtil.getLoginIdAsString(); + } + // 文件夹名称不能为空 + // TODO: 添加文件夹名称校验,后续最好更规范些,写个工具类专门校验,用正则表达式 + if (folderName == null || folderName.trim().isEmpty()) { + return Result.error("文件夹名称不能为空"); + } + if (folderName.length() > 50) { + return Result.error("文件夹名称过长"); + } + + // 文件夹名称前置一个/ + String folderName1 = "/" + folderName; + // 目标文件夹 + File targetDir = Paths.get(businessDataPath, folderName1).toFile(); + if (parentId != 0L) { + // 获取父文件夹路径 + targetDir = Paths.get(businessDataMapper.getPath(parentId), folderName1).toFile(); + } else { + // 如果是根目录,检查默认路径是否存在,不存在则创建 + File defaultPathDir = new File(businessDataPath); + if (!defaultPathDir.exists()) { + boolean created = defaultPathDir.mkdirs(); + if (!created) { + return Result.error("默认路径创建失败: " + businessDataPath); + } + } + } + // 创建文件夹和新增文件夹路径 + if (!targetDir.exists()) { + // 创建文件夹 + boolean created = targetDir.mkdirs(); + if (!created) { + throw new RuntimeException("文件夹创建失败: " + targetDir.getAbsolutePath()); + } + // 上面是新增文件夹功能,但没有往数据库插入文件夹相关数据,所以下面新增 + // 创建BusinessDataEntity对象并设置属性 + BusinessDataEntity businessDataEntity = new BusinessDataEntity( + null, + folderName, + parentId, + loginIdAsLong, + LocalDateTime.now(), + LocalDateTime.now(), + false, + targetDir.getAbsolutePath()); + // 插入到数据库 + businessDataMapper.insert(businessDataEntity); + return Result.okM("文件夹创建成功"); + } else { + return Result.error("文件夹已存在: "); + } + } + + @ApiOperation("获取文件夹路径") + public String getPath(Long parentId) { + return businessDataMapper.getPath(parentId); + } + + @ApiOperation("删除文件夹") + @Override + public Result delete(Long folderId) { + // 获取文件夹路径 + String folderPath = businessDataMapper.getPath(folderId); + + // 创建Path对象并删除文件夹 + Path folder = Paths.get(folderPath); + if (Files.exists(folder)) { + try { + // 使用Files.walk获取所有文件和目录,按深度排序后删除 + java.util.stream.Stream filePaths = Files.walk(folder); + filePaths.sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + filePaths.close(); + + // 删除数据库中文件夹的数据 + businessDataMapper.delete(folderId); + // 删除文件夹下文件的数据 + businessDataFileService.delete(null, folderId); + return Result.okM("删除成功"); + } catch (Exception e) { + return Result.okM("删除成功"); + } + } else { + return Result.error("文件夹不存在: " + folderPath); + } + } + + @ApiOperation("重命名文件夹") + @Override + public Result reName(Long folderId, String newName) { + // 获取文件夹路径 + String folderPath = businessDataMapper.getPath(folderId); + String newPath = folderPath.substring(0, folderPath.lastIndexOf('\\')) + "\\" + newName; + // + // //想命名的原文件的路径 + // File file = new File("f:/a/a.xlsx"); + // //将原文件更改为f:\a\b.xlsx,其中路径是必要的。注意 + // file.renameTo(new File("f:/a/b.xlsx")); + // 想命名的原文件夹的路径 + File file1 = new File(folderPath); + // 将原文件夹更改为A,其中路径是必要的。注意 + file1.renameTo(new File(newPath)); + LocalDateTime now = LocalDateTime.now(); + + BusinessDataEntity businessDataEntity = new BusinessDataEntity( + folderId, + newName, + null, + null, + null, + now, + null, + newPath); + businessDataMapper.reName(businessDataEntity); + return Result.okM("重命名成功"); + } +} 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 new file mode 100644 index 0000000..1fa86dd --- /dev/null +++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java @@ -0,0 +1,363 @@ +package com.dite.znpt.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.dite.znpt.domain.entity.EquipmentApprovalEntity; +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.websocket.SimpleWebSocketHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author Bear.G + * @date 2025/1/8/周三 17:55 + * @description 设备审批服务实现类 + */ +@Slf4j +@Service +public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { + + @Resource + private EquipmentApprovalMapper equipmentApprovalMapper; + + @Override + public IPage getPendingApprovals(EquipmentApprovalListReq req) { + // 创建分页对象,处理null值 + 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::getApprovalStatus, "PENDING"); + + // 添加查询条件 + addQueryConditions(wrapper, req); + + IPage result = equipmentApprovalMapper.selectPage(page, wrapper); + + return convertToRespPage(result); + } + + @Override + public IPage getApprovedApprovals(EquipmentApprovalListReq req) { + // 创建分页对象,处理null值 + 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.in(EquipmentApprovalEntity::getApprovalStatus, "APPROVED", "REJECTED"); + + // 添加查询条件 + addQueryConditions(wrapper, req); + + IPage result = equipmentApprovalMapper.selectPage(page, wrapper); + + return convertToRespPage(result); + } + + @Override + public void approve(String approvalId, EquipmentApprovalReq req) { + EquipmentApprovalEntity entity = equipmentApprovalMapper.selectById(approvalId); + if (entity == null) { + throw new RuntimeException("审批记录不存在"); + } + + entity.setApprovalStatus("APPROVED"); + entity.setApproverName(req.getApproverName()); + entity.setApproverId(req.getApproverId()); + entity.setApprovalTime(LocalDateTime.now()); + entity.setApprovalComment(req.getApprovalComment()); + + equipmentApprovalMapper.updateById(entity); + } + + @Override + public void reject(String approvalId, EquipmentApprovalReq req) { + EquipmentApprovalEntity entity = equipmentApprovalMapper.selectById(approvalId); + if (entity == null) { + throw new RuntimeException("审批记录不存在"); + } + + entity.setApprovalStatus("REJECTED"); + entity.setApproverName(req.getApproverName()); + entity.setApproverId(req.getApproverId()); + entity.setApprovalTime(LocalDateTime.now()); + entity.setApprovalComment(req.getApprovalComment()); + + equipmentApprovalMapper.updateById(entity); + } + + @Override + public EquipmentApprovalResp getApprovalDetail(String approvalId) { + EquipmentApprovalEntity entity = equipmentApprovalMapper.selectById(approvalId); + if (entity == null) { + return null; + } + + return convertToResp(entity); + } + + @Override + public Object getApprovalStats() { + Map stats = new HashMap<>(); + + // 待审批数量 + LambdaQueryWrapper pendingWrapper = new LambdaQueryWrapper<>(); + pendingWrapper.eq(EquipmentApprovalEntity::getApprovalStatus, "PENDING"); + long pendingCount = equipmentApprovalMapper.selectCount(pendingWrapper); + stats.put("pendingCount", pendingCount); + + // 已通过数量 + LambdaQueryWrapper approvedWrapper = new LambdaQueryWrapper<>(); + approvedWrapper.eq(EquipmentApprovalEntity::getApprovalStatus, "APPROVED"); + long approvedCount = equipmentApprovalMapper.selectCount(approvedWrapper); + stats.put("approvedCount", approvedCount); + + // 已拒绝数量 + LambdaQueryWrapper rejectedWrapper = new LambdaQueryWrapper<>(); + rejectedWrapper.eq(EquipmentApprovalEntity::getApprovalStatus, "REJECTED"); + long rejectedCount = equipmentApprovalMapper.selectCount(rejectedWrapper); + stats.put("rejectedCount", rejectedCount); + + return stats; + } + + /** + * 添加查询条件 + */ + 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); + } + + /** + * 转换为响应对象 + */ + private EquipmentApprovalResp convertToResp(EquipmentApprovalEntity entity) { + EquipmentApprovalResp resp = new EquipmentApprovalResp(); + BeanUtils.copyProperties(entity, resp); + return resp; + } + + /** + * 转换为响应分页对象 + */ + private IPage convertToRespPage(IPage page) { + List records = page.getRecords().stream() + .map(this::convertToResp) + .collect(Collectors.toList()); + + Page respPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); + respPage.setRecords(records); + + 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); + + // 发送通知 - 使用日志记录,后续可以扩展为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()); + } + + @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/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 selectList(ProjectMemberListReq req) { + public PageResult getProjectTeamMembers(TeamMemberQuery query) { + // 设置分页参数 PageUtil.startPage(); - List list = this.baseMapper.queryBySelective(req); - enrichMemberInfo(list); - return list; - } - - @Override - public List selectByProjectId(String projectId) { - List list = this.baseMapper.queryByProjectId(projectId); - enrichMemberInfo(list); - return list; - } - - @Override - public List selectByTurbineId(String turbineId) { - List list = this.baseMapper.queryByTurbineId(turbineId); - enrichMemberInfo(list); - return list; - } - - @Override - public List selectByTaskGroupId(String taskGroupId) { - List list = this.baseMapper.queryByTaskGroupId(taskGroupId); - enrichMemberInfo(list); - return list; - } - - @Override - public List selectByTaskId(String taskId) { - List list = this.baseMapper.queryByTaskId(taskId); - enrichMemberInfo(list); - return list; - } - - @Override - public List selectByUserId(String userId) { - List list = this.baseMapper.queryByUserId(userId); - enrichMemberInfo(list); - return list; - } - - @Override - public List selectByProjectIdAndRoleType(String projectId, String roleType) { - List list = this.baseMapper.queryByProjectIdAndRoleType(projectId, roleType); - enrichMemberInfo(list); - return list; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void saveData(ProjectMemberReq req) { - // 验证用户是否存在 - UserEntity user = userService.getById(req.getUserId()); - if (user == null) { - throw new ServiceException(Message.USER_ID_NOT_EXIST_OR_ILLEGAL); - } - - // 检查是否已存在相同的关联 - boolean exists = lambdaQuery() - .eq(ProjectMemberEntity::getProjectId, req.getProjectId()) - .eq(ProjectMemberEntity::getUserId, req.getUserId()) - .eq(StrUtil.isNotEmpty(req.getTurbineId()), ProjectMemberEntity::getTurbineId, req.getTurbineId()) - .eq(StrUtil.isNotEmpty(req.getTaskGroupId()), ProjectMemberEntity::getTaskGroupId, req.getTaskGroupId()) - .eq(StrUtil.isNotEmpty(req.getTaskId()), ProjectMemberEntity::getTaskId, req.getTaskId()) - .eq(ProjectMemberEntity::getRoleType, req.getRoleType()) - .exists(); - - if (exists) { - throw new ServiceException("该用户在此项目中已存在相同角色"); - } - - ProjectMemberEntity entity = BeanUtil.copyProperties(req, ProjectMemberEntity.class); - if (StrUtil.isEmpty(entity.getStatus())) { - entity.setStatus("ACTIVE"); - } - save(entity); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateData(ProjectMemberReq req) { - if (StrUtil.isEmpty(req.getMemberId())) { - throw new ServiceException("关联ID不能为空"); - } - - ProjectMemberEntity entity = getById(req.getMemberId()); - if (entity == null) { - throw new ServiceException(Message.PROJECT_ID_IS_NOT_EXIST); - } - - BeanUtil.copyProperties(req, entity); - updateById(entity); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteById(String memberId) { - removeById(memberId); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void batchAddMembers(List reqList) { - if (CollUtil.isEmpty(reqList)) { - return; - } - - for (ProjectMemberReq req : reqList) { - saveData(req); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteByProjectId(String projectId) { - lambdaUpdate() - .eq(ProjectMemberEntity::getProjectId, projectId) - .remove(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteByTurbineId(String turbineId) { - lambdaUpdate() - .eq(ProjectMemberEntity::getTurbineId, turbineId) - .remove(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteByTaskGroupId(String taskGroupId) { - lambdaUpdate() - .eq(ProjectMemberEntity::getTaskGroupId, taskGroupId) - .remove(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteByTaskId(String taskId) { - lambdaUpdate() - .eq(ProjectMemberEntity::getTaskId, taskId) - .remove(); + + // 查询团队成员列表 + List list = this.baseMapper.queryTeamMembers(query); + + // 按用户ID去重,保留第一个记录 + Map uniqueMembers = list.stream() + .collect(Collectors.toMap( + ProjectMemberResp::getUserId, + member -> member, + (existing, replacement) -> existing // 如果有重复,保留第一个 + )); + + // 转换为列表 + List uniqueList = new ArrayList<>(uniqueMembers.values()); + + // 丰富成员信息 + enrichMemberInfo(uniqueList); + + // 返回分页结果 + return PageResult.ok(uniqueList); } /** - * 丰富成员信息(用户信息、角色描述、岗位描述) + * 丰富成员信息 */ private void enrichMemberInfo(List list) { if (CollUtil.isEmpty(list)) { @@ -200,34 +80,218 @@ public class ProjectMemberServiceImpl extends ServiceImpl userIds = list.stream() .map(ProjectMemberResp::getUserId) + .filter(StrUtil::isNotBlank) .distinct() .collect(Collectors.toList()); - // 查询用户信息 - Map userMap = userService.listByIds(userIds) - .stream() + if (CollUtil.isEmpty(userIds)) { + return; + } + + // 批量查询用户信息 + List users = userService.listByIds(userIds); + Map userMap = users.stream() .collect(Collectors.toMap(UserEntity::getUserId, Function.identity())); - // 填充用户信息和描述 + // 填充用户信息 list.forEach(member -> { - // 填充用户信息 UserEntity user = userMap.get(member.getUserId()); if (user != null) { - member.setUserName(user.getName()); - member.setUserAccount(user.getAccount()); - member.setUserAvatar(user.getAvatar()); + // 映射前端需要的字段 + member.setName(user.getName() != null ? user.getName() : ""); + member.setPhone(user.getMobile() != null ? user.getMobile() : ""); + member.setEmail(user.getEmail() != null ? user.getEmail() : ""); + + // 保留原有字段用于内部处理 + member.setUserAccount(user.getAccount() != null ? user.getAccount() : ""); + member.setUserAvatar(user.getAvatar() != null ? user.getAvatar() : ""); + } else { + // 如果用户信息不存在,设置默认值 + member.setName(""); + member.setPhone(""); + member.setEmail(""); + member.setUserAccount(""); + member.setUserAvatar(""); } - - // 填充角色类型描述 - member.setRoleTypeDesc(ProjectRoleTypeEnum.getDescByCode(member.getRoleType())); - - // 填充岗位代码描述 - if (StrUtil.isNotEmpty(member.getJobCode())) { - member.setJobCodeDesc(ProjectJobCodeEnum.getDescByCode(member.getJobCode())); + + // 映射岗位信息 - 使用角色类型描述作为岗位 + member.setPosition(member.getRoleTypeDesc() != null ? member.getRoleTypeDesc() : ""); + + // 映射技能标签 - 暂时设为空,因为数据库中没有这个字段 + member.setSkills(""); + + // 处理其他可能为NULL的字段 + if (member.getTurbineId() == null) { + member.setTurbineId(""); + } + if (member.getTurbineName() == null) { + member.setTurbineName(""); + } + if (member.getTaskGroupId() == null) { + member.setTaskGroupId(""); + } + if (member.getTaskGroupName() == null) { + member.setTaskGroupName(""); + } + if (member.getTaskId() == null) { + member.setTaskId(""); + } + if (member.getTaskName() == null) { + member.setTaskName(""); + } + if (member.getRemark() == null) { + member.setRemark(""); + } + + // 设置状态描述 + if (member.getStatus() != null) { + if ("ACTIVE".equals(member.getStatus())) { + member.setStatusDesc("在职"); + } else if ("INACTIVE".equals(member.getStatus())) { + member.setStatusDesc("离职"); + } else if ("PENDING".equals(member.getStatus())) { + member.setStatusDesc("待入职"); + } else { + member.setStatusDesc("未知"); + } + } else { + member.setStatusDesc("未知"); + } + + // 设置角色类型描述 + if (member.getRoleType() != null) { + if ("PROJECT_MANAGER".equals(member.getRoleType())) { + member.setRoleTypeDesc("项目经理"); + } else if ("SAFETY_OFFICER".equals(member.getRoleType())) { + member.setRoleTypeDesc("安全员"); + } else if ("QUALITY_OFFICER".equals(member.getRoleType())) { + member.setRoleTypeDesc("质量员"); + } else if ("CONSTRUCTOR".equals(member.getRoleType())) { + member.setRoleTypeDesc("施工员"); + } else if ("TEAM_LEADER".equals(member.getRoleType())) { + member.setRoleTypeDesc("施工组长"); + } else { + member.setRoleTypeDesc("其他"); + } + } else { + member.setRoleTypeDesc("其他"); } }); } + @Override + public ProjectMemberResp createTeamMember(TeamMemberReq req) { + // 验证请求参数 + validateTeamMemberRequest(req); + + // 创建项目成员实体 + ProjectMemberEntity entity = new ProjectMemberEntity(); + BeanUtil.copyProperties(req, entity); + + // 保存到数据库 + this.save(entity); + + // 返回创建后的成员信息 + return getTeamMemberById(entity.getMemberId()); + } + + @Override + public ProjectMemberResp updateTeamMember(String memberId, TeamMemberReq req) { + // 验证成员是否存在 + ProjectMemberEntity existingMember = this.getById(memberId); + if (existingMember == null) { + throw new ServiceException("项目成员不存在"); + } + + // 验证请求参数 + validateTeamMemberRequest(req); + + // 更新成员信息 + BeanUtil.copyProperties(req, existingMember); + this.updateById(existingMember); + + // 返回更新后的成员信息 + return getTeamMemberById(memberId); + } + + @Override + public boolean deleteTeamMembers(String... memberIds) { + if (memberIds == null || memberIds.length == 0) { + throw new ServiceException("请选择要删除的成员"); + } + + // 验证所有成员是否存在 + List members = this.listByIds(CollUtil.toList(memberIds)); + if (members.size() != memberIds.length) { + throw new ServiceException("部分成员不存在"); + } + + // 批量删除 + return this.removeByIds(CollUtil.toList(memberIds)); + } + + /** + * 验证团队成员请求参数 + */ + private void validateTeamMemberRequest(TeamMemberReq req) { + // 验证项目是否存在 + ProjectEntity project = projectService.getById(req.getProjectId()); + if (project == null) { + throw new ServiceException(Message.PROJECT_ID_IS_NOT_EXIST); + } + + // 验证用户是否存在 + UserEntity user = userService.getById(req.getUserId()); + if (user == null) { + throw new ServiceException("用户不存在"); + } + + // 验证机组是否存在(如果指定了机组) + if (StrUtil.isNotBlank(req.getTurbineId())) { + TurbineEntity turbine = turbineService.getById(req.getTurbineId()); + if (turbine == null) { + throw new ServiceException("机组不存在"); + } + } + + // 验证任务组是否存在(如果指定了任务组) + if (StrUtil.isNotBlank(req.getTaskGroupId())) { + ProjectTaskGroupEntity taskGroup = projectTaskGroupService.getById(req.getTaskGroupId()); + if (taskGroup == null) { + throw new ServiceException("任务组不存在"); + } + } + + // 验证任务是否存在(如果指定了任务) + if (StrUtil.isNotBlank(req.getTaskId())) { + ProjectTaskEntity task = projectTaskService.getById(req.getTaskId()); + if (task == null) { + throw new ServiceException("任务不存在"); + } + } + } + + /** + * 根据成员ID获取成员信息 + */ + private ProjectMemberResp getTeamMemberById(String memberId) { + ProjectMemberEntity entity = this.getById(memberId); + if (entity == null) { + return null; + } + + // 构建查询条件 + TeamMemberQuery query = new TeamMemberQuery(); + query.setProjectId(entity.getProjectId()); + + // 查询并返回单个成员信息 + List list = this.baseMapper.queryTeamMembers(query); + return list.stream() + .filter(member -> member.getMemberId().equals(memberId)) + .findFirst() + .orElse(null); + } + // ========================== 项目看板相关方法实现 ========================== @Override @@ -293,8 +357,11 @@ public class ProjectMemberServiceImpl extends ServiceImpl projectMembers = selectByProjectId(projectId); + // 获取项目人员信息 - 使用新的查询方法 + TeamMemberQuery query = new TeamMemberQuery(); + query.setProjectId(projectId); + PageResult memberResult = getProjectTeamMembers(query); + List projectMembers = memberResult.getRows(); resp.setProjectMembers(projectMembers); // 计算团队规模 @@ -303,7 +370,7 @@ public class ProjectMemberServiceImpl extends ServiceImpl "PROJECT_MANAGER".equals(member.getRoleType())) - .map(ProjectMemberResp::getUserName) + .map(ProjectMemberResp::getName) .findFirst() .orElse(""); resp.setManager(managerName); @@ -398,15 +465,18 @@ public class ProjectMemberServiceImpl extends ServiceImpl members = selectByProjectId(project.getProjectId()); + // 获取项目人员信息 - 使用新的查询方法 + TeamMemberQuery query = new TeamMemberQuery(); + query.setProjectId(project.getProjectId()); + PageResult memberResult = getProjectTeamMembers(query); + List members = memberResult.getRows(); // 按角色类型分组,并去重用户名 Map memberNames = members.stream() .collect(Collectors.groupingBy( ProjectMemberResp::getRoleType, Collectors.mapping( - ProjectMemberResp::getUserName, + ProjectMemberResp::getName, Collectors.collectingAndThen( Collectors.toSet(), // 使用Set去重 set -> String.join(",", set) @@ -423,16 +493,28 @@ public class ProjectMemberServiceImpl extends ServiceImpl teamMembers = members.stream() - .map(member -> { - ProjectKanbanDataResp.ProjectKanbanItem.TeamMemberResp teamMember = new ProjectKanbanDataResp.ProjectKanbanItem.TeamMemberResp(); - BeanUtil.copyProperties(member, teamMember); - return teamMember; - }) + .collect(Collectors.toMap( + ProjectMemberResp::getUserId, // 按用户ID去重 + member -> { + ProjectKanbanDataResp.ProjectKanbanItem.TeamMemberResp teamMember = new ProjectKanbanDataResp.ProjectKanbanItem.TeamMemberResp(); + // 先复制所有同名字段 + BeanUtil.copyProperties(member, teamMember); + // 手动处理字段名不一致的字段 + teamMember.setUserName(member.getName()); // name -> userName + return teamMember; + }, + (existing, replacement) -> existing // 如果有重复,保留第一个 + )) + .values() + .stream() .collect(Collectors.toList()); item.setTeamMembers(teamMembers); diff --git a/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java index 1bc85e5..04dbc10 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/ProjectTaskServiceImpl.java @@ -2,9 +2,11 @@ package com.dite.znpt.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dite.znpt.constant.Message; import com.dite.znpt.domain.entity.AttachInfoEntity; @@ -19,11 +21,13 @@ import com.dite.znpt.exception.ServiceException; import com.dite.znpt.mapper.ProjectTaskGroupMapper; import com.dite.znpt.mapper.ProjectTaskMapper; import com.dite.znpt.service.AttachInfoService; +import com.dite.znpt.service.ProjectService; import com.dite.znpt.service.ProjectTaskService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; import java.time.LocalDate; import java.util.*; import java.util.function.Function; @@ -41,6 +45,9 @@ public class ProjectTaskServiceImpl 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/websocket/SimpleWebSocketHandler.java b/core/src/main/java/com/dite/znpt/websocket/SimpleWebSocketHandler.java new file mode 100644 index 0000000..4851e0c --- /dev/null +++ b/core/src/main/java/com/dite/znpt/websocket/SimpleWebSocketHandler.java @@ -0,0 +1,96 @@ +package com.dite.znpt.websocket; + +import org.springframework.stereotype.Component; +import org.springframework.web.socket.*; + +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Map; + +/** + * 简单的WebSocket处理器 + */ +@Component +public class SimpleWebSocketHandler implements WebSocketHandler { + + // 存储所有连接的会话 + private static final Map 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/core/src/main/resources/mapper/ProjectMemberMapper.xml b/core/src/main/resources/mapper/ProjectMemberMapper.xml index f8925d6..9d2ef2e 100644 --- a/core/src/main/resources/mapper/ProjectMemberMapper.xml +++ b/core/src/main/resources/mapper/ProjectMemberMapper.xml @@ -2,34 +2,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - SELECT pm.member_id, pm.project_id, @@ -41,18 +15,34 @@ pm.task_id, pt.task_name, pm.user_id, - u.name as user_name, + u.name as name, u.account as user_account, u.avatar as user_avatar, + u.mobile as phone, + u.email as email, pm.role_type, - pm.role_type as role_type_desc, + CASE + WHEN pm.role_type = 'PROJECT_MANAGER' THEN '项目经理' + WHEN pm.role_type = 'SAFETY_OFFICER' THEN '安全员' + WHEN pm.role_type = 'QUALITY_OFFICER' THEN '质量员' + WHEN pm.role_type = 'CONSTRUCTOR' THEN '施工员' + WHEN pm.role_type = 'TEAM_LEADER' THEN '施工组长' + ELSE '其他' + END as role_type_desc, pm.job_code, pm.job_code as job_code_desc, pm.job_desc, pm.join_date, pm.leave_date, pm.status, - pm.remark + CASE + WHEN pm.status = 'ACTIVE' THEN '在职' + WHEN pm.status = 'INACTIVE' THEN '离职' + WHEN pm.status = 'PENDING' THEN '待入职' + ELSE '未知' + END as status_desc, + pm.remark, + pm.create_time FROM project_member pm LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci @@ -63,252 +53,17 @@ AND pm.project_id = #{projectId} - - AND pm.turbine_id = #{turbineId} + + AND u.name LIKE CONCAT('%', #{name}, '%') - - AND pm.task_group_id = #{taskGroupId} - - - AND pm.task_id = #{taskId} - - - AND pm.user_id = #{userId} - - - AND pm.role_type = #{roleType} - - - AND pm.job_code = #{jobCode} + + AND pm.role_type = #{position} AND pm.status = #{status} - - AND u.name LIKE CONCAT('%', #{userName}, '%') - - - AND u.account LIKE CONCAT('%', #{userAccount}, '%') - ORDER BY pm.create_time DESC - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/src/main/java/com/dite/znpt/web/controller/BusinessDataFileController.java b/web/src/main/java/com/dite/znpt/web/controller/BusinessDataFileController.java index a54e8f2..f838342 100644 --- a/web/src/main/java/com/dite/znpt/web/controller/BusinessDataFileController.java +++ b/web/src/main/java/com/dite/znpt/web/controller/BusinessDataFileController.java @@ -1,137 +1,89 @@ -package com.dite.znpt.web.controller; - -import com.dite.znpt.domain.Result; -import com.dite.znpt.domain.entity.BusinessDataFileEntity; -import com.dite.znpt.domain.page.PageBean; -import com.dite.znpt.mapper.BusinessDataFileMapper; -import com.dite.znpt.service.BusinessDataFileService; -import com.dite.znpt.service.BusinessDataService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import java.io.*; -import java.net.URLEncoder; -import java.util.Date; - -/* - * @Description: 商务资料管理,文件夹层 - */ - -@Api(tags = "文件接口") -@RestController -@Slf4j -@RequestMapping("/businessData/file") -@ApiOperation("商务资料管理,文件层") -public class BusinessDataFileController { - @Resource - private BusinessDataFileService businessDataFileService; - @Resource - private BusinessDataService businessDataService; - @Resource - private BusinessDataFileMapper businessDataFileMapper; - - @ApiOperation(value = "分页查询文件", httpMethod = "GET") - @GetMapping("/list") - public Result pageSelect(@RequestParam(defaultValue = "1") Integer page, - @RequestParam(defaultValue = "10") Integer pageSize, - @RequestParam(defaultValue = "0") Long folderId, - @RequestParam(required = false) String fileName) { - PageBean pageBean = businessDataFileService.pageSelect(page, pageSize, folderId, fileName); - return Result.ok(pageBean); - } - - @ApiOperation(value = "增加文件") - @PostMapping("/add") - public Result add(@RequestParam("file") MultipartFile file, - @RequestParam Long folderId) { - - if (file.isEmpty()) { - return Result.error("上传文件为空"); - } - // TODO 以后可以优化,就算文件名一样,加个(1),(2)这种 - - try { - byte[] bytes = file.getBytes(); - String uploadDir = businessDataService.getPath(folderId); - - File uploadedFile = new File(uploadDir + "\\" + file.getOriginalFilename()); - if (uploadedFile.exists()) { - return Result.error("文件已存在"); - } - file.transferTo(uploadedFile); - - // 保存文件信息到数据 - BusinessDataFileEntity fileEntity = new BusinessDataFileEntity(); - fileEntity.setFolderId(folderId); - fileEntity.setFileName(file.getOriginalFilename()); - fileEntity.setFilePath(uploadDir + "\\" + file.getOriginalFilename()); - fileEntity.setFileType(file.getContentType()); - fileEntity.setFileSize(file.getSize()); - fileEntity.setUploadTime(new Date()); - fileEntity.setUploaderId(0L); - System.out.println(uploadDir + "\\" + file.getOriginalFilename()); - businessDataFileService.add(fileEntity); - - return Result.okM("上传成功"); - } catch (IOException e) { - e.printStackTrace(); - return Result.error("上传失败"); - } - } - - @ApiOperation(value = "删除文件") - @DeleteMapping("/delete") - public Result delete(@RequestParam Long fileId) { - businessDataFileService.delete(fileId, null); - return Result.okM("删除成功"); - } - - @ApiOperation(value = "下载文件") - @GetMapping("/download") - public void download(@RequestParam("fileId") Long fileId, HttpServletResponse response) { - String path = businessDataFileService.getPath(fileId); - try { - // path是指想要下载的文件的路径 - File file = new File(path); - log.info(file.getPath()); - // 获取文件名 - String filename = file.getName(); - // 获取文件后缀名 - String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase(); - log.info("文件后缀名:" + ext); - - // 将文件写入输入流 - FileInputStream fileInputStream = new FileInputStream(file); - InputStream fis = new BufferedInputStream(fileInputStream); - byte[] buffer = new byte[fis.available()]; - fis.read(buffer); - fis.close(); - - // 清空response - response.reset(); - // 设置response的Header - response.setCharacterEncoding("UTF-8"); - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); - // 告知浏览器文件的大小 - response.addHeader("Content-Length", "" + file.length()); - OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); - response.setContentType("application/octet-stream"); - outputStream.write(buffer); - outputStream.flush(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - @ApiOperation(value = "重命名文件", httpMethod = "PUT") - @PutMapping("/rename") - public Result reName(@RequestParam Long fileId, @RequestParam String newFileName) { - return businessDataFileService.reName(fileId, newFileName); - } - -} +package com.dite.znpt.web.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.dite.znpt.domain.Result; +import com.dite.znpt.domain.entity.BusinessDataFileEntity; +import com.dite.znpt.domain.page.PageBean; +import com.dite.znpt.mapper.BusinessDataFileMapper; +import com.dite.znpt.mapper.BusinessDataMapper; + +import com.dite.znpt.service.BusinessDataFileService; +import com.dite.znpt.service.BusinessDataService; +import com.dite.znpt.service.impl.BusinessDataFileServiceImpl; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import org.springframework.web.multipart.MultipartFile; + +/* + * @Description: 商务资料管理,文件夹层 + * 袁彬彬写的,其他人合并的时候,不允许改我的部分。 + */ + +@Api(tags = "文件接口") +@RestController +@Slf4j +@RequestMapping("/businessData/file") +@ApiOperation("商务资料管理,文件层") +public class BusinessDataFileController { + @Resource + private BusinessDataFileService businessDataFileService; + @Resource + private BusinessDataService businessDataService; + @Resource + private BusinessDataFileMapper businessDataFileMapper; + + @ApiOperation(value = "分页查询文件", httpMethod = "GET") + @GetMapping("/list") + public Result pageSelect(@RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer pageSize, + @RequestParam(defaultValue = "0") Long folderId, + @RequestParam(required = false) String fileName) { + PageBean pageBean = businessDataFileService.pageSelect(page, pageSize, folderId, fileName); + return Result.ok(pageBean); + } + + @ApiOperation(value = "增加文件") + @PostMapping("/add") + public Result add(@RequestParam("file") MultipartFile file, + @RequestParam Long folderId) { + return businessDataFileService.addfile(file, folderId); + } + + @ApiOperation(value = "删除文件") + @DeleteMapping("/delete") + public Result delete(@RequestParam Long fileId) { + businessDataFileService.delete(fileId, null); + return Result.okM("删除成功"); + } + + @ApiOperation(value = "下载文件") + @GetMapping("/download") + public void download(@RequestParam("fileId") Long fileId, HttpServletResponse response) { + businessDataFileService.upload(fileId, response); + } + + @ApiOperation(value = "重命名文件", httpMethod = "PUT") + @PutMapping("/rename") + public Result reName(@RequestParam Long fileId, @RequestParam String newFileName) { + return businessDataFileService.reName(fileId, newFileName); + } + + + @ApiOperation(value = "文件预览") + @GetMapping("/preview") + public void preview(@RequestParam("fileId") Long fileId, HttpServletResponse response) { + businessDataFileService.preview(fileId, response); + } + +} 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 new file mode 100644 index 0000000..ef16e0a --- /dev/null +++ b/web/src/main/java/com/dite/znpt/web/controller/EquipmentApprovalController.java @@ -0,0 +1,138 @@ +package com.dite.znpt.web.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.dite.znpt.domain.PageResult; +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; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Bear.G + * @date 2025/1/8/周三 18:00 + * @description 设备审批控制器 + */ +@Api(tags = "设备审批管理") +@RestController +@RequestMapping("/equipment/approval") +public class EquipmentApprovalController { + + private static final Logger log = LoggerFactory.getLogger(EquipmentApprovalController.class); + + @Resource + private EquipmentApprovalService equipmentApprovalService; + + @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()); + } + + @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()); + } + + @ApiOperation(value = "审批通过", httpMethod = "POST") + @PostMapping("/{approvalId}/approve") + public Result approve(@PathVariable String approvalId, @Validated @RequestBody EquipmentApprovalReq req) { + equipmentApprovalService.approve(approvalId, req); + return Result.ok(); + } + + @ApiOperation(value = "审批拒绝", httpMethod = "POST") + @PostMapping("/{approvalId}/reject") + public Result reject(@PathVariable String approvalId, @Validated @RequestBody EquipmentApprovalReq req) { + equipmentApprovalService.reject(approvalId, req); + return Result.ok(); + } + + @ApiOperation(value = "获取审批详情", httpMethod = "GET") + @GetMapping("/{approvalId}") + public Result getApprovalDetail(@PathVariable String approvalId) { + return Result.ok(equipmentApprovalService.getApprovalDetail(approvalId)); + } + + @ApiOperation(value = "获取审批统计信息", httpMethod = "GET") + @GetMapping("/stats") + 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 4a670f7..220ccfa 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 @@ -4,14 +4,12 @@ import com.dite.znpt.domain.PageResult; import com.dite.znpt.domain.Result; import com.dite.znpt.domain.vo.*; import com.dite.znpt.service.ProjectMemberService; -import com.dite.znpt.util.PageUtil; -import com.dite.znpt.util.ValidationGroup; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.validation.Valid; import java.util.List; /** @@ -28,103 +26,33 @@ public class ProjectMemberController { @Resource private ProjectMemberService projectMemberService; - @ApiOperation(value = "查询项目人员列表", httpMethod = "GET") - @GetMapping("/list") - public PageResult list(ProjectMemberListReq req) { - PageUtil.startPage(); - return PageResult.ok(projectMemberService.selectList(req)); + @ApiOperation(value = "获取项目团队成员列表(支持筛选、分页、搜索)", httpMethod = "GET") + @GetMapping("/project/{projectId}/team-members") + public PageResult getProjectTeamMembers( + @PathVariable String projectId, + TeamMemberQuery query) { + query.setProjectId(projectId); + return projectMemberService.getProjectTeamMembers(query); } - @ApiOperation(value = "根据项目ID查询项目人员", httpMethod = "GET") - @GetMapping("/project/{projectId}") - public Result> getByProjectId(@PathVariable String projectId) { - return Result.ok(projectMemberService.selectByProjectId(projectId)); + @ApiOperation(value = "创建团队成员", httpMethod = "POST") + @PostMapping("/team-member") + public Result createTeamMember(@Valid @RequestBody TeamMemberReq req) { + return Result.ok(projectMemberService.createTeamMember(req)); } - @ApiOperation(value = "根据机组ID查询机组人员", httpMethod = "GET") - @GetMapping("/turbine/{turbineId}") - public Result> getByTurbineId(@PathVariable String turbineId) { - return Result.ok(projectMemberService.selectByTurbineId(turbineId)); + @ApiOperation(value = "更新团队成员信息", httpMethod = "PUT") + @PutMapping("/team-member/{memberId}") + public Result updateTeamMember( + @PathVariable String memberId, + @Valid @RequestBody TeamMemberReq req) { + return Result.ok(projectMemberService.updateTeamMember(memberId, req)); } - @ApiOperation(value = "根据任务组ID查询任务组人员", httpMethod = "GET") - @GetMapping("/task-group/{taskGroupId}") - public Result> getByTaskGroupId(@PathVariable String taskGroupId) { - return Result.ok(projectMemberService.selectByTaskGroupId(taskGroupId)); - } - - @ApiOperation(value = "根据任务ID查询任务人员", httpMethod = "GET") - @GetMapping("/task/{taskId}") - public Result> getByTaskId(@PathVariable String taskId) { - return Result.ok(projectMemberService.selectByTaskId(taskId)); - } - - @ApiOperation(value = "根据用户ID查询用户参与的项目", httpMethod = "GET") - @GetMapping("/user/{userId}") - public Result> getByUserId(@PathVariable String userId) { - return Result.ok(projectMemberService.selectByUserId(userId)); - } - - @ApiOperation(value = "根据项目ID和角色类型查询人员", httpMethod = "GET") - @GetMapping("/project/{projectId}/role/{roleType}") - public Result> getByProjectIdAndRoleType(@PathVariable String projectId, @PathVariable String roleType) { - return Result.ok(projectMemberService.selectByProjectIdAndRoleType(projectId, roleType)); - } - - @ApiOperation(value = "新增项目人员", httpMethod = "POST") - @PostMapping - public Result add(@Validated(ValidationGroup.Insert.class) @RequestBody ProjectMemberReq req) { - projectMemberService.saveData(req); - return Result.ok(); - } - - @ApiOperation(value = "修改项目人员", httpMethod = "PUT") - @PutMapping - public Result edit(@Validated(ValidationGroup.Update.class) @RequestBody ProjectMemberReq req) { - projectMemberService.updateData(req); - return Result.ok(); - } - - @ApiOperation(value = "删除项目人员", httpMethod = "DELETE") - @DeleteMapping("/{memberId}") - public Result remove(@PathVariable String memberId) { - projectMemberService.deleteById(memberId); - return Result.ok(); - } - - @ApiOperation(value = "批量添加项目人员", httpMethod = "POST") - @PostMapping("/batch") - public Result batchAdd(@RequestBody List reqList) { - projectMemberService.batchAddMembers(reqList); - return Result.ok(); - } - - @ApiOperation(value = "根据项目ID删除所有项目人员", httpMethod = "DELETE") - @DeleteMapping("/project/{projectId}") - public Result removeByProjectId(@PathVariable String projectId) { - projectMemberService.deleteByProjectId(projectId); - return Result.ok(); - } - - @ApiOperation(value = "根据机组ID删除所有机组人员", httpMethod = "DELETE") - @DeleteMapping("/turbine/{turbineId}") - public Result removeByTurbineId(@PathVariable String turbineId) { - projectMemberService.deleteByTurbineId(turbineId); - return Result.ok(); - } - - @ApiOperation(value = "根据任务组ID删除所有任务组人员", httpMethod = "DELETE") - @DeleteMapping("/task-group/{taskGroupId}") - public Result removeByTaskGroupId(@PathVariable String taskGroupId) { - projectMemberService.deleteByTaskGroupId(taskGroupId); - return Result.ok(); - } - - @ApiOperation(value = "根据任务ID删除所有任务人员", httpMethod = "DELETE") - @DeleteMapping("/task/{taskId}") - public Result removeByTaskId(@PathVariable String taskId) { - projectMemberService.deleteByTaskId(taskId); - return Result.ok(); + @ApiOperation(value = "删除团队成员(支持单个或批量删除)", httpMethod = "DELETE") + @DeleteMapping("/team-member/batch") + public Result deleteTeamMembers(@RequestBody List ids) { + return Result.ok(projectMemberService.deleteTeamMembers(ids.toArray(new String[0]))); } // ========================== 项目看板相关接口 ========================== 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/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: diff --git a/web/src/main/resources/application.yml b/web/src/main/resources/application.yml index 7adbb7d..36bdba7 100644 --- a/web/src/main/resources/application.yml +++ b/web/src/main/resources/application.yml @@ -10,9 +10,9 @@ spring: servlet: multipart: # 单个文件大小 - max-file-size: 100MB + max-file-size: 1000MB # 设置总上传的文件大小 - max-request-size: 200MB + max-request-size: 2000MB application: name: znpt mvc: @@ -28,4 +28,4 @@ flowable: # true 会对数据库中所有表进行更新操作。如果表不存在,则自动创建(建议开发时使用) database-schema-update: false # 关闭定时任务JOB - async-executor-activate: false \ No newline at end of file + async-executor-activate: false