diff --git a/core/src/main/java/com/dite/znpt/config/TaskConfig.java b/core/src/main/java/com/dite/znpt/config/TaskConfig.java
new file mode 100644
index 0000000..2726c63
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/config/TaskConfig.java
@@ -0,0 +1,24 @@
+package com.dite.znpt.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+/**
+ * @author hedechao
+ * @date 2025/8/11 11:02
+ * @Description: 形变配置线程
+ */
+@Configuration
+public class TaskConfig {
+ @Bean("clearanceExecutor") // 方法返回的对象会被注册成 Bean,名字叫 clearanceExecutor
+ public ThreadPoolTaskExecutor clearanceExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(2); // 核心线程数
+ executor.setMaxPoolSize(4); // 最大线程数
+ executor.setQueueCapacity(100); // 队列容量
+ executor.setThreadNamePrefix("clearance-"); // 线程名前缀
+ executor.initialize(); // 初始化
+ return executor;
+ }
+}
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 e6d836b..79afc9f 100644
--- a/core/src/main/java/com/dite/znpt/domain/entity/EquipmentEntity.java
+++ b/core/src/main/java/com/dite/znpt/domain/entity/EquipmentEntity.java
@@ -177,6 +177,15 @@ public class EquipmentEntity extends AuditableEntity implements Serializable {
@ApiModelProperty("发票状态")
private String invoiceStatus;
+ @ApiModelProperty("采购状态,NOT_STARTED-未开始,PENDING_APPROVAL-待审批,APPROVED-已通过,REJECTED-已拒绝,COMPLETED-已完成")
+ private String procurementStatus;
+
+ @ApiModelProperty("收货状态,NOT_RECEIVED-未收货,PARTIALLY_RECEIVED-部分收货,RECEIVED-已收货")
+ private String receiptStatus;
+
+ @ApiModelProperty("支付状态,NOT_PAID-未支付,PARTIALLY_PAID-部分支付,PAID-已支付")
+ private String paymentStatus;
+
@ApiModelProperty("附件")
private String attachments;
diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ExpenseTypeEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ExpenseTypeEntity.java
new file mode 100644
index 0000000..d702485
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/entity/ExpenseTypeEntity.java
@@ -0,0 +1,27 @@
+package com.dite.znpt.domain.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("expense_type")
+@ApiModel(value="ExpenseTypeEntity对象", description="支出类型表")
+public class ExpenseTypeEntity {
+ @TableId(type = IdType.AUTO)
+ private Integer Id;
+
+ @ApiModelProperty("支出类型名称")
+ private String name;
+
+ @ApiModelProperty("父级id")
+ private Integer parentId;
+}
diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ProjectEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ProjectEntity.java
index 943620b..875b6c3 100644
--- a/core/src/main/java/com/dite/znpt/domain/entity/ProjectEntity.java
+++ b/core/src/main/java/com/dite/znpt/domain/entity/ProjectEntity.java
@@ -89,7 +89,7 @@ public class ProjectEntity extends AuditableEntity implements Serializable {
@ExcelProperty("项目规模")
@ApiModelProperty("项目规模")
@TableField("scale")
- private String scale;
+ private Integer scale;
@ExcelProperty("总工期,单位天")
@ApiModelProperty("总工期,单位天")
diff --git a/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java
index e2a25e8..2776261 100644
--- a/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java
+++ b/core/src/main/java/com/dite/znpt/domain/entity/ProjectTaskEntity.java
@@ -85,5 +85,13 @@ public class ProjectTaskEntity extends AuditableEntity implements Serializable {
@ApiModelProperty("项目id")
@TableField("project_id")
private String projectId;
+
+ @ApiModelProperty("任务规模")
+ @TableField("scales")
+ private Integer scales;
+
+ @ApiModelProperty("已完成数")
+ @TableField("finished")
+ private Integer finished;
}
diff --git a/core/src/main/java/com/dite/znpt/domain/entity/VideoMonitorEntity.java b/core/src/main/java/com/dite/znpt/domain/entity/VideoMonitorEntity.java
new file mode 100644
index 0000000..d289d9a
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/entity/VideoMonitorEntity.java
@@ -0,0 +1,170 @@
+package com.dite.znpt.domain.entity;
+
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 视频监测信息
+ */
+@ApiModel(description="视频监测信息")
+@Schema(description="视频监测信息")
+@Data
+@TableName(value = "video_monitor")
+public class VideoMonitorEntity implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 视频id
+ */
+ @TableId(value = "video_id", type = IdType.ASSIGN_UUID)
+ @ApiModelProperty(value="视频id")
+ @Schema(description="视频id")
+ private String videoId;
+
+ /**
+ * 项目id
+ */
+ @TableField(value = "project_id")
+ @ApiModelProperty(value="项目id")
+ @Schema(description="项目id")
+ private String projectId;
+
+ /**
+ * 机组id
+ */
+ @TableField(value = "turbine_id")
+ @ApiModelProperty(value="机组id")
+ @Schema(description="机组id")
+ private String turbineId;
+
+ /**
+ * 视频名称
+ */
+ @TableField(value = "video_name")
+ @ApiModelProperty(value="视频名称")
+ @Schema(description="视频名称")
+ private String videoName;
+
+ /**
+ * 视频路径
+ */
+ @TableField(value = "video_path")
+ @ApiModelProperty(value="视频路径")
+ @Schema(description="视频路径")
+ private String videoPath;
+
+ /**
+ * 0 正常 1 已删除
+ */
+ @TableField(value = "is_deleted")
+ @ApiModelProperty(value="0 正常 1 已删除")
+ @Schema(description="0 正常 1 已删除")
+ private Boolean isDeleted;
+
+ /**
+ * 0 待审核 1 已上线 2 下线
+ */
+ @TableField(value = "`status`")
+ @ApiModelProperty(value="0 待审核 1 已上线 2 下线")
+ @Schema(description="0 待审核 1 已上线 2 下线")
+ private Byte status;
+
+ /**
+ * 预处理后的视频路径
+ */
+ @TableField(value = "pre_image_path")
+ @ApiModelProperty(value="预处理后的视频路径")
+ @Schema(description="预处理后的视频路径")
+ private String preImagePath;
+
+ /**
+ * 是否处理,默认0
+ */
+ @TableField(value = "pre_treatment")
+ @ApiModelProperty(value="是否处理,默认0")
+ @Schema(description="是否处理,默认0")
+ private Boolean preTreatment;
+
+ /**
+ * 修改人
+ */
+ @TableField(value = "update_by")
+ @ApiModelProperty(value="修改人")
+ @Schema(description="修改人")
+ private String updateBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(value = "create_time",fill = FieldFill.INSERT)
+ @ApiModelProperty(value="创建时间")
+ @Schema(description="创建时间")
+ private Date createTime;
+
+ /**
+ * 创建人
+ */
+ @TableField(value = "create_by")
+ @ApiModelProperty(value="创建人")
+ @Schema(description="创建人")
+ private String createBy;
+
+ /**
+ * 修改时间
+ */
+ @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
+ @ApiModelProperty(value="修改时间")
+ @Schema(description="修改时间")
+ private Date updateTime;
+
+ /**
+ * 风速
+ */
+ @TableField(value = "wind_speed")
+ @ApiModelProperty(value="风速")
+ @Schema(description="风速")
+ private String windSpeed;
+
+ /**
+ * 转速
+ */
+ @TableField(value = "rpm")
+ @ApiModelProperty(value="转速")
+ @Schema(description="转速")
+ private String rpm;
+
+ /**
+ * 检测类型
+ */
+ @TableField(value = "`type`")
+ @ApiModelProperty(value="检测类型")
+ @Schema(description="检测类型")
+ private String type;
+
+ /**
+ * 业务扩展字段
+ */
+ @TableField(value = "extra",typeHandler = JacksonTypeHandler.class)
+ @ApiModelProperty(value="业务扩展字段")
+ @Schema(description="业务扩展字段")
+ private JSONObject extra;
+
+ /**
+ * 上传时间
+ */
+ @TableField(value = "upload_time")
+ @ApiModelProperty(value="上传时间")
+ @Schema(description="上传时间")
+ private Date uploadTime;
+}
\ No newline at end of file
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
index 39b5833..55cae55 100644
--- a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalListReq.java
+++ b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentApprovalListReq.java
@@ -43,6 +43,9 @@ public class EquipmentApprovalListReq implements Serializable {
@ApiModelProperty("当前页码")
private Integer page;
+ @ApiModelProperty("当前页码 - 与前端保持一致")
+ private Integer pageNum;
+
@ApiModelProperty("每页大小")
private Integer pageSize;
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java
index d936b01..e0529f5 100644
--- a/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java
+++ b/core/src/main/java/com/dite/znpt/domain/vo/EquipmentResp.java
@@ -154,6 +154,18 @@ public class EquipmentResp implements Serializable {
@ApiModelProperty("总价")
private BigDecimal totalPrice;
+ @ApiModelProperty("采购状态,NOT_STARTED-未开始,PENDING_APPROVAL-待审批,APPROVED-已通过,REJECTED-已拒绝,COMPLETED-已完成")
+ private String procurementStatus;
+
+ @ApiModelProperty("收货状态,NOT_RECEIVED-未收货,PARTIALLY_RECEIVED-部分收货,RECEIVED-已收货")
+ private String receiptStatus;
+
+ @ApiModelProperty("支付状态,NOT_PAID-未支付,PARTIALLY_PAID-部分支付,PAID-已支付")
+ private String paymentStatus;
+
+ @ApiModelProperty("审批状态,PENDING-待审批,APPROVED-已通过,REJECTED-已拒绝")
+ private String approvalStatus;
+
// 移除备用状态字段,使用现有的 location_status 字段
// @ApiModelProperty("备用状态")
// private String spareStatus;
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/GanttChartReq.java b/core/src/main/java/com/dite/znpt/domain/vo/GanttChartReq.java
new file mode 100644
index 0000000..7e96367
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/vo/GanttChartReq.java
@@ -0,0 +1,45 @@
+package com.dite.znpt.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+/**
+ * 甘特图查询请求类
+ */
+@Data
+@ApiModel(value = "GanttChartReq", description = "甘特图查询请求")
+public class GanttChartReq {
+
+ @ApiModelProperty("项目ID")
+ private String projectId;
+
+ @ApiModelProperty("任务组ID")
+ private String taskGroupId;
+
+ @ApiModelProperty("任务状态")
+ private Integer status;
+
+ @ApiModelProperty("负责人ID")
+ private String mainUserId;
+
+ @ApiModelProperty("开始时间范围-开始")
+ private LocalDate startDateFrom;
+
+ @ApiModelProperty("开始时间范围-结束")
+ private LocalDate startDateTo;
+
+ @ApiModelProperty("结束时间范围-开始")
+ private LocalDate endDateFrom;
+
+ @ApiModelProperty("结束时间范围-结束")
+ private LocalDate endDateTo;
+
+ @ApiModelProperty("是否包含已完成任务")
+ private Boolean includeCompleted = true;
+
+ @ApiModelProperty("是否只显示逾期任务")
+ private Boolean overdueOnly = false;
+}
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/GanttChartResp.java b/core/src/main/java/com/dite/znpt/domain/vo/GanttChartResp.java
new file mode 100644
index 0000000..69e38a0
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/vo/GanttChartResp.java
@@ -0,0 +1,91 @@
+package com.dite.znpt.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * 甘特图数据响应类
+ */
+@Data
+@ApiModel(value = "GanttChartResp", description = "甘特图数据响应")
+public class GanttChartResp {
+
+ @ApiModelProperty("任务ID")
+ private String taskId;
+
+ @ApiModelProperty("任务名称")
+ private String taskName;
+
+ @ApiModelProperty("任务编号")
+ private String taskCode;
+
+ @ApiModelProperty("上级任务ID")
+ private String parentTaskId;
+
+ @ApiModelProperty("任务组ID")
+ private String taskGroupId;
+
+ @ApiModelProperty("任务组名称")
+ private String taskGroupName;
+
+ @ApiModelProperty("计划开始时间")
+ private LocalDate planStartDate;
+
+ @ApiModelProperty("计划结束时间")
+ private LocalDate planEndDate;
+
+ @ApiModelProperty("实际开始时间")
+ private LocalDate actualStartDate;
+
+ @ApiModelProperty("实际结束时间")
+ private LocalDate actualEndDate;
+
+ @ApiModelProperty("任务状态:0未开始,1进行中,2已结束")
+ private Integer status;
+
+ @ApiModelProperty("任务状态描述")
+ private String statusDesc;
+
+ @ApiModelProperty("是否逾期:0未逾期,1已逾期")
+ private Integer overdueStatus;
+
+ @ApiModelProperty("任务负责人ID")
+ private String mainUserId;
+
+ @ApiModelProperty("任务负责人姓名")
+ private String mainUserName;
+
+ @ApiModelProperty("任务参与人")
+ private String userIds;
+
+ @ApiModelProperty("任务参与人姓名列表")
+ private List participantNames;
+
+ @ApiModelProperty("进度百分比")
+ private Integer progress;
+
+ @ApiModelProperty("任务层级")
+ private Integer level;
+
+ @ApiModelProperty("任务在时间轴上的位置(天数)")
+ private Integer position;
+
+ @ApiModelProperty("任务持续时间(天数)")
+ private Integer duration;
+
+ @ApiModelProperty("子任务列表")
+ private List children;
+
+ @ApiModelProperty("任务备注")
+ private String remark;
+
+ @ApiModelProperty("项目ID")
+ private String projectId;
+
+ @ApiModelProperty("项目名称")
+ private String projectName;
+}
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectInitTaskReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectInitTaskReq.java
new file mode 100644
index 0000000..7ec32f1
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectInitTaskReq.java
@@ -0,0 +1,44 @@
+package com.dite.znpt.domain.vo;
+
+import com.dite.znpt.util.ValidationGroup;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.time.LocalDate;
+
+@Data
+@ApiModel("项目初始化任务请求参数")
+public class ProjectInitTaskReq {
+ @ApiModelProperty("任务名称")
+ private String taskName;
+
+ @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目任务编号不能为空")
+ @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 100, message = "项目任务编号长度不能超过100字符")
+ @ApiModelProperty("项目任务编号")
+ private String taskCode;
+
+ @NotNull(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "计划开始时间不能为空")
+ @ApiModelProperty("计划开始时间")
+ private LocalDate planStartDate;
+
+ @NotNull(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "计划结束时间不能为空")
+ @ApiModelProperty("计划结束时间")
+ private LocalDate planEndDate;
+
+ @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "任务组id不能为空")
+ @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 32, message = "任务组id长度不能超过32字符")
+ @ApiModelProperty("任务组id")
+ private String taskGroupId;
+
+ @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "任务负责人id不能为空")
+ @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 100, message = "任务负责人id长度不能超过100字符")
+ @ApiModelProperty("任务负责人id")
+ private String mainUserId;
+
+ @ApiModelProperty("任务规模")
+ private Integer scales;
+}
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java
index 2e7e598..ed1748d 100644
--- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java
+++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanDataResp.java
@@ -17,20 +17,29 @@ import java.util.List;
@ApiModel(value="ProjectKanbanDataResp对象", description="项目看板数据响应")
public class ProjectKanbanDataResp {
- @ApiModelProperty("待施工项目列表")
+ @ApiModelProperty("未开工项目列表")
private List pendingProjects;
- @ApiModelProperty("施工中项目列表")
+ @ApiModelProperty("筹备中项目列表")
+ private List preparingProjects;
+
+ @ApiModelProperty("开工中项目列表")
private List inProgressProjects;
+ @ApiModelProperty("暂停中项目列表")
+ private List suspendedProjects;
+
@ApiModelProperty("已完工项目列表")
private List completedProjects;
- @ApiModelProperty("已审核项目列表")
- private List auditedProjects;
+ @ApiModelProperty("验收中项目列表")
+ private List acceptanceProjects;
- @ApiModelProperty("已验收项目列表")
- private List acceptedProjects;
+ @ApiModelProperty("回款中项目列表")
+ private List collectionProjects;
+
+ @ApiModelProperty("已结算项目列表")
+ private List settledProjects;
@Data
@ApiModel(value="ProjectKanbanItem对象", description="项目看板项目项")
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java
index fe2f6f0..d15296a 100644
--- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java
+++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectKanbanStatsResp.java
@@ -19,17 +19,26 @@ public class ProjectKanbanStatsResp {
@ApiModelProperty("待施工项目数")
private Long pendingProjectCount;
- @ApiModelProperty("施工中项目数")
+ @ApiModelProperty("筹备中项目数")
+ private Long preparingProjectCount;
+
+ @ApiModelProperty("开工中项目数")
private Long inProgressProjectCount;
+ @ApiModelProperty("暂停中项目数")
+ private Long suspendedProjectCount;
+
@ApiModelProperty("已完工项目数")
private Long completedProjectCount;
- @ApiModelProperty("已审核项目数")
- private Long auditedProjectCount;
+ @ApiModelProperty("验收中项目数")
+ private Long acceptanceProjectCount;
- @ApiModelProperty("已验收项目数")
- private Long acceptedProjectCount;
+ @ApiModelProperty("回款中项目数")
+ private Long collectionProjectCount;
+
+ @ApiModelProperty("已结算项目数")
+ private Long settledProjectCount;
@ApiModelProperty("总机组数")
private Long totalTurbineCount;
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java
index 5fdcc16..b590940 100644
--- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java
+++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectReq.java
@@ -1,5 +1,6 @@
package com.dite.znpt.domain.vo;
+import com.dite.znpt.domain.entity.ProjectTaskEntity;
import com.dite.znpt.util.ValidationGroup;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -10,6 +11,7 @@ import javax.validation.constraints.Size;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
+import java.util.List;
/**
* @Author: gaoxiong
@@ -31,7 +33,6 @@ public class ProjectReq implements Serializable {
@ApiModelProperty("项目来源")
private String projectOrigin;
- @NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目预算不能为空")
@ApiModelProperty("项目预算")
private Integer projectBudget;
@@ -77,9 +78,8 @@ public class ProjectReq implements Serializable {
@ApiModelProperty("检查单位联系电话")
private String inspectionPhone;
- @Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 20, message = "项目规模长度不能超过20字符")
@ApiModelProperty("项目规模")
- private String scale;
+ private Integer scale;
@ApiModelProperty("总工期,单位天")
private Integer duration;
@@ -127,4 +127,7 @@ public class ProjectReq implements Serializable {
@ApiModelProperty("其他杂费")
private Double othersCost;
+
+ @ApiModelProperty("项目初始任务")
+ private List tasks;
}
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ProjectResp.java b/core/src/main/java/com/dite/znpt/domain/vo/ProjectResp.java
index 16eb289..47c02b8 100644
--- a/core/src/main/java/com/dite/znpt/domain/vo/ProjectResp.java
+++ b/core/src/main/java/com/dite/znpt/domain/vo/ProjectResp.java
@@ -6,6 +6,7 @@ import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
+import java.util.List;
/**
* @author huise23
@@ -45,5 +46,8 @@ public class ProjectResp extends ProjectReq implements Serializable {
@ApiModelProperty("状态:0待施工,1施工中,2已完工,3已审核,4已验收")
private String statusLabel;
+
+ @ApiModelProperty("任务列表")
+ private List taskList;
}
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/ReceiptRequest.java b/core/src/main/java/com/dite/znpt/domain/vo/ReceiptRequest.java
new file mode 100644
index 0000000..8892e98
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/vo/ReceiptRequest.java
@@ -0,0 +1,160 @@
+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;
+
+/**
+ * 收货请求参数(扩展版,包含完整设备信息)
+ *
+ * @author system
+ * @date 2025-01-08
+ */
+@Data
+@ApiModel(value = "收货请求参数", description = "收货请求参数,包含收货信息和设备信息")
+public class ReceiptRequest {
+
+ @ApiModelProperty("设备序列号(收货时自动生成)")
+ private String equipmentSn;
+
+ @ApiModelProperty("库存条码(收货时自动生成)")
+ private String inventoryBarcode;
+
+ // 收货特有信息
+ @NotBlank(message = "收货时间不能为空")
+ @ApiModelProperty("收货时间")
+ private String receiptTime;
+
+ @NotBlank(message = "收货人不能为空")
+ @ApiModelProperty("收货人")
+ private String receiptPerson;
+
+ @NotNull(message = "收货数量不能为空")
+ @ApiModelProperty("收货数量")
+ private Integer receiptQuantity;
+
+ @ApiModelProperty("收货备注")
+ private String receiptRemark;
+
+ @NotBlank(message = "外观检查结果不能为空")
+ @ApiModelProperty("外观检查结果")
+ private String appearanceCheck;
+
+ @NotBlank(message = "功能测试结果不能为空")
+ @ApiModelProperty("功能测试结果")
+ private String functionTest;
+
+ @NotBlank(message = "包装完整性不能为空")
+ @ApiModelProperty("包装完整性")
+ private String packageIntegrity;
+
+ @NotBlank(message = "配件完整性不能为空")
+ @ApiModelProperty("配件完整性")
+ private String accessoryIntegrity;
+
+ @NotBlank(message = "检查结果不能为空")
+ @ApiModelProperty("检查结果")
+ private String checkResult;
+
+ @ApiModelProperty("检查备注")
+ private String checkRemark;
+
+ @NotBlank(message = "入库位置不能为空")
+ @ApiModelProperty("入库位置")
+ private String storageLocation;
+
+ @NotBlank(message = "库管员不能为空")
+ @ApiModelProperty("库管员")
+ private String storageManager;
+
+ // 设备基本信息(从采购数据继承)
+ @ApiModelProperty("设备名称")
+ private String equipmentName;
+
+ @ApiModelProperty("设备型号")
+ private String equipmentModel;
+
+ @ApiModelProperty("设备类型")
+ private String equipmentType;
+
+ @ApiModelProperty("品牌")
+ private String brand;
+
+ @ApiModelProperty("配置规格/参数")
+ private String specification;
+
+ @ApiModelProperty("资产编号")
+ private String assetCode;
+
+ // 采购信息(从采购数据继承)
+ @ApiModelProperty("采购订单号")
+ private String purchaseOrder;
+
+ @ApiModelProperty("供应商名称")
+ private String supplierName;
+
+ @ApiModelProperty("采购价格")
+ private BigDecimal purchasePrice;
+
+ @ApiModelProperty("采购时间")
+ private String purchaseTime;
+
+ @ApiModelProperty("数量")
+ private Integer quantity;
+
+ @ApiModelProperty("单价")
+ private BigDecimal unitPrice;
+
+ @ApiModelProperty("总价")
+ private BigDecimal totalPrice;
+
+ // 入库信息
+ @ApiModelProperty("入库时间")
+ private String inStockTime;
+
+ @ApiModelProperty("物理位置")
+ private String physicalLocation;
+
+ @ApiModelProperty("位置状态")
+ private String locationStatus;
+
+ @ApiModelProperty("负责人")
+ private String responsiblePerson;
+
+ // 状态信息
+ @ApiModelProperty("设备状态")
+ private String equipmentStatus;
+
+ @ApiModelProperty("使用状态")
+ private String useStatus;
+
+ @ApiModelProperty("健康状态")
+ private String healthStatus;
+
+ @ApiModelProperty("收货状态")
+ private String receiptStatus;
+
+ // 其他管理信息
+ @ApiModelProperty("折旧方法")
+ private String depreciationMethod;
+
+ @ApiModelProperty("折旧年限")
+ private Integer depreciationYears;
+
+ @ApiModelProperty("残值")
+ private BigDecimal salvageValue;
+
+ @ApiModelProperty("当前净值")
+ private BigDecimal currentNetValue;
+
+ // 系统字段
+ @ApiModelProperty("创建时间")
+ private String createTime;
+
+ @ApiModelProperty("更新时间")
+ private String updateTime;
+}
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberUpdateReq.java b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberUpdateReq.java
new file mode 100644
index 0000000..f375d8c
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/vo/TeamMemberUpdateReq.java
@@ -0,0 +1,60 @@
+package com.dite.znpt.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * @author wangna
+ * @date 2025/08/05
+ * @Description: 团队成员更新请求类(用于更新操作,移除必填验证)
+ */
+@Data
+@ApiModel(value="TeamMemberUpdateReq对象", description="团队成员更新请求类")
+public class TeamMemberUpdateReq implements Serializable {
+
+ @ApiModelProperty("项目ID")
+ private String projectId;
+
+ @ApiModelProperty("机组ID(可选)")
+ private String turbineId;
+
+ @ApiModelProperty("任务组ID(可选)")
+ private String taskGroupId;
+
+ @ApiModelProperty("任务ID(可选)")
+ private String taskId;
+
+ @ApiModelProperty("用户ID")
+ private String userId;
+
+ @ApiModelProperty("项目角色类型:PROJECT_MANAGER-项目经理,SAFETY_OFFICER-安全员,QUALITY_OFFICER-质量员,CONSTRUCTOR-施工人员,TEAM_LEADER-施工组长")
+ private String roleType;
+
+ @ApiModelProperty("具体岗位代码(如:GROUND_SERVICE-地勤,DRIVER-司机,ASCENDING-登高等)")
+ private String jobCode;
+
+ @ApiModelProperty("岗位描述")
+ private String jobDesc;
+
+ @ApiModelProperty("加入时间")
+ private LocalDate joinDate;
+
+ @ApiModelProperty("离开时间")
+ private LocalDate leaveDate;
+
+ @ApiModelProperty("状态:ACTIVE-在职,INACTIVE-离职,PENDING-待入职")
+ private String status = "ACTIVE";
+
+ @ApiModelProperty("备注")
+ private String remark;
+
+ @ApiModelProperty("用户电话")
+ private String phone;
+
+ @ApiModelProperty("用户邮箱")
+ private String email;
+}
diff --git a/core/src/main/java/com/dite/znpt/domain/vo/VideoReq.java b/core/src/main/java/com/dite/znpt/domain/vo/VideoReq.java
new file mode 100644
index 0000000..1b146e2
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/domain/vo/VideoReq.java
@@ -0,0 +1,29 @@
+package com.dite.znpt.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author hedechao
+ * @date 2025/8/8 09:10
+ * @Description:
+ */
+@Data
+@ApiModel("视频列表查询实体")
+public class VideoReq implements Serializable {
+ @Serial
+ private static final long serialVersionUID = 771014582625089979L;
+ @ApiModelProperty("项目id")
+ private String projectId;
+ @ApiModelProperty("视频类型")
+ private String[] type;
+ @ApiModelProperty("机组id")
+ private String turbineId;
+ @ApiModelProperty("是否已审核,0未审核,1已审核")
+ private Boolean State;
+}
+
diff --git a/core/src/main/java/com/dite/znpt/enums/PaymentStatusEnum.java b/core/src/main/java/com/dite/znpt/enums/PaymentStatusEnum.java
new file mode 100644
index 0000000..27a8dcf
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/enums/PaymentStatusEnum.java
@@ -0,0 +1,52 @@
+package com.dite.znpt.enums;
+
+import cn.hutool.json.JSONObject;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 支付状态枚举
+ *
+ * @author system
+ * @date 2025-01-08
+ */
+@Getter
+public enum PaymentStatusEnum {
+ NOT_PAID("NOT_PAID", "未支付"),
+ PARTIALLY_PAID("PARTIALLY_PAID", "部分支付"),
+ PAID("PAID", "已支付");
+
+ private final String code;
+ private final String desc;
+
+ PaymentStatusEnum(String code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public static PaymentStatusEnum getByCode(String code) {
+ for (PaymentStatusEnum e : PaymentStatusEnum.values()) {
+ if (e.code.equals(code)) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ public static String getDescByCode(String code) {
+ PaymentStatusEnum e = getByCode(code);
+ return null == e ? null : e.desc;
+ }
+
+ public static List listAll() {
+ List list = new ArrayList<>(PaymentStatusEnum.values().length);
+ for (PaymentStatusEnum e : PaymentStatusEnum.values()) {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.set(e.code, e.desc);
+ list.add(jsonObject);
+ }
+ return list;
+ }
+}
diff --git a/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java b/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java
index 7836468..7fbbeff 100644
--- a/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java
+++ b/core/src/main/java/com/dite/znpt/enums/ProjectStatusEnum.java
@@ -15,11 +15,14 @@ import java.util.List;
@Getter
@AllArgsConstructor
public enum ProjectStatusEnum {
- PENDING(0, "待施工"),
- IN_PROGRESS(1, "施工中"),
- COMPLETED(2, "已完工"),
- AUDITED(3, "已审核"),
- ACCEPTED(4, "已验收");
+ PENDING(0, "未开工"),
+ PREPARING(1, "筹备中"),
+ IN_PROGRESS(2, "开工中"),
+ SUSPENDED(3, "暂停中"),
+ COMPLETED(4, "已完工"),
+ IN_ACCEPTANCE(5, "验收中"),
+ IN_COLLECTION(6, "回款中"),
+ SETTLED(7, "已结算");
private final int code;
private final String desc;
diff --git a/core/src/main/java/com/dite/znpt/enums/ReceiptStatusEnum.java b/core/src/main/java/com/dite/znpt/enums/ReceiptStatusEnum.java
new file mode 100644
index 0000000..b2174bc
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/enums/ReceiptStatusEnum.java
@@ -0,0 +1,52 @@
+package com.dite.znpt.enums;
+
+import cn.hutool.json.JSONObject;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 收货状态枚举
+ *
+ * @author system
+ * @date 2025-01-08
+ */
+@Getter
+public enum ReceiptStatusEnum {
+ NOT_RECEIVED("NOT_RECEIVED", "未收货"),
+ PARTIALLY_RECEIVED("PARTIALLY_RECEIVED", "部分收货"),
+ RECEIVED("RECEIVED", "已收货");
+
+ private final String code;
+ private final String desc;
+
+ ReceiptStatusEnum(String code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public static ReceiptStatusEnum getByCode(String code) {
+ for (ReceiptStatusEnum e : ReceiptStatusEnum.values()) {
+ if (e.code.equals(code)) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ public static String getDescByCode(String code) {
+ ReceiptStatusEnum e = getByCode(code);
+ return null == e ? null : e.desc;
+ }
+
+ public static List listAll() {
+ List list = new ArrayList<>(ReceiptStatusEnum.values().length);
+ for (ReceiptStatusEnum e : ReceiptStatusEnum.values()) {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.set(e.code, e.desc);
+ list.add(jsonObject);
+ }
+ return list;
+ }
+}
diff --git a/core/src/main/java/com/dite/znpt/enums/VideoMonitorEnum.java b/core/src/main/java/com/dite/znpt/enums/VideoMonitorEnum.java
new file mode 100644
index 0000000..4149417
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/enums/VideoMonitorEnum.java
@@ -0,0 +1,45 @@
+package com.dite.znpt.enums;
+
+import cn.hutool.json.JSONObject;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Getter
+public enum VideoMonitorEnum {
+ CLEARANCE("clearance","净空监测"),
+ DEFORMATION("deformation","形变监测");
+
+ private final String code;
+ private final String desc;
+
+ VideoMonitorEnum(String code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public static VideoMonitorEnum getByCode(String code) {
+ for (VideoMonitorEnum e : VideoMonitorEnum.values()) {
+ if (e.code.equals(code)) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ public static String getDescByCode(String code) {
+ VideoMonitorEnum e = getByCode(code);
+ return null == e ? null : e.desc;
+ }
+
+ public static List listAll() {
+ List list = new ArrayList<>(UserStatusEnum.values().length);
+ for (VideoMonitorEnum e : VideoMonitorEnum.values()) {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.set(e.code, e.desc);
+ list.add(jsonObject);
+ }
+ return list;
+ }
+}
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 02d682b..930d70d 100644
--- a/core/src/main/java/com/dite/znpt/mapper/BusinessDataFileMapper.java
+++ b/core/src/main/java/com/dite/znpt/mapper/BusinessDataFileMapper.java
@@ -17,13 +17,34 @@ public interface BusinessDataFileMapper {
// 新增文件预览方法
- public List List(@Param("folderId") Long folderId, @Param("fileName") String fileName);
- void delete(@Param("fileId") Long fileId,@Param("folderId") Long folderId);
+// public List List(@Param("folderId") Long folderId, @Param("fileName") String fileName);
+
+ public List List(
+ @Param("folderId") Long folderId,
+ @Param("fileName") String fileName,
+ @Param("sortField") String sortField,
+ @Param("sortOrder") String sortOrder);
+ 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);
+ void reName(@Param("fileId") Long fileId,
+ @Param("newFileName") String newFileName,
+ @Param("newFilePath") String newFilePath);
+
+// // 批量更新文件路径
+// void updateFilePathByFolderId(
+// @Param("folderId") Long folderId,
+// @Param("newFolderPath") String newFolderPath,
+// @Param("separator") String separator);
+
+ // 批量更新子文件夹下文件的路径
+ void updateSubFilePaths(@Param("oldParentPath1") String oldParentPath1,
+ @Param("newParentPath1") String newParentPath1,
+ @Param("oldParentPath2") String oldParentPath2
+ );
}
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 b7e4bae..f8d2d80 100644
--- a/core/src/main/java/com/dite/znpt/mapper/BusinessDataMapper.java
+++ b/core/src/main/java/com/dite/znpt/mapper/BusinessDataMapper.java
@@ -29,4 +29,12 @@ public interface BusinessDataMapper {
void reName(BusinessDataEntity businessDataEntity);
public List ListWithCondition(@Param("folderName") String folderName);
+
+ // 批量更新子文件夹路径
+ void updateSubFolderPaths(@Param("oldParentPath1") String oldParentPath,
+ @Param("newParentPath1") String newParentPath,
+ @Param("processedOldParentPath") String processedOldParentPath,
+ @Param("processedNewParentPath") String processedNewParentPath,
+ @Param("folderId") Long folderId
+ );
}
diff --git a/core/src/main/java/com/dite/znpt/mapper/ExpenseTypeMapper.java b/core/src/main/java/com/dite/znpt/mapper/ExpenseTypeMapper.java
new file mode 100644
index 0000000..927b0f3
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/mapper/ExpenseTypeMapper.java
@@ -0,0 +1,11 @@
+package com.dite.znpt.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dite.znpt.domain.entity.ExpenseTypeEntity;
+import org.mapstruct.Mapper;
+
+import java.util.List;
+
+public interface ExpenseTypeMapper extends BaseMapper {
+ List search(String key);
+}
diff --git a/core/src/main/java/com/dite/znpt/mapper/ProjectTaskMapper.java b/core/src/main/java/com/dite/znpt/mapper/ProjectTaskMapper.java
index afb1d09..4101f84 100644
--- a/core/src/main/java/com/dite/znpt/mapper/ProjectTaskMapper.java
+++ b/core/src/main/java/com/dite/znpt/mapper/ProjectTaskMapper.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.domain.entity.ProjectTaskEntity;
import com.dite.znpt.domain.vo.ProjectTaskListReq;
import com.dite.znpt.domain.vo.ProjectTaskResp;
+import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -13,6 +14,7 @@ import java.util.List;
* @date 2025/06/24 16:44
* @Description: 项目任务信息表数据库访问层
*/
+@Mapper
public interface ProjectTaskMapper extends BaseMapper {
List queryBySelective(ProjectTaskListReq projectTaskReq);
diff --git a/core/src/main/java/com/dite/znpt/mapper/VideoMonitorEntityMapper.java b/core/src/main/java/com/dite/znpt/mapper/VideoMonitorEntityMapper.java
new file mode 100644
index 0000000..831e9a3
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/mapper/VideoMonitorEntityMapper.java
@@ -0,0 +1,12 @@
+package com.dite.znpt.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dite.znpt.domain.entity.VideoMonitorEntity;
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+
+public interface VideoMonitorEntityMapper extends BaseMapper {
+ List selectAllByProjectIdAndPartId(@Param("projectId") String projectId, @Param("partId") String partId);
+
+ int batchInsert(@Param("list") List list);
+}
\ 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 9eafc83..d82cb53 100644
--- a/core/src/main/java/com/dite/znpt/service/BusinessDataFileService.java
+++ b/core/src/main/java/com/dite/znpt/service/BusinessDataFileService.java
@@ -9,13 +9,16 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
+import java.io.File;
@ApiOperation("商务资料文件service")
@Service
public interface BusinessDataFileService {
+// @ApiOperation("分页查询文件")
+// PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName);
@ApiOperation("分页查询文件")
- PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName);
+ PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName, String sortField, String sortOrder);
@ApiOperation("删除文件")
Result delete(@RequestParam(value = "fileId", required = false) Long fileId,@RequestParam(value = "foldelId", required = false) Long folderId);
@@ -38,4 +41,11 @@ public interface BusinessDataFileService {
@ApiOperation("预览文件")
void preview(Long fileId, HttpServletResponse response);
+
+// @ApiOperation("批量更新文件路径")
+// public void updateFilePathByFolderId(Long folderId, String newFolderPath);
+
+ @ApiOperation("批量更新子文件夹下文件的路径")
+ void updateSubFilePaths(String oldParentPath, String newParentPath);
+
}
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 f4a826c..90fabda 100644
--- a/core/src/main/java/com/dite/znpt/service/BusinessDataService.java
+++ b/core/src/main/java/com/dite/znpt/service/BusinessDataService.java
@@ -15,4 +15,6 @@ public interface BusinessDataService {
Result delete(Long folderId);
Result reName(Long folderId, String newName);
+ void updateSubFolderPaths(String oldParentPath1, String newParentPath1, Long folderId);
+
}
diff --git a/core/src/main/java/com/dite/znpt/service/EquipmentService.java b/core/src/main/java/com/dite/znpt/service/EquipmentService.java
index 0f7a604..dbded87 100644
--- a/core/src/main/java/com/dite/znpt/service/EquipmentService.java
+++ b/core/src/main/java/com/dite/znpt/service/EquipmentService.java
@@ -6,6 +6,7 @@ import com.dite.znpt.domain.entity.EquipmentEntity;
import com.dite.znpt.domain.vo.EquipmentListReq;
import com.dite.znpt.domain.vo.EquipmentReq;
import com.dite.znpt.domain.vo.EquipmentResp;
+import com.dite.znpt.domain.vo.ReceiptRequest;
import java.util.List;
import java.util.Map;
@@ -53,6 +54,11 @@ public interface EquipmentService extends IService {
*/
Object getProcurementStats();
+ /**
+ * 确认收货并自动入库
+ */
+ void receiveGoodsAndStockIn(String equipmentId, ReceiptRequest req);
+
/**
* 导出采购记录
*/
@@ -72,4 +78,19 @@ public interface EquipmentService extends IService {
* 修改设备采购记录
*/
void updateProcurement(String equipmentId, EquipmentReq req);
+
+ /**
+ * 分页查询设备盘库记录
+ */
+ IPage inventoryPage(EquipmentListReq req);
+
+ /**
+ * 执行设备盘库
+ */
+ void executeInventory(String equipmentId, String inventoryResult, String remark);
+
+ /**
+ * 批量执行设备盘库
+ */
+ void batchExecuteInventory(List equipmentIds, String inventoryResult, String remark);
}
diff --git a/core/src/main/java/com/dite/znpt/service/EquipmentStatusUpdateService.java b/core/src/main/java/com/dite/znpt/service/EquipmentStatusUpdateService.java
new file mode 100644
index 0000000..2963dde
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/EquipmentStatusUpdateService.java
@@ -0,0 +1,51 @@
+package com.dite.znpt.service;
+
+/**
+ * 设备状态更新服务接口
+ * 用于处理设备审批后的状态更新,避免循环依赖
+ *
+ * @author Bear.G
+ * @date 2025/1/8/周三 17:50
+ */
+public interface EquipmentStatusUpdateService {
+
+ /**
+ * 更新设备采购状态
+ *
+ * @param equipmentId 设备ID
+ * @param status 新状态
+ */
+ void updateProcurementStatus(String equipmentId, String status);
+
+ /**
+ * 更新设备借用状态
+ *
+ * @param equipmentId 设备ID
+ * @param status 新状态
+ */
+ void updateBorrowStatus(String equipmentId, String status);
+
+ /**
+ * 更新设备归还状态
+ *
+ * @param equipmentId 设备ID
+ * @param status 新状态
+ */
+ void updateReturnStatus(String equipmentId, String status);
+
+ /**
+ * 更新设备位置状态
+ *
+ * @param equipmentId 设备ID
+ * @param locationStatus 新位置状态
+ */
+ void updateLocationStatus(String equipmentId, String locationStatus);
+
+ /**
+ * 更新设备使用状态
+ *
+ * @param equipmentId 设备ID
+ * @param useStatus 新使用状态
+ */
+ void updateUseStatus(String equipmentId, String useStatus);
+}
diff --git a/core/src/main/java/com/dite/znpt/service/ExpenseTypeService.java b/core/src/main/java/com/dite/znpt/service/ExpenseTypeService.java
new file mode 100644
index 0000000..da3a6f7
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/ExpenseTypeService.java
@@ -0,0 +1,11 @@
+package com.dite.znpt.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.dite.znpt.domain.entity.ExpenseTypeEntity;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+public interface ExpenseTypeService extends IService {
+ List search(String key);
+}
diff --git a/core/src/main/java/com/dite/znpt/service/GanttChartService.java b/core/src/main/java/com/dite/znpt/service/GanttChartService.java
new file mode 100644
index 0000000..d3e1c26
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/GanttChartService.java
@@ -0,0 +1,55 @@
+package com.dite.znpt.service;
+
+import com.dite.znpt.domain.vo.GanttChartReq;
+import com.dite.znpt.domain.vo.GanttChartResp;
+
+import java.util.List;
+
+/**
+ * 甘特图服务接口
+ */
+public interface GanttChartService {
+
+ /**
+ * 获取项目甘特图数据
+ *
+ * @param req 查询条件
+ * @return 甘特图数据列表
+ */
+ List getGanttChartData(GanttChartReq req);
+
+ /**
+ * 获取项目甘特图统计信息
+ *
+ * @param projectId 项目ID
+ * @return 统计信息
+ */
+ Object getGanttChartStatistics(String projectId);
+
+ /**
+ * 获取项目甘特图时间轴信息
+ *
+ * @param projectId 项目ID
+ * @return 时间轴信息
+ */
+ Object getGanttChartTimeline(String projectId);
+
+ /**
+ * 更新任务进度
+ *
+ * @param taskId 任务ID
+ * @param progress 进度百分比
+ * @return 是否成功
+ */
+ boolean updateTaskProgress(String taskId, Integer progress);
+
+ /**
+ * 拖拽更新任务时间
+ *
+ * @param taskId 任务ID
+ * @param startDate 开始时间
+ * @param endDate 结束时间
+ * @return 是否成功
+ */
+ boolean updateTaskTime(String taskId, String startDate, String endDate);
+}
diff --git a/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java b/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java
index 939ff8a..c622b9e 100644
--- a/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java
+++ b/core/src/main/java/com/dite/znpt/service/ProjectMemberService.java
@@ -27,6 +27,11 @@ public interface ProjectMemberService extends IService {
*/
ProjectMemberResp updateTeamMember(String memberId, TeamMemberReq req);
+ /**
+ * 更新团队成员信息(使用更新专用请求类)
+ */
+ ProjectMemberResp updateTeamMember(String memberId, TeamMemberUpdateReq req);
+
/**
* 删除团队成员(支持单个或批量删除)
*/
diff --git a/core/src/main/java/com/dite/znpt/service/VideoMonitorService.java b/core/src/main/java/com/dite/znpt/service/VideoMonitorService.java
new file mode 100644
index 0000000..6ef70bb
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/VideoMonitorService.java
@@ -0,0 +1,60 @@
+package com.dite.znpt.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.dite.znpt.domain.PageResult;
+import com.dite.znpt.domain.entity.VideoMonitorEntity;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ *
+ * 视频信息 服务类
+ *
+ *
+ * @author hdc
+ * @since 2025-08-07
+ */
+public interface VideoMonitorService extends IService {
+ /**
+ * 批量上传视频
+ */
+ List uploadBatch(String projectId,
+ String partId,
+ String type,
+ MultipartFile[] files) throws IOException;
+
+ /**
+ * 单文件上传
+ */
+ VideoMonitorEntity upload(String projectId,
+ String partId,
+ String type,
+ MultipartFile file) throws IOException;
+
+ /**
+ * 分页列表
+ */
+ PageResult page(Integer pageNo,
+ Integer pageSize,
+ String projectId,
+ String partId);
+
+ /**
+ * 列表
+ */
+ List list(String projectId, String partId);
+
+ /**
+ * 删除
+ */
+ void delete(String videoId);
+
+ /**
+ * 下载/播放
+ */
+ void download(String videoId, HttpServletResponse response) throws IOException;
+
+}
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 660f034..0c6e2a9 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
@@ -52,18 +52,37 @@ public class BusinessDataFileServiceImpl implements BusinessDataFileService {
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("分页查询文件")
+// @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("分页查询文件")
+// @Override
+// public PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName, String sortField, String sortOrder) {
+// PageHelper.startPage(page, pageSize);
+// List list = businessDataFileMapper.List(folderId, fileName, sortField, sortOrder);
+// Page p = (Page) list;
+// PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
+// return pageBean;
+// }
+ @ApiOperation("分页查询文件")
+ @Override
+ public PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName, String sortField, String sortOrder) {
+ PageHelper.startPage(page, pageSize);
+ List list = businessDataFileMapper.List(folderId, fileName, sortField, sortOrder);
+ 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("删除成功");
@@ -137,8 +156,11 @@ public class BusinessDataFileServiceImpl implements BusinessDataFileService {
}
// 构建新文件路径
+ // 获取父目录
String parentPath = oldFile.getParent();
+ // 获取文件扩展名
String fileExtension = "";
+ // 获取文件名(不包含扩展名)
String fileNameWithoutExt = newFileName;
// 获取原文件扩展名
@@ -228,7 +250,7 @@ public class BusinessDataFileServiceImpl implements BusinessDataFileService {
byte[] bytes = file.getBytes();
String uploadDir = businessDataService.getPath(folderId);
- File uploadedFile = new File(uploadDir + "\\" + file.getOriginalFilename());
+ File uploadedFile = new File(uploadDir + File.separator + file.getOriginalFilename());
if (uploadedFile.exists()) {
return Result.error("文件已存在");
}
@@ -238,12 +260,11 @@ public class BusinessDataFileServiceImpl implements BusinessDataFileService {
BusinessDataFileEntity fileEntity = new BusinessDataFileEntity();
fileEntity.setFolderId(folderId);
fileEntity.setFileName(file.getOriginalFilename());
- fileEntity.setFilePath(uploadDir + "\\" + file.getOriginalFilename());
+ fileEntity.setFilePath(uploadDir + File.separator + 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("上传成功");
@@ -527,4 +548,21 @@ public class BusinessDataFileServiceImpl implements BusinessDataFileService {
}
}
+// @ApiOperation("批量更新文件路径")
+// @Override
+// public void updateFilePathByFolderId(Long folderId, String newFolderPath) {
+// businessDataFileMapper.updateFilePathByFolderId(folderId, newFolderPath, File.separator);
+// }
+
+ @ApiOperation("批量更新子文件夹下文件的路径")
+ @Override
+ public void updateSubFilePaths(String oldParentPath1, String newParentPath1) {
+ // 处理路径中的分隔符,如果是反斜杠则替换为双反斜杠
+ String oldParentPath2 = oldParentPath1;
+ if ("\\".equals(File.separator)) {
+ oldParentPath2 = oldParentPath1.replace("\\", "\\\\");
+ }
+ businessDataFileMapper.updateSubFilePaths(oldParentPath1, newParentPath1, oldParentPath2);
+ }
+
}
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 2f17a2b..f4360cf 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
@@ -70,7 +70,7 @@ public class BusinessDataServiceImpl implements BusinessDataService {
}
// 文件夹名称前置一个/
- String folderName1 = "/" + folderName;
+ String folderName1 = File.separator + folderName;
// 目标文件夹
File targetDir = Paths.get(businessDataPath, folderName1).toFile();
if (parentId != 0L) {
@@ -147,23 +147,37 @@ public class BusinessDataServiceImpl implements BusinessDataService {
}
}
+ @ApiOperation("批量更新子文件夹路径")
+ @Override
+ public void updateSubFolderPaths(String oldParentPath1, String newParentPath1,Long folderId) {
+ // 处理路径中的分隔符,如果是反斜杠则替换为双反斜杠
+ String processedOldParentPath = oldParentPath1;
+ String processedNewParentPath = newParentPath1;
+ if ("\\".equals(File.separator)) {
+ processedOldParentPath = oldParentPath1.replace("\\", "\\\\");
+ processedNewParentPath = newParentPath1.replace("\\", "\\\\");
+ }
+
+ businessDataMapper.updateSubFolderPaths(oldParentPath1,newParentPath1,processedOldParentPath, processedNewParentPath, folderId);
+ }
@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"));
- // 想命名的原文件夹的路径
+ String newPath = folderPath.substring(0, folderPath.lastIndexOf(File.separator)) + File.separator + newName;
+
+ // 重命名物理文件夹
File file1 = new File(folderPath);
- // 将原文件夹更改为A,其中路径是必要的。注意
- file1.renameTo(new File(newPath));
+ boolean renameSuccess = file1.renameTo(new File(newPath));
+
+ if (!renameSuccess) {
+ return Result.error("文件夹重命名失败");
+ }
+
LocalDateTime now = LocalDateTime.now();
+ // 更新文件夹信息
BusinessDataEntity businessDataEntity = new BusinessDataEntity(
folderId,
newName,
@@ -174,6 +188,21 @@ public class BusinessDataServiceImpl implements BusinessDataService {
null,
newPath);
businessDataMapper.reName(businessDataEntity);
+
+// // 批量更新该文件夹下所有文件的路径
+// businessDataFileService.updateFilePathByFolderId(folderId, newPath);
+
+
+ String folderPath1 = folderPath+File.separator;
+ String newPath1 = newPath+File.separator;
+
+ // 批量更新子文件夹下所有文件的路径
+ businessDataFileService.updateSubFilePaths(folderPath1, newPath1);
+ // 批量更新子文件夹的路径
+ updateSubFolderPaths(folderPath1, newPath1,folderId);
+
return Result.okM("重命名成功");
}
+
+
}
diff --git a/core/src/main/java/com/dite/znpt/service/impl/ClearanceTask.java b/core/src/main/java/com/dite/znpt/service/impl/ClearanceTask.java
new file mode 100644
index 0000000..1990405
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/impl/ClearanceTask.java
@@ -0,0 +1,51 @@
+package com.dite.znpt.service.impl;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.dite.znpt.domain.entity.VideoMonitorEntity;
+import com.dite.znpt.enums.FilePathEnum;
+import com.dite.znpt.util.PythonUtil;
+import lombok.RequiredArgsConstructor;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+
+@RequiredArgsConstructor
+public class ClearanceTask implements Runnable {
+
+ private final String videoAbsolutePath; // 上传后的完整磁盘路径
+ private final String outputDir; // 结果目录
+ private final String videoId; // 数据库主键,用于更新状态
+ private final VideoMonitorServiceImpl service;
+
+ @Override
+ public void run() {
+ try {
+ // 1. 调用 Python(阻塞,但跑在子线程)
+ PythonUtil.runClearance(videoAbsolutePath,outputDir);
+ // 2. 更新数据库:status = 已完成 / 预处理成功
+ VideoMonitorEntity update = new VideoMonitorEntity();
+ update.setVideoId(videoId);
+ update.setPreTreatment(true); // 或自定义状态字段
+ update.setPreImagePath(FilePathEnum.VIDEO.getFileDownPath(outputDir));
+ File resultFile = new File(outputDir, "results.json");
+ if (!resultFile.exists()) {
+ throw new IllegalStateException("results.json 不存在");
+ }
+ String jsonStr = FileUtil.readString(resultFile, StandardCharsets.UTF_8);
+
+ // 3. 转成 hutool 的 JSONObject(对应 MySQL 的 JSON 字段)
+ JSONObject jsonObj = JSONUtil.parseObj(jsonStr);
+ update.setExtra(jsonObj);
+ service.updateById(update);
+
+ } catch (Exception e) {
+ // 失败时可将 status 置为失败
+ VideoMonitorEntity update = new VideoMonitorEntity();
+ update.setVideoId(videoId);
+ update.setStatus((byte) -1); // 自定义失败码
+ service.updateById(update);
+ }
+ }
+}
diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java
index 1fa86dd..99636dd 100644
--- a/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java
+++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java
@@ -10,7 +10,10 @@ import com.dite.znpt.domain.vo.EquipmentApprovalReq;
import com.dite.znpt.domain.vo.EquipmentApprovalResp;
import com.dite.znpt.domain.vo.EquipmentProcurementApplyReq;
import com.dite.znpt.service.EquipmentApprovalService;
+import com.dite.znpt.service.EquipmentStatusUpdateService;
+import com.dite.znpt.util.PageUtil;
import com.dite.znpt.websocket.SimpleWebSocketHandler;
+import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@@ -34,13 +37,22 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
@Resource
private EquipmentApprovalMapper equipmentApprovalMapper;
+
+ @Resource
+ private EquipmentStatusUpdateService equipmentStatusUpdateService;
@Override
public IPage getPendingApprovals(EquipmentApprovalListReq req) {
- // 创建分页对象,处理null值
- Integer pageNum = req.getPage() != null ? req.getPage() : 1;
+ log.info("开始执行待审批设备分页查询,请求参数: {}", req);
+
+ // 获取分页参数
+ Integer pageNum = req.getPageNum() != null ? req.getPageNum() : 1;
Integer pageSize = req.getPageSize() != null ? req.getPageSize() : 10;
- Page page = new Page<>(pageNum, pageSize);
+
+ log.info("分页参数 - pageNum: {}, pageSize: {}", pageNum, pageSize);
+
+ // 使用分页插件
+ PageUtil.startPage();
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EquipmentApprovalEntity::getApprovalStatus, "PENDING");
@@ -48,17 +60,38 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
// 添加查询条件
addQueryConditions(wrapper, req);
- IPage result = equipmentApprovalMapper.selectPage(page, wrapper);
+ // 执行查询
+ List approvalList = equipmentApprovalMapper.selectList(wrapper);
- return convertToRespPage(result);
+ // 转换为响应对象
+ List respList = approvalList.stream()
+ .map(this::convertToResp)
+ .collect(Collectors.toList());
+
+ // 获取分页信息
+ PageInfo pageInfo = new PageInfo<>(approvalList);
+
+ log.info("待审批设备分页查询完成,共查询 {} 条记录,当前页码: {}, 总页码: {}", pageInfo.getTotal(), pageInfo.getPageNum(), pageInfo.getPages());
+
+ // 创建响应分页对象
+ Page result = new Page<>(pageNum, pageSize, pageInfo.getTotal());
+ result.setRecords(respList);
+
+ return result;
}
@Override
public IPage getApprovedApprovals(EquipmentApprovalListReq req) {
- // 创建分页对象,处理null值
- Integer pageNum = req.getPage() != null ? req.getPage() : 1;
+ log.info("开始执行已审批设备分页查询,请求参数: {}", req);
+
+ // 获取分页参数
+ Integer pageNum = req.getPageNum() != null ? req.getPageNum() : 1;
Integer pageSize = req.getPageSize() != null ? req.getPageSize() : 10;
- Page page = new Page<>(pageNum, pageSize);
+
+ log.info("分页参数 - pageNum: {}, pageSize: {}", pageNum, pageSize);
+
+ // 使用分页插件
+ PageUtil.startPage();
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.in(EquipmentApprovalEntity::getApprovalStatus, "APPROVED", "REJECTED");
@@ -66,9 +99,24 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
// 添加查询条件
addQueryConditions(wrapper, req);
- IPage result = equipmentApprovalMapper.selectPage(page, wrapper);
+ // 执行查询
+ List approvalList = equipmentApprovalMapper.selectList(wrapper);
- return convertToRespPage(result);
+ // 转换为响应对象
+ List respList = approvalList.stream()
+ .map(this::convertToResp)
+ .collect(Collectors.toList());
+
+ // 获取分页信息
+ PageInfo pageInfo = new PageInfo<>(approvalList);
+
+ log.info("已审批设备分页查询完成,共查询 {} 条记录,当前页码: {}, 总页码: {}", pageInfo.getTotal(), pageInfo.getPageNum(), pageInfo.getPages());
+
+ // 创建响应分页对象
+ Page result = new Page<>(pageNum, pageSize, pageInfo.getTotal());
+ result.setRecords(respList);
+
+ return result;
}
@Override
@@ -85,6 +133,21 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
entity.setApprovalComment(req.getApprovalComment());
equipmentApprovalMapper.updateById(entity);
+
+ // 审批通过后,更新设备状态
+ try {
+ if ("PROCUREMENT".equals(entity.getBusinessType())) {
+ equipmentStatusUpdateService.updateProcurementStatus(entity.getEquipmentId(), "APPROVED");
+ } else if ("BORROW".equals(entity.getBusinessType())) {
+ equipmentStatusUpdateService.updateBorrowStatus(entity.getEquipmentId(), "APPROVED");
+ } else if ("RETURN".equals(entity.getBusinessType())) {
+ equipmentStatusUpdateService.updateReturnStatus(entity.getEquipmentId(), "APPROVED");
+ }
+ log.info("设备状态更新成功,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId);
+ } catch (Exception e) {
+ log.error("设备状态更新失败,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId, e);
+ // 不抛出异常,避免影响审批流程
+ }
}
@Override
@@ -101,6 +164,21 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
entity.setApprovalComment(req.getApprovalComment());
equipmentApprovalMapper.updateById(entity);
+
+ // 审批拒绝后,更新设备状态
+ try {
+ if ("PROCUREMENT".equals(entity.getBusinessType())) {
+ equipmentStatusUpdateService.updateProcurementStatus(entity.getEquipmentId(), "REJECTED");
+ } else if ("BORROW".equals(entity.getBusinessType())) {
+ equipmentStatusUpdateService.updateBorrowStatus(entity.getEquipmentId(), "REJECTED");
+ } else if ("RETURN".equals(entity.getBusinessType())) {
+ equipmentStatusUpdateService.updateReturnStatus(entity.getEquipmentId(), "REJECTED");
+ }
+ log.info("设备状态更新成功,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId);
+ } catch (Exception e) {
+ log.error("设备状态更新失败,设备ID: {}, 审批ID: {}", entity.getEquipmentId(), approvalId, e);
+ // 不抛出异常,避免影响审批流程
+ }
}
@Override
@@ -262,6 +340,15 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
// 保存到数据库
equipmentApprovalMapper.insert(entity);
+ // 更新设备采购状态 - 新增逻辑
+ try {
+ equipmentStatusUpdateService.updateProcurementStatus(req.getEquipmentId(), "PENDING_APPROVAL");
+ log.info("设备采购状态更新成功,设备ID: {}", req.getEquipmentId());
+ } catch (Exception e) {
+ log.error("设备采购状态更新失败,设备ID: {}", req.getEquipmentId(), e);
+ // 不抛出异常,避免影响审批流程
+ }
+
// 发送通知 - 使用日志记录,后续可以扩展为WebSocket通知
log.info("采购申请提交成功,设备名称: {}, 申请人: {}",
req.getEquipmentName(), getCurrentUserName());
@@ -279,16 +366,147 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
log.info("采购申请提交成功,审批ID: {}", entity.getApprovalId());
}
+
+ /**
+ * 更新设备采购状态
+ */
+ private void updateEquipmentProcurementStatus(String equipmentId, String status) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过状态更新");
+ return;
+ }
+
+ try {
+ log.info("准备更新设备采购状态,设备ID: {}, 新状态: {}", equipmentId, status);
+
+ // 这里可以添加具体的更新逻辑
+ // 例如:equipmentMapper.updateProcurementStatus(equipmentId, status);
+ // 由于循环依赖问题,建议通过事件机制或异步处理来避免循环依赖
+
+ // 暂时记录日志,后续可以通过以下方式实现:
+ // 1. 使用Spring事件机制
+ // 2. 使用异步处理
+ // 3. 重构服务架构避免循环依赖
+
+ } catch (Exception e) {
+ log.error("更新设备采购状态失败,设备ID: {}, 状态: {}", equipmentId, status, e);
+ throw e;
+ }
+ }
+
+
+
+ /**
+ * 审批通过后更新设备状态
+ */
+ private void updateEquipmentStatusAfterApproval(EquipmentApprovalEntity entity) {
+ if (entity == null || entity.getEquipmentId() == null) {
+ log.warn("审批实体或设备ID为空,跳过状态更新");
+ return;
+ }
+
+ try {
+ log.info("审批通过后更新设备状态,设备ID: {}, 业务类型: {}", entity.getEquipmentId(), entity.getBusinessType());
+
+ // 根据业务类型更新不同的设备状态
+ if ("PROCUREMENT".equals(entity.getBusinessType())) {
+ // 采购审批通过,更新设备状态为已采购
+ updateEquipmentProcurementStatus(entity.getEquipmentId(), "APPROVED");
+ } else if ("BORROW".equals(entity.getBusinessType())) {
+ // 借用审批通过,更新设备状态为已借用
+ updateEquipmentBorrowStatus(entity.getEquipmentId(), "APPROVED");
+ } else if ("RETURN".equals(entity.getBusinessType())) {
+ // 归还审批通过,更新设备状态为已归还
+ updateEquipmentReturnStatus(entity.getEquipmentId(), "APPROVED");
+ }
+
+ log.info("设备状态更新成功,设备ID: {}", entity.getEquipmentId());
+ } catch (Exception e) {
+ log.error("审批通过后更新设备状态失败,设备ID: {}", entity.getEquipmentId(), e);
+ throw e;
+ }
+ }
+
+ /**
+ * 审批拒绝后更新设备状态
+ */
+ private void updateEquipmentStatusAfterRejection(EquipmentApprovalEntity entity) {
+ if (entity == null || entity.getEquipmentId() == null) {
+ log.warn("审批实体或设备ID为空,跳过状态更新");
+ return;
+ }
+
+ try {
+ log.info("审批拒绝后更新设备状态,设备ID: {}, 业务类型: {}", entity.getEquipmentId(), entity.getBusinessType());
+
+ // 根据业务类型更新不同的设备状态
+ if ("PROCUREMENT".equals(entity.getBusinessType())) {
+ // 采购审批拒绝,更新设备状态为审批拒绝
+ updateEquipmentProcurementStatus(entity.getEquipmentId(), "REJECTED");
+ } else if ("BORROW".equals(entity.getBusinessType())) {
+ // 借用审批拒绝,更新设备状态为借用拒绝
+ updateEquipmentBorrowStatus(entity.getEquipmentId(), "REJECTED");
+ } else if ("RETURN".equals(entity.getBusinessType())) {
+ // 归还审批拒绝,更新设备状态为归还拒绝
+ updateEquipmentReturnStatus(entity.getEquipmentId(), "REJECTED");
+ }
+
+ log.info("设备状态更新成功,设备ID: {}", entity.getEquipmentId());
+ } catch (Exception e) {
+ log.error("审批拒绝后更新设备状态失败,设备ID: {}", entity.getEquipmentId(), e);
+ throw e;
+ }
+ }
+
+ /**
+ * 更新设备借用状态
+ */
+ private void updateEquipmentBorrowStatus(String equipmentId, String status) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过借用状态更新");
+ return;
+ }
+
+ try {
+ log.info("准备更新设备借用状态,设备ID: {}, 新状态: {}", equipmentId, status);
+ // 这里可以添加具体的更新逻辑
+ // 例如:equipmentMapper.updateBorrowStatus(equipmentId, status);
+ } catch (Exception e) {
+ log.error("更新设备借用状态失败,设备ID: {}, 状态: {}", equipmentId, status, e);
+ throw e;
+ }
+ }
+
+ /**
+ * 更新设备归还状态
+ */
+ private void updateEquipmentReturnStatus(String equipmentId, String status) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过归还状态更新");
+ return;
+ }
+
+ try {
+ log.info("准备更新设备归还状态,设备ID: {}, 新状态: {}", equipmentId, status);
+ // 这里可以添加具体的更新逻辑
+ // 例如:equipmentMapper.updateReturnStatus(equipmentId, status);
+ } catch (Exception e) {
+ log.error("更新设备归还状态失败,设备ID: {}, 状态: {}", equipmentId, status, e);
+ throw e;
+ }
+ }
@Override
public IPage getMyProcurementApplications(EquipmentApprovalListReq req) {
log.info("开始获取我的采购申请,请求参数: {}", req);
- // 创建分页对象
- Integer pageNum = req.getPage() != null ? req.getPage() : 1;
+ // 创建分页对象 - 使用pageNum保持一致性
+ Integer pageNum = req.getPageNum() != null ? req.getPageNum() : 1;
Integer pageSize = req.getPageSize() != null ? req.getPageSize() : 10;
Page page = new Page<>(pageNum, pageSize);
+ log.info("分页参数 - pageNum: {}, pageSize: {}", pageNum, pageSize);
+
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
// 只查询当前用户的申请
@@ -300,6 +518,8 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService {
IPage result = equipmentApprovalMapper.selectPage(page, wrapper);
+ log.info("我的采购申请分页查询完成,共查询 {} 条记录,当前页码: {}, 总页码: {}", result.getTotal(), result.getCurrent(), result.getPages());
+
return convertToRespPage(result);
}
diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java
index 8f15c6e..9dcd42e 100644
--- a/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java
+++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentServiceImpl.java
@@ -16,14 +16,20 @@ import com.dite.znpt.enums.LocationStatusEnum;
import com.dite.znpt.exception.ServiceException;
import com.dite.znpt.mapper.EquipmentMapper;
import com.dite.znpt.service.EquipmentService;
+import com.dite.znpt.util.PageUtil;
+import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
+import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
+import com.dite.znpt.domain.vo.ReceiptRequest;
+import cn.dev33.satoken.stp.StpUtil;
+import org.springframework.beans.BeanUtils;
/**
* @author Bear.G
@@ -38,10 +44,14 @@ public class EquipmentServiceImpl extends ServiceImpl page(EquipmentListReq req) {
log.info("开始执行设备分页查询,请求参数: {}", req);
- // 创建分页对象,处理null值
- Integer pageNum = req.getPage() != null ? req.getPage() : (req.getPageNum() != null ? req.getPageNum() : 1);
+ // 获取分页参数
+ Integer pageNum = req.getPageNum() != null ? req.getPageNum() : 1;
Integer pageSize = req.getPageSize() != null ? req.getPageSize() : 10;
- Page page = new Page<>(pageNum, pageSize);
+
+ log.info("分页参数 - pageNum: {}, pageSize: {}", pageNum, pageSize);
+
+ // 使用分页插件
+ PageUtil.startPage();
// 构建查询条件
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
@@ -117,9 +127,14 @@ public class EquipmentServiceImpl extends ServiceImpl equipmentPage = this.page(page, queryWrapper);
-
- log.info("查询完成,总记录数: {}, 当前页记录数: {}", equipmentPage.getTotal(), equipmentPage.getRecords().size());
+ // 执行查询
+ List equipmentList = this.list(queryWrapper);
+ log.info("查询完成,当前页记录数: {}, 总记录数: {}",
+ equipmentList.size());
+
// 转换为响应对象
- List equipmentRespList = equipmentPage.getRecords().stream()
+ List equipmentRespList = equipmentList.stream()
.map(this::convertToResp)
.collect(Collectors.toList());
- // 创建响应分页对象
- Page respPage = new Page<>(equipmentPage.getCurrent(), equipmentPage.getSize(), equipmentPage.getTotal());
+ // 获取分页信息 - 使用正确的实体类型
+ PageInfo pageInfo = new PageInfo<>(equipmentList);
+
+ log.info("获取总数: {}", pageInfo.getTotal());
+ // 创建响应分页对象 - 使用正确的分页参数
+ Page respPage = new Page<>(pageNum, pageSize, pageInfo.getTotal());
respPage.setRecords(equipmentRespList);
return respPage;
@@ -562,6 +475,18 @@ public class EquipmentServiceImpl extends ServiceImpl procurementPage(EquipmentListReq req) {
log.info("开始执行设备采购记录分页查询,请求参数: {}", req);
- // 创建分页对象,处理null值
- Integer pageNum = req.getPage() != null ? req.getPage() : (req.getPageNum() != null ? req.getPageNum() : 1);
+ // 获取分页参数
+ Integer pageNum = req.getPageNum() != null ? req.getPageNum() : 1;
Integer pageSize = req.getPageSize() != null ? req.getPageSize() : 10;
- Page page = new Page<>(pageNum, pageSize);
+
+ log.info("分页参数 - pageNum: {}, pageSize: {}", pageNum, pageSize);
+
+ // 使用分页插件
+ PageUtil.startPage();
// 构建查询条件,参考设备分页查询的逻辑
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
@@ -621,14 +578,9 @@ public class EquipmentServiceImpl extends ServiceImpl result = this.page(page, queryWrapper);
+ List equipmentList = this.list(queryWrapper);
// 转换为响应对象
- List records = result.getRecords().stream()
+ List records = equipmentList.stream()
.map(this::convertToResp)
.collect(Collectors.toList());
- // 创建新的分页结果
- Page respPage = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
- respPage.setRecords(records);
+ // 获取分页信息 - 使用正确的实体类型
+ PageInfo pageInfo = new PageInfo<>(equipmentList);
- log.info("设备采购记录分页查询完成,总记录数: {}", result.getTotal());
- return respPage;
+ log.info("设备采购分页查询完成,共查询 {} 条记录,当前页码: {}, 总页码: {}", pageInfo.getTotal(), pageInfo.getPageNum(), pageInfo.getPages());
+
+ // 创建响应分页对象 - 使用正确的分页参数
+ Page result = new Page<>(pageNum, pageSize, pageInfo.getTotal());
+ result.setRecords(records);
+
+ return result;
}
@Transactional(rollbackFor = Exception.class)
@@ -750,11 +714,12 @@ public class EquipmentServiceImpl extends ServiceImpl inventoryPage(EquipmentListReq req) {
+ log.info("开始执行设备盘库分页查询,请求参数: {}", req);
+
+ // 获取分页参数
+ Integer pageNum = req.getPageNum() != null ? req.getPageNum() : 1;
+ Integer pageSize = req.getPageSize() != null ? req.getPageSize() : 10;
+
+ log.info("分页参数 - pageNum: {}, pageSize: {}", pageNum, pageSize);
+
+ // 使用分页插件
+ PageUtil.startPage();
+
+ // 构建查询条件
+ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
+
+ // 添加搜索条件
+ if (StringUtils.hasText(req.getEquipmentName())) {
+ queryWrapper.like(EquipmentEntity::getEquipmentName, req.getEquipmentName());
+ }
+ if (StringUtils.hasText(req.getEquipmentType())) {
+ queryWrapper.eq(EquipmentEntity::getEquipmentType, req.getEquipmentType());
+ }
+ if (StringUtils.hasText(req.getAssetCode())) {
+ queryWrapper.like(EquipmentEntity::getAssetCode, req.getAssetCode());
+ }
+ if (StringUtils.hasText(req.getBrand())) {
+ queryWrapper.like(EquipmentEntity::getBrand, req.getBrand());
+ }
+ if (StringUtils.hasText(req.getLocationStatus())) {
+ queryWrapper.eq(EquipmentEntity::getLocationStatus, req.getLocationStatus());
+ }
+ if (StringUtils.hasText(req.getResponsiblePerson())) {
+ queryWrapper.like(EquipmentEntity::getResponsiblePerson, req.getResponsiblePerson());
+ }
+ if (StringUtils.hasText(req.getInventoryBarcode())) {
+ queryWrapper.like(EquipmentEntity::getInventoryBarcode, req.getInventoryBarcode());
+ }
+
+ // 按创建时间倒序排列
+ queryWrapper.orderByDesc(EquipmentEntity::getCreateTime);
+
+ // 执行查询
+ IPage page = this.page(new Page<>(pageNum, pageSize), queryWrapper);
+
+ // 转换为响应对象
+ IPage result = page.convert(this::convertToResp);
+
+ log.info("设备盘库分页查询完成,总记录数: {}, 当前页记录数: {}", result.getTotal(), result.getRecords().size());
+
+ return result;
+ }
+
+ @Override
+ public void executeInventory(String equipmentId, String inventoryResult, String remark) {
+ log.info("执行设备盘库,设备ID: {}, 盘点结果: {}, 备注: {}", equipmentId, inventoryResult, remark);
+
+ // 验证设备是否存在
+ EquipmentEntity equipment = this.getById(equipmentId);
+ if (equipment == null) {
+ throw new ServiceException("设备不存在");
+ }
+
+ // 更新盘点状态
+ EquipmentEntity updateEquipment = new EquipmentEntity();
+ updateEquipment.setEquipmentId(equipmentId);
+ updateEquipment.setInventoryTimeStatus1(LocalDateTime.now().toString() + "_" + inventoryResult);
+ updateEquipment.setDynamicRecord(remark);
+
+ // 保存更新
+ boolean success = this.updateById(updateEquipment);
+ if (!success) {
+ throw new ServiceException("执行设备盘库失败");
+ }
+
+ log.info("设备盘库执行成功,设备ID: {}", equipmentId);
+ }
+
+ @Override
+ public void batchExecuteInventory(List equipmentIds, String inventoryResult, String remark) {
+ log.info("批量执行设备盘库,设备ID列表: {}, 盘点结果: {}, 备注: {}", equipmentIds, inventoryResult, remark);
+
+ if (equipmentIds == null || equipmentIds.isEmpty()) {
+ throw new ServiceException("设备ID列表不能为空");
+ }
+
+ // 批量更新盘点状态
+ List updateList = equipmentIds.stream()
+ .map(equipmentId -> {
+ EquipmentEntity equipment = new EquipmentEntity();
+ equipment.setEquipmentId(equipmentId);
+ equipment.setInventoryTimeStatus1(LocalDateTime.now().toString() + "_" + inventoryResult);
+ equipment.setDynamicRecord(remark);
+ return equipment;
+ })
+ .collect(Collectors.toList());
+
+ // 批量更新
+ boolean success = this.updateBatchById(updateList);
+ if (!success) {
+ throw new ServiceException("批量执行设备盘库失败");
+ }
+
+ log.info("批量设备盘库执行成功,处理设备数量: {}", equipmentIds.size());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void receiveGoodsAndStockIn(String equipmentId, ReceiptRequest req) {
+ log.info("开始处理设备收货和入库,设备ID: {}", equipmentId);
+ log.info("收货请求数据: {}", req);
+
+ // 1. 查找采购记录
+ EquipmentEntity procurementRecord = this.getById(equipmentId);
+ if (procurementRecord == null) {
+ throw new ServiceException("采购记录不存在");
+ }
+
+ log.info("找到采购记录: {}", procurementRecord);
+
+ // 2. 更新现有设备记录(而不是创建新记录)
+ EquipmentEntity equipment = new EquipmentEntity();
+ equipment.setEquipmentId(equipmentId);
+
+ // 设置收货相关信息
+ if (StringUtils.hasText(req.getReceiptTime())) {
+ try {
+ equipment.setInStockTime(LocalDateTime.parse(req.getReceiptTime().replace(" ", "T")));
+ } catch (Exception e) {
+ log.warn("解析收货时间失败,使用当前时间: {}", req.getReceiptTime());
+ equipment.setInStockTime(LocalDateTime.now());
+ }
+ } else {
+ equipment.setInStockTime(LocalDateTime.now());
+ }
+
+ // 设置收货状态为已收货
+ equipment.setReceiptStatus("RECEIVED");
+
+ // 设置采购状态为已完成(而不是已收货)
+ equipment.setProcurementStatus("COMPLETED");
+
+ // 设置设备状态为库存中
+ equipment.setLocationStatus("in_stock");
+ equipment.setUseStatus("0"); // 空闲中
+
+ // 设置其他收货相关字段
+ if (StringUtils.hasText(req.getStorageLocation())) {
+ equipment.setPhysicalLocation(req.getStorageLocation());
+ }
+ if (StringUtils.hasText(req.getStorageManager())) {
+ equipment.setResponsiblePerson(req.getStorageManager());
+ }
+
+ // 记录收货人信息到资产备注中
+ if (StringUtils.hasText(req.getReceiptPerson())) {
+ String currentRemark = procurementRecord.getAssetRemark();
+ String receiptInfo = String.format("收货人:%s,收货时间:%s",
+ req.getReceiptPerson(),
+ req.getReceiptTime() != null ? req.getReceiptTime() : LocalDateTime.now().toString());
+
+ if (StringUtils.hasText(currentRemark)) {
+ equipment.setAssetRemark(currentRemark + ";" + receiptInfo);
+ } else {
+ equipment.setAssetRemark(receiptInfo);
+ }
+ }
+
+ // 设置设备序列号(如果收货时生成了新的)
+ if (StringUtils.hasText(req.getEquipmentSn())) {
+ equipment.setEquipmentSn(req.getEquipmentSn());
+ }
+
+ // 设置库存条码
+ if (StringUtils.hasText(req.getInventoryBarcode())) {
+ equipment.setInventoryBarcode(req.getInventoryBarcode());
+ }
+
+ // 设置更新时间和操作人
+ equipment.setUpdateTime(LocalDateTime.now());
+ equipment.setUpdateBy(StpUtil.getLoginIdAsString());
+
+ log.info("准备更新设备记录,设备ID: {}, 收货状态: {}, 采购状态: {}",
+ equipmentId, equipment.getReceiptStatus(), equipment.getProcurementStatus());
+
+ // 3. 更新设备记录
+ boolean updateResult = this.updateById(equipment);
+ if (!updateResult) {
+ throw new ServiceException("更新设备记录失败");
+ }
+
+ log.info("设备收货和入库成功,设备ID: {}, 收货状态: {}, 采购状态: {}",
+ equipmentId, equipment.getReceiptStatus(), equipment.getProcurementStatus());
+ }
}
diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentStatusUpdateServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentStatusUpdateServiceImpl.java
new file mode 100644
index 0000000..62a1c4a
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentStatusUpdateServiceImpl.java
@@ -0,0 +1,232 @@
+package com.dite.znpt.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.dite.znpt.domain.entity.EquipmentEntity;
+import com.dite.znpt.mapper.EquipmentMapper;
+import com.dite.znpt.service.EquipmentStatusUpdateService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+import java.time.LocalDateTime;
+
+/**
+ * 设备状态更新服务实现类
+ * 使用MyBatis Plus来更新设备状态,避免循环依赖
+ *
+ * @author Bear.G
+ * @date 2025/1/8/周三 17:50
+ */
+@Slf4j
+@Service
+public class EquipmentStatusUpdateServiceImpl implements EquipmentStatusUpdateService {
+
+ @Resource
+ private EquipmentMapper equipmentMapper;
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateProcurementStatus(String equipmentId, String status) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过采购状态更新");
+ return;
+ }
+
+ try {
+ log.info("开始更新设备采购状态,设备ID: {}, 新状态: {}", equipmentId, status);
+
+ // 使用MyBatis Plus的LambdaUpdateWrapper来更新设备状态
+ LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();
+ updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId);
+
+ // 根据状态设置相应的字段
+ if ("APPROVED".equals(status)) {
+ // 审批通过:设置采购状态为已通过,位置状态为库存中,使用状态为空闲中
+ updateWrapper.set(EquipmentEntity::getProcurementStatus, "APPROVED");
+ updateWrapper.set(EquipmentEntity::getLocationStatus, "in_stock");
+ updateWrapper.set(EquipmentEntity::getUseStatus, "0");
+ updateWrapper.set(EquipmentEntity::getInStockTime, LocalDateTime.now());
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备采购审批通过,设置状态为已通过");
+ } else if ("REJECTED".equals(status)) {
+ // 审批拒绝:设置采购状态为已拒绝,位置状态为未入库,使用状态为空闲中
+ updateWrapper.set(EquipmentEntity::getProcurementStatus, "REJECTED");
+ updateWrapper.set(EquipmentEntity::getLocationStatus, "not_in_stock");
+ updateWrapper.set(EquipmentEntity::getUseStatus, "0");
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备采购审批拒绝,设置状态为已拒绝");
+ } else if ("PENDING_APPROVAL".equals(status) || "PENDING".equals(status)) {
+ // 待审批:设置采购状态为待审批,位置状态为待审批,使用状态为空闲中
+ updateWrapper.set(EquipmentEntity::getProcurementStatus, "PENDING_APPROVAL");
+ updateWrapper.set(EquipmentEntity::getLocationStatus, "pending_approval");
+ updateWrapper.set(EquipmentEntity::getUseStatus, "0");
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备采购申请提交,设置状态为待审批");
+ } else if ("COMPLETED".equals(status)) {
+ // 采购完成:设置采购状态为已完成,位置状态为库存中,使用状态为空闲中
+ updateWrapper.set(EquipmentEntity::getProcurementStatus, "COMPLETED");
+ updateWrapper.set(EquipmentEntity::getLocationStatus, "in_stock");
+ updateWrapper.set(EquipmentEntity::getUseStatus, "0");
+ updateWrapper.set(EquipmentEntity::getInStockTime, LocalDateTime.now());
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备采购完成,设置状态为已完成");
+ }
+
+ // 执行更新
+ int updateCount = equipmentMapper.update(null, updateWrapper);
+ if (updateCount > 0) {
+ log.info("设备采购状态更新成功,设备ID: {}, 新状态: {}, 影响行数: {}", equipmentId, status, updateCount);
+ } else {
+ log.warn("设备采购状态更新失败,设备ID: {}, 新状态: {}, 可能设备不存在", equipmentId, status);
+ }
+
+ } catch (Exception e) {
+ log.error("更新设备采购状态失败,设备ID: {}, 状态: {}", equipmentId, status, e);
+ throw e;
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateBorrowStatus(String equipmentId, String status) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过借用状态更新");
+ return;
+ }
+
+ try {
+ log.info("开始更新设备借用状态,设备ID: {}, 新状态: {}", equipmentId, status);
+
+ LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();
+ updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId);
+
+ if ("APPROVED".equals(status)) {
+ // 借用审批通过:设置位置状态为外借中,使用状态为使用中
+ updateWrapper.set(EquipmentEntity::getLocationStatus, "borrowed");
+ updateWrapper.set(EquipmentEntity::getUseStatus, "1");
+ updateWrapper.set(EquipmentEntity::getBorrowingTime, LocalDateTime.now());
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备借用审批通过,设置状态为外借中");
+ } else if ("REJECTED".equals(status)) {
+ // 借用审批拒绝:保持原有状态
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备借用审批拒绝,保持原有状态");
+ }
+
+ // 执行更新
+ int updateCount = equipmentMapper.update(null, updateWrapper);
+ if (updateCount > 0) {
+ log.info("设备借用状态更新成功,设备ID: {}, 新状态: {}, 影响行数: {}", equipmentId, status, updateCount);
+ } else {
+ log.warn("设备借用状态更新失败,设备ID: {}, 新状态: {}, 可能设备不存在", equipmentId, status);
+ }
+
+ } catch (Exception e) {
+ log.error("更新设备借用状态失败,设备ID: {}, 状态: {}", equipmentId, status, e);
+ throw e;
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateReturnStatus(String equipmentId, String status) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过归还状态更新");
+ return;
+ }
+
+ try {
+ log.info("开始更新设备归还状态,设备ID: {}, 新状态: {}", equipmentId, status);
+
+ LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();
+ updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId);
+
+ if ("APPROVED".equals(status)) {
+ // 归还审批通过:设置位置状态为库存中,使用状态为空闲中
+ updateWrapper.set(EquipmentEntity::getLocationStatus, "in_stock");
+ updateWrapper.set(EquipmentEntity::getUseStatus, "0");
+ updateWrapper.set(EquipmentEntity::getReturnTime, LocalDateTime.now());
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备归还审批通过,设置状态为库存中");
+ } else if ("REJECTED".equals(status)) {
+ // 归还审批拒绝:保持原有状态
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+ log.info("设备归还审批拒绝,保持原有状态");
+ }
+
+ // 执行更新
+ int updateCount = equipmentMapper.update(null, updateWrapper);
+ if (updateCount > 0) {
+ log.info("设备归还状态更新成功,设备ID: {}, 新状态: {}, 影响行数: {}", equipmentId, status, updateCount);
+ } else {
+ log.warn("设备归还状态更新失败,设备ID: {}, 新状态: {}, 可能设备不存在", equipmentId, status);
+ }
+
+ } catch (Exception e) {
+ log.error("更新设备归还状态失败,设备ID: {}, 状态: {}", equipmentId, status, e);
+ throw e;
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateLocationStatus(String equipmentId, String locationStatus) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过位置状态更新");
+ return;
+ }
+
+ try {
+ log.info("开始更新设备位置状态,设备ID: {}, 新位置状态: {}", equipmentId, locationStatus);
+
+ LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();
+ updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId);
+ updateWrapper.set(EquipmentEntity::getLocationStatus, locationStatus);
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+
+ // 执行更新
+ int updateCount = equipmentMapper.update(null, updateWrapper);
+ if (updateCount > 0) {
+ log.info("设备位置状态更新成功,设备ID: {}, 新位置状态: {}, 影响行数: {}", equipmentId, locationStatus, updateCount);
+ } else {
+ log.warn("设备位置状态更新失败,设备ID: {}, 新位置状态: {}, 可能设备不存在", equipmentId, locationStatus);
+ }
+
+ } catch (Exception e) {
+ log.error("更新设备位置状态失败,设备ID: {}, 位置状态: {}", equipmentId, locationStatus, e);
+ throw e;
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateUseStatus(String equipmentId, String useStatus) {
+ if (equipmentId == null || equipmentId.trim().isEmpty()) {
+ log.warn("设备ID为空,跳过使用状态更新");
+ return;
+ }
+
+ try {
+ log.info("开始更新设备使用状态,设备ID: {}, 新使用状态: {}", equipmentId, useStatus);
+
+ LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();
+ updateWrapper.eq(EquipmentEntity::getEquipmentId, equipmentId);
+ updateWrapper.set(EquipmentEntity::getUseStatus, useStatus);
+ updateWrapper.set(EquipmentEntity::getStatusChangeTime, LocalDateTime.now());
+
+ // 执行更新
+ int updateCount = equipmentMapper.update(null, updateWrapper);
+ if (updateCount > 0) {
+ log.info("设备使用状态更新成功,设备ID: {}, 新使用状态: {}, 影响行数: {}", equipmentId, useStatus, updateCount);
+ } else {
+ log.warn("设备使用状态更新失败,设备ID: {}, 新使用状态: {}, 可能设备不存在", equipmentId, useStatus);
+ }
+
+ } catch (Exception e) {
+ log.error("更新设备使用状态失败,设备ID: {}, 使用状态: {}", equipmentId, useStatus, e);
+ throw e;
+ }
+ }
+}
diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentUseRecordServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentUseRecordServiceImpl.java
index 33e7555..4df621a 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
@@ -50,8 +50,13 @@ public class EquipmentUseRecordServiceImpl extends ServiceImpl page(EquipmentUseRecordListReq req) {
+ // 使用分页插件
PageUtil.startPage();
- return this.list(req);
+
+ // 执行查询
+ List result = this.list(req);
+
+ return result;
}
@Override
diff --git a/core/src/main/java/com/dite/znpt/service/impl/ExpenseTypeServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/ExpenseTypeServiceImpl.java
new file mode 100644
index 0000000..e2013a5
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/impl/ExpenseTypeServiceImpl.java
@@ -0,0 +1,18 @@
+package com.dite.znpt.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import com.dite.znpt.mapper.ExpenseTypeMapper;
+import com.dite.znpt.domain.entity.ExpenseTypeEntity;
+import com.dite.znpt.service.ExpenseTypeService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class ExpenseTypeServiceImpl extends ServiceImpl implements ExpenseTypeService {
+ @Override
+ public List search(String key) {
+ return this.baseMapper.search(key);
+ }
+}
diff --git a/core/src/main/java/com/dite/znpt/service/impl/GanttChartServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/GanttChartServiceImpl.java
new file mode 100644
index 0000000..e1f8f44
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/service/impl/GanttChartServiceImpl.java
@@ -0,0 +1,486 @@
+package com.dite.znpt.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.dite.znpt.domain.entity.ProjectTaskEntity;
+import com.dite.znpt.domain.entity.UserEntity;
+import com.dite.znpt.domain.vo.GanttChartReq;
+import com.dite.znpt.domain.vo.GanttChartResp;
+import com.dite.znpt.mapper.ProjectTaskMapper;
+import com.dite.znpt.service.GanttChartService;
+import com.dite.znpt.service.UserService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.stream.Collectors;
+
+/**
+ * 甘特图服务实现类
+ */
+@Service
+@RequiredArgsConstructor
+public class GanttChartServiceImpl implements GanttChartService {
+
+ private final ProjectTaskMapper projectTaskMapper;
+ private final UserService userService;
+
+ @Override
+ public List getGanttChartData(GanttChartReq req) {
+ // 查询所有任务
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+
+ if (StrUtil.isNotBlank(req.getProjectId())) {
+ queryWrapper.eq("project_id", req.getProjectId());
+ }
+ if (StrUtil.isNotBlank(req.getTaskGroupId())) {
+ queryWrapper.eq("task_group_id", req.getTaskGroupId());
+ }
+ if (req.getStatus() != null) {
+ queryWrapper.eq("status", req.getStatus());
+ }
+ if (StrUtil.isNotBlank(req.getMainUserId())) {
+ queryWrapper.eq("main_user_id", req.getMainUserId());
+ }
+ if (req.getStartDateFrom() != null) {
+ queryWrapper.ge("plan_start_date", req.getStartDateFrom());
+ }
+ if (req.getStartDateTo() != null) {
+ queryWrapper.le("plan_start_date", req.getStartDateTo());
+ }
+ if (req.getEndDateFrom() != null) {
+ queryWrapper.ge("plan_end_date", req.getEndDateFrom());
+ }
+ if (req.getEndDateTo() != null) {
+ queryWrapper.le("plan_end_date", req.getEndDateTo());
+ }
+ if (req.getOverdueOnly() != null && req.getOverdueOnly()) {
+ queryWrapper.eq("overdue_status", 1);
+ }
+ if (req.getIncludeCompleted() != null && !req.getIncludeCompleted()) {
+ queryWrapper.ne("status", 2);
+ }
+
+ queryWrapper.orderByAsc("plan_start_date");
+
+ List taskList = projectTaskMapper.selectList(queryWrapper);
+
+ // 获取用户信息
+ final Set userIds = new HashSet<>();
+ taskList.forEach(task -> {
+ if (StrUtil.isNotBlank(task.getMainUserId())) {
+ userIds.add(task.getMainUserId());
+ }
+ if (StrUtil.isNotBlank(task.getUserIds())) {
+ userIds.addAll(Arrays.asList(task.getUserIds().split(",")));
+ }
+ });
+
+ final Map userMap = new HashMap<>();
+ if (CollUtil.isNotEmpty(userIds)) {
+ List users = userService.listByIds(userIds);
+ userMap.putAll(users.stream().collect(Collectors.toMap(UserEntity::getUserId, user -> user)));
+ }
+
+ // 批量获取项目时间范围,避免重复查询
+ final Map projectStartDates = new HashMap<>();
+ if (StrUtil.isNotBlank(req.getProjectId())) {
+ // 如果指定了项目ID,直接获取该项目的时间范围
+ LocalDate projectStart = getProjectStartDate(req.getProjectId());
+ projectStartDates.put(req.getProjectId(), projectStart);
+ } else {
+ // 如果没有指定项目ID,获取所有相关项目的时间范围
+ Set projectIds = taskList.stream()
+ .map(ProjectTaskEntity::getProjectId)
+ .filter(StrUtil::isNotBlank)
+ .collect(Collectors.toSet());
+
+ for (String projectId : projectIds) {
+ LocalDate projectStart = getProjectStartDate(projectId);
+ projectStartDates.put(projectId, projectStart);
+ }
+ }
+
+ // 转换为甘特图数据
+ List ganttData = taskList.stream().map(task -> {
+ GanttChartResp resp = BeanUtil.copyProperties(task, GanttChartResp.class);
+
+ // 设置状态描述
+ switch (task.getStatus()) {
+ case 0:
+ resp.setStatusDesc("未开始");
+ break;
+ case 1:
+ resp.setStatusDesc("进行中");
+ break;
+ case 2:
+ resp.setStatusDesc("已结束");
+ break;
+ default:
+ resp.setStatusDesc("未知");
+ }
+
+ // 设置负责人姓名
+ if (StrUtil.isNotBlank(task.getMainUserId()) && userMap.containsKey(task.getMainUserId())) {
+ resp.setMainUserName(userMap.get(task.getMainUserId()).getName());
+ }
+
+ // 设置参与人姓名列表
+ if (StrUtil.isNotBlank(task.getUserIds())) {
+ List participantNames = Arrays.stream(task.getUserIds().split(","))
+ .filter(userId -> userMap.containsKey(userId))
+ .map(userId -> userMap.get(userId).getName())
+ .collect(Collectors.toList());
+ resp.setParticipantNames(participantNames);
+ }
+
+ // 计算进度(这里可以根据实际业务逻辑调整)
+ if (task.getStatus() == 2) {
+ resp.setProgress(100);
+ } else if (task.getStatus() == 1) {
+ resp.setProgress(50); // 默认进度,实际应该从数据库字段获取
+ } else {
+ resp.setProgress(0);
+ }
+
+ // 计算任务在时间轴上的位置和持续时间
+ LocalDate projectStart = projectStartDates.get(task.getProjectId());
+ if (projectStart != null && task.getPlanStartDate() != null) {
+ int position = (int) ChronoUnit.DAYS.between(projectStart, task.getPlanStartDate());
+ resp.setPosition(position);
+ }
+
+ // 计算任务持续时间
+ if (task.getPlanStartDate() != null && task.getPlanEndDate() != null) {
+ int duration = (int) ChronoUnit.DAYS.between(task.getPlanStartDate(), task.getPlanEndDate()) + 1;
+ resp.setDuration(duration);
+ } else {
+ resp.setDuration(1); // 默认持续1天
+ }
+
+ return resp;
+ }).collect(Collectors.toList());
+
+ // 构建树形结构
+ return buildTreeStructure(ganttData);
+ }
+
+ @Override
+ public Object getGanttChartStatistics(String projectId) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("project_id", projectId);
+
+ List taskList = projectTaskMapper.selectList(queryWrapper);
+
+ Map statistics = new HashMap<>();
+ statistics.put("totalTasks", taskList.size());
+ statistics.put("notStarted", (int) taskList.stream().filter(task -> task.getStatus() == 0).count());
+ statistics.put("inProgress", (int) taskList.stream().filter(task -> task.getStatus() == 1).count());
+ statistics.put("completed", (int) taskList.stream().filter(task -> task.getStatus() == 2).count());
+ statistics.put("overdue", (int) taskList.stream().filter(task -> task.getOverdueStatus() == 1).count());
+
+ // 计算总体进度
+ if (taskList.size() > 0) {
+ final double avgProgress = taskList.stream()
+ .mapToInt(task -> {
+ if (task.getStatus() == 2) return 100;
+ else if (task.getStatus() == 1) return 50;
+ else return 0;
+ })
+ .average()
+ .orElse(0.0);
+ statistics.put("overallProgress", Math.round(avgProgress));
+ } else {
+ statistics.put("overallProgress", 0);
+ }
+
+ return statistics;
+ }
+
+ @Override
+ public Object getGanttChartTimeline(String projectId) {
+ if (StrUtil.isBlank(projectId)) {
+ return null;
+ }
+
+ LocalDate projectStartDate = getProjectStartDate(projectId);
+ LocalDate projectEndDate = getProjectEndDate(projectId);
+
+ Map timeline = new HashMap<>();
+ timeline.put("projectId", projectId);
+ timeline.put("startDate", projectStartDate);
+ timeline.put("endDate", projectEndDate);
+ timeline.put("totalDays", ChronoUnit.DAYS.between(projectStartDate, projectEndDate) + 1);
+
+ // 计算时间轴上的关键时间点(比如每周、每月)
+ List
+ *
+ * @author hdc
+ * @since 2025-08-07
+ */
+@Service
+public class VideoMonitorServiceImpl extends ServiceImpl implements VideoMonitorService {
+ @Resource
+ private TurbineService turbineService;
+ @Autowired
+ private ProjectService projectService;
+ @Resource(name = "clearanceExecutor")
+ private ThreadPoolTaskExecutor clearanceExecutor;
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public List uploadBatch(String projectId,
+ String turbineId,
+ String type,
+ MultipartFile[] files) throws IOException {
+ if (files == null || files.length == 0) {
+ throw new ServiceException("上传文件为空");
+ }
+ if (Objects.isNull(projectService.detail(projectId))) {
+ throw new ServiceException(Message.PROJECT_ID_IS_NOT_EXIST);
+ }
+ if (StrUtil.isNotBlank(turbineId) && turbineService.getById(turbineId) == null) {
+ throw new ServiceException(Message.PART_ID_IS_NOT_EXIST);
+ }
+ String userId = StpUtil.getLoginIdAsString();
+ String dateStr = DateUtil.today();
+ String storeDir = FilePathEnum.VIDEO.getFileAbsolutePathPrefix()
+ + projectId;
+ if (!turbineId.isEmpty() )
+ storeDir+=File.separator+turbineId+ File.separator + dateStr;
+ else
+ storeDir+=File.separator + dateStr;
+
+ FileUtil.mkdir(storeDir);
+
+ List list = Lists.newArrayList();
+
+ for (MultipartFile file : files) {
+ String original = file.getOriginalFilename();
+ String suffix = FileUtil.extName(original);
+ if (suffix != null && !suffix.equals("mp4")) throw new ServerException("非视频文件");
+ String uuid = IdUtil.simpleUUID();
+ String fileName = uuid + StrUtil.DOT + suffix;
+ String absolutePath = storeDir + File.separator + fileName;
+
+ File dest = new File(absolutePath);
+ file.transferTo(dest);
+
+ VideoMonitorEntity entity = new VideoMonitorEntity();
+ entity.setVideoId(uuid);
+ entity.setProjectId(projectId);
+ entity.setTurbineId(turbineId);
+ entity.setVideoName(original);
+ entity.setVideoPath(FilePathEnum.VIDEO.getFileDownPath(absolutePath));
+ entity.setType(type);
+ entity.setStatus((byte) 0); // 待审核
+ entity.setPreTreatment(false);
+ entity.setIsDeleted(false);
+ entity.setCreateTime(new Date());
+ entity.setUploadTime(new Date());
+ entity.setUpdateBy(userId);
+ entity.setCreateBy(userId);
+ list.add(entity);
+ if (type.equals(VideoMonitorEnum.CLEARANCE.getCode()))
+ clearanceExecutor.execute(
+ new ClearanceTask(absolutePath, storeDir+File.separator+ type+File.separator+uuid, uuid, this)
+ );
+ else if (type.equals(VideoMonitorEnum.DEFORMATION.getCode())) {
+ //TODO
+ }
+ }
+
+ saveBatch(list);
+ return list;
+ }
+
+ @Override
+ public VideoMonitorEntity upload(String projectId,
+ String partId,
+ String type,
+ MultipartFile file) throws IOException {
+ return uploadBatch(projectId, partId, type, new MultipartFile[]{file}).get(0);
+ }
+
+ @Override
+ public PageResult page(Integer pageNo,
+ Integer pageSize,
+ String projectId,
+ String partId) {
+ LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
+ wrapper.eq(StrUtil.isNotBlank(projectId),VideoMonitorEntity::getProjectId, projectId)
+ .eq(StrUtil.isNotBlank(partId), VideoMonitorEntity::getTurbineId, partId)
+ .orderByDesc(VideoMonitorEntity::getCreateTime);
+ Page page = page(Page.of(pageNo, pageSize), wrapper);
+ return PageResult.ok(page.getRecords(), page.getTotal());
+ }
+
+ @Override
+ public List list(String projectId, String partId) {
+ return lambdaQuery()
+ .eq(StrUtil.isNotBlank(projectId),VideoMonitorEntity::getProjectId, projectId)
+ .eq(StrUtil.isNotBlank(partId), VideoMonitorEntity::getTurbineId, partId)
+ .list();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(String videoId) {
+ VideoMonitorEntity entity = getById(videoId);
+ if (Objects.isNull(entity)) {
+ throw new ServiceException("视频不存在");
+ }
+ entity.setIsDeleted(true);
+ entity.setUpdateBy(StpUtil.getLoginIdAsString());
+ updateById(entity);
+ // 物理删除文件
+ FileUtil.del(FilePathEnum.VIDEO.getFileAbsolutePath(entity.getVideoPath()));
+ }
+
+ @Override
+ public void download(String videoId, HttpServletResponse response) throws IOException {
+ VideoMonitorEntity entity = getById(videoId);
+ if (entity == null || Boolean.TRUE.equals(entity.getIsDeleted())) {
+ throw new ServiceException("视频不存在或已删除");
+ }
+ File file = new File(FilePathEnum.VIDEO.getFileAbsolutePath(entity.getVideoPath()));
+ if (!file.exists()) {
+ throw new ServiceException("视频文件不存在");
+ }
+ response.setContentType("video/mp4");
+ response.setHeader("Content-Disposition",
+ "inline; filename=" + URLEncoder.encode(entity.getVideoName(), StandardCharsets.UTF_8));
+ FileUtil.writeToStream(file, response.getOutputStream());
+ }
+}
diff --git a/core/src/main/java/com/dite/znpt/util/PythonUtil.java b/core/src/main/java/com/dite/znpt/util/PythonUtil.java
new file mode 100644
index 0000000..a4329ea
--- /dev/null
+++ b/core/src/main/java/com/dite/znpt/util/PythonUtil.java
@@ -0,0 +1,49 @@
+package com.dite.znpt.util;
+
+import cn.hutool.extra.spring.SpringUtil;
+import org.springframework.core.env.Environment;
+
+import java.io.IOException;
+
+/**
+ * @author hedechao
+ * @Date 2025/8/11 09:04
+ * @Description: 形变python脚本执行工具
+ */
+public class PythonUtil {
+ /**
+ * 调用叶片净空计算脚本
+ *
+ * @param videoPath 待检测视频路径
+ * @throws IOException 如果启动进程失败
+ * @throws InterruptedException 如果等待进程完成被中断
+ */
+ public static void runClearance(
+ String videoPath,
+ String outputPath
+ ) throws IOException, InterruptedException {
+ String pyScriptPath=SpringUtil.getBean(Environment.class).getProperty("pyScript.clearance");
+ String modelPath=SpringUtil.getBean(Environment.class).getProperty("model.tip-hub");
+ // 1. 构造命令
+ ProcessBuilder pb = new ProcessBuilder(
+ "python", // 也可以是 python3 / 绝对路径
+ pyScriptPath,
+ "--video_path=" + videoPath,
+ "--model_path=" + modelPath,
+ "--output_dir=" + outputPath
+ );
+
+ // 2. 把子进程的标准输出 / 错误流重定向到 Java 控制台(可选)
+ pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+ // 3. 启动进程并等待完成
+ Process process = pb.start();
+ int exitCode = process.waitFor();
+ if (exitCode != 0) {
+ throw new RuntimeException("脚本返回非 0 状态码: " + exitCode);
+ }
+
+ System.out.println("净空计算完成,结果已保存到: " + outputPath);
+ }
+}
diff --git a/core/src/main/resources/mapper/BusinessDataFileMapper.xml b/core/src/main/resources/mapper/BusinessDataFileMapper.xml
index 3a129f4..62e2583 100644
--- a/core/src/main/resources/mapper/BusinessDataFileMapper.xml
+++ b/core/src/main/resources/mapper/BusinessDataFileMapper.xml
@@ -1,6 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
delete from business_data_part_file
@@ -46,5 +94,20 @@
where file_id = #{fileId}
+
+
+
+
+
+
+
+
+
+
+ update business_data_part_file
+ set file_path = replace(file_path, #{oldParentPath1}, #{newParentPath1})
+ where file_path like concat(#{oldParentPath2}, '%')
+
+
diff --git a/core/src/main/resources/mapper/BusinessDataMapper.xml b/core/src/main/resources/mapper/BusinessDataMapper.xml
index f714eae..e6d9332 100644
--- a/core/src/main/resources/mapper/BusinessDataMapper.xml
+++ b/core/src/main/resources/mapper/BusinessDataMapper.xml
@@ -51,5 +51,14 @@
+
+
+
+ update business_data_part
+ set folder_path = replace(folder_path, #{oldParentPath1}, #{newParentPath1}),
+ update_time = now()
+ where folder_path like concat(#{processedOldParentPath}, '%')
+
+
diff --git a/core/src/main/resources/mapper/ExpenseTypeMapper.xml b/core/src/main/resources/mapper/ExpenseTypeMapper.xml
new file mode 100644
index 0000000..4c9eb93
--- /dev/null
+++ b/core/src/main/resources/mapper/ExpenseTypeMapper.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/core/src/main/resources/mapper/VideoMonitorMapper.xml b/core/src/main/resources/mapper/VideoMonitorMapper.xml
new file mode 100644
index 0000000..37a7f78
--- /dev/null
+++ b/core/src/main/resources/mapper/VideoMonitorMapper.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ video_id, project_id, part_id, video_name, video_path, is_deleted, `status`, pre_image_path,
+ pre_treatment, update_by, create_time, create_by, update_time, wind_speed, rpm, `type`,
+ extra, upload_time
+
+
+
+
+ insert into video_monitor
+ (project_id, part_id, video_name, video_path, is_deleted, `status`, pre_image_path,
+ pre_treatment, update_by, create_time, create_by, update_time, wind_speed, rpm,
+ `type`, extra, upload_time)
+ values
+
+ (#{item.projectId}, #{item.turbineId}, #{item.videoName}, #{item.videoPath}, #{item.isDeleted},
+ #{item.status}, #{item.preImagePath}, #{item.preTreatment}, #{item.updateBy}, #{item.createTime},
+ #{item.createBy}, #{item.updateTime}, #{item.windSpeed}, #{item.rpm}, #{item.type},
+ #{item.extra}, #{item.uploadTime})
+
+
+
\ 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 f838342..a8b3451 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
@@ -43,15 +43,26 @@ public class BusinessDataFileController {
@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 = "分页查询文件", 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 = "分页查询文件", 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,
+ @RequestParam(required = false) String sortField,
+ @RequestParam(required = false) String sortOrder) {
+ PageBean pageBean = businessDataFileService.pageSelect(page, pageSize, folderId, fileName, sortField, sortOrder);
+ return Result.ok(pageBean);
+ }
@ApiOperation(value = "增加文件")
@PostMapping("/add")
diff --git a/web/src/main/java/com/dite/znpt/web/controller/EquipmentController.java b/web/src/main/java/com/dite/znpt/web/controller/EquipmentController.java
index bbfdccb..1b8280c 100644
--- a/web/src/main/java/com/dite/znpt/web/controller/EquipmentController.java
+++ b/web/src/main/java/com/dite/znpt/web/controller/EquipmentController.java
@@ -15,6 +15,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
+import java.util.List;
+import com.dite.znpt.domain.vo.ReceiptRequest;
/**
* @author Bear.G
@@ -103,9 +105,50 @@ public class EquipmentController {
return Result.ok();
}
+ @ApiOperation(value = "分页查询设备盘库记录", httpMethod = "GET")
+ @GetMapping("/inventory/page")
+ public PageResult inventoryPage(EquipmentListReq req) {
+ log.info("=== 设备盘库记录查询接口被调用 ===");
+ log.info("接收到的请求参数: {}", req);
+
+ IPage page = equipmentService.inventoryPage(req);
+ return PageResult.ok(page.getRecords(), page.getTotal());
+ }
+
+ @ApiOperation(value = "执行设备盘库", httpMethod = "POST")
+ @PostMapping("/inventory/{equipmentId}")
+ public Result> executeInventory(
+ @PathVariable String equipmentId,
+ @RequestParam String inventoryResult,
+ @RequestParam(required = false) String remark) {
+ equipmentService.executeInventory(equipmentId, inventoryResult, remark);
+ return Result.ok();
+ }
+
+ @ApiOperation(value = "批量执行设备盘库", httpMethod = "POST")
+ @PostMapping("/inventory/batch")
+ public Result> batchExecuteInventory(
+ @RequestParam List equipmentIds,
+ @RequestParam String inventoryResult,
+ @RequestParam(required = false) String remark) {
+ equipmentService.batchExecuteInventory(equipmentIds, inventoryResult, remark);
+ return Result.ok();
+ }
+
@ApiOperation(value = "获取采购统计信息", httpMethod = "GET")
@GetMapping("/procurement/stats")
public Result> getProcurementStats(){
return Result.ok(equipmentService.getProcurementStats());
}
+
+ @ApiOperation(value = "确认收货并自动入库", httpMethod = "POST")
+ @PostMapping("/procurement/receipt/{equipmentId}")
+ public Result> receiveGoods(@PathVariable String equipmentId, @Validated @RequestBody ReceiptRequest req) {
+ log.info("=== 设备收货接口被调用 ===");
+ log.info("设备ID: {}", equipmentId);
+ log.info("收货数据: {}", req);
+
+ equipmentService.receiveGoodsAndStockIn(equipmentId, req);
+ return Result.ok("收货成功,设备已自动入库");
+ }
}
diff --git a/web/src/main/java/com/dite/znpt/web/controller/ExpenseTypeController.java b/web/src/main/java/com/dite/znpt/web/controller/ExpenseTypeController.java
new file mode 100644
index 0000000..5b3eb1d
--- /dev/null
+++ b/web/src/main/java/com/dite/znpt/web/controller/ExpenseTypeController.java
@@ -0,0 +1,68 @@
+package com.dite.znpt.web.controller;
+
+import cn.hutool.core.io.LimitedInputStream;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.dite.znpt.domain.Result;
+import com.dite.znpt.domain.entity.ExpenseTypeEntity;
+import com.dite.znpt.service.ExpenseTypeService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Api(tags = "支出类型信息")
+@RestController
+@RequestMapping("/expenseType")
+public class ExpenseTypeController {
+ @Resource
+ private ExpenseTypeService expenseTypeService;
+
+ @GetMapping("")
+ @ApiOperation(value = "查询一级支出类型", httpMethod = "GET")
+ public Result> list() {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.isNull("parent_id");
+ List list = expenseTypeService.list(queryWrapper);
+ return Result.ok(list);
+ }
+
+ @GetMapping("/{pid}")
+ @ApiOperation(value = "查询二级支出类型", httpMethod = "GET")
+ public Result> list2(@PathVariable Integer pid) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("parent_id", pid);
+ List list = expenseTypeService.list(queryWrapper);
+ return Result.ok(list);
+ }
+
+ @PostMapping("")
+ @ApiOperation(value = "新增支出类型", httpMethod = "POST")
+ public Result save(@RequestBody ExpenseTypeEntity expenseTypeEntity) {
+ boolean b = expenseTypeService.save(expenseTypeEntity);
+ return Result.ok(b);
+ }
+
+ @PutMapping("")
+ @ApiOperation(value = "更新支出类型", httpMethod = "PUT")
+ public Result update(@RequestBody ExpenseTypeEntity expenseTypeEntity) {
+ boolean b = expenseTypeService.updateById(expenseTypeEntity);
+ return Result.ok(b);
+ }
+
+ @DeleteMapping("/{id}")
+ @ApiOperation(value = "删除支出类型", httpMethod = "DELETE")
+ public Result delete(@PathVariable Integer id) {
+ boolean b = expenseTypeService.removeById(id);
+ return Result.ok(b);
+ }
+
+ @GetMapping("search/{key}")
+ @ApiOperation(value = "查询支出类型", httpMethod = "GET")
+ public Result> search(@PathVariable String key) {
+ List list = expenseTypeService.search(key);
+ return Result.ok(list);
+ }
+}
diff --git a/web/src/main/java/com/dite/znpt/web/controller/GanttChartController.java b/web/src/main/java/com/dite/znpt/web/controller/GanttChartController.java
new file mode 100644
index 0000000..6da8f57
--- /dev/null
+++ b/web/src/main/java/com/dite/znpt/web/controller/GanttChartController.java
@@ -0,0 +1,61 @@
+package com.dite.znpt.web.controller;
+
+import com.dite.znpt.domain.Result;
+import com.dite.znpt.domain.vo.GanttChartReq;
+import com.dite.znpt.domain.vo.GanttChartResp;
+import com.dite.znpt.service.GanttChartService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 甘特图控制器
+ */
+@Api(tags = "甘特图管理")
+@RestController
+@RequestMapping("/gantt-chart")
+public class GanttChartController {
+
+ @Resource
+ private GanttChartService ganttChartService;
+
+ @ApiOperation(value = "获取项目甘特图数据", httpMethod = "GET")
+ @GetMapping("/data")
+ public Result> getGanttChartData(GanttChartReq req) {
+ List data = ganttChartService.getGanttChartData(req);
+ return Result.ok(data);
+ }
+
+ @ApiOperation(value = "获取项目甘特图统计信息", httpMethod = "GET")
+ @GetMapping("/statistics/{projectId}")
+ public Result