This commit is contained in:
高雄 2025-08-06 14:28:33 +08:00
commit 24d275045a
211 changed files with 5356 additions and 8553 deletions

View File

@ -7,6 +7,7 @@ import com.dite.znpt.domain.vo.PartResp;
import com.dite.znpt.enums.FilePathEnum;
import com.dite.znpt.service.ImageService;
import com.dite.znpt.service.PartService;
import com.dite.znpt.service.job.AutoExpirationJobService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
@ -26,6 +27,7 @@ public class Schedule {
private final ImageService imageService;
private final PartService partService;
private final ExtUtilConfig extUtilConfig;
private final AutoExpirationJobService autoExpirationJobService;
/**
* 功能描述图像预处理持续运行
@ -67,4 +69,16 @@ public class Schedule {
}
imageService.updateBatchById(successList);
}
/**
* 功能描述自动到期检测每天凌晨2点执行
*
* @author System
* @date 2025/1/1
**/
@Scheduled(cron = "0 0 2 * * ?")
public void autoExpirationCheck() {
log.info("开始执行自动到期检测定时任务...");
autoExpirationJobService.executeAutoExpirationJob();
}
}

View File

@ -38,7 +38,6 @@ public class SwaggerConfig {
.enable(true)//开启Swagger文档
.select()
.apis(RequestHandlerSelectors.basePackage("com.dite"))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.globalRequestParameters(parameters);

View File

@ -2,10 +2,14 @@ package com.dite.znpt.config;
import cn.hutool.core.collection.ListUtil;
import com.dite.znpt.enums.FilePathEnum;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@ -28,6 +32,14 @@ public class WebMvcConfig implements WebMvcConfigurer {
}
}
/**
* 配置HTTP消息转换器确保UTF-8编码
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// // 注册 Sa-Token 拦截器定义详细认证规则

View File

@ -0,0 +1,18 @@
package com.dite.znpt.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
/**
* 制度确认DTO
* @author wangna
* @date 2025/07/29
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RegulationConfirmDTO {
private Boolean agreeTerms = true; // 是否同意条款默认为true
}

View File

@ -0,0 +1,27 @@
package com.dite.znpt.domain.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author wangna
* @date 2025/07/29
* @Description: 制度类型请求DTO
*/
@Data
@ApiModel(value = "RegulationTypeRequest", description = "制度类型请求")
public class RegulationTypeRequest {
@ApiModelProperty("类型名称")
private String typeName;
@ApiModelProperty("排序顺序")
private Integer sortOrder;
@ApiModelProperty("是否启用")
private String isEnabled;
@ApiModelProperty("备注")
private String remark;
}

View File

@ -0,0 +1,84 @@
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 com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
/**
* @author System
* @date 2025/1/1
* @description 自动到期检测配置实体
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("auto_expiration_config")
@ApiModel(value="AutoExpirationConfigEntity对象", description="自动到期检测配置")
public class AutoExpirationConfigEntity extends AuditableEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("配置ID")
@TableId(value = "config_id", type = IdType.ASSIGN_UUID)
private String configId;
@ApiModelProperty("表名")
@TableField("table_name")
private String tableName;
@ApiModelProperty("表描述")
@TableField("table_desc")
private String tableDesc;
@ApiModelProperty("主键字段")
@TableField("primary_key_field")
private String primaryKeyField;
@ApiModelProperty("到期时间字段")
@TableField("expire_date_field")
private String expireDateField;
@ApiModelProperty("关联用户字段")
@TableField("user_id_field")
private String userIdField;
@ApiModelProperty("用户姓名字段")
@TableField("user_name_field")
private String userNameField;
@ApiModelProperty("业务名称字段")
@TableField("business_name_field")
private String businessNameField;
@ApiModelProperty("提前提醒天数")
@TableField("remind_days")
private Integer remindDays;
@ApiModelProperty("是否启用0-禁用1-启用)")
@TableField("enabled")
private String enabled;
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
@ApiModelProperty("删除标志0代表存在1代表删除")
@TableField("del_flag")
private String delFlag;
/**
* 保存前处理
*/
public void preSave() {
// 可以在这里添加保存前的逻辑处理
}
}

View File

@ -0,0 +1,85 @@
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 com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* @author System
* @date 2025/1/1
* @description 到期检测结果实体
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("expiration_result")
@ApiModel(value="ExpirationResultEntity对象", description="到期检测结果")
public class ExpirationResultEntity extends AuditableEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("结果ID")
@TableId(value = "result_id", type = IdType.ASSIGN_UUID)
private String resultId;
@ApiModelProperty("配置ID")
@TableField("config_id")
private String configId;
@ApiModelProperty("表名")
@TableField("table_name")
private String tableName;
@ApiModelProperty("业务ID")
@TableField("business_id")
private String businessId;
@ApiModelProperty("业务名称")
@TableField("business_name")
private String businessName;
@ApiModelProperty("关联用户ID")
@TableField("user_id")
private String userId;
@ApiModelProperty("关联用户姓名")
@TableField("user_name")
private String userName;
@ApiModelProperty("到期日期")
@TableField("expire_date")
private LocalDate expireDate;
@ApiModelProperty("剩余天数")
@TableField("remaining_days")
private Integer remainingDays;
@ApiModelProperty("状态0-正常1-即将到期2-已到期)")
@TableField("status")
private String status;
@ApiModelProperty("检测时间")
@TableField("check_time")
private java.time.LocalDateTime checkTime;
@ApiModelProperty("删除标志0代表存在1代表删除")
@TableField("del_flag")
private String delFlag;
/**
* 保存前处理
*/
public void preSave() {
// 可以在这里添加保存前的逻辑处理
}
}

View File

@ -91,24 +91,31 @@ public class ProjectEntity extends AuditableEntity implements Serializable {
@TableField("turbine_model")
private String turbineModel;
@ApiModelProperty("施工人员id")
// 人员管理已迁移到 project_member
// 以下字段保留用于向后兼容但建议使用 ProjectMemberService 进行人员管理
@ApiModelProperty("施工人员id已废弃请使用ProjectMemberService")
@TableField("constructor_ids")
@Deprecated
private String constructorIds;
@ApiModelProperty("安全员id")
@ApiModelProperty("安全员id已废弃请使用ProjectMemberService")
@TableField("auditor_id")
@Deprecated
private String auditorId;
@ApiModelProperty("质量员id")
@ApiModelProperty("质量员id已废弃请使用ProjectMemberService")
@TableField("quality_officer_id")
@Deprecated
private String qualityOfficerId;
@ApiModelProperty("项目经理id")
@ApiModelProperty("项目经理id已废弃请使用ProjectMemberService")
@TableField("project_manager_id")
@Deprecated
private String projectManagerId;
@ApiModelProperty("施工组长id")
@ApiModelProperty("施工组长id已废弃请使用ProjectMemberService")
@TableField("construct_team_leader_id")
@Deprecated
private String constructTeamLeaderId;
@ApiModelProperty("技术方案图片,多个用逗号隔开")

View File

@ -0,0 +1,99 @@
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 com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目人员关联表实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("project_member")
@ApiModel(value="ProjectMemberEntity对象", description="项目人员关联表")
public class ProjectMemberEntity extends AuditableEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("关联ID")
@TableId(value = "member_id", type = IdType.ASSIGN_UUID)
private String memberId;
@ApiModelProperty("项目ID")
@TableField("project_id")
private String projectId;
@ApiModelProperty("机组ID可选关联到具体机组")
@TableField("turbine_id")
private String turbineId;
@ApiModelProperty("任务组ID可选关联到具体任务组")
@TableField("task_group_id")
private String taskGroupId;
@ApiModelProperty("任务ID可选关联到具体任务")
@TableField("task_id")
private String taskId;
@ApiModelProperty("用户ID")
@TableField("user_id")
private String userId;
@ApiModelProperty("项目角色类型PROJECT_MANAGER-项目经理SAFETY_OFFICER-安全员QUALITY_OFFICER-质量员CONSTRUCTOR-施工人员TEAM_LEADER-施工组长")
@TableField("role_type")
private String roleType;
@ApiModelProperty("具体岗位代码GROUND_SERVICE-地勤DRIVER-司机ASCENDING-登高等)")
@TableField("job_code")
private String jobCode;
@ApiModelProperty("岗位描述")
@TableField("job_desc")
private String jobDesc;
@ApiModelProperty("加入时间")
@TableField("join_date")
private LocalDate joinDate;
@ApiModelProperty("离开时间")
@TableField("leave_date")
private LocalDate leaveDate;
@ApiModelProperty("状态ACTIVE-在职INACTIVE-离职SUSPENDED-暂停")
@TableField("status")
private String status;
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
// 非数据库字段用于显示
@TableField(exist = false)
@ApiModelProperty("用户姓名")
private String userName;
@TableField(exist = false)
@ApiModelProperty("用户账号")
private String userAccount;
@TableField(exist = false)
@ApiModelProperty("角色类型描述")
private String roleTypeDesc;
@TableField(exist = false)
@ApiModelProperty("岗位代码描述")
private String jobCodeDesc;
}

View File

@ -0,0 +1,66 @@
package com.dite.znpt.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.alibaba.excel.annotation.ExcelProperty;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度确认实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("regulation_confirmation")
@ApiModel(value="RegulationConfirmationEntity对象", description="制度确认")
public class RegulationConfirmationEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty("确认ID")
@ApiModelProperty("确认ID")
@TableId(value = "confirmation_id", type = IdType.ASSIGN_UUID)
private String confirmationId;
@ExcelProperty("制度ID")
@ApiModelProperty("制度ID")
@TableField("regulation_id")
private String regulationId;
@ExcelProperty("确认人ID")
@ApiModelProperty("确认人ID")
@TableField("confirmer_id")
private String confirmerId;
@ExcelProperty("确认人姓名")
@ApiModelProperty("确认人姓名")
@TableField("confirmer_name")
private String confirmerName;
@ExcelProperty("确认人部门")
@ApiModelProperty("确认人部门")
@TableField("confirmer_dept")
private String confirmerDept;
@ExcelProperty("确认状态")
@ApiModelProperty("确认状态CONFIRMED-已确认")
@TableField("status")
private String status;
@ExcelProperty("确认时间")
@ApiModelProperty("确认时间")
@TableField("confirm_time")
private LocalDateTime confirmTime;
@ExcelProperty("删除标志0代表存在1代表删除")
@ApiModelProperty("删除标志0代表存在1代表删除")
@TableField("del_flag")
private String delFlag;
}

View File

@ -0,0 +1,106 @@
package com.dite.znpt.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.alibaba.excel.annotation.ExcelProperty;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度草案实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("regulation_draft")
@ApiModel(value="RegulationDraftEntity对象", description="制度草案")
public class RegulationDraftEntity extends AuditableEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty("草案ID")
@ApiModelProperty("草案ID")
@TableId(value = "draft_id", type = IdType.ASSIGN_UUID)
private String draftId;
@ExcelProperty("制度标题")
@ApiModelProperty("制度标题")
@TableField("title")
private String title;
@ExcelProperty("制度内容")
@ApiModelProperty("制度内容")
@TableField("content")
private String content;
@ExcelProperty("制度类型")
@ApiModelProperty("制度类型")
@TableField("regulation_type")
private String regulationType;
@ExcelProperty("草案状态")
@ApiModelProperty("草案状态DRAFT-草稿REVIEWING-审核中APPROVED-已通过REJECTED-已拒绝")
@TableField("status")
private String status;
@ExcelProperty("创建人ID")
@ApiModelProperty("创建人ID")
@TableField("creator_id")
private String creatorId;
@ExcelProperty("创建人姓名")
@ApiModelProperty("创建人姓名")
@TableField("creator_name")
private String creatorName;
@ExcelProperty("审核人ID")
@ApiModelProperty("审核人ID")
@TableField("reviewer_id")
private String reviewerId;
@ExcelProperty("审核人姓名")
@ApiModelProperty("审核人姓名")
@TableField("reviewer_name")
private String reviewerName;
@ExcelProperty("审核时间")
@ApiModelProperty("审核时间")
@TableField("review_time")
private LocalDateTime reviewTime;
@ExcelProperty("审核意见")
@ApiModelProperty("审核意见")
@TableField("review_comment")
private String reviewComment;
@ExcelProperty("适用范围")
@ApiModelProperty("适用范围")
@TableField("scope")
private String scope;
@ExcelProperty("制度级别")
@ApiModelProperty("制度级别HIGH-高级MEDIUM-中级LOW-低级")
@TableField("level")
private String level;
@ExcelProperty("版本号")
@ApiModelProperty("版本号")
@TableField("version")
private String version;
@ExcelProperty("备注")
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
@ExcelProperty("删除标志0代表存在1代表删除")
@ApiModelProperty("删除标志0代表存在1代表删除")
@TableField("del_flag")
private String delFlag;
}

View File

@ -0,0 +1,103 @@
package com.dite.znpt.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.alibaba.excel.annotation.ExcelProperty;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度规范仓库实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("regulation")
@ApiModel(value="RegulationEntity对象", description="制度规范仓库")
public class RegulationEntity extends AuditableEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty("制度ID")
@ApiModelProperty("制度ID")
@TableId(value = "regulation_id", type = IdType.ASSIGN_UUID)
private String regulationId;
@ExcelProperty("制度标题")
@ApiModelProperty("制度标题")
@TableField("title")
private String title;
@ExcelProperty("制度内容")
@ApiModelProperty("制度内容")
@TableField("content")
private String content;
@ExcelProperty("制度类型")
@ApiModelProperty("制度类型")
@TableField("regulation_type")
private String type;
@ExcelProperty("制度状态")
@ApiModelProperty("制度状态DRAFT-草案APPROVED-已公示PUBLISHED-已发布ARCHIVED-已归档")
@TableField("status")
private String status;
@ExcelProperty("发布时间")
@ApiModelProperty("发布时间")
@TableField("publish_time")
private LocalDateTime publishTime;
@ExcelProperty("生效时间")
@ApiModelProperty("生效时间")
@TableField("effective_time")
private LocalDateTime effectiveTime;
@ExcelProperty("失效时间")
@ApiModelProperty("失效时间")
@TableField("expire_time")
private LocalDateTime expireTime;
@ExcelProperty("适用范围")
@ApiModelProperty("适用范围")
@TableField("scope")
private String scope;
@ExcelProperty("制度级别")
@ApiModelProperty("制度级别HIGH-高级MEDIUM-中级LOW-低级")
@TableField("level")
private String level;
@ExcelProperty("版本号")
@ApiModelProperty("版本号")
@TableField("version")
private String version;
@ExcelProperty("备注")
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
@ExcelProperty("删除标志0代表存在1代表删除")
@ApiModelProperty("删除标志0代表存在1代表删除")
@TableField("del_flag")
private String delFlag;
@TableField(exist = false)
@ApiModelProperty("当前用户确认状态pending-待确认confirmed-已确认")
private String confirmStatus;
@TableField(exist = false)
@ApiModelProperty("创建人姓名")
private String createByName;
@TableField(exist = false)
@ApiModelProperty("制度类型")
private String regulationType;
}

View File

@ -0,0 +1,156 @@
package com.dite.znpt.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.alibaba.excel.annotation.ExcelProperty;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度提案实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("regulation_proposal")
@ApiModel(value="RegulationProposalEntity对象", description="制度提案")
public class RegulationProposalEntity extends AuditableEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty("提案ID")
@ApiModelProperty("提案ID")
@TableId(value = "proposal_id", type = IdType.ASSIGN_UUID)
private String proposalId;
@ExcelProperty("提案标题")
@ApiModelProperty("提案标题")
@TableField("title")
private String title;
@ExcelProperty("提案内容")
@ApiModelProperty("提案内容")
@TableField("content")
private String content;
@ExcelProperty("提案类型")
@ApiModelProperty("提案类型")
@TableField("proposal_type")
private String proposalType;
@ExcelProperty("提案状态")
@ApiModelProperty("提案状态SUBMITTED-已提交DISCUSSING-讨论中APPROVED-已通过REJECTED-已拒绝CONVERTED-已转为草案")
@TableField("status")
private String status;
@ExcelProperty("提案人ID")
@ApiModelProperty("提案人ID")
@TableField("proposer_id")
private String proposerId;
@ExcelProperty("提案人姓名")
@ApiModelProperty("提案人姓名")
@TableField("proposer_name")
private String proposerName;
@ExcelProperty("提案人部门")
@ApiModelProperty("提案人部门")
@TableField("proposer_dept")
private String proposerDept;
@ExcelProperty("讨论组ID")
@ApiModelProperty("讨论组ID")
@TableField("discussion_group_id")
private String discussionGroupId;
@ExcelProperty("讨论组名称")
@ApiModelProperty("讨论组名称")
@TableField("discussion_group_name")
private String discussionGroupName;
@ExcelProperty("讨论开始时间")
@ApiModelProperty("讨论开始时间")
@TableField("discussion_start_time")
private LocalDateTime discussionStartTime;
@ExcelProperty("讨论结束时间")
@ApiModelProperty("讨论结束时间")
@TableField("discussion_end_time")
private LocalDateTime discussionEndTime;
@ExcelProperty("讨论状态")
@ApiModelProperty("讨论状态NOT_STARTED-未开始DISCUSSING-讨论中FINISHED-已结束")
@TableField("discussion_status")
private String discussionStatus;
@ExcelProperty("支持人数")
@ApiModelProperty("支持人数")
@TableField("support_count")
private Integer supportCount;
@ExcelProperty("反对人数")
@ApiModelProperty("反对人数")
@TableField("oppose_count")
private Integer opposeCount;
@ExcelProperty("总参与人数")
@ApiModelProperty("总参与人数")
@TableField("total_participants")
private Integer totalParticipants;
@ExcelProperty("审核人ID")
@ApiModelProperty("审核人ID")
@TableField("reviewer_id")
private String reviewerId;
@ExcelProperty("审核人姓名")
@ApiModelProperty("审核人姓名")
@TableField("reviewer_name")
private String reviewerName;
@ExcelProperty("审核时间")
@ApiModelProperty("审核时间")
@TableField("review_time")
private LocalDateTime reviewTime;
@ExcelProperty("审核意见")
@ApiModelProperty("审核意见")
@TableField("review_comment")
private String reviewComment;
@ExcelProperty("转为草案ID")
@ApiModelProperty("转为草案ID")
@TableField("converted_draft_id")
private String convertedDraftId;
@ExcelProperty("适用范围")
@ApiModelProperty("适用范围")
@TableField("scope")
private String scope;
@ExcelProperty("制度级别")
@ApiModelProperty("制度级别HIGH-高级MEDIUM-中级LOW-低级")
@TableField("level")
private String level;
@ExcelProperty("紧急程度")
@ApiModelProperty("紧急程度HIGH-高MEDIUM-中LOW-低")
@TableField("urgency_level")
private String urgencyLevel;
@ExcelProperty("备注")
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
@ExcelProperty("删除标志0代表存在1代表删除")
@ApiModelProperty("删除标志0代表存在1代表删除")
@TableField("del_flag")
private String delFlag;
}

View File

@ -0,0 +1,59 @@
package com.dite.znpt.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.dite.znpt.domain.AuditableEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.alibaba.excel.annotation.ExcelProperty;
import java.io.Serializable;
/**
* @author wangna
* @date 2025/07/29
* @Description: 制度类型实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("regulation_type")
@ApiModel(value="RegulationTypeEntity对象", description="制度类型")
public class RegulationTypeEntity extends AuditableEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty("类型ID")
@ApiModelProperty("类型ID")
@TableId(value = "type_id", type = IdType.ASSIGN_UUID)
private String typeId;
@ExcelProperty("类型名称")
@ApiModelProperty("类型名称")
@TableField("type_name")
private String typeName;
@ExcelProperty("是否启用")
@ApiModelProperty("是否启用1-启用0-禁用)")
@TableField("is_enabled")
private String isEnabled;
@ExcelProperty("排序顺序")
@ApiModelProperty("排序顺序")
@TableField("sort_order")
private Integer sortOrder;
@ExcelProperty("备注")
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
@ExcelProperty("删除标志0代表存在1代表删除")
@ApiModelProperty("删除标志0代表存在1代表删除")
@TableField("del_flag")
private String delFlag;
@TableField(exist = false)
@ApiModelProperty("创建人姓名")
private String createrName;
}

View File

@ -106,4 +106,8 @@ public class ImageListResp implements Serializable {
@ApiModelProperty("项目id")
private String projectId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("上传时间")
private LocalDateTime createTime;
}

View File

@ -1,11 +1,13 @@
package com.dite.znpt.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
@ -60,4 +62,8 @@ public class ImageResp implements Serializable {
@ApiModelProperty("项目id")
private String projectId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("上传时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,180 @@
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;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目详情响应VO
*/
@Data
@ApiModel(value="ProjectDetailResp对象", description="项目详情响应")
public class ProjectDetailResp {
@ApiModelProperty("项目ID")
private String projectId;
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty("项目封面")
private String coverUrl;
@ApiModelProperty("风场名称")
private String farmName;
@ApiModelProperty("风场地址")
private String farmAddress;
@ApiModelProperty("委托单位")
private String client;
@ApiModelProperty("委托单位联系人")
private String clientContact;
@ApiModelProperty("委托单位联系电话")
private String clientPhone;
@ApiModelProperty("检查单位")
private String inspectionUnit;
@ApiModelProperty("检查单位联系人")
private String inspectionContact;
@ApiModelProperty("检查单位联系电话")
private String inspectionPhone;
@ApiModelProperty("项目规模")
private String scale;
@ApiModelProperty("总工期(天数)")
private Integer duration;
@ApiModelProperty("风机型号")
private String turbineModel;
@ApiModelProperty("项目状态")
private Integer status;
@ApiModelProperty("项目状态描述")
private String statusLabel;
@ApiModelProperty("开始时间")
private LocalDate startDate;
@ApiModelProperty("结束时间")
private LocalDate endDate;
@ApiModelProperty("创建时间")
private String createTime;
@ApiModelProperty("更新时间")
private String updateTime;
// 项目人员信息从新关联表获取
@ApiModelProperty("项目人员列表")
private List<ProjectMemberResp> projectMembers;
// 项目机组信息
@ApiModelProperty("项目机组列表")
private List<TurbineInfo> turbines;
// 项目任务信息
@ApiModelProperty("项目任务列表")
private List<TaskInfo> tasks;
// 项目预算信息
@ApiModelProperty("项目预算列表")
private List<BudgetInfo> budgets;
// 项目日报信息
@ApiModelProperty("项目日报列表")
private List<DailyReportInfo> dailyReports;
@Data
@ApiModel(value="TurbineInfo对象", description="机组信息")
public static class TurbineInfo {
@ApiModelProperty("机组ID")
private String turbineId;
@ApiModelProperty("机组名称")
private String turbineName;
@ApiModelProperty("机组编码")
private String turbineCode;
@ApiModelProperty("机组状态")
private Integer status;
@ApiModelProperty("机组状态描述")
private String statusLabel;
}
@Data
@ApiModel(value="TaskInfo对象", description="任务信息")
public static class TaskInfo {
@ApiModelProperty("任务ID")
private String taskId;
@ApiModelProperty("任务名称")
private String taskName;
@ApiModelProperty("任务状态")
private Integer status;
@ApiModelProperty("任务状态描述")
private String statusLabel;
@ApiModelProperty("计划开始时间")
private LocalDate planStartDate;
@ApiModelProperty("计划结束时间")
private LocalDate planEndDate;
@ApiModelProperty("实际开始时间")
private LocalDate actualStartDate;
@ApiModelProperty("实际结束时间")
private LocalDate actualEndDate;
}
@Data
@ApiModel(value="BudgetInfo对象", description="预算信息")
public static class BudgetInfo {
@ApiModelProperty("预算ID")
private String budgetId;
@ApiModelProperty("预算名称")
private String budgetName;
@ApiModelProperty("预算类型")
private String budgetType;
@ApiModelProperty("预算金额(万元)")
private Double budgetAmount;
@ApiModelProperty("预算说明")
private String budgetDesc;
}
@Data
@ApiModel(value="DailyReportInfo对象", description="日报信息")
public static class DailyReportInfo {
@ApiModelProperty("日报ID")
private String reportId;
@ApiModelProperty("日报日期")
private LocalDate reportDate;
@ApiModelProperty("日报提交人")
private String submitUserName;
@ApiModelProperty("创建时间")
private String createTime;
}
}

View File

@ -0,0 +1,107 @@
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;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目看板数据响应VO
*/
@Data
@ApiModel(value="ProjectKanbanDataResp对象", description="项目看板数据响应")
public class ProjectKanbanDataResp {
@ApiModelProperty("待施工项目列表")
private List<ProjectKanbanItem> pendingProjects;
@ApiModelProperty("施工中项目列表")
private List<ProjectKanbanItem> inProgressProjects;
@ApiModelProperty("已完工项目列表")
private List<ProjectKanbanItem> completedProjects;
@ApiModelProperty("已审核项目列表")
private List<ProjectKanbanItem> auditedProjects;
@ApiModelProperty("已验收项目列表")
private List<ProjectKanbanItem> acceptedProjects;
@Data
@ApiModel(value="ProjectKanbanItem对象", description="项目看板项目项")
public static class ProjectKanbanItem {
@ApiModelProperty("项目ID")
private String projectId;
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty("项目封面")
private String coverUrl;
@ApiModelProperty("风场名称")
private String farmName;
@ApiModelProperty("风场地址")
private String farmAddress;
@ApiModelProperty("项目规模")
private String scale;
@ApiModelProperty("总工期(天数)")
private Integer duration;
@ApiModelProperty("风机型号")
private String turbineModel;
@ApiModelProperty("项目状态")
private Integer status;
@ApiModelProperty("项目状态描述")
private String statusLabel;
@ApiModelProperty("开始时间")
private LocalDate startDate;
@ApiModelProperty("结束时间")
private LocalDate endDate;
@ApiModelProperty("项目经理")
private String projectManagerName;
@ApiModelProperty("安全员")
private String safetyOfficerName;
@ApiModelProperty("质量员")
private String qualityOfficerName;
@ApiModelProperty("施工组长")
private String constructionTeamLeaderName;
@ApiModelProperty("施工人员")
private String constructorNames;
@ApiModelProperty("机组数量")
private Long turbineCount;
@ApiModelProperty("任务数量")
private Long taskCount;
@ApiModelProperty("已完成任务数量")
private Long completedTaskCount;
@ApiModelProperty("项目进度百分比")
private Integer progressPercentage;
@ApiModelProperty("创建时间")
private String createTime;
@ApiModelProperty("更新时间")
private String updateTime;
}
}

View File

@ -0,0 +1,81 @@
package com.dite.znpt.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目看板统计数据响应VO
*/
@Data
@ApiModel(value="ProjectKanbanStatsResp对象", description="项目看板统计数据响应")
public class ProjectKanbanStatsResp {
@ApiModelProperty("总项目数")
private Long totalProjectsCount;
@ApiModelProperty("待施工项目数")
private Long pendingProjectCount;
@ApiModelProperty("施工中项目数")
private Long inProgressProjectCount;
@ApiModelProperty("已完工项目数")
private Long completedProjectCount;
@ApiModelProperty("已审核项目数")
private Long auditedProjectCount;
@ApiModelProperty("已验收项目数")
private Long acceptedProjectCount;
@ApiModelProperty("总机组数")
private Long totalTurbineCount;
@ApiModelProperty("待施工机组数")
private Long pendingTurbineCount;
@ApiModelProperty("施工中机组数")
private Long inProgressTurbineCount;
@ApiModelProperty("已完工机组数")
private Long completedTurbineCount;
@ApiModelProperty("已审核机组数")
private Long auditedTurbineCount;
@ApiModelProperty("已验收机组数")
private Long acceptedTurbineCount;
@ApiModelProperty("总任务数")
private Long totalTaskCount;
@ApiModelProperty("未开始任务数")
private Long pendingTaskCount;
@ApiModelProperty("进行中任务数")
private Long inProgressTaskCount;
@ApiModelProperty("已完成任务数")
private Long completedTaskCount;
@ApiModelProperty("总人员数")
private Long totalMemberCount;
@ApiModelProperty("项目经理数")
private Long projectManagerCount;
@ApiModelProperty("安全员数")
private Long safetyOfficerCount;
@ApiModelProperty("质量员数")
private Long qualityOfficerCount;
@ApiModelProperty("施工人员数")
private Long constructorCount;
@ApiModelProperty("施工组长数")
private Long teamLeaderCount;
}

View File

@ -0,0 +1,45 @@
package com.dite.znpt.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目人员查询请求VO
*/
@Data
@ApiModel(value="ProjectMemberListReq对象", description="项目人员查询请求")
public class ProjectMemberListReq {
@ApiModelProperty("项目ID")
private String projectId;
@ApiModelProperty("机组ID")
private String turbineId;
@ApiModelProperty("任务组ID")
private String taskGroupId;
@ApiModelProperty("任务ID")
private String taskId;
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("角色类型")
private String roleType;
@ApiModelProperty("岗位代码")
private String jobCode;
@ApiModelProperty("状态")
private String status;
@ApiModelProperty("用户姓名(模糊查询)")
private String userName;
@ApiModelProperty("用户账号(模糊查询)")
private String userAccount;
}

View File

@ -0,0 +1,62 @@
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.time.LocalDate;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目人员请求VO
*/
@Data
@ApiModel(value="ProjectMemberReq对象", description="项目人员请求")
public class ProjectMemberReq {
@ApiModelProperty("关联ID更新时必填")
private String memberId;
@NotBlank(message = "项目ID不能为空")
@ApiModelProperty("项目ID")
private String projectId;
@ApiModelProperty("机组ID可选")
private String turbineId;
@ApiModelProperty("任务组ID可选")
private String taskGroupId;
@ApiModelProperty("任务ID可选")
private String taskId;
@NotBlank(message = "用户ID不能为空")
@ApiModelProperty("用户ID")
private String userId;
@NotBlank(message = "角色类型不能为空")
@ApiModelProperty("角色类型")
private String roleType;
@ApiModelProperty("岗位代码")
private String jobCode;
@ApiModelProperty("岗位描述")
private String jobDesc;
@NotNull(message = "加入时间不能为空")
@ApiModelProperty("加入时间")
private LocalDate joinDate;
@ApiModelProperty("离开时间")
private LocalDate leaveDate;
@ApiModelProperty("状态")
private String status;
@ApiModelProperty("备注")
private String remark;
}

View File

@ -0,0 +1,83 @@
package com.dite.znpt.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDate;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目人员响应VO
*/
@Data
@ApiModel(value="ProjectMemberResp对象", description="项目人员响应")
public class ProjectMemberResp {
@ApiModelProperty("关联ID")
private String memberId;
@ApiModelProperty("项目ID")
private String projectId;
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty("机组ID")
private String turbineId;
@ApiModelProperty("机组名称")
private String turbineName;
@ApiModelProperty("任务组ID")
private String taskGroupId;
@ApiModelProperty("任务组名称")
private String taskGroupName;
@ApiModelProperty("任务ID")
private String taskId;
@ApiModelProperty("任务名称")
private String taskName;
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("用户姓名")
private String userName;
@ApiModelProperty("用户账号")
private String userAccount;
@ApiModelProperty("用户头像")
private String userAvatar;
@ApiModelProperty("角色类型")
private String roleType;
@ApiModelProperty("角色类型描述")
private String roleTypeDesc;
@ApiModelProperty("岗位代码")
private String jobCode;
@ApiModelProperty("岗位代码描述")
private String jobCodeDesc;
@ApiModelProperty("岗位描述")
private String jobDesc;
@ApiModelProperty("加入时间")
private LocalDate joinDate;
@ApiModelProperty("离开时间")
private LocalDate leaveDate;
@ApiModelProperty("状态")
private String status;
@ApiModelProperty("备注")
private String remark;
}

View File

@ -19,7 +19,7 @@ public class UserResp extends UserReq implements Serializable{
@Serial
private static final long serialVersionUID = -2831232930040845716L;
@ApiModelProperty("用户")
@ApiModelProperty("用户id")
private String userId;
@ApiModelProperty("所属部门")
@ -39,6 +39,8 @@ public class UserResp extends UserReq implements Serializable{
@ApiModelProperty("在职状态描述")
private String userStatusLabel;
@ApiModelProperty("用户姓名")
private String userName;

View File

@ -0,0 +1,72 @@
package com.dite.znpt.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目岗位代码枚举
*/
@Getter
@AllArgsConstructor
public enum ProjectJobCodeEnum {
// 地勤相关岗位
GROUND_SERVICE("GROUND_SERVICE", "地勤"),
GROUND_SERVICE_LEADER("GROUND_SERVICE_LEADER", "地勤组长"),
// 司机相关岗位
DRIVER("DRIVER", "司机"),
DRIVER_LEADER("DRIVER_LEADER", "司机组长"),
// 登高相关岗位
ASCENDING("ASCENDING", "登高"),
ASCENDING_LEADER("ASCENDING_LEADER", "登高组长"),
// 防雷相关岗位
ANTI_THUNDER("ANTI_THUNDER", "防雷"),
ANTI_THUNDER_LEADER("ANTI_THUNDER_LEADER", "防雷组长"),
// 外部工作相关岗位
OUT_WORK("OUT_WORK", "外部工作"),
OUT_WORK_LEADER("OUT_WORK_LEADER", "外部工作组长"),
// 管理岗位
PROJECT_MANAGER("PROJECT_MANAGER", "项目经理"),
SAFETY_MANAGER("SAFETY_MANAGER", "安全经理"),
QUALITY_MANAGER("QUALITY_MANAGER", "质量经理"),
SITE_MANAGER("SITE_MANAGER", "现场经理"),
// 其他岗位
TECHNICIAN("TECHNICIAN", "技术员"),
SUPERVISOR("SUPERVISOR", "监理"),
COORDINATOR("COORDINATOR", "协调员");
private final String code;
private final String desc;
/**
* 根据代码获取描述
*/
public static String getDescByCode(String code) {
for (ProjectJobCodeEnum jobCode : values()) {
if (jobCode.getCode().equals(code)) {
return jobCode.getDesc();
}
}
return "";
}
/**
* 根据代码获取枚举
*/
public static ProjectJobCodeEnum getByCode(String code) {
for (ProjectJobCodeEnum jobCode : values()) {
if (jobCode.getCode().equals(code)) {
return jobCode;
}
}
return null;
}
}

View File

@ -0,0 +1,53 @@
package com.dite.znpt.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目角色类型枚举
*/
@Getter
@AllArgsConstructor
public enum ProjectRoleTypeEnum {
PROJECT_MANAGER("PROJECT_MANAGER", "项目经理"),
SAFETY_OFFICER("SAFETY_OFFICER", "安全员"),
QUALITY_OFFICER("QUALITY_OFFICER", "质量员"),
CONSTRUCTOR("CONSTRUCTOR", "施工人员"),
TEAM_LEADER("TEAM_LEADER", "施工组长"),
SENIOR_PROJECT_MANAGER("SENIOR_PROJECT_MANAGER", "大项目经理"),
REMOTE_ADVISOR("REMOTE_ADVISOR", "项目远程顾问"),
EXTERNAL_COLLABORATOR("EXTERNAL_COLLABORATOR", "外部协作者"),
FINANCIAL_MANAGER("FINANCIAL_MANAGER", "财务经理"),
BUSINESS_MANAGER("BUSINESS_MANAGER", "商务经理"),
SITE_MANAGER("SITE_MANAGER", "现场经理");
private final String code;
private final String desc;
/**
* 根据代码获取描述
*/
public static String getDescByCode(String code) {
for (ProjectRoleTypeEnum roleType : values()) {
if (roleType.getCode().equals(code)) {
return roleType.getDesc();
}
}
return "";
}
/**
* 根据代码获取枚举
*/
public static ProjectRoleTypeEnum getByCode(String code) {
for (ProjectRoleTypeEnum roleType : values()) {
if (roleType.getCode().equals(code)) {
return roleType;
}
}
return null;
}
}

View File

@ -0,0 +1,14 @@
package com.dite.znpt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.domain.entity.AutoExpirationConfigEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @author System
* @date 2025/1/1
* @description 自动到期检测配置Mapper
*/
@Mapper
public interface AutoExpirationConfigMapper extends BaseMapper<AutoExpirationConfigEntity> {
}

View File

@ -0,0 +1,14 @@
package com.dite.znpt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.domain.entity.ExpirationResultEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @author System
* @date 2025/1/1
* @description 到期检测结果Mapper
*/
@Mapper
public interface ExpirationResultMapper extends BaseMapper<ExpirationResultEntity> {
}

View File

@ -0,0 +1,54 @@
package com.dite.znpt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.domain.entity.ProjectMemberEntity;
import com.dite.znpt.domain.vo.ProjectMemberListReq;
import com.dite.znpt.domain.vo.ProjectMemberResp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目人员关联表Mapper接口
*/
@Mapper
public interface ProjectMemberMapper extends BaseMapper<ProjectMemberEntity> {
/**
* 根据条件查询项目人员列表
*/
List<ProjectMemberResp> queryBySelective(ProjectMemberListReq req);
/**
* 根据项目ID查询项目人员列表
*/
List<ProjectMemberResp> queryByProjectId(@Param("projectId") String projectId);
/**
* 根据机组ID查询机组人员列表
*/
List<ProjectMemberResp> queryByTurbineId(@Param("turbineId") String turbineId);
/**
* 根据任务组ID查询任务组人员列表
*/
List<ProjectMemberResp> queryByTaskGroupId(@Param("taskGroupId") String taskGroupId);
/**
* 根据任务ID查询任务人员列表
*/
List<ProjectMemberResp> queryByTaskId(@Param("taskId") String taskId);
/**
* 根据用户ID查询用户参与的项目列表
*/
List<ProjectMemberResp> queryByUserId(@Param("userId") String userId);
/**
* 根据项目ID和角色类型查询人员列表
*/
List<ProjectMemberResp> queryByProjectIdAndRoleType(@Param("projectId") String projectId, @Param("roleType") String roleType);
}

View File

@ -0,0 +1,14 @@
package com.dite.znpt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.domain.entity.RegulationConfirmationEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度确认Mapper接口
*/
@Mapper
public interface RegulationConfirmationMapper extends BaseMapper<RegulationConfirmationEntity> {
}

View File

@ -0,0 +1,35 @@
package com.dite.znpt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dite.znpt.domain.entity.RegulationEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度规范仓库Mapper接口
*/
@Mapper
public interface RegulationMapper extends BaseMapper<RegulationEntity> {
/**
* 分页查询制度列表包含创建人姓名
* @param page 分页参数
* @param status 状态
* @param type 类型
* @param title 提案标题
* @param proposer 提案人
* @param confirmStatus 确认状态
* @param userId 当前用户ID
* @return 分页结果
*/
Page<RegulationEntity> selectRegulationListWithCreator(Page<RegulationEntity> page,
@Param("status") String status,
@Param("type") String type,
@Param("title") String title,
@Param("proposer") String proposer,
@Param("confirmStatus") String confirmStatus,
@Param("userId") String userId);
}

View File

@ -0,0 +1,29 @@
package com.dite.znpt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dite.znpt.domain.entity.RegulationTypeEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 制度类型Mapper接口
* @author wangna
* @date 2025/07/29
*/
@Mapper
public interface RegulationTypeMapper extends BaseMapper<RegulationTypeEntity> {
/**
* 分页查询制度类型列表包含创建人姓名
* @param page 分页参数
* @param typeName 类型名称
* @param status 是否启用1-启用0-禁用
* @param remark 备注
* @return 分页结果
*/
Page<RegulationTypeEntity> selectRegulationTypeListWithCreator(Page<RegulationTypeEntity> page,
@Param("typeName") String typeName,
@Param("status") String status,
@Param("remark") String remark);
}

View File

@ -0,0 +1,61 @@
package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.AutoExpirationConfigEntity;
import com.dite.znpt.domain.entity.ExpirationResultEntity;
import java.util.List;
import java.util.Map;
/**
* @author System
* @date 2025/1/1
* @description 自动到期检测服务接口
*/
public interface AutoExpirationService extends IService<AutoExpirationConfigEntity> {
/**
* 执行自动到期检测
*/
void executeAutoExpirationCheck();
/**
* 获取到期检测结果
* @param status 状态筛选
* @return 检测结果列表
*/
List<ExpirationResultEntity> getExpirationResults(String status);
/**
* 获取统计信息
* @return 统计信息
*/
Map<String, Object> getStatistics();
/**
* 手动检测指定表
* @param tableName 表名
*/
void checkTableExpiration(String tableName);
/**
* 检查表是否已配置到期检测
* @param tableName 表名
* @return 配置信息如果未配置返回null
*/
AutoExpirationConfigEntity getTableConfig(String tableName);
/**
* 批量检查多个表的配置状态
* @param tableNames 表名列表
* @return 配置状态映射
*/
Map<String, Boolean> getTablesConfigStatus(List<String> tableNames);
/**
* 智能配置表检测
* @param tableName 表名
* @return 配置结果
*/
AutoExpirationConfigEntity autoConfigureTable(String tableName);
}

View File

@ -25,7 +25,7 @@ public interface ImageService extends IService<ImageEntity> {
List<ImageReq> batchUploadDefectImage(String partId, String imageSource, ImageCollectReq collectReq, MultipartFile[] files);
List<ImageReq> uploadProjectBatch(String projectId, String imageSource, MultipartFile[] files);
List<ImageReq> uploadProjectBatch(String projectId, String imageSource, ImageCollectReq collectReq, MultipartFile[] files);
List<String> batchUploadCommonImage(String imageSource, ImageWorkReq imageWorkReq, MultipartFile[] file) throws IOException;

View File

@ -0,0 +1,107 @@
package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.ProjectMemberEntity;
import com.dite.znpt.domain.vo.*;
import java.util.List;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目人员关联表服务接口
*/
public interface ProjectMemberService extends IService<ProjectMemberEntity> {
/**
* 查询项目人员列表
*/
List<ProjectMemberResp> selectList(ProjectMemberListReq req);
/**
* 根据项目ID查询项目人员列表
*/
List<ProjectMemberResp> selectByProjectId(String projectId);
/**
* 根据机组ID查询机组人员列表
*/
List<ProjectMemberResp> selectByTurbineId(String turbineId);
/**
* 根据任务组ID查询任务组人员列表
*/
List<ProjectMemberResp> selectByTaskGroupId(String taskGroupId);
/**
* 根据任务ID查询任务人员列表
*/
List<ProjectMemberResp> selectByTaskId(String taskId);
/**
* 根据用户ID查询用户参与的项目列表
*/
List<ProjectMemberResp> selectByUserId(String userId);
/**
* 根据项目ID和角色类型查询人员列表
*/
List<ProjectMemberResp> selectByProjectIdAndRoleType(String projectId, String roleType);
/**
* 新增项目人员
*/
void saveData(ProjectMemberReq req);
/**
* 更新项目人员
*/
void updateData(ProjectMemberReq req);
/**
* 删除项目人员
*/
void deleteById(String memberId);
/**
* 批量添加项目人员
*/
void batchAddMembers(List<ProjectMemberReq> reqList);
/**
* 根据项目ID删除所有项目人员
*/
void deleteByProjectId(String projectId);
/**
* 根据机组ID删除所有机组人员
*/
void deleteByTurbineId(String turbineId);
/**
* 根据任务组ID删除所有任务组人员
*/
void deleteByTaskGroupId(String taskGroupId);
/**
* 根据任务ID删除所有任务人员
*/
void deleteByTaskId(String taskId);
// ========================== 项目看板相关方法 ==========================
/**
* 获取项目看板统计数据
*/
ProjectKanbanStatsResp getProjectKanbanStats();
/**
* 获取项目看板数据
*/
ProjectKanbanDataResp getProjectKanbanData();
/**
* 获取项目详情
*/
ProjectDetailResp getProjectDetail(String projectId);
}

View File

@ -0,0 +1,14 @@
package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.RegulationConfirmationEntity;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度确认Service接口
*/
public interface RegulationConfirmationService extends IService<RegulationConfirmationEntity> {
// 继承自IService的方法已经足够使用
// 包括save, update, remove, list, page, lambdaQuery等
}

View File

@ -0,0 +1,68 @@
package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.RegulationEntity;
import com.dite.znpt.domain.Result;
/**
* @author wangna
* @date 2025/07/29
* @Description: 制度规范仓库Service接口
*/
public interface RegulationService extends IService<RegulationEntity> {
/**
* 获取制度列表
* @param page 页码
* @param pageSize 页大小
* @param status 状态
* @param type 类型
* @param title 提案标题
* @param proposer 提案人
* @param confirmStatus 确认状态
* @return 结果
*/
Result getRegulationList(Integer page, Integer pageSize, String status, String type, String title, String proposer, String confirmStatus);
/**
* 创建制度提案
* @param regulation 制度信息
* @return 结果
*/
Result createRegulationProposal(RegulationEntity regulation);
/**
* 更新制度提案
* @param regulation 制度信息
* @return 结果
*/
Result updateRegulationProposal(RegulationEntity regulation);
/**
* 删除制度提案
* @param regulationId 制度ID
* @return 结果
*/
Result deleteRegulationProposal(String regulationId);
/**
* 获取制度详情
* @param regulationId 制度ID
* @return 结果
*/
Result getRegulationDetail(String regulationId);
/**
* 确认制度知晓
* @param regulationId 制度ID
* @return 结果
*/
Result confirmRegulation(String regulationId);
/**
* 公示制度
* @param regulationId 制度ID
* @return 结果
*/
Result approveRegulation(String regulationId);
}

View File

@ -0,0 +1,45 @@
package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.RegulationTypeEntity;
import com.dite.znpt.domain.Result;
/**
* 制度类型Service接口
* @author wangna
* @date 2025/07/29
*/
public interface RegulationTypeService extends IService<RegulationTypeEntity> {
/**
* 获取制度类型列表
* @param page 页码
* @param size 页大小
* @param typeName 类型名称
* @param status 是否启用1-启用0-禁用
* @param remark 备注
* @return 结果
*/
Result getRegulationTypes(Integer page, Integer size, String typeName, String status, String remark);
/**
* 创建制度类型
* @param regulationType 制度类型信息
* @return 结果
*/
Result createRegulationType(RegulationTypeEntity regulationType);
/**
* 更新制度类型
* @param regulationType 制度类型信息
* @return 结果
*/
Result updateRegulationType(RegulationTypeEntity regulationType);
/**
* 删除制度类型
* @param typeId 类型ID
* @return 结果
*/
Result deleteRegulationType(String typeId);
}

View File

@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.RoleMenuEntity;
import com.dite.znpt.domain.vo.RoleMenuReq;
import java.util.List;
/**
* @author Bear.G
@ -12,6 +11,5 @@ import java.util.List;
* @description
*/
public interface RoleMenuService extends IService<RoleMenuEntity> {
void bindRoleMenu(RoleMenuReq req);
}

View File

@ -19,6 +19,7 @@ import com.dite.znpt.service.PartService;
import com.dite.znpt.util.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
@ -98,6 +99,7 @@ public class AudioFileInfoServiceImpl extends ServiceImpl<AudioFileInfoMapper, A
}
@Override
@Transactional(rollbackFor = Exception.class)
public List<AudioFileInfoResp> batchUpload(String imageId, MultipartFile[] files) {
ImageEntity image = imageMapper.selectById(imageId);
if(null == image){
@ -120,7 +122,7 @@ public class AudioFileInfoServiceImpl extends ServiceImpl<AudioFileInfoMapper, A
}
}
}
baseMapper.insert(list);
saveBatch(list);
return BeanUtil.copyToList(list, AudioFileInfoResp.class);
}
}

View File

@ -0,0 +1,341 @@
package com.dite.znpt.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.domain.entity.AutoExpirationConfigEntity;
import com.dite.znpt.domain.entity.ExpirationResultEntity;
import com.dite.znpt.mapper.AutoExpirationConfigMapper;
import com.dite.znpt.mapper.ExpirationResultMapper;
import com.dite.znpt.service.AutoExpirationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author System
* @date 2025/1/1
* @description 自动到期检测服务实现类
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class AutoExpirationServiceImpl extends ServiceImpl<AutoExpirationConfigMapper, AutoExpirationConfigEntity> implements AutoExpirationService {
@Autowired
private ExpirationResultMapper expirationResultMapper;
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void executeAutoExpirationCheck() {
log.info("开始执行自动到期检测...");
// 获取所有启用的配置
List<AutoExpirationConfigEntity> configs = lambdaQuery()
.eq(AutoExpirationConfigEntity::getEnabled, "1")
.eq(AutoExpirationConfigEntity::getDelFlag, "0")
.list();
if (CollUtil.isEmpty(configs)) {
log.info("没有找到启用的到期检测配置");
return;
}
// 清空之前的检测结果
expirationResultMapper.delete(null);
// 逐个检测每个配置的表
for (AutoExpirationConfigEntity config : configs) {
try {
checkTableExpiration(config);
} catch (Exception e) {
log.error("检测表 {} 时发生错误: {}", config.getTableName(), e.getMessage(), e);
}
}
log.info("自动到期检测完成,共检测 {} 个表", configs.size());
}
@Override
public List<ExpirationResultEntity> getExpirationResults(String status) {
LambdaQueryWrapper<ExpirationResultEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ExpirationResultEntity::getDelFlag, "0");
if (StrUtil.isNotBlank(status)) {
wrapper.eq(ExpirationResultEntity::getStatus, status);
}
wrapper.orderByDesc(ExpirationResultEntity::getExpireDate);
return expirationResultMapper.selectList(wrapper);
}
@Override
public Map<String, Object> getStatistics() {
Map<String, Object> statistics = new HashMap<>();
// 统计各状态的数量
List<ExpirationResultEntity> allResults = expirationResultMapper.selectList(null);
long normalCount = allResults.stream()
.filter(r -> "0".equals(r.getStatus()))
.count();
long expiringCount = allResults.stream()
.filter(r -> "1".equals(r.getStatus()))
.count();
long expiredCount = allResults.stream()
.filter(r -> "2".equals(r.getStatus()))
.count();
statistics.put("total", allResults.size());
statistics.put("normal", normalCount);
statistics.put("expiring", expiringCount);
statistics.put("expired", expiredCount);
return statistics;
}
@Override
public void checkTableExpiration(String tableName) {
AutoExpirationConfigEntity config = lambdaQuery()
.eq(AutoExpirationConfigEntity::getTableName, tableName)
.eq(AutoExpirationConfigEntity::getEnabled, "1")
.one();
if (config == null) {
throw new RuntimeException("未找到表 " + tableName + " 的配置信息");
}
checkTableExpiration(config);
}
/**
* 检测指定配置的表
*/
private void checkTableExpiration(AutoExpirationConfigEntity config) {
log.info("开始检测表: {}", config.getTableName());
// 构建查询SQL
String sql = buildQuerySql(config);
try {
List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);
for (Map<String, Object> row : results) {
processExpirationResult(config, row);
}
log.info("表 {} 检测完成,共处理 {} 条记录", config.getTableName(), results.size());
} catch (Exception e) {
log.error("检测表 {} 时发生错误: {}", config.getTableName(), e.getMessage(), e);
}
}
/**
* 构建查询SQL
*/
private String buildQuerySql(AutoExpirationConfigEntity config) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT ");
sql.append(config.getPrimaryKeyField()).append(" as business_id, ");
sql.append(config.getExpireDateField()).append(" as expire_date ");
if (StrUtil.isNotBlank(config.getUserIdField())) {
sql.append(", ").append(config.getUserIdField()).append(" as user_id ");
}
if (StrUtil.isNotBlank(config.getUserNameField())) {
sql.append(", ").append(config.getUserNameField()).append(" as user_name ");
}
if (StrUtil.isNotBlank(config.getBusinessNameField())) {
sql.append(", ").append(config.getBusinessNameField()).append(" as business_name ");
}
sql.append(" FROM ").append(config.getTableName());
sql.append(" WHERE ").append(config.getExpireDateField()).append(" IS NOT NULL");
return sql.toString();
}
/**
* 处理到期检测结果
*/
private void processExpirationResult(AutoExpirationConfigEntity config, Map<String, Object> row) {
try {
ExpirationResultEntity result = new ExpirationResultEntity();
result.preSave();
result.setConfigId(config.getConfigId());
result.setTableName(config.getTableName());
result.setBusinessId(String.valueOf(row.get("business_id")));
result.setBusinessName(String.valueOf(row.get("business_name")));
result.setUserId(String.valueOf(row.get("user_id")));
result.setUserName(String.valueOf(row.get("user_name")));
// 处理到期日期
Object expireDateObj = row.get("expire_date");
if (expireDateObj != null) {
LocalDate expireDate = parseDate(expireDateObj);
result.setExpireDate(expireDate);
// 计算剩余天数和状态
LocalDate today = LocalDate.now();
long remainingDays = ChronoUnit.DAYS.between(today, expireDate);
result.setRemainingDays((int) remainingDays);
// 设置状态
if (remainingDays < 0) {
result.setStatus("2"); // 已到期
} else if (remainingDays <= config.getRemindDays()) {
result.setStatus("1"); // 即将到期
} else {
result.setStatus("0"); // 正常
}
}
result.setCheckTime(LocalDateTime.now());
result.setDelFlag("0");
expirationResultMapper.insert(result);
} catch (Exception e) {
log.error("处理检测结果时发生错误: {}", e.getMessage(), e);
}
}
/**
* 解析日期
*/
private LocalDate parseDate(Object dateObj) {
if (dateObj instanceof LocalDate) {
return (LocalDate) dateObj;
} else if (dateObj instanceof java.sql.Date) {
return ((java.sql.Date) dateObj).toLocalDate();
} else if (dateObj instanceof java.util.Date) {
// 使用 DateUtil.toLocalDateTime 然后转换为 LocalDate
return DateUtil.toLocalDateTime((java.util.Date) dateObj).toLocalDate();
} else {
return LocalDate.parse(dateObj.toString());
}
}
@Override
public AutoExpirationConfigEntity getTableConfig(String tableName) {
return lambdaQuery()
.eq(AutoExpirationConfigEntity::getTableName, tableName)
.eq(AutoExpirationConfigEntity::getEnabled, "1")
.eq(AutoExpirationConfigEntity::getDelFlag, "0")
.one();
}
@Override
public Map<String, Boolean> getTablesConfigStatus(List<String> tableNames) {
Map<String, Boolean> statusMap = new HashMap<>();
if (CollUtil.isEmpty(tableNames)) {
return statusMap;
}
// 查询所有已配置的表
List<AutoExpirationConfigEntity> configs = lambdaQuery()
.in(AutoExpirationConfigEntity::getTableName, tableNames)
.eq(AutoExpirationConfigEntity::getEnabled, "1")
.eq(AutoExpirationConfigEntity::getDelFlag, "0")
.list();
// 构建已配置的表名集合
Set<String> configuredTables = configs.stream()
.map(AutoExpirationConfigEntity::getTableName)
.collect(Collectors.toSet());
// 为每个表设置配置状态
for (String tableName : tableNames) {
statusMap.put(tableName, configuredTables.contains(tableName));
}
return statusMap;
}
@Override
public AutoExpirationConfigEntity autoConfigureTable(String tableName) {
// 检查是否已配置
AutoExpirationConfigEntity existingConfig = getTableConfig(tableName);
if (existingConfig != null) {
log.info("表 {} 已存在配置", tableName);
return existingConfig;
}
// 根据表名生成默认配置
AutoExpirationConfigEntity config = generateDefaultConfig(tableName);
try {
config.preSave();
save(config);
log.info("为表 {} 自动创建配置", tableName);
return config;
} catch (Exception e) {
log.error("自动配置表 {} 失败: {}", tableName, e.getMessage(), e);
throw new RuntimeException("自动配置失败: " + e.getMessage());
}
}
/**
* 根据表名生成默认配置
*/
private AutoExpirationConfigEntity generateDefaultConfig(String tableName) {
AutoExpirationConfigEntity config = new AutoExpirationConfigEntity();
config.setConfigId("config-" + System.currentTimeMillis());
config.setTableName(tableName);
config.setEnabled("1");
config.setDelFlag("0");
config.setRemindDays(30);
config.setRemark("自动配置的到期检测");
// 根据表名设置默认字段
switch (tableName) {
case "certification":
config.setTableDesc("证书到期检测");
config.setPrimaryKeyField("certification_id");
config.setExpireDateField("validity_date_end");
config.setUserIdField("user_id");
config.setBusinessNameField("certification_name");
break;
case "insurance_info":
config.setTableDesc("保险到期检测");
config.setPrimaryKeyField("insurance_id");
config.setExpireDateField("expire_date");
config.setUserIdField("user_id");
config.setBusinessNameField("insurance_name");
break;
case "regulation":
config.setTableDesc("规章制度到期检测");
config.setPrimaryKeyField("regulation_id");
config.setExpireDateField("expire_date");
config.setUserIdField("create_by");
config.setBusinessNameField("regulation_name");
break;
default:
// 通用配置
config.setTableDesc(tableName + "到期检测");
config.setPrimaryKeyField("id");
config.setExpireDateField("expire_date");
config.setUserIdField("user_id");
config.setBusinessNameField("name");
break;
}
return config;
}
}

View File

@ -141,10 +141,13 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, ImageEntity> impl
if (StrUtil.isEmpty(imageSource) || Objects.isNull(ImageSourceEnum.getByCode(imageSource))) {
throw new ServiceException(Message.IMAGE_SOURCE_IS_NOT_EXIST);
}
PartResp partResp = partService.detail(partId);
if(null == files || files.length == 0){
throw new ServiceException(Message.IMAGE_IS_EMPTY);
}
PartResp partResp = partService.detail(partId);
if (Objects.isNull(partResp)) {
throw new ServiceException(Message.PART_ID_IS_NOT_EXIST);
}
List<ImageReq> list = new ArrayList<>(files.length);
File temCategory = new File(FilePathEnum.IMAGE_TEMP.getFileAbsolutePathPrefix());
if (!temCategory.exists()) {
@ -161,7 +164,7 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, ImageEntity> impl
if (!file.isEmpty()) {
try {
String path = temPathPrefix + file.getOriginalFilename();
FileUtil.writeBytes(file.getBytes(),path);
FileUtil.writeFromStream(file.getInputStream(),path);
String fileDownPath = FilePathEnum.IMAGE_TEMP.getFileDownPath(path);
ImageReq imageReq = imageRespBuilder(path, fileDownPath);
imageReq.setImageId(IdUtil.simpleUUID());
@ -185,7 +188,7 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, ImageEntity> impl
@SneakyThrows
@Override
public List<ImageReq> uploadProjectBatch(String projectId, String imageSource, MultipartFile[] files) {
public List<ImageReq> uploadProjectBatch(String projectId, String imageSource, ImageCollectReq collectReq, MultipartFile[] files) {
if (Objects.isNull(projectService.getById(projectId))) {
throw new ServiceException(Message.PROJECT_ID_IS_NOT_EXIST);
}
@ -202,13 +205,13 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, ImageEntity> impl
List<ImageReq> list = new ArrayList<>(files.length);
List<ImageEntity> imageList = new ArrayList<>();
ImageCollectEntity imageCollect = new ImageCollectEntity();
ImageCollectEntity imageCollect = Optional.ofNullable(BeanUtil.copyProperties(collectReq, ImageCollectEntity.class)).orElse(new ImageCollectEntity());
imageCollect.setCollectId(IdUtil.simpleUUID());
imageCollect.setCollectorId(StpUtil.getLoginIdAsString());
imageCollect.setCollectorName(userService.getById(StpUtil.getLoginIdAsString()).getName());
for (MultipartFile multipartFile : files) {
String absolutePath = path_prefix + multipartFile.getOriginalFilename();
FileUtil.writeBytes(multipartFile.getBytes(),absolutePath);
FileUtil.writeFromStream(multipartFile.getInputStream(),absolutePath);
String fileDownPath = FilePathEnum.IMAGE.getFileDownPath(absolutePath);
ImageEntity imageEntity = new ImageEntity();
try {

View File

@ -99,7 +99,7 @@ public class PartServiceImpl extends ServiceImpl<PartMapper, PartEntity> impleme
if(StrUtil.isNotEmpty(turbine.getProjectId())){
ProjectEntity project = projectService.getById(turbine.getProjectId());
if(null != project){
resp.setProjectId(resp.getProjectId());
resp.setProjectId(project.getProjectId());
resp.setProjectName(project.getProjectName());
}
}

View File

@ -0,0 +1,413 @@
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.extension.service.impl.ServiceImpl;
import com.dite.znpt.constant.Message;
import com.dite.znpt.domain.entity.*;
import com.dite.znpt.domain.vo.*;
import com.dite.znpt.enums.ProjectJobCodeEnum;
import com.dite.znpt.enums.ProjectRoleTypeEnum;
import com.dite.znpt.enums.ProjectStatusEnum;
import com.dite.znpt.enums.ProjectTaskStateEnum;
import com.dite.znpt.exception.ServiceException;
import com.dite.znpt.mapper.ProjectMemberMapper;
import com.dite.znpt.service.*;
import com.dite.znpt.util.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author wangna
* @date 2025/08/05
* @Description: 项目人员关联表服务实现类
*/
@Service
@RequiredArgsConstructor
public class ProjectMemberServiceImpl extends ServiceImpl<ProjectMemberMapper, ProjectMemberEntity> implements ProjectMemberService {
private final UserService userService;
// 添加其他服务依赖
private final ProjectService projectService;
private final TurbineService turbineService;
private final ProjectTaskService projectTaskService;
private final ProjectBudgetInfoService projectBudgetInfoService;
private final ProjectDailyReportService projectDailyReportService;
@Override
public List<ProjectMemberResp> selectList(ProjectMemberListReq req) {
PageUtil.startPage();
List<ProjectMemberResp> list = this.baseMapper.queryBySelective(req);
enrichMemberInfo(list);
return list;
}
@Override
public List<ProjectMemberResp> selectByProjectId(String projectId) {
List<ProjectMemberResp> list = this.baseMapper.queryByProjectId(projectId);
enrichMemberInfo(list);
return list;
}
@Override
public List<ProjectMemberResp> selectByTurbineId(String turbineId) {
List<ProjectMemberResp> list = this.baseMapper.queryByTurbineId(turbineId);
enrichMemberInfo(list);
return list;
}
@Override
public List<ProjectMemberResp> selectByTaskGroupId(String taskGroupId) {
List<ProjectMemberResp> list = this.baseMapper.queryByTaskGroupId(taskGroupId);
enrichMemberInfo(list);
return list;
}
@Override
public List<ProjectMemberResp> selectByTaskId(String taskId) {
List<ProjectMemberResp> list = this.baseMapper.queryByTaskId(taskId);
enrichMemberInfo(list);
return list;
}
@Override
public List<ProjectMemberResp> selectByUserId(String userId) {
List<ProjectMemberResp> list = this.baseMapper.queryByUserId(userId);
enrichMemberInfo(list);
return list;
}
@Override
public List<ProjectMemberResp> selectByProjectIdAndRoleType(String projectId, String roleType) {
List<ProjectMemberResp> list = this.baseMapper.queryByProjectIdAndRoleType(projectId, roleType);
enrichMemberInfo(list);
return list;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveData(ProjectMemberReq req) {
// 验证用户是否存在
UserEntity user = userService.getById(req.getUserId());
if (user == null) {
throw new ServiceException(Message.USER_ID_NOT_EXIST_OR_ILLEGAL);
}
// 检查是否已存在相同的关联
boolean exists = lambdaQuery()
.eq(ProjectMemberEntity::getProjectId, req.getProjectId())
.eq(ProjectMemberEntity::getUserId, req.getUserId())
.eq(StrUtil.isNotEmpty(req.getTurbineId()), ProjectMemberEntity::getTurbineId, req.getTurbineId())
.eq(StrUtil.isNotEmpty(req.getTaskGroupId()), ProjectMemberEntity::getTaskGroupId, req.getTaskGroupId())
.eq(StrUtil.isNotEmpty(req.getTaskId()), ProjectMemberEntity::getTaskId, req.getTaskId())
.eq(ProjectMemberEntity::getRoleType, req.getRoleType())
.exists();
if (exists) {
throw new ServiceException("该用户在此项目中已存在相同角色");
}
ProjectMemberEntity entity = BeanUtil.copyProperties(req, ProjectMemberEntity.class);
if (StrUtil.isEmpty(entity.getStatus())) {
entity.setStatus("ACTIVE");
}
save(entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateData(ProjectMemberReq req) {
if (StrUtil.isEmpty(req.getMemberId())) {
throw new ServiceException("关联ID不能为空");
}
ProjectMemberEntity entity = getById(req.getMemberId());
if (entity == null) {
throw new ServiceException(Message.PROJECT_ID_IS_NOT_EXIST);
}
BeanUtil.copyProperties(req, entity);
updateById(entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteById(String memberId) {
removeById(memberId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void batchAddMembers(List<ProjectMemberReq> reqList) {
if (CollUtil.isEmpty(reqList)) {
return;
}
for (ProjectMemberReq req : reqList) {
saveData(req);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByProjectId(String projectId) {
lambdaUpdate()
.eq(ProjectMemberEntity::getProjectId, projectId)
.remove();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByTurbineId(String turbineId) {
lambdaUpdate()
.eq(ProjectMemberEntity::getTurbineId, turbineId)
.remove();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByTaskGroupId(String taskGroupId) {
lambdaUpdate()
.eq(ProjectMemberEntity::getTaskGroupId, taskGroupId)
.remove();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByTaskId(String taskId) {
lambdaUpdate()
.eq(ProjectMemberEntity::getTaskId, taskId)
.remove();
}
/**
* 丰富成员信息用户信息角色描述岗位描述
*/
private void enrichMemberInfo(List<ProjectMemberResp> list) {
if (CollUtil.isEmpty(list)) {
return;
}
// 获取所有用户ID
List<String> userIds = list.stream()
.map(ProjectMemberResp::getUserId)
.distinct()
.collect(Collectors.toList());
// 查询用户信息
Map<String, UserEntity> userMap = userService.listByIds(userIds)
.stream()
.collect(Collectors.toMap(UserEntity::getUserId, Function.identity()));
// 填充用户信息和描述
list.forEach(member -> {
// 填充用户信息
UserEntity user = userMap.get(member.getUserId());
if (user != null) {
member.setUserName(user.getName());
member.setUserAccount(user.getAccount());
member.setUserAvatar(user.getAvatar());
}
// 填充角色类型描述
member.setRoleTypeDesc(ProjectRoleTypeEnum.getDescByCode(member.getRoleType()));
// 填充岗位代码描述
if (StrUtil.isNotEmpty(member.getJobCode())) {
member.setJobCodeDesc(ProjectJobCodeEnum.getDescByCode(member.getJobCode()));
}
});
}
// ========================== 项目看板相关方法实现 ==========================
@Override
public ProjectKanbanStatsResp getProjectKanbanStats() {
ProjectKanbanStatsResp resp = new ProjectKanbanStatsResp();
// 统计项目数量
resp.setTotalProjectsCount(projectService.count());
resp.setPendingProjectCount(projectService.lambdaQuery().eq(ProjectEntity::getStatus, 0).count());
resp.setInProgressProjectCount(projectService.lambdaQuery().eq(ProjectEntity::getStatus, 1).count());
resp.setCompletedProjectCount(projectService.lambdaQuery().eq(ProjectEntity::getStatus, 2).count());
resp.setAuditedProjectCount(projectService.lambdaQuery().eq(ProjectEntity::getStatus, 3).count());
resp.setAcceptedProjectCount(projectService.lambdaQuery().eq(ProjectEntity::getStatus, 4).count());
// 统计机组数量
resp.setTotalTurbineCount(turbineService.count());
resp.setPendingTurbineCount(turbineService.lambdaQuery().eq(TurbineEntity::getStatus, 0).count());
resp.setInProgressTurbineCount(turbineService.lambdaQuery().eq(TurbineEntity::getStatus, 1).count());
resp.setCompletedTurbineCount(turbineService.lambdaQuery().eq(TurbineEntity::getStatus, 2).count());
resp.setAuditedTurbineCount(turbineService.lambdaQuery().eq(TurbineEntity::getStatus, 3).count());
resp.setAcceptedTurbineCount(turbineService.lambdaQuery().eq(TurbineEntity::getStatus, 4).count());
// 统计任务数量
resp.setTotalTaskCount(projectTaskService.count());
resp.setPendingTaskCount(projectTaskService.lambdaQuery().eq(ProjectTaskEntity::getStatus, 0).count());
resp.setInProgressTaskCount(projectTaskService.lambdaQuery().eq(ProjectTaskEntity::getStatus, 1).count());
resp.setCompletedTaskCount(projectTaskService.lambdaQuery().eq(ProjectTaskEntity::getStatus, 2).count());
// 统计人员数量
resp.setTotalMemberCount(this.count());
resp.setProjectManagerCount(this.lambdaQuery().eq(ProjectMemberEntity::getRoleType, "PROJECT_MANAGER").count());
resp.setSafetyOfficerCount(this.lambdaQuery().eq(ProjectMemberEntity::getRoleType, "SAFETY_OFFICER").count());
resp.setQualityOfficerCount(this.lambdaQuery().eq(ProjectMemberEntity::getRoleType, "QUALITY_OFFICER").count());
resp.setConstructorCount(this.lambdaQuery().eq(ProjectMemberEntity::getRoleType, "CONSTRUCTOR").count());
resp.setTeamLeaderCount(this.lambdaQuery().eq(ProjectMemberEntity::getRoleType, "TEAM_LEADER").count());
return resp;
}
@Override
public ProjectKanbanDataResp getProjectKanbanData() {
ProjectKanbanDataResp resp = new ProjectKanbanDataResp();
// 获取各状态的项目列表
resp.setPendingProjects(getProjectKanbanItems(0));
resp.setInProgressProjects(getProjectKanbanItems(1));
resp.setCompletedProjects(getProjectKanbanItems(2));
resp.setAuditedProjects(getProjectKanbanItems(3));
resp.setAcceptedProjects(getProjectKanbanItems(4));
return resp;
}
@Override
public ProjectDetailResp getProjectDetail(String projectId) {
// 获取项目基本信息
ProjectEntity project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException(Message.PROJECT_ID_IS_NOT_EXIST);
}
ProjectDetailResp resp = new ProjectDetailResp();
BeanUtil.copyProperties(project, resp);
resp.setStatusLabel(ProjectStatusEnum.getDescByCode(resp.getStatus()));
// 获取项目人员信息
resp.setProjectMembers(selectByProjectId(projectId));
// 获取项目机组信息
List<TurbineEntity> turbines = turbineService.lambdaQuery()
.eq(TurbineEntity::getProjectId, projectId)
.list();
resp.setTurbines(turbines.stream().map(turbine -> {
ProjectDetailResp.TurbineInfo info = new ProjectDetailResp.TurbineInfo();
BeanUtil.copyProperties(turbine, info);
info.setStatusLabel(ProjectStatusEnum.getDescByCode(info.getStatus()));
return info;
}).collect(Collectors.toList()));
// 获取项目任务信息
List<ProjectTaskEntity> tasks = projectTaskService.lambdaQuery()
.eq(ProjectTaskEntity::getProjectId, projectId)
.list();
resp.setTasks(tasks.stream().map(task -> {
ProjectDetailResp.TaskInfo info = new ProjectDetailResp.TaskInfo();
BeanUtil.copyProperties(task, info);
info.setStatusLabel(ProjectTaskStateEnum.getDescByCode(info.getStatus()));
return info;
}).collect(Collectors.toList()));
// 获取项目预算信息
List<ProjectBudgetInfoEntity> budgets = projectBudgetInfoService.lambdaQuery()
.eq(ProjectBudgetInfoEntity::getProjectId, projectId)
.list();
resp.setBudgets(budgets.stream().map(budget -> {
ProjectDetailResp.BudgetInfo info = new ProjectDetailResp.BudgetInfo();
BeanUtil.copyProperties(budget, info);
return info;
}).collect(Collectors.toList()));
// 获取项目日报信息
List<ProjectDailyReportEntity> dailyReports = projectDailyReportService.lambdaQuery()
.eq(ProjectDailyReportEntity::getProjectId, projectId)
.orderByDesc(ProjectDailyReportEntity::getReportDate)
.last("LIMIT 10")
.list();
resp.setDailyReports(dailyReports.stream().map(report -> {
ProjectDetailResp.DailyReportInfo info = new ProjectDetailResp.DailyReportInfo();
BeanUtil.copyProperties(report, info);
// 获取提交人姓名
UserEntity user = userService.getById(report.getSubmitUser());
info.setSubmitUserName(user != null ? user.getName() : "");
return info;
}).collect(Collectors.toList()));
return resp;
}
/**
* 获取项目看板项目项列表
*/
private List<ProjectKanbanDataResp.ProjectKanbanItem> getProjectKanbanItems(Integer status) {
List<ProjectEntity> projects = projectService.lambdaQuery()
.eq(ProjectEntity::getStatus, status)
.orderByDesc(ProjectEntity::getCreateTime)
.list();
return projects.stream().map(project -> {
ProjectKanbanDataResp.ProjectKanbanItem item = new ProjectKanbanDataResp.ProjectKanbanItem();
BeanUtil.copyProperties(project, item);
item.setStatusLabel(ProjectStatusEnum.getDescByCode(item.getStatus()));
// 获取项目人员信息
List<ProjectMemberResp> members = selectByProjectId(project.getProjectId());
// 按角色类型分组并去重用户名
Map<String, String> memberNames = members.stream()
.collect(Collectors.groupingBy(
ProjectMemberResp::getRoleType,
Collectors.mapping(
ProjectMemberResp::getUserName,
Collectors.collectingAndThen(
Collectors.toSet(), // 使用Set去重
set -> String.join(",", set)
)
)
));
item.setProjectManagerName(memberNames.get("PROJECT_MANAGER"));
item.setSafetyOfficerName(memberNames.get("SAFETY_OFFICER"));
item.setQualityOfficerName(memberNames.get("QUALITY_OFFICER"));
item.setConstructionTeamLeaderName(memberNames.get("TEAM_LEADER"));
item.setConstructorNames(memberNames.get("CONSTRUCTOR"));
// 统计机组数量
Long turbineCount = turbineService.lambdaQuery()
.eq(TurbineEntity::getProjectId, project.getProjectId())
.count();
item.setTurbineCount(turbineCount);
// 统计任务数量
Long taskCount = projectTaskService.lambdaQuery()
.eq(ProjectTaskEntity::getProjectId, project.getProjectId())
.count();
item.setTaskCount(taskCount);
// 统计已完成任务数量
Long completedTaskCount = projectTaskService.lambdaQuery()
.eq(ProjectTaskEntity::getProjectId, project.getProjectId())
.eq(ProjectTaskEntity::getStatus, 2)
.count();
item.setCompletedTaskCount(completedTaskCount);
// 计算项目进度百分比
if (taskCount > 0) {
item.setProgressPercentage((int) (completedTaskCount * 100 / taskCount));
} else {
item.setProgressPercentage(0);
}
return item;
}).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,18 @@
package com.dite.znpt.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.domain.entity.RegulationConfirmationEntity;
import com.dite.znpt.mapper.RegulationConfirmationMapper;
import com.dite.znpt.service.RegulationConfirmationService;
import org.springframework.stereotype.Service;
/**
* @author wangna
* @date 2025/07/28
* @Description: 制度确认服务实现类
*/
@Service
public class RegulationConfirmationServiceImpl extends ServiceImpl<RegulationConfirmationMapper, RegulationConfirmationEntity> implements RegulationConfirmationService {
// 继承自ServiceImpl的方法已经足够使用
// 包括save, update, remove, list, page, lambdaQuery等
}

View File

@ -0,0 +1,275 @@
package com.dite.znpt.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.RegulationEntity;
import com.dite.znpt.domain.entity.RegulationConfirmationEntity;
import com.dite.znpt.domain.vo.UserResp;
import com.dite.znpt.mapper.RegulationMapper;
import com.dite.znpt.service.RegulationService;
import com.dite.znpt.service.RegulationConfirmationService;
import com.dite.znpt.service.UserService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* @author wangna
* @date 2025/07/29
* @Description: 制度规范仓库Service实现类
*/
@Service
public class RegulationServiceImpl extends ServiceImpl<RegulationMapper, RegulationEntity> implements RegulationService {
private final RegulationConfirmationService regulationConfirmationService;
private final UserService userService;
public RegulationServiceImpl(RegulationConfirmationService regulationConfirmationService, UserService userService) {
this.regulationConfirmationService = regulationConfirmationService;
this.userService = userService;
}
/**
* 每天凌晨1点自动将公示期10天已到的已公示制度变为已发布
*/
@Scheduled(cron = "0 0 1 * * ?")
@Transactional(rollbackFor = Exception.class)
public void autoPublishApprovedRegulations() {
LocalDateTime tenDaysAgo = LocalDateTime.now().minusDays(10);
// 查询需要自动发布的制度状态为APPROVED且更新时间超过10天
LambdaQueryWrapper<RegulationEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RegulationEntity::getStatus, "APPROVED");
wrapper.le(RegulationEntity::getUpdateTime, tenDaysAgo);
wrapper.eq(RegulationEntity::getDelFlag, "0");
java.util.List<RegulationEntity> approvedRegulations = this.list(wrapper);
for (RegulationEntity regulation : approvedRegulations) {
// 更新制度状态和发布信息
regulation.setStatus("PUBLISHED");
regulation.setPublishTime(LocalDateTime.now());
regulation.setEffectiveTime(LocalDateTime.now()); // 设置生效时间为当前时间
regulation.setUpdateTime(LocalDateTime.now());
regulation.setUpdateBy("系统自动发布");
this.updateById(regulation);
}
if (!approvedRegulations.isEmpty()) {
System.out.println("自动发布完成,共发布 " + approvedRegulations.size() + " 个制度");
}
}
@Override
@Transactional(readOnly = true)
public Result getRegulationList(Integer page, Integer pageSize, String status, String type, String title, String proposer, String confirmStatus) {
try {
Page<RegulationEntity> pageParam = new Page<>(page, pageSize);
String userId = StpUtil.getLoginIdAsString();
// 使用关联查询获取创建人姓名和确认状态
Page<RegulationEntity> result = this.baseMapper.selectRegulationListWithCreator(pageParam, status, type, title, proposer, confirmStatus, userId);
return Result.ok(result);
} catch (Exception e) {
return Result.error("获取制度列表失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result createRegulationProposal(RegulationEntity regulation) {
try {
regulation.setRegulationId(java.util.UUID.randomUUID().toString());
regulation.setStatus("DRAFT");
regulation.setCreateTime(LocalDateTime.now());
String userId = StpUtil.getLoginIdAsString();
regulation.setCreateBy(userId);
regulation.setUpdateTime(LocalDateTime.now());
regulation.setUpdateBy(userId);
regulation.setDelFlag("0");
this.save(regulation);
return Result.okM("制度提案创建成功");
} catch (Exception e) {
return Result.error("制度提案创建失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result updateRegulationProposal(RegulationEntity regulation) {
try {
RegulationEntity existing = this.getById(regulation.getRegulationId());
if (existing == null) {
return Result.error("制度提案不存在");
}
// 只能更新DRAFT状态的提案
if (!"DRAFT".equals(existing.getStatus())) {
return Result.error("只能更新草稿状态的制度提案");
}
// 只能由创建人更新
if (!existing.getCreateBy().equals(StpUtil.getLoginIdAsString())) {
return Result.error("只能更新自己创建的制度提案");
}
String userId = StpUtil.getLoginIdAsString();
regulation.setUpdateTime(LocalDateTime.now());
regulation.setUpdateBy(userId);
regulation.setStatus("DRAFT"); // 确保状态保持为DRAFT
this.updateById(regulation);
return Result.okM("制度提案更新成功");
} catch (Exception e) {
return Result.error("制度提案更新失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result deleteRegulationProposal(String regulationId) {
try {
RegulationEntity regulation = this.getById(regulationId);
if (regulation == null) {
return Result.error("制度提案不存在");
}
// 只能删除DRAFT状态的提案
if (!"DRAFT".equals(regulation.getStatus())) {
return Result.error("只能删除草稿状态的制度提案");
}
// 只能由创建人删除
if (!regulation.getCreateBy().equals(StpUtil.getLoginIdAsString())) {
return Result.error("只能删除自己创建的制度提案");
}
// 软删除
regulation.setDelFlag("1");
regulation.setUpdateTime(LocalDateTime.now());
regulation.setUpdateBy(StpUtil.getLoginIdAsString());
this.updateById(regulation);
return Result.okM("制度提案删除成功");
} catch (Exception e) {
return Result.error("制度提案删除失败:" + e.getMessage());
}
}
@Override
@Transactional(readOnly = true)
public Result getRegulationDetail(String regulationId) {
try {
RegulationEntity regulation = this.getById(regulationId);
if (regulation == null) {
return Result.error("制度不存在");
}
// 获取创建人姓名
if (regulation.getCreateBy() != null && !regulation.getCreateBy().isEmpty()) {
try {
UserResp user = userService.detail(regulation.getCreateBy());
if (user != null) {
regulation.setCreateByName(user.getName());
}
} catch (Exception e) {
// 如果查询失败使用用户ID作为备选
regulation.setCreateByName(regulation.getCreateBy());
}
}
// 设置制度类型名称
if (regulation.getType() != null && !regulation.getType().isEmpty()) {
regulation.setRegulationType(regulation.getType());
}
return Result.ok(regulation);
} catch (Exception e) {
return Result.error("获取制度详情失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result confirmRegulation(String regulationId) {
try {
RegulationEntity regulation = this.getById(regulationId);
if (regulation == null) {
return Result.error("制度不存在");
}
// 检查是否已经确认过
RegulationConfirmationEntity existingConfirmation = regulationConfirmationService.lambdaQuery()
.eq(RegulationConfirmationEntity::getRegulationId, regulationId)
.eq(RegulationConfirmationEntity::getConfirmerId, StpUtil.getLoginIdAsString())
.eq(RegulationConfirmationEntity::getDelFlag, "0")
.one();
if (existingConfirmation != null) {
return Result.error("您已经确认过该制度");
}
// 创建确认记录
RegulationConfirmationEntity confirmation = new RegulationConfirmationEntity();
confirmation.setConfirmationId(java.util.UUID.randomUUID().toString());
confirmation.setRegulationId(regulationId);
confirmation.setConfirmerId(StpUtil.getLoginIdAsString());
UserResp user = userService.detail(StpUtil.getLoginIdAsString());
if (user != null) {
confirmation.setConfirmerName(user.getName());
confirmation.setConfirmerDept(user.getDeptName());
}
confirmation.setStatus("CONFIRMED");
confirmation.setConfirmTime(LocalDateTime.now());
confirmation.setDelFlag("0");
regulationConfirmationService.save(confirmation);
return Result.okM("制度确认成功");
} catch (Exception e) {
return Result.error("制度确认失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result approveRegulation(String regulationId) {
try {
RegulationEntity regulation = this.getById(regulationId);
if (regulation == null) {
return Result.error("制度不存在");
}
// 检查制度状态只有DRAFT状态的制度才能公示
if (!"DRAFT".equals(regulation.getStatus())) {
return Result.error("只能公示草稿状态的制度");
}
// 检查权限只有创建人才能公示
if (!regulation.getCreateBy().equals(StpUtil.getLoginIdAsString())) {
return Result.error("只能公示自己创建的制度");
}
// 更新制度状态为已公示
regulation.setStatus("APPROVED");
regulation.setUpdateTime(LocalDateTime.now());
regulation.setUpdateBy(StpUtil.getLoginIdAsString());
this.updateById(regulation);
return Result.okM("制度公示成功");
} catch (Exception e) {
return Result.error("制度公示失败:" + e.getMessage());
}
}
}

View File

@ -0,0 +1,125 @@
package com.dite.znpt.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.RegulationEntity;
import com.dite.znpt.domain.entity.RegulationTypeEntity;
import com.dite.znpt.mapper.RegulationMapper;
import com.dite.znpt.mapper.RegulationTypeMapper;
import com.dite.znpt.service.RegulationTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* 制度类型Service实现类
* @author wangna
* @date 2025/07/29
*/
@Service
public class RegulationTypeServiceImpl extends ServiceImpl<RegulationTypeMapper, RegulationTypeEntity> implements RegulationTypeService {
@Autowired
private RegulationMapper regulationMapper;
@Override
@Transactional(readOnly = true)
public Result getRegulationTypes(Integer page, Integer size, String typeName, String status, String remark) {
try {
Page<RegulationTypeEntity> pageParam = new Page<>(page, size);
// 使用连表查询获取创建人姓名
Page<RegulationTypeEntity> result = this.baseMapper.selectRegulationTypeListWithCreator(pageParam, typeName, status, remark);
return Result.ok(result);
} catch (Exception e) {
return Result.error("获取制度类型列表失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result createRegulationType(RegulationTypeEntity regulationType) {
try {
regulationType.setTypeId(java.util.UUID.randomUUID().toString());
regulationType.setCreateTime(LocalDateTime.now());
String userId = StpUtil.getLoginIdAsString();
regulationType.setCreateBy(userId);
regulationType.setUpdateTime(LocalDateTime.now());
regulationType.setUpdateBy(userId);
regulationType.setDelFlag("0");
// 如果没有设置排序顺序设置为当前最大值+1
if (regulationType.getSortOrder() == null) {
Integer maxSortOrder = this.lambdaQuery()
.eq(RegulationTypeEntity::getDelFlag, "0")
.orderByDesc(RegulationTypeEntity::getSortOrder)
.last("LIMIT 1")
.oneOpt()
.map(RegulationTypeEntity::getSortOrder)
.orElse(0);
regulationType.setSortOrder(maxSortOrder + 1);
}
this.save(regulationType);
return Result.okM("制度类型创建成功");
} catch (Exception e) {
return Result.error("制度类型创建失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result updateRegulationType(RegulationTypeEntity regulationType) {
try {
RegulationTypeEntity existing = this.getById(regulationType.getTypeId());
if (existing == null) {
return Result.error("制度类型不存在");
}
regulationType.setUpdateTime(LocalDateTime.now());
regulationType.setUpdateBy(cn.dev33.satoken.stp.StpUtil.getLoginIdAsString());
this.updateById(regulationType);
return Result.okM("制度类型更新成功");
} catch (Exception e) {
return Result.error("制度类型更新失败:" + e.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result deleteRegulationType(String typeId) {
try {
RegulationTypeEntity regulationType = this.getById(typeId);
if (regulationType == null) {
return Result.error("制度类型不存在");
}
// 检查是否有制度使用此类型
String typeName = regulationType.getTypeName();
// 检查制度表中是否有使用此类型的记录包括所有状态
long regulationCount = regulationMapper.selectCount(
new LambdaQueryWrapper<RegulationEntity>()
.eq(RegulationEntity::getType, typeName)
.eq(RegulationEntity::getDelFlag, "0")
);
// 如果有制度使用此类型则不允许删除
if (regulationCount > 0) {
return Result.error("该制度类型正在被使用,无法删除。请先删除或修改使用该类型的制度。");
}
regulationType.setDelFlag("1");
this.updateById(regulationType);
return Result.okM("制度类型删除成功");
} catch (Exception e) {
return Result.error("制度类型删除失败:" + e.getMessage());
}
}
}

View File

@ -88,9 +88,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> impleme
@Override
public List<UserListResp> list(UserListReq req) {
return this.baseMapper.queryBySelective(req).stream().map(resp -> {
resp.setUserTypeLabel(UserTypeEnum.getDescByCode(resp.getUserType()));
resp.setUserStatusLabel(UserStatusEnum.getDescByCode(resp.getUserStatus()));
return resp;
resp.setUserTypeLabel(UserTypeEnum.getDescByCode(resp.getUserType()));
resp.setUserStatusLabel(UserStatusEnum.getDescByCode(resp.getUserStatus()));
return resp;
}).collect(Collectors.toList());
}
@ -107,7 +107,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> impleme
UserEntity entity = this.getById(userId);
UserResp userResp= Converts.INSTANCE.toUserResp(entity);
if(StrUtil.isNotBlank(userResp.getDeptId())){
userResp.setUserId(deptService.getById(userResp.getDeptId()).getDeptName());
userResp.setUserName(entity.getName());
userResp.setDeptName(deptService.getById(userResp.getDeptId()).getDeptName());
}
userResp.setUserTypeLabel(UserTypeEnum.getDescByCode(userResp.getUserType()));
userResp.setUserStatusLabel(UserStatusEnum.getDescByCode(userResp.getUserStatus()));

View File

@ -0,0 +1,14 @@
package com.dite.znpt.service.job;
/**
* @author System
* @date 2025/1/1
* @description 自动到期检测定时任务服务接口
*/
public interface AutoExpirationJobService {
/**
* 执行自动到期检测任务
*/
void executeAutoExpirationJob();
}

View File

@ -0,0 +1,31 @@
package com.dite.znpt.service.job.impl;
import com.dite.znpt.service.AutoExpirationService;
import com.dite.znpt.service.job.AutoExpirationJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author System
* @date 2025/1/1
* @description 自动到期检测定时任务服务实现类
*/
@Slf4j
@Service
public class AutoExpirationJobServiceImpl implements AutoExpirationJobService {
@Autowired
private AutoExpirationService autoExpirationService;
@Override
public void executeAutoExpirationJob() {
log.info("开始执行自动到期检测定时任务...");
try {
autoExpirationService.executeAutoExpirationCheck();
log.info("自动到期检测定时任务执行完成");
} catch (Exception e) {
log.error("自动到期检测定时任务执行失败: {}", e.getMessage(), e);
}
}
}

View File

@ -6,7 +6,7 @@
i.image_id, i.image_name, i.part_id, p.part_name, i.image_resolution, i.focal_distance, i.shooting_time, i.camera_manufacturer,
i.camera_model, i.GPS, ic.weather, ic.humidness, CONCAT(ic.temperature_min, '℃', '~',temperature_max, '℃') AS temperature, ic.wind_level,
ic.shooting_method, ic.shooting_distance,ic.collector_name, i.image_type, i.image_path, ic.image_source, i.review_state, i.image_type_label,
i.pre_image_path, i.project_id, i.pre_treatment
i.pre_image_path, i.project_id, i.pre_treatment, i.create_time, i.create_by
FROM image i
LEFT JOIN image_collect ic ON i.collect_id = ic.collect_id
LEFT JOIN part p ON i.part_id = p.part_id
@ -30,6 +30,7 @@
and i.review_state = #{reviewState}
</if>
</where>
order by i.create_time desc
</select>
<resultMap id="imageRespMap" type="com.dite.znpt.domain.vo.ImageResp">
@ -78,7 +79,7 @@
i.focal_distance35, i.x_resolution, i.y_resolution, i.resolution_units, i.shooting_time, i.camera_manufacturer, i.camera_model,
i.latitude, i.latitude, i.altitude, ic.collect_id, ic.weather, CONCAT(ic.temperature_min, '℃', '~',temperature_max, '℃') AS temperature,
ic.wind_level, ic.shooting_method, ic.shooting_distance, ic.collector_name, ic.image_source, i.review_state, i.image_type, i.image_type_label,
i.pre_treatment, i.project_id
i.pre_treatment, i.project_id, i.create_time
FROM image i
LEFT JOIN image_collect ic ON i.collect_id = ic.collect_id
WHERE i.image_id = #{imageId}

View File

@ -0,0 +1,314 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dite.znpt.mapper.ProjectMemberMapper">
<!-- 基础结果映射 -->
<resultMap id="BaseResultMap" type="com.dite.znpt.domain.vo.ProjectMemberResp">
<id column="member_id" property="memberId" jdbcType="VARCHAR"/>
<result column="project_id" property="projectId" jdbcType="VARCHAR"/>
<result column="project_name" property="projectName" jdbcType="VARCHAR"/>
<result column="turbine_id" property="turbineId" jdbcType="VARCHAR"/>
<result column="turbine_name" property="turbineName" jdbcType="VARCHAR"/>
<result column="task_group_id" property="taskGroupId" jdbcType="VARCHAR"/>
<result column="task_group_name" property="taskGroupName" jdbcType="VARCHAR"/>
<result column="task_id" property="taskId" jdbcType="VARCHAR"/>
<result column="task_name" property="taskName" jdbcType="VARCHAR"/>
<result column="user_id" property="userId" jdbcType="VARCHAR"/>
<result column="user_name" property="userName" jdbcType="VARCHAR"/>
<result column="user_account" property="userAccount" jdbcType="VARCHAR"/>
<result column="user_avatar" property="userAvatar" jdbcType="VARCHAR"/>
<result column="role_type" property="roleType" jdbcType="VARCHAR"/>
<result column="role_type_desc" property="roleTypeDesc" jdbcType="VARCHAR"/>
<result column="job_code" property="jobCode" jdbcType="VARCHAR"/>
<result column="job_code_desc" property="jobCodeDesc" jdbcType="VARCHAR"/>
<result column="job_desc" property="jobDesc" jdbcType="VARCHAR"/>
<result column="join_date" property="joinDate" jdbcType="DATE"/>
<result column="leave_date" property="leaveDate" jdbcType="DATE"/>
<result column="status" property="status" jdbcType="VARCHAR"/>
<result column="remark" property="remark" jdbcType="VARCHAR"/>
</resultMap>
<!-- 根据条件查询项目人员列表 -->
<select id="queryBySelective" resultMap="BaseResultMap">
SELECT
pm.member_id,
pm.project_id,
p.project_name,
pm.turbine_id,
t.turbine_name,
pm.task_group_id,
ptg.group_name as task_group_name,
pm.task_id,
pt.task_name,
pm.user_id,
u.name as user_name,
u.account as user_account,
u.avatar as user_avatar,
pm.role_type,
pm.role_type as role_type_desc,
pm.job_code,
pm.job_code as job_code_desc,
pm.job_desc,
pm.join_date,
pm.leave_date,
pm.status,
pm.remark
FROM project_member pm
LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci
LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task_group ptg ON pm.task_group_id COLLATE utf8mb4_general_ci = ptg.group_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task pt ON pm.task_id COLLATE utf8mb4_general_ci = pt.task_id COLLATE utf8mb4_general_ci
LEFT JOIN user u ON pm.user_id COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
<where>
<if test="projectId != null and projectId != ''">
AND pm.project_id = #{projectId}
</if>
<if test="turbineId != null and turbineId != ''">
AND pm.turbine_id = #{turbineId}
</if>
<if test="taskGroupId != null and taskGroupId != ''">
AND pm.task_group_id = #{taskGroupId}
</if>
<if test="taskId != null and taskId != ''">
AND pm.task_id = #{taskId}
</if>
<if test="userId != null and userId != ''">
AND pm.user_id = #{userId}
</if>
<if test="roleType != null and roleType != ''">
AND pm.role_type = #{roleType}
</if>
<if test="jobCode != null and jobCode != ''">
AND pm.job_code = #{jobCode}
</if>
<if test="status != null and status != ''">
AND pm.status = #{status}
</if>
<if test="userName != null and userName != ''">
AND u.name LIKE CONCAT('%', #{userName}, '%')
</if>
<if test="userAccount != null and userAccount != ''">
AND u.account LIKE CONCAT('%', #{userAccount}, '%')
</if>
</where>
ORDER BY pm.create_time DESC
</select>
<!-- 根据项目ID查询项目人员列表 -->
<select id="queryByProjectId" resultMap="BaseResultMap">
SELECT
pm.member_id,
pm.project_id,
p.project_name,
pm.turbine_id,
t.turbine_name,
pm.task_group_id,
ptg.group_name as task_group_name,
pm.task_id,
pt.task_name,
pm.user_id,
u.name as user_name,
u.account as user_account,
u.avatar as user_avatar,
pm.role_type,
pm.role_type as role_type_desc,
pm.job_code,
pm.job_code as job_code_desc,
pm.job_desc,
pm.join_date,
pm.leave_date,
pm.status,
pm.remark
FROM project_member pm
LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci
LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task_group ptg ON pm.task_group_id COLLATE utf8mb4_general_ci = ptg.group_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task pt ON pm.task_id COLLATE utf8mb4_general_ci = pt.task_id COLLATE utf8mb4_general_ci
LEFT JOIN user u ON pm.user_id COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
WHERE pm.project_id = #{projectId}
AND pm.status = 'ACTIVE'
ORDER BY pm.create_time DESC
</select>
<!-- 根据机组ID查询机组人员列表 -->
<select id="queryByTurbineId" resultMap="BaseResultMap">
SELECT
pm.member_id,
pm.project_id,
p.project_name,
pm.turbine_id,
t.turbine_name,
pm.task_group_id,
ptg.group_name as task_group_name,
pm.task_id,
pt.task_name,
pm.user_id,
u.name as user_name,
u.account as user_account,
u.avatar as user_avatar,
pm.role_type,
pm.role_type as role_type_desc,
pm.job_code,
pm.job_code as job_code_desc,
pm.job_desc,
pm.join_date,
pm.leave_date,
pm.status,
pm.remark
FROM project_member pm
LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci
LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task_group ptg ON pm.task_group_id COLLATE utf8mb4_general_ci = ptg.group_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task pt ON pm.task_id COLLATE utf8mb4_general_ci = pt.task_id COLLATE utf8mb4_general_ci
LEFT JOIN user u ON pm.user_id COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
WHERE pm.turbine_id = #{turbineId}
AND pm.status = 'ACTIVE'
ORDER BY pm.create_time DESC
</select>
<!-- 根据任务组ID查询任务组人员列表 -->
<select id="queryByTaskGroupId" resultMap="BaseResultMap">
SELECT
pm.member_id,
pm.project_id,
p.project_name,
pm.turbine_id,
t.turbine_name,
pm.task_group_id,
ptg.group_name as task_group_name,
pm.task_id,
pt.task_name,
pm.user_id,
u.name as user_name,
u.account as user_account,
u.avatar as user_avatar,
pm.role_type,
pm.role_type as role_type_desc,
pm.job_code,
pm.job_code as job_code_desc,
pm.job_desc,
pm.join_date,
pm.leave_date,
pm.status,
pm.remark
FROM project_member pm
LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci
LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task_group ptg ON pm.task_group_id COLLATE utf8mb4_general_ci = ptg.group_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task pt ON pm.task_id COLLATE utf8mb4_general_ci = pt.task_id COLLATE utf8mb4_general_ci
LEFT JOIN user u ON pm.user_id COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
WHERE pm.task_group_id = #{taskGroupId}
AND pm.status = 'ACTIVE'
ORDER BY pm.create_time DESC
</select>
<!-- 根据任务ID查询任务人员列表 -->
<select id="queryByTaskId" resultMap="BaseResultMap">
SELECT
pm.member_id,
pm.project_id,
p.project_name,
pm.turbine_id,
t.turbine_name,
pm.task_group_id,
ptg.group_name as task_group_name,
pm.task_id,
pt.task_name,
pm.user_id,
u.name as user_name,
u.account as user_account,
u.avatar as user_avatar,
pm.role_type,
pm.role_type as role_type_desc,
pm.job_code,
pm.job_code as job_code_desc,
pm.job_desc,
pm.join_date,
pm.leave_date,
pm.status,
pm.remark
FROM project_member pm
LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci
LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task_group ptg ON pm.task_group_id COLLATE utf8mb4_general_ci = ptg.group_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task pt ON pm.task_id COLLATE utf8mb4_general_ci = pt.task_id COLLATE utf8mb4_general_ci
LEFT JOIN user u ON pm.user_id COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
WHERE pm.task_id = #{taskId}
AND pm.status = 'ACTIVE'
ORDER BY pm.create_time DESC
</select>
<!-- 根据用户ID查询用户参与的项目列表 -->
<select id="queryByUserId" resultMap="BaseResultMap">
SELECT
pm.member_id,
pm.project_id,
p.project_name,
pm.turbine_id,
t.turbine_name,
pm.task_group_id,
ptg.group_name as task_group_name,
pm.task_id,
pt.task_name,
pm.user_id,
u.name as user_name,
u.account as user_account,
u.avatar as user_avatar,
pm.role_type,
pm.role_type as role_type_desc,
pm.job_code,
pm.job_code as job_code_desc,
pm.job_desc,
pm.join_date,
pm.leave_date,
pm.status,
pm.remark
FROM project_member pm
LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci
LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task_group ptg ON pm.task_group_id COLLATE utf8mb4_general_ci = ptg.group_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task pt ON pm.task_id COLLATE utf8mb4_general_ci = pt.task_id COLLATE utf8mb4_general_ci
LEFT JOIN user u ON pm.user_id COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
WHERE pm.user_id = #{userId}
AND pm.status = 'ACTIVE'
ORDER BY pm.create_time DESC
</select>
<!-- 根据项目ID和角色类型查询人员列表 -->
<select id="queryByProjectIdAndRoleType" resultMap="BaseResultMap">
SELECT
pm.member_id,
pm.project_id,
p.project_name,
pm.turbine_id,
t.turbine_name,
pm.task_group_id,
ptg.group_name as task_group_name,
pm.task_id,
pt.task_name,
pm.user_id,
u.name as user_name,
u.account as user_account,
u.avatar as user_avatar,
pm.role_type,
pm.role_type as role_type_desc,
pm.job_code,
pm.job_code as job_code_desc,
pm.job_desc,
pm.join_date,
pm.leave_date,
pm.status,
pm.remark
FROM project_member pm
LEFT JOIN project p ON pm.project_id COLLATE utf8mb4_general_ci = p.project_id COLLATE utf8mb4_general_ci
LEFT JOIN turbine t ON pm.turbine_id COLLATE utf8mb4_general_ci = t.turbine_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task_group ptg ON pm.task_group_id COLLATE utf8mb4_general_ci = ptg.group_id COLLATE utf8mb4_general_ci
LEFT JOIN project_task pt ON pm.task_id COLLATE utf8mb4_general_ci = pt.task_id COLLATE utf8mb4_general_ci
LEFT JOIN user u ON pm.user_id COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
WHERE pm.project_id = #{projectId}
AND pm.role_type = #{roleType}
AND pm.status = 'ACTIVE'
ORDER BY pm.create_time DESC
</select>
</mapper>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dite.znpt.mapper.RegulationMapper">
<!-- 分页查询制度列表(包含创建人姓名和制度类型名称) -->
<select id="selectRegulationListWithCreator" resultType="com.dite.znpt.domain.entity.RegulationEntity">
SELECT
r.*,
u.name as createByName,
rt.type_name as regulationType,
CASE
WHEN rc.status IS NOT NULL THEN rc.status
ELSE 'PENDING'
END as confirmStatus
FROM regulation r
LEFT JOIN user u ON r.create_by COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
LEFT JOIN regulation_type rt ON r.regulation_type = rt.type_name
LEFT JOIN regulation_confirmation rc ON r.regulation_id = rc.regulation_id
AND rc.confirmer_id = #{userId}
AND rc.del_flag = '0'
<where>
r.del_flag = '0'
<if test="status != null and status != ''">
AND r.status = #{status}
</if>
<if test="type != null and type != ''">
AND r.regulation_type = #{type}
</if>
<if test="title != null and title != ''">
AND r.title LIKE CONCAT('%', #{title}, '%')
</if>
<if test="proposer != null and proposer != ''">
AND u.name LIKE CONCAT('%', #{proposer}, '%')
</if>
<if test="confirmStatus != null and confirmStatus != ''">
<choose>
<when test="confirmStatus == 'CONFIRMED'">
AND rc.status = 'CONFIRMED'
</when>
<when test="confirmStatus == 'PENDING'">
AND rc.status IS NULL
</when>
</choose>
</if>
</where>
ORDER BY r.create_time DESC
</select>
</mapper>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dite.znpt.mapper.RegulationTypeMapper">
<sql id="Base_Column_List">
rt.type_id, rt.type_name, rt.is_enabled, rt.sort_order, rt.remark, rt.del_flag,
rt.create_by, rt.create_time, rt.update_by, rt.update_time
</sql>
<select id="selectRegulationTypeListWithCreator" resultType="com.dite.znpt.domain.entity.RegulationTypeEntity">
SELECT
rt.type_id, rt.type_name, rt.is_enabled, rt.sort_order, rt.remark, rt.del_flag,
rt.create_by, rt.create_time, rt.update_by, rt.update_time,
u.name as createrName
FROM regulation_type rt
LEFT JOIN user u ON rt.create_by COLLATE utf8mb4_general_ci = u.user_id COLLATE utf8mb4_general_ci
<where>
rt.del_flag = '0'
<if test="typeName != null and typeName != ''">
AND rt.type_name LIKE concat('%', #{typeName}, '%')
</if>
<if test="status != null and status != ''">
AND rt.is_enabled = #{status}
</if>
<if test="remark != null and remark != ''">
AND rt.remark LIKE concat('%', #{remark}, '%')
</if>
</where>
ORDER BY rt.sort_order ASC, rt.create_time DESC
</select>
</mapper>

View File

@ -0,0 +1,138 @@
# 自动到期检测功能使用说明
## 功能概述
自动到期检测功能是一个智能的到期时间监控系统,能够自动检测数据库中各种表格的到期时间字段,并提供到期提醒功能。
## 主要特性
1. **自动检测**: 系统会自动扫描配置的表格,检测其中的到期时间字段
2. **灵活配置**: 可以配置任意表格的到期检测规则
3. **智能提醒**: 支持提前提醒天数配置
4. **状态管理**: 自动计算剩余天数并设置状态(正常/即将到期/已到期)
5. **定时执行**: 每天凌晨2点自动执行检测任务
## 数据库表结构
### 1. 自动到期检测配置表 (auto_expiration_config)
| 字段名 | 类型 | 说明 |
|--------|------|------|
| config_id | varchar(64) | 配置ID |
| table_name | varchar(100) | 表名 |
| table_desc | varchar(200) | 表描述 |
| primary_key_field | varchar(100) | 主键字段 |
| expire_date_field | varchar(100) | 到期时间字段 |
| user_id_field | varchar(100) | 关联用户字段 |
| user_name_field | varchar(100) | 用户姓名字段 |
| business_name_field | varchar(100) | 业务名称字段 |
| remind_days | int | 提前提醒天数 |
| enabled | varchar(1) | 是否启用0-禁用1-启用) |
### 2. 到期检测结果表 (expiration_result)
| 字段名 | 类型 | 说明 |
|--------|------|------|
| result_id | varchar(64) | 结果ID |
| table_name | varchar(100) | 表名 |
| business_id | varchar(64) | 业务ID |
| business_name | varchar(200) | 业务名称 |
| user_id | varchar(64) | 关联用户ID |
| user_name | varchar(100) | 关联用户姓名 |
| expire_date | date | 到期日期 |
| remaining_days | int | 剩余天数 |
| status | varchar(1) | 状态0-正常1-即将到期2-已到期) |
## API接口
### 1. 手动执行到期检测
```
POST /auto-expiration/execute
```
### 2. 获取到期检测结果
```
GET /auto-expiration/results?status=1
```
参数说明:
- status: 状态筛选0-正常1-即将到期2-已到期)
### 3. 获取统计信息
```
GET /auto-expiration/statistics
```
### 4. 检测指定表
```
POST /auto-expiration/check-table/{tableName}
```
### 5. 保存配置
```
POST /auto-expiration/config
```
### 6. 获取所有配置
```
GET /auto-expiration/configs
```
### 7. 删除配置
```
DELETE /auto-expiration/config/{configId}
```
## 配置示例
### 人员资质证书检测配置
```json
{
"tableName": "certification",
"tableDesc": "人员资质证书",
"primaryKeyField": "certification_id",
"expireDateField": "validity_date_end",
"userIdField": "user_id",
"businessNameField": "certification_name",
"remindDays": 30,
"enabled": "1"
}
```
### 人员保险检测配置
```json
{
"tableName": "insurance_info",
"tableDesc": "人员保险",
"primaryKeyField": "insurance_info_id",
"expireDateField": "expire_date",
"userIdField": "user_id",
"userNameField": "name",
"businessNameField": "insurance_type_name",
"remindDays": 30,
"enabled": "1"
}
```
## 使用步骤
1. **创建数据库表**: 执行 `auto_expiration_tables.sql` 创建必要的表结构
2. **配置检测规则**: 通过API或直接插入数据配置需要检测的表格
3. **启动定时任务**: 系统会自动在每天凌晨2点执行检测
4. **查看检测结果**: 通过API接口查看检测结果和统计信息
## 扩展说明
系统支持检测任意表格的到期时间字段,只需要在配置表中添加相应的配置即可。支持的字段类型包括:
- LocalDate
- LocalDateTime
- Date
- Timestamp
系统会自动识别并处理这些日期类型。
## 注意事项
1. 确保配置的字段名在目标表中存在
2. 到期时间字段不能为空
3. 建议为检测结果表添加适当的索引以提高查询性能
4. 可以根据业务需要调整提前提醒天数

View File

@ -0,0 +1,51 @@
-- 自动到期检测配置表
CREATE TABLE `auto_expiration_config` (
`config_id` varchar(64) NOT NULL COMMENT '配置ID',
`table_name` varchar(100) NOT NULL COMMENT '表名',
`table_desc` varchar(200) DEFAULT NULL COMMENT '表描述',
`primary_key_field` varchar(100) NOT NULL COMMENT '主键字段',
`expire_date_field` varchar(100) NOT NULL COMMENT '到期时间字段',
`user_id_field` varchar(100) DEFAULT NULL COMMENT '关联用户字段',
`user_name_field` varchar(100) DEFAULT NULL COMMENT '用户姓名字段',
`business_name_field` varchar(100) DEFAULT NULL COMMENT '业务名称字段',
`remind_days` int(11) DEFAULT 30 COMMENT '提前提醒天数',
`enabled` varchar(1) DEFAULT '1' COMMENT '是否启用0-禁用1-启用)',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`del_flag` varchar(1) DEFAULT '0' COMMENT '删除标志0代表存在1代表删除',
PRIMARY KEY (`config_id`),
UNIQUE KEY `uk_table_name` (`table_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自动到期检测配置表';
-- 到期检测结果表
CREATE TABLE `expiration_result` (
`result_id` varchar(64) NOT NULL COMMENT '结果ID',
`config_id` varchar(64) DEFAULT NULL COMMENT '配置ID',
`table_name` varchar(100) NOT NULL COMMENT '表名',
`business_id` varchar(64) NOT NULL COMMENT '业务ID',
`business_name` varchar(200) DEFAULT NULL COMMENT '业务名称',
`user_id` varchar(64) DEFAULT NULL COMMENT '关联用户ID',
`user_name` varchar(100) DEFAULT NULL COMMENT '关联用户姓名',
`expire_date` date NOT NULL COMMENT '到期日期',
`remaining_days` int(11) DEFAULT NULL COMMENT '剩余天数',
`status` varchar(1) DEFAULT '0' COMMENT '状态0-正常1-即将到期2-已到期)',
`check_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '检测时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`del_flag` varchar(1) DEFAULT '0' COMMENT '删除标志0代表存在1代表删除',
PRIMARY KEY (`result_id`),
KEY `idx_table_name` (`table_name`),
KEY `idx_status` (`status`),
KEY `idx_expire_date` (`expire_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='到期检测结果表';
-- 插入示例配置数据
INSERT INTO `auto_expiration_config` (`config_id`, `table_name`, `table_desc`, `primary_key_field`, `expire_date_field`, `user_id_field`, `user_name_field`, `business_name_field`, `remind_days`, `enabled`, `remark`) VALUES
('1', 'certification', '人员资质证书', 'certification_id', 'validity_date_end', 'user_id', NULL, 'certification_name', 30, '1', '人员资质证书到期检测'),
('2', 'insurance_info', '人员保险', 'insurance_info_id', 'expire_date', 'user_id', 'name', 'insurance_type_name', 30, '1', '人员保险到期检测'),
('3', 'regulation', '制度管理', 'regulation_id', 'expire_time', NULL, NULL, 'regulation_name', 30, '1', '制度到期检测');

View File

@ -0,0 +1,107 @@
-- =============================================
-- 项目人员表扩展测试数据
-- 使用多个真实用户ID和项目ID使用UUID()生成member_id
-- @author AI Assistant
-- @date 2025/01/27
-- =============================================
-- 清空现有数据(可选)
-- DELETE FROM project_member WHERE project_id IN ('0b71a1259c49918c6595c9720ad1db5d', '7f321271c13483aa31cb743d604603a5', '8e0da59bd0c640b5b65dccd72606ea39', '96e0debf78187300f144d7f3450a2477', 'bbd28ed8627d6bd9fd8fa7476af6242a', 'd446d998d7c40005bf9af53ac264ef6e', 'd6c5b8408a42a8390297751756ecff23', 'eb64015cf2d0b40574c1d6f476876822', 'fb7e3b731ee496cec46ca1db64117676');
-- 插入项目人员测试数据
INSERT INTO project_member (
member_id,
project_id,
user_id,
role_type,
job_code,
job_desc,
join_date,
status,
remark
) VALUES
-- 项目1: 0b71a1259c49918c6595c9720ad1db5d
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '0ab4a72af4184a1614d4c25a5bb65ece', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-15', 'ACTIVE', '项目总负责人'),
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '0bc98a66761915e31fbf86e468d6ba20', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-15', 'ACTIVE', '负责项目安全管理'),
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '149c94f937a7d36cda70a81f343d090a', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-15', 'ACTIVE', '负责项目质量管理'),
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '15129b4764ced7900ef5d51c20cefa35', 'TEAM_LEADER', 'SITE_MANAGER', '现场经理', '2025-01-15', 'ACTIVE', '负责现场施工管理'),
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '1632433c2073532a074b0079cca5eb18', 'CONSTRUCTOR', 'GROUND_SERVICE', '地勤人员', '2025-01-15', 'ACTIVE', '负责地面施工工作'),
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '1995a0da943d188506548bd42a2ee39d', 'CONSTRUCTOR', 'DRIVER', '司机', '2025-01-15', 'ACTIVE', '负责设备运输和人员接送'),
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '1b2641edb4c9a8f14658edaa8e6a36e3', 'CONSTRUCTOR', 'ASCENDING', '登高人员', '2025-01-15', 'ACTIVE', '负责高空作业'),
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '1d476bc4de6d71f6a43497d943adec9c', 'CONSTRUCTOR', 'ANTI_THUNDER', '防雷人员', '2025-01-15', 'ACTIVE', '负责防雷设施安装'),
-- 项目2: 7f321271c13483aa31cb743d604603a5
(UUID(), '7f321271c13483aa31cb743d604603a5', '1dae46a6ecbc2408c8b137187fc13d06', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-16', 'ACTIVE', '项目总负责人'),
(UUID(), '7f321271c13483aa31cb743d604603a5', '1f319a6f25b65ebd50711707e5e08d1a', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-16', 'ACTIVE', '负责项目安全管理'),
(UUID(), '7f321271c13483aa31cb743d604603a5', '22ff9d065f3ad826f5e22ba18a20248c', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-16', 'ACTIVE', '负责项目质量管理'),
(UUID(), '7f321271c13483aa31cb743d604603a5', '2fd0581e10f4c4f70e5148de3d61bc06', 'TEAM_LEADER', 'SITE_MANAGER', '现场经理', '2025-01-16', 'ACTIVE', '负责现场施工管理'),
(UUID(), '7f321271c13483aa31cb743d604603a5', '3042cb085eb41721faa8f4d985921424', 'CONSTRUCTOR', 'GROUND_SERVICE', '地勤人员', '2025-01-16', 'ACTIVE', '负责地面施工工作'),
(UUID(), '7f321271c13483aa31cb743d604603a5', '3169163eb58fff961955179fbdc22507', 'CONSTRUCTOR', 'DRIVER', '司机', '2025-01-16', 'ACTIVE', '负责设备运输和人员接送'),
-- 项目3: 8e0da59bd0c640b5b65dccd72606ea39
(UUID(), '8e0da59bd0c640b5b65dccd72606ea39', '324afaf4e89213b6f5fcf1fa57663940', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-17', 'ACTIVE', '项目总负责人'),
(UUID(), '8e0da59bd0c640b5b65dccd72606ea39', '375f87a103e5bcad6e6a402177044891', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-17', 'ACTIVE', '负责项目安全管理'),
(UUID(), '8e0da59bd0c640b5b65dccd72606ea39', '3b5f2db9bac776be536d893f726deeba', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-17', 'ACTIVE', '负责项目质量管理'),
(UUID(), '8e0da59bd0c640b5b65dccd72606ea39', '44d335410542c5fd4989780dd11dca66', 'TEAM_LEADER', 'SITE_MANAGER', '现场经理', '2025-01-17', 'ACTIVE', '负责现场施工管理'),
(UUID(), '8e0da59bd0c640b5b65dccd72606ea39', '4e171ce81c18183bc8f06da8bd47a3d8', 'CONSTRUCTOR', 'GROUND_SERVICE', '地勤人员', '2025-01-17', 'ACTIVE', '负责地面施工工作'),
-- 项目4: 96e0debf78187300f144d7f3450a2477
(UUID(), '96e0debf78187300f144d7f3450a2477', '0ab4a72af4184a1614d4c25a5bb65ece', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-18', 'ACTIVE', '项目总负责人'),
(UUID(), '96e0debf78187300f144d7f3450a2477', '0bc98a66761915e31fbf86e468d6ba20', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-18', 'ACTIVE', '负责项目安全管理'),
(UUID(), '96e0debf78187300f144d7f3450a2477', '149c94f937a7d36cda70a81f343d090a', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-18', 'ACTIVE', '负责项目质量管理'),
(UUID(), '96e0debf78187300f144d7f3450a2477', '15129b4764ced7900ef5d51c20cefa35', 'CONSTRUCTOR', 'ASCENDING', '登高人员', '2025-01-18', 'ACTIVE', '负责高空作业'),
(UUID(), '96e0debf78187300f144d7f3450a2477', '1632433c2073532a074b0079cca5eb18', 'CONSTRUCTOR', 'ANTI_THUNDER', '防雷人员', '2025-01-18', 'ACTIVE', '负责防雷设施安装'),
-- 项目5: bbd28ed8627d6bd9fd8fa7476af6242a
(UUID(), 'bbd28ed8627d6bd9fd8fa7476af6242a', '1995a0da943d188506548bd42a2ee39d', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-19', 'ACTIVE', '项目总负责人'),
(UUID(), 'bbd28ed8627d6bd9fd8fa7476af6242a', '1b2641edb4c9a8f14658edaa8e6a36e3', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-19', 'ACTIVE', '负责项目安全管理'),
(UUID(), 'bbd28ed8627d6bd9fd8fa7476af6242a', '1d476bc4de6d71f6a43497d943adec9c', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-19', 'ACTIVE', '负责项目质量管理'),
(UUID(), 'bbd28ed8627d6bd9fd8fa7476af6242a', '1dae46a6ecbc2408c8b137187fc13d06', 'TEAM_LEADER', 'SITE_MANAGER', '现场经理', '2025-01-19', 'ACTIVE', '负责现场施工管理'),
(UUID(), 'bbd28ed8627d6bd9fd8fa7476af6242a', '1f319a6f25b65ebd50711707e5e08d1a', 'CONSTRUCTOR', 'GROUND_SERVICE', '地勤人员', '2025-01-19', 'ACTIVE', '负责地面施工工作'),
-- 项目6: d446d998d7c40005bf9af53ac264ef6e
(UUID(), 'd446d998d7c40005bf9af53ac264ef6e', '22ff9d065f3ad826f5e22ba18a20248c', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-20', 'ACTIVE', '项目总负责人'),
(UUID(), 'd446d998d7c40005bf9af53ac264ef6e', '2fd0581e10f4c4f70e5148de3d61bc06', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-20', 'ACTIVE', '负责项目安全管理'),
(UUID(), 'd446d998d7c40005bf9af53ac264ef6e', '3042cb085eb41721faa8f4d985921424', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-20', 'ACTIVE', '负责项目质量管理'),
(UUID(), 'd446d998d7c40005bf9af53ac264ef6e', '3169163eb58fff961955179fbdc22507', 'CONSTRUCTOR', 'DRIVER', '司机', '2025-01-20', 'ACTIVE', '负责设备运输和人员接送'),
-- 项目7: d6c5b8408a42a8390297751756ecff23
(UUID(), 'd6c5b8408a42a8390297751756ecff23', '324afaf4e89213b6f5fcf1fa57663940', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-21', 'ACTIVE', '项目总负责人'),
(UUID(), 'd6c5b8408a42a8390297751756ecff23', '375f87a103e5bcad6e6a402177044891', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-21', 'ACTIVE', '负责项目安全管理'),
(UUID(), 'd6c5b8408a42a8390297751756ecff23', '3b5f2db9bac776be536d893f726deeba', 'CONSTRUCTOR', 'ASCENDING', '登高人员', '2025-01-21', 'ACTIVE', '负责高空作业'),
(UUID(), 'd6c5b8408a42a8390297751756ecff23', '44d335410542c5fd4989780dd11dca66', 'CONSTRUCTOR', 'ANTI_THUNDER', '防雷人员', '2025-01-21', 'ACTIVE', '负责防雷设施安装'),
-- 项目8: eb64015cf2d0b40574c1d6f476876822
(UUID(), 'eb64015cf2d0b40574c1d6f476876822', '4e171ce81c18183bc8f06da8bd47a3d8', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-22', 'ACTIVE', '项目总负责人'),
(UUID(), 'eb64015cf2d0b40574c1d6f476876822', '0ab4a72af4184a1614d4c25a5bb65ece', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-22', 'ACTIVE', '负责项目安全管理'),
(UUID(), 'eb64015cf2d0b40574c1d6f476876822', '0bc98a66761915e31fbf86e468d6ba20', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-22', 'ACTIVE', '负责项目质量管理'),
(UUID(), 'eb64015cf2d0b40574c1d6f476876822', '149c94f937a7d36cda70a81f343d090a', 'TEAM_LEADER', 'SITE_MANAGER', '现场经理', '2025-01-22', 'ACTIVE', '负责现场施工管理'),
-- 项目9: fb7e3b731ee496cec46ca1db64117676
(UUID(), 'fb7e3b731ee496cec46ca1db64117676', '15129b4764ced7900ef5d51c20cefa35', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-23', 'ACTIVE', '项目总负责人'),
(UUID(), 'fb7e3b731ee496cec46ca1db64117676', '1632433c2073532a074b0079cca5eb18', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-23', 'ACTIVE', '负责项目安全管理'),
(UUID(), 'fb7e3b731ee496cec46ca1db64117676', '1995a0da943d188506548bd42a2ee39d', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-23', 'ACTIVE', '负责项目质量管理'),
(UUID(), 'fb7e3b731ee496cec46ca1db64117676', '1b2641edb4c9a8f14658edaa8e6a36e3', 'CONSTRUCTOR', 'GROUND_SERVICE', '地勤人员', '2025-01-23', 'ACTIVE', '负责地面施工工作'),
(UUID(), 'fb7e3b731ee496cec46ca1db64117676', '1d476bc4de6d71f6a43497d943adec9c', 'CONSTRUCTOR', 'DRIVER', '司机', '2025-01-23', 'ACTIVE', '负责设备运输和人员接送');
-- =============================================
-- 查询示例
-- =============================================
-- 查询所有项目的在职人员
-- SELECT * FROM project_member WHERE status = 'ACTIVE';
-- 查询特定项目的所有人员
-- SELECT * FROM project_member WHERE project_id = '0b71a1259c49918c6595c9720ad1db5d' AND status = 'ACTIVE';
-- 查询所有项目经理
-- SELECT * FROM project_member WHERE role_type = 'PROJECT_MANAGER' AND status = 'ACTIVE';
-- 按项目统计人员数量
-- SELECT project_id, COUNT(*) as member_count FROM project_member WHERE status = 'ACTIVE' GROUP BY project_id;
-- 按角色类型统计人员数量
-- SELECT role_type, COUNT(*) as count FROM project_member WHERE status = 'ACTIVE' GROUP BY role_type;
-- 查询特定用户参与的所有项目
-- SELECT DISTINCT project_id FROM project_member WHERE user_id = '0ab4a72af4184a1614d4c25a5bb65ece' AND status = 'ACTIVE';

View File

@ -0,0 +1,137 @@
-- =============================================
-- 项目人员关联表
-- 用于管理项目、机组、任务组、任务的人员关系
-- @author wangna
-- @date 2025/08/05
-- =============================================
-- 项目人员关联表
CREATE TABLE `project_member` (
`member_id` varchar(64) NOT NULL COMMENT '关联ID',
`project_id` varchar(64) NOT NULL COMMENT '项目ID',
`turbine_id` varchar(64) DEFAULT NULL COMMENT '机组ID可选关联到具体机组',
`task_group_id` varchar(64) DEFAULT NULL COMMENT '任务组ID可选关联到具体任务组',
`task_id` varchar(64) DEFAULT NULL COMMENT '任务ID可选关联到具体任务',
`user_id` varchar(64) NOT NULL COMMENT '用户ID',
`role_type` varchar(50) NOT NULL COMMENT '项目角色类型',
`job_code` varchar(50) DEFAULT NULL COMMENT '具体岗位代码',
`job_desc` varchar(500) DEFAULT NULL COMMENT '岗位描述',
`join_date` date NOT NULL COMMENT '加入时间',
`leave_date` date DEFAULT NULL COMMENT '离开时间',
`status` varchar(20) DEFAULT 'ACTIVE' COMMENT '状态ACTIVE-在职INACTIVE-离职SUSPENDED-暂停',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`member_id`),
KEY `idx_project_id` (`project_id`),
KEY `idx_turbine_id` (`turbine_id`),
KEY `idx_task_group_id` (`task_group_id`),
KEY `idx_task_id` (`task_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_role_type` (`role_type`),
KEY `idx_status` (`status`),
UNIQUE KEY `uk_project_user_role` (`project_id`, `user_id`, `role_type`, `turbine_id`, `task_group_id`, `task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='项目人员关联表';
-- 添加复合索引以提高查询性能
CREATE INDEX `idx_project_member_composite` ON `project_member` (`project_id`, `status`, `role_type`);
CREATE INDEX `idx_project_member_user_status` ON `project_member` (`user_id`, `status`);
CREATE INDEX `idx_project_member_turbine_status` ON `project_member` (`turbine_id`, `status`);
CREATE INDEX `idx_project_member_task_status` ON `project_member` (`task_id`, `status`);
-- =============================================
-- 数据迁移脚本(可选)
-- 将现有项目的人员数据迁移到新表
-- =============================================
-- 迁移项目经理数据
INSERT INTO project_member (member_id, project_id, user_id, role_type, job_code, join_date, status, create_time)
SELECT
UUID() as member_id,
project_id,
project_manager_id as user_id,
'PROJECT_MANAGER' as role_type,
'PROJECT_MANAGER' as job_code,
create_time as join_date,
'ACTIVE' as status,
create_time
FROM project
WHERE project_manager_id IS NOT NULL AND project_manager_id != '';
-- 迁移安全员数据
INSERT INTO project_member (member_id, project_id, user_id, role_type, job_code, join_date, status, create_time)
SELECT
UUID() as member_id,
project_id,
auditor_id as user_id,
'SAFETY_OFFICER' as role_type,
'SAFETY_MANAGER' as job_code,
create_time as join_date,
'ACTIVE' as status,
create_time
FROM project
WHERE auditor_id IS NOT NULL AND auditor_id != '';
-- 迁移质量员数据
INSERT INTO project_member (member_id, project_id, user_id, role_type, job_code, join_date, status, create_time)
SELECT
UUID() as member_id,
project_id,
quality_officer_id as user_id,
'QUALITY_OFFICER' as role_type,
'QUALITY_MANAGER' as job_code,
create_time as join_date,
'ACTIVE' as status,
create_time
FROM project
WHERE quality_officer_id IS NOT NULL AND quality_officer_id != '';
-- 迁移施工组长数据
INSERT INTO project_member (member_id, project_id, user_id, role_type, job_code, join_date, status, create_time)
SELECT
UUID() as member_id,
project_id,
construct_team_leader_id as user_id,
'TEAM_LEADER' as role_type,
'TEAM_LEADER' as job_code,
create_time as join_date,
'ACTIVE' as status,
create_time
FROM project
WHERE construct_team_leader_id IS NOT NULL AND construct_team_leader_id != '';
-- 迁移施工人员数据需要处理逗号分隔的多个ID
-- 注意这个脚本需要根据实际情况调整因为constructor_ids是逗号分隔的字符串
-- 建议在应用层处理这个迁移逻辑
-- =============================================
-- 示例数据插入
-- =============================================
-- 插入示例项目人员数据
INSERT INTO project_member (member_id, project_id, user_id, role_type, job_code, job_desc, join_date, status, remark) VALUES
('pm001', 'project001', 'user001', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-01', 'ACTIVE', '项目负责人'),
('pm002', 'project001', 'user002', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-01', 'ACTIVE', '负责项目安全'),
('pm003', 'project001', 'user003', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-01', 'ACTIVE', '负责项目质量'),
('pm004', 'project001', 'user004', 'CONSTRUCTOR', 'GROUND_SERVICE', '地勤人员', '2025-01-01', 'ACTIVE', '地勤工作'),
('pm005', 'project001', 'user005', 'CONSTRUCTOR', 'DRIVER', '司机', '2025-01-01', 'ACTIVE', '负责运输'),
('pm006', 'project001', 'user006', 'CONSTRUCTOR', 'ASCENDING', '登高人员', '2025-01-01', 'ACTIVE', '高空作业');
-- =============================================
-- 查询示例
-- =============================================
-- 查询项目所有人员
-- SELECT * FROM project_member WHERE project_id = 'project001' AND status = 'ACTIVE';
-- 查询项目的项目经理
-- SELECT * FROM project_member WHERE project_id = 'project001' AND role_type = 'PROJECT_MANAGER' AND status = 'ACTIVE';
-- 查询用户参与的所有项目
-- SELECT DISTINCT project_id FROM project_member WHERE user_id = 'user001' AND status = 'ACTIVE';
-- 查询机组人员
-- SELECT * FROM project_member WHERE turbine_id = 'turbine001' AND status = 'ACTIVE';
CREATE INDEX `idx_project_member_task_status` ON `project_member` (`task_id`, `status`);

View File

@ -0,0 +1,53 @@
-- =============================================
-- 项目人员表测试数据
-- 基于项目ID: 0b71a1259c49918c6595c9720ad1db5d
-- 使用真实用户ID使用UUID()生成member_id
-- @author AI Assistant
-- @date 2025/01/27
-- =============================================
-- 清空现有数据(可选)
-- DELETE FROM project_member WHERE project_id = '0b71a1259c49918c6595c9720ad1db5d';
-- 插入项目人员测试数据
INSERT INTO project_member (
member_id,
project_id,
user_id,
role_type,
job_code,
job_desc,
join_date,
status,
remark
) VALUES
-- 项目经理
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '008ecfac153be83890c42f9fed0a48cd', 'PROJECT_MANAGER', 'PROJECT_MANAGER', '项目经理', '2025-01-15', 'ACTIVE', '项目总负责人'),
-- 安全员
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '014d6fd83182ac03d05967e16748ab80', 'SAFETY_OFFICER', 'SAFETY_MANAGER', '安全经理', '2025-01-15', 'ACTIVE', '负责项目安全管理'),
-- 质量员
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '0465342288d0637398b64ca73da76090', 'QUALITY_OFFICER', 'QUALITY_MANAGER', '质量经理', '2025-01-15', 'ACTIVE', '负责项目质量管理'),
-- 施工组长
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '008ecfac153be83890c42f9fed0a48cd', 'TEAM_LEADER', 'SITE_MANAGER', '现场经理', '2025-01-15', 'ACTIVE', '负责现场施工管理'),
-- 地勤人员
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '014d6fd83182ac03d05967e16748ab80', 'CONSTRUCTOR', 'GROUND_SERVICE', '地勤人员', '2025-01-15', 'ACTIVE', '负责地面施工工作'),
-- 司机
(UUID(), '0b71a1259c49918c6595c9720ad1db5d', '0465342288d0637398b64ca73da76090', 'CONSTRUCTOR', 'DRIVER', '司机', '2025-01-15', 'ACTIVE', '负责设备运输和人员接送');
-- =============================================
-- 查询示例
-- =============================================
-- 查询项目所有在职人员
-- SELECT * FROM project_member WHERE project_id = '0b71a1259c49918c6595c9720ad1db5d' AND status = 'ACTIVE';
-- 查询项目的项目经理
-- SELECT * FROM project_member WHERE project_id = '0b71a1259c49918c6595c9720ad1db5d' AND role_type = 'PROJECT_MANAGER' AND status = 'ACTIVE';
-- 按角色类型统计人员数量
-- SELECT role_type, COUNT(*) as count FROM project_member WHERE project_id = '0b71a1259c49918c6595c9720ad1db5d' AND status = 'ACTIVE' GROUP BY role_type;

323
doc/regulation_api_test.md Normal file
View File

@ -0,0 +1,323 @@
# 制度模块API测试文档
## 1. 获取制度列表 (流程管理页面)
### 请求信息
- **URL**: `GET /api/regulation?page=1&size=10`
- **Method**: GET
### 请求参数
- `page`: 页码从1开始必填
- `size`: 每页数量(必填)
### 响应格式
```json
{
"status": 200,
"data": {
"records": [
{
"regulationId": "reg001",
"title": "员工考勤管理制度优化提案",
"content": "建议优化考勤管理制度,增加弹性工作时间,提高员工工作积极性...",
"regulationType": "人事制度",
"status": "VOTING",
"createBy": "张三",
"publishTime": "2024-01-01T12:00:00",
"effectiveTime": "2024-01-01T12:00:00",
"expireTime": "2024-01-08T12:00:00",
"scope": "全体员工",
"level": "MEDIUM",
"version": "1.0",
"remark": "需要与人事部门协调实施",
"createBy": "admin",
"updateBy": "admin",
"createTime": "2024-01-01 10:00:00",
"updateTime": "2024-01-01 12:00:00",
"page": 1,
"pageSize": 10,
"delFlag": "0",
"voteFor": 15,
"voteAgainst": 3,
"voteAbstain": 2
}
],
"total": 4,
"size": 10,
"current": 1,
"pages": 1
}
}
```
## 2. 创建制度提案
### 请求信息
- **URL**: `POST /api/regulation/proposal`
- **Content-Type**: `application/json`
### 请求参数
```json
{
"title": "员工考勤管理制度优化提案",
"content": "建议优化考勤管理制度,增加弹性工作时间...",
"regulationType": "人事制度",
"scope": "全体员工",
"level": "MEDIUM",
"remark": "需要与人事部门协调实施"
}
```
### 响应格式
```json
{
"status": 200,
"data": {
"regulationId": "reg005",
"title": "员工考勤管理制度优化提案",
"content": "建议优化考勤管理制度,增加弹性工作时间...",
"regulationType": "人事制度",
"status": "DRAFT",
"createBy": "当前用户",
"publishTime": "2024-01-25T10:30:00",
"effectiveTime": "2024-01-25T10:30:00",
"expireTime": "2025-01-25T10:30:00",
"scope": "全体员工",
"level": "MEDIUM",
"version": "1.0",
"remark": "需要与人事部门协调实施",
"createBy": "admin",
"updateBy": "admin",
"createTime": "2024-01-25 10:30:00",
"updateTime": "2024-01-25 10:30:00",
"page": 1,
"pageSize": 10,
"delFlag": "0"
}
}
```
## 3. 更新制度提案
### 请求信息
- **URL**: `PUT /api/regulation/proposal/{regulationId}`
- **Content-Type**: `application/json`
### 请求参数
```json
{
"title": "员工考勤管理制度优化提案",
"content": "建议优化考勤管理制度,增加弹性工作时间...",
"regulationType": "人事制度",
"scope": "全体员工",
"level": "MEDIUM",
"remark": "需要与人事部门协调实施"
}
```
### 响应格式
```json
{
"status": 200,
"message": "制度提案更新成功"
}
```
## 4. 删除制度提案
### 请求信息
- **URL**: `DELETE /api/regulation/proposal/{regulationId}`
- **Method**: DELETE
### 响应格式
```json
{
"status": 200,
"data": {
"success": true
}
}
```
## 5. 获取制度详情
### 请求信息
- **URL**: `GET /api/regulation/{regulationId}`
- **Method**: GET
### 响应格式
```json
{
"status": 200,
"data": {
"regulationId": "reg001",
"title": "员工考勤管理制度优化提案",
"content": "建议优化考勤管理制度,增加弹性工作时间...",
"regulationType": "人事制度",
"status": "VOTING",
"createBy": "张三",
"publishTime": "2024-01-01T12:00:00",
"effectiveTime": "2024-01-01T12:00:00",
"expireTime": "2024-01-08T12:00:00",
"scope": "全体员工",
"level": "MEDIUM",
"version": "1.0",
"remark": "需要与人事部门协调实施",
"createBy": "admin",
"updateBy": "admin",
"createTime": "2024-01-01 10:00:00",
"updateTime": "2024-01-01 12:00:00",
"page": 1,
"pageSize": 10,
"delFlag": "0",
"voteFor": 15,
"voteAgainst": 3,
"voteAbstain": 2
}
}
```
## 6. 提交投票
### 请求信息
- **URL**: `POST /api/regulation/{regulationId}/vote`
- **Content-Type**: `application/json`
### 请求参数
```json
{
"voteType": "FOR", // FOR: 赞成, AGAINST: 反对, ABSTAIN: 弃权
"reason": "这个提案很有建设性" // 可选
}
```
### 响应格式
```json
{
"status": 200,
"data": {
"success": true
}
}
```
## 7. 获取投票结果
### 请求信息
- **URL**: `GET /api/regulation/{regulationId}/vote-result`
- **Method**: GET
### 响应格式
```json
{
"status": 200,
"data": {
"regulationId": "reg001",
"voteFor": 15,
"voteAgainst": 3,
"voteAbstain": 2,
"totalVotes": 20,
"approvalRate": 0.75
}
}
```
## 8. 发布制度
### 请求信息
- **URL**: `POST /api/regulation/{regulationId}/publish`
- **Method**: POST
### 响应格式
```json
{
"status": 200,
"message": "制度发布成功"
}
```
## 9. 获取已发布制度列表
### 请求信息
- **URL**: `GET /api/regulation/published?page=1&size=10`
- **Method**: GET
### 请求参数
- `page`: 页码默认1
- `size`: 页大小默认10
### 响应格式
```json
{
"status": 200,
"data": {
"records": [
{
"regulationId": "reg001",
"title": "员工考勤管理制度",
"content": "规范员工考勤管理...",
"status": "PUBLISHED",
"publishTime": "2024-01-01T12:00:00",
"confirmStatus": "pending"
}
],
"total": 1,
"size": 10,
"current": 1
}
}
```
## 10. 确认制度知晓
### 请求信息
- **URL**: `POST /api/regulation/{regulationId}/confirm`
- **Content-Type**: `application/json`
### 请求参数
```json
{
"confirmComment": "已阅读并同意遵守该制度"
}
```
### 响应格式
```json
{
"status": 200,
"message": "制度确认成功"
}
```
## 11. 批量确认制度
### 请求信息
- **URL**: `POST /api/regulation/confirm-all`
- **Method**: POST
### 响应格式
```json
{
"status": 200,
"data": {
"success": true,
"confirmedCount": 5
}
}
```
## 测试步骤
1. **执行建表语句**: 运行 `regulation_tables.sql`
2. **插入测试数据**: 运行 `regulation_test_data.sql`
3. **启动应用**: 确保后端服务正常运行
4. **测试接口**: 使用Postman或其他工具测试上述接口
## 注意事项
1. 所有接口都需要用户登录认证
2. ID字段使用UUID自动生成无需手动设置
3. 创建时间和更新时间会自动设置
4. 创建人和更新人会从当前登录用户获取
5. 制度状态包括DRAFT草稿、VOTING投票中、PUBLISHED已发布、ARCHIVED已归档
6. 投票类型FOR赞成、AGAINST反对、ABSTAIN弃权

View File

@ -0,0 +1,221 @@
# 制度模块说明文档
## 概述
制度模块是一个完整的企业制度管理系统,包含制度规范仓库、制度草案、个人制度提案等功能,支持投票、发布等完整的制度管理流程。
## 功能模块
### 1. 制度规范仓库 (RegulationEntity)
**功能描述:** 存储正式发布的制度,支持全员知晓承诺的确认
**主要功能:**
- 制度发布管理
- 制度版本控制
- 制度状态管理(草案、已发布、已归档)
- 制度生效时间管理
- 制度适用范围管理
**核心字段:**
- `regulation_id`: 制度ID
- `title`: 制度标题
- `content`: 制度内容
- `status`: 制度状态
- `publisher_id`: 发布人ID
- `publish_time`: 发布时间
- `effective_time`: 生效时间
- `expire_time`: 失效时间
### 2. 制度草案 (RegulationDraftEntity)
**功能描述:** 制度草案管理,包含投票、发布过程
**主要功能:**
- 草案创建和编辑
- 审核流程管理
- 投票系统
- 投票结果统计
- 草案状态跟踪
**核心字段:**
- `draft_id`: 草案ID
- `status`: 草案状态(草稿、审核中、已通过、已拒绝)
- `vote_status`: 投票状态
- `approve_votes`: 赞成票数
- `reject_votes`: 反对票数
- `pass_threshold`: 通过阈值
### 3. 制度提案 (RegulationProposalEntity)
**功能描述:** 个人制度提案,支持审核和转为草案
**主要功能:**
- 提案提交
- 提案审核
- 提案转为草案
**核心字段:**
- `proposal_id`: 提案ID
- `proposer_id`: 提案人ID
- `status`: 提案状态
- `reviewer_id`: 审核人ID
- `converted_draft_id`: 转为草案ID
### 4. 制度投票 (RegulationVoteEntity)
**功能描述:** 投票系统,支持对草案和提案进行投票
**主要功能:**
- 投票记录管理
- 投票选项(赞成、反对、弃权)
- 投票统计
- 防重复投票
**核心字段:**
- `vote_id`: 投票ID
- `related_id`: 关联ID草案或提案
- `related_type`: 关联类型
- `vote_option`: 投票选项
- `voter_id`: 投票人ID
### 5. 制度确认 (RegulationConfirmationEntity)
**功能描述:** 全员知晓承诺的确认系统
**主要功能:**
- 确认任务创建
- 确认状态管理
- 确认统计
- 阅读时长记录
**核心字段:**
- `confirmation_id`: 确认ID
- `regulation_id`: 制度ID
- `confirmer_id`: 确认人ID
- `status`: 确认状态
- `read_duration`: 阅读时长
## 业务流程
### 制度发布流程
1. **提案阶段**
- 个人提交制度提案
- 进行小组讨论
- 讨论结果统计
2. **草案阶段**
- 提案转为草案
- 草案审核
- 投票表决
- 投票结果统计
3. **发布阶段**
- 通过投票的草案转为正式制度
- 制度发布
- 全员确认
### 投票流程
1. **开始投票**
- 设置投票时间
- 设置通过阈值
- 通知相关人员
2. **投票进行**
- 用户参与投票
- 实时统计投票结果
- 防重复投票
3. **投票结束**
- 统计最终结果
- 判断是否通过
- 更新相关状态
### 确认流程
1. **创建确认任务**
- 批量创建确认任务
- 通知相关人员
2. **确认进行**
- 用户阅读制度
- 确认知晓
- 记录阅读时长
3. **确认统计**
- 统计确认情况
- 生成确认报告
## 技术实现
### 数据库设计
- 采用MyBatis Plus框架
- 支持软删除
- 包含审计字段(创建人、创建时间、更新人、更新时间)
- 合理的索引设计
### 服务层设计
- 采用Service接口 + 实现类的设计模式
- 支持事务管理
- 统一的异常处理
- 统一的返回结果格式
### 核心特性
- **防重复操作**: 投票和确认都支持防重复机制
- **状态管理**: 完整的状态流转管理
- **统计功能**: 支持各种统计和报表功能
- **扩展性**: 模块化设计,易于扩展
## 使用说明
### 1. 数据库初始化
执行 `doc/regulation_tables.sql` 创建相关数据表。
### 2. 服务调用示例
```java
// 发布制度
RegulationEntity regulation = new RegulationEntity();
regulation.setTitle("员工手册");
regulation.setContent("员工手册内容...");
regulationService.publishRegulation(regulation);
// 创建草案
RegulationDraftEntity draft = new RegulationDraftEntity();
draft.setTitle("新制度草案");
draftService.createDraft(draft);
// 提交提案
RegulationProposalEntity proposal = new RegulationProposalEntity();
proposal.setTitle("制度改进提案");
proposalService.submitProposal(proposal);
// 投票
RegulationVoteEntity vote = new RegulationVoteEntity();
vote.setVoteOption("APPROVE");
voteService.vote(vote);
// 确认制度
RegulationConfirmationEntity confirmation = new RegulationConfirmationEntity();
confirmationService.confirmRegulation(confirmation);
```
## 注意事项
1. **数据一致性**: 所有操作都支持事务管理,确保数据一致性
2. **权限控制**: 需要配合权限系统使用,控制用户操作权限
3. **性能优化**: 大数据量时需要考虑分页和索引优化
4. **日志记录**: 重要操作需要记录操作日志
## 扩展建议
1. **消息通知**: 集成消息系统,支持邮件、短信通知
2. **工作流**: 集成工作流引擎,支持更复杂的审批流程
3. **文档管理**: 集成文档管理系统,支持附件上传
4. **报表系统**: 集成报表系统,支持更丰富的统计报表

145
doc/regulation_tables.sql Normal file
View File

@ -0,0 +1,145 @@
-- 制度模块数据库表创建脚本
-- @author wangna
-- @date 2025/07/28
-- 制度类型表
CREATE TABLE `regulation_type` (
`type_id` varchar(64) NOT NULL COMMENT '类型ID',
`type_name` varchar(100) NOT NULL COMMENT '类型名称',
`sort_order` int DEFAULT 0 COMMENT '排序顺序',
`is_enabled` char(1) DEFAULT '1' COMMENT '是否启用1-启用0-禁用)',
`remark` text COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0代表存在1代表删除',
PRIMARY KEY (`type_id`),
UNIQUE KEY `uk_type_name` (`type_name`),
KEY `idx_sort_order` (`sort_order`),
KEY `idx_is_enabled` (`is_enabled`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='制度类型';
-- 插入制度类型测试数据
INSERT INTO `regulation_type` (`type_id`, `type_name`, `sort_order`, `is_enabled`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES
('type_001', '人事制度', 1, '1', '人力资源管理相关制度', 'admin', '2024-01-01 10:00:00', 'admin', '2024-01-01 10:00:00', '0'),
('type_002', '财务制度', 2, '1', '财务管理相关制度', 'admin', '2024-01-01 10:00:00', 'admin', '2024-01-01 10:00:00', '0'),
('type_003', '安全制度', 3, '1', '安全管理相关制度', 'admin', '2024-01-01 10:00:00', 'admin', '2024-01-01 10:00:00', '0'),
('type_004', '设备制度', 4, '1', '设备管理相关制度', 'admin', '2024-01-01 10:00:00', 'admin', '2024-01-01 10:00:00', '0'),
('type_005', '行政制度', 5, '1', '行政管理相关制度', 'admin', '2024-01-01 10:00:00', 'admin', '2024-01-01 10:00:00', '0');
-- 制度规范仓库表
CREATE TABLE `regulation` (
`regulation_id` varchar(64) NOT NULL COMMENT '制度ID',
`title` varchar(255) NOT NULL COMMENT '制度标题',
`content` text COMMENT '制度内容',
`regulation_type` varchar(50) DEFAULT NULL COMMENT '制度类型',
`status` varchar(20) DEFAULT 'DRAFT' COMMENT '制度状态DRAFT-草案PUBLISHED-已发布ARCHIVED-已归档',
`publisher_id` varchar(64) DEFAULT NULL COMMENT '发布人ID',
`publisher_name` varchar(100) DEFAULT NULL COMMENT '发布人姓名',
`publish_time` datetime DEFAULT NULL COMMENT '发布时间',
`effective_time` datetime DEFAULT NULL COMMENT '生效时间',
`expire_time` datetime DEFAULT NULL COMMENT '失效时间',
`scope` varchar(255) DEFAULT NULL COMMENT '适用范围',
`level` varchar(20) DEFAULT 'MEDIUM' COMMENT '制度级别HIGH-高级MEDIUM-中级LOW-低级',
`version` varchar(20) DEFAULT '1.0' COMMENT '版本号',
`remark` text COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0代表存在1代表删除',
PRIMARY KEY (`regulation_id`),
KEY `idx_status` (`status`),
KEY `idx_type` (`regulation_type`),
KEY `idx_publisher` (`publisher_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='制度规范仓库';
-- 制度草案表
CREATE TABLE `regulation_draft` (
`draft_id` varchar(64) NOT NULL COMMENT '草案ID',
`title` varchar(255) NOT NULL COMMENT '制度标题',
`content` text COMMENT '制度内容',
`regulation_type` varchar(50) DEFAULT NULL COMMENT '制度类型',
`status` varchar(20) DEFAULT 'DRAFT' COMMENT '草案状态DRAFT-草稿REVIEWING-审核中APPROVED-已通过REJECTED-已拒绝',
`creator_id` varchar(64) DEFAULT NULL COMMENT '创建人ID',
`creator_name` varchar(100) DEFAULT NULL COMMENT '创建人姓名',
`reviewer_id` varchar(64) DEFAULT NULL COMMENT '审核人ID',
`reviewer_name` varchar(100) DEFAULT NULL COMMENT '审核人姓名',
`review_time` datetime DEFAULT NULL COMMENT '审核时间',
`review_comment` text COMMENT '审核意见',
`scope` varchar(255) DEFAULT NULL COMMENT '适用范围',
`level` varchar(20) DEFAULT 'MEDIUM' COMMENT '制度级别HIGH-高级MEDIUM-中级LOW-低级',
`version` varchar(20) DEFAULT '1.0' COMMENT '版本号',
`remark` text COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0代表存在1代表删除',
PRIMARY KEY (`draft_id`),
KEY `idx_status` (`status`),
KEY `idx_creator` (`creator_id`),
KEY `idx_reviewer` (`reviewer_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='制度草案';
-- 制度提案表
CREATE TABLE `regulation_proposal` (
`proposal_id` varchar(64) NOT NULL COMMENT '提案ID',
`title` varchar(255) NOT NULL COMMENT '提案标题',
`content` text COMMENT '提案内容',
`proposal_type` varchar(50) DEFAULT NULL COMMENT '提案类型',
`status` varchar(20) DEFAULT 'SUBMITTED' COMMENT '提案状态SUBMITTED-已提交DISCUSSING-讨论中APPROVED-已通过REJECTED-已拒绝CONVERTED-已转为草案',
`proposer_id` varchar(64) DEFAULT NULL COMMENT '提案人ID',
`proposer_name` varchar(100) DEFAULT NULL COMMENT '提案人姓名',
`proposer_dept` varchar(100) DEFAULT NULL COMMENT '提案人部门',
`discussion_group_id` varchar(64) DEFAULT NULL COMMENT '讨论组ID',
`discussion_group_name` varchar(100) DEFAULT NULL COMMENT '讨论组名称',
`discussion_start_time` datetime DEFAULT NULL COMMENT '讨论开始时间',
`discussion_end_time` datetime DEFAULT NULL COMMENT '讨论结束时间',
`discussion_status` varchar(20) DEFAULT 'NOT_STARTED' COMMENT '讨论状态NOT_STARTED-未开始DISCUSSING-讨论中FINISHED-已结束',
`support_count` int DEFAULT 0 COMMENT '支持人数',
`oppose_count` int DEFAULT 0 COMMENT '反对人数',
`total_participants` int DEFAULT 0 COMMENT '总参与人数',
`reviewer_id` varchar(64) DEFAULT NULL COMMENT '审核人ID',
`reviewer_name` varchar(100) DEFAULT NULL COMMENT '审核人姓名',
`review_time` datetime DEFAULT NULL COMMENT '审核时间',
`review_comment` text COMMENT '审核意见',
`converted_draft_id` varchar(64) DEFAULT NULL COMMENT '转为草案ID',
`scope` varchar(255) DEFAULT NULL COMMENT '适用范围',
`level` varchar(20) DEFAULT 'MEDIUM' COMMENT '制度级别HIGH-高级MEDIUM-中级LOW-低级',
`urgency_level` varchar(20) DEFAULT 'MEDIUM' COMMENT '紧急程度HIGH-高MEDIUM-中LOW-低',
`remark` text COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0代表存在1代表删除',
PRIMARY KEY (`proposal_id`),
KEY `idx_status` (`status`),
KEY `idx_proposer` (`proposer_id`),
KEY `idx_reviewer` (`reviewer_id`),
KEY `idx_discussion_status` (`discussion_status`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='制度提案';
-- 制度确认表
CREATE TABLE `regulation_confirmation` (
`confirmation_id` varchar(64) NOT NULL COMMENT '确认ID',
`regulation_id` varchar(64) NOT NULL COMMENT '制度ID',
`confirmer_id` varchar(64) NOT NULL COMMENT '确认人ID',
`confirmer_name` varchar(100) DEFAULT NULL COMMENT '确认人姓名',
`confirmer_dept` varchar(100) DEFAULT NULL COMMENT '确认人部门',
`status` varchar(20) DEFAULT 'CONFIRMED' COMMENT '确认状态CONFIRMED-已确认',
`confirm_time` datetime DEFAULT NULL COMMENT '确认时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0代表存在1代表删除',
PRIMARY KEY (`confirmation_id`),
UNIQUE KEY `uk_confirmer_regulation` (`confirmer_id`, `regulation_id`),
KEY `idx_regulation` (`regulation_id`),
KEY `idx_confirmer` (`confirmer_id`),
KEY `idx_status` (`status`),
KEY `idx_confirm_time` (`confirm_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='制度确认';

View File

@ -0,0 +1,35 @@
-- 制度模块测试数据
-- @author wangna
-- @date 2025/07/29
-- 插入测试用户数据(如果不存在)
INSERT INTO `sys_user` (`user_id`, `username`, `nickname`, `email`, `phonenumber`, `sex`, `avatar`, `password`, `status`, `login_ip`, `login_date`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `del_flag`) VALUES
('1', 'admin', '管理员', 'admin@example.com', '13800138000', '0', '', '$2a$10$7JB720yubVSOfvVWdBYoOeymFwJ9WxqHhqjqKqKqKqKqKqKqKqKqK', '0', '127.0.0.1', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', '管理员', '0'),
('2', 'user1', '张三', 'zhangsan@example.com', '13800138001', '0', '', '$2a$10$7JB720yubVSOfvVWdBYoOeymFwJ9WxqHhqjqKqKqKqKqKqKqKqKqK', '0', '127.0.0.1', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', '普通用户', '0'),
('3', 'user2', '李四', 'lisi@example.com', '13800138002', '0', '', '$2a$10$7JB720yubVSOfvVWdBYoOeymFwJ9WxqHhqjqKqKqKqKqKqKqKqKqK', '0', '127.0.0.1', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', '普通用户', '0'),
('4', 'user3', '王五', 'wangwu@example.com', '13800138003', '0', '', '$2a$10$7JB720yubVSOfvVWdBYoOeymFwJ9WxqHhqjqKqKqKqKqKqKqKqKqK', '0', '127.0.0.1', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', '普通用户', '0')
ON DUPLICATE KEY UPDATE `update_time` = NOW();
-- 插入测试制度数据符合前端API格式
INSERT INTO `regulation` (`regulation_id`, `title`, `content`, `regulation_type`, `status`, `publisher_id`, `publisher_name`, `publish_time`, `effective_time`, `expire_time`, `scope`, `level`, `version`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `del_flag`) VALUES
('reg001', '员工考勤管理制度优化提案', '建议优化考勤管理制度,增加弹性工作时间,提高员工工作积极性...', '人事制度', 'VOTING', '2', '张三', '2024-01-01 12:00:00', '2024-01-01 12:00:00', '2024-01-08 12:00:00', '全体员工', 'MEDIUM', '1.0', 'admin', '2024-01-01 10:00:00', 'admin', '2024-01-01 12:00:00', '需要与人事部门协调实施', '0'),
('reg002', '财务报销流程简化提案', '建议简化财务报销流程,提高工作效率,减少审批环节...', '财务制度', 'PUBLISHED', '3', '李四', '2024-01-15 14:30:00', '2024-01-15 14:30:00', '2024-12-31 23:59:59', '财务部门及相关员工', 'HIGH', '1.0', 'admin', '2024-01-15 14:00:00', 'admin', '2024-01-15 14:30:00', '已获得财务部门支持', '0'),
('reg003', '技术管理制度', '为规范技术管理流程,提高技术管理水平,特制定本制度...', '技术制度', 'DRAFT', '2', '张三', NULL, NULL, NULL, '技术部门', 'MEDIUM', '1.0', 'admin', '2024-01-25 16:00:00', 'admin', '2024-01-25 16:00:00', '技术管理制度草案', '0'),
('reg004', '项目管理制度', '为规范项目管理流程,提高项目执行效率,特制定本制度...', '项目制度', 'ARCHIVED', '1', '管理员', '2024-01-10 11:00:00', '2024-01-11 00:00:00', '2024-12-31 23:59:59', '项目部门', 'MEDIUM', '1.0', 'admin', '2024-01-10 10:00:00', 'admin', '2024-01-10 11:00:00', '项目管理规范', '0'),
('reg005', '远程办公管理制度', '随着远程办公的普及,需要制定相应的管理制度来规范远程办公行为...', '人事制度', 'DRAFT', '2', '张三', NULL, NULL, NULL, '全体员工', 'HIGH', '1.0', 'admin', '2024-01-27 10:00:00', 'admin', '2024-01-27 10:00:00', '远程办公管理提案', '0'),
('reg006', '数据安全管理制度', '为保护公司数据安全,防止数据泄露,需要制定数据安全管理制度...', '安全制度', 'PENDING', '2', '张三', NULL, NULL, NULL, '全体员工', 'HIGH', '1.0', 'admin', '2024-01-28 09:00:00', 'admin', '2024-01-28 09:00:00', '数据安全管理提案', '0');
-- 插入制度草案数据
INSERT INTO `regulation_draft` (`draft_id`, `regulation_id`, `title`, `content`, `draft_type`, `status`, `creator_id`, `creator_name`, `reviewer_id`, `reviewer_name`, `vote_status`, `vote_start_time`, `vote_end_time`, `approval_status`, `approval_time`, `approval_comment`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `del_flag`) VALUES
('draft_001', 'reg003', '技术管理制度', '为规范技术管理流程,提高技术管理水平,特制定本制度...', '技术制度', 'DRAFT', '2', '张三', '1', '管理员', 'PENDING', NULL, NULL, 'PENDING', NULL, NULL, 'admin', '2024-01-25 16:00:00', 'admin', '2024-01-25 16:00:00', '技术管理制度草案', '0'),
('draft_002', 'reg005', '远程办公管理制度', '随着远程办公的普及,需要制定相应的管理制度来规范远程办公行为...', '人事制度', 'REVIEWING', '2', '张三', '1', '管理员', 'VOTING', '2024-01-26 09:00:00', '2024-01-28 18:00:00', 'PENDING', NULL, NULL, 'admin', '2024-01-26 08:00:00', 'admin', '2024-01-26 09:00:00', '远程办公管理制度草案', '0');
-- 插入制度提案数据
INSERT INTO `regulation_proposal` (`proposal_id`, `regulation_id`, `title`, `description`, `proposal_type`, `status`, `proposer_id`, `proposer_name`, `proposer_dept`, `reviewer_id`, `reviewer_name`, `review_status`, `review_time`, `review_comment`, `priority`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `del_flag`) VALUES
('proposal_001', 'reg001', '员工考勤管理制度优化提案', '建议优化考勤管理制度,增加弹性工作时间,提高员工工作积极性...', '人事制度', 'APPROVED', '2', '张三', '技术部', '1', '管理员', 'APPROVED', '2024-01-27 14:00:00', '同意提案,可以开始制定制度', 'HIGH', 'admin', '2024-01-27 10:00:00', 'admin', '2024-01-27 14:00:00', '员工考勤管理提案', '0'),
('proposal_002', 'reg006', '数据安全管理制度', '为保护公司数据安全,防止数据泄露,需要制定数据安全管理制度...', '安全制度', 'PENDING', '2', '张三', '技术部', '1', '管理员', 'PENDING', NULL, NULL, 'HIGH', 'admin', '2024-01-28 09:00:00', 'admin', '2024-01-28 09:00:00', '数据安全管理提案', '0');
-- 插入制度确认数据
INSERT INTO `regulation_confirmation` (`confirmation_id`, `regulation_id`, `confirmer_id`, `confirmer_name`, `confirmer_dept`, `status`, `confirm_time`, `confirm_comment`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `del_flag`) VALUES
('confirm_001', 'reg002', '2', '张三', '技术部', 'CONFIRMED', '2024-01-16 10:00:00', '已阅读并确认知晓', 'admin', '2024-01-16 10:00:00', 'admin', '2024-01-16 10:00:00', '财务报销制度确认', '0'),
('confirm_002', 'reg002', '3', '李四', '财务部', 'CONFIRMED', '2024-01-21 15:00:00', '已阅读并确认知晓', 'admin', '2024-01-21 15:00:00', 'admin', '2024-01-21 15:00:00', '财务报销制度确认', '0');

View File

@ -12,7 +12,6 @@
</properties>
<modules>
<module>core</module>
<module>sip</module>
<module>web</module>
<module>flowable</module>
</modules>

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.dite.znpt</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>sip</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.dite.znpt</groupId>
<artifactId>core</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- sip协议栈 -->
<dependency>
<groupId>javax.sip</groupId>
<artifactId>jain-sip-ri</artifactId>
<version>1.3.0-91</version>
</dependency>
<!-- xml解析库 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
</project>

View File

@ -1,30 +0,0 @@
package com.dite.znpt.monitor.config;
import cn.hutool.core.collection.CollUtil;
import com.dite.znpt.monitor.domain.vo.video.StreamMediaFormat;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* 媒体格式配置
*
* @author huise23
* @since 2023-07-31 09:08:05
*/
@Configuration
public class MediaFormatConfig {
@Bean
public static List<StreamMediaFormat> streamMediaFormatList() {
List<StreamMediaFormat> formatList = CollUtil.newArrayList();
formatList.add(new StreamMediaFormat("flv",null,"1"));
formatList.add(new StreamMediaFormat("mp4",null,"0"));
formatList.add(new StreamMediaFormat("hls",null,"0"));
formatList.add(new StreamMediaFormat("webrtc",null,"1"));
return formatList;
}
}

View File

@ -1,37 +0,0 @@
package com.dite.znpt.monitor.constant;
/**
* @author yunp
* @since 2022/7/14
*/
public class Constants {
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* 路径拼接符 /
*/
public static final String File_SEPARATOR = "/";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 默认字符串分隔符
*/
public static final String DEFAULT_DELIMITER = ",";
}

View File

@ -1,37 +0,0 @@
package com.dite.znpt.monitor.constant;
/**
* @author yunp
* @since 2022/8/4
* @description 缓存key定义key全部以iot开头
*/
public class IotCacheConstants {
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 图标库 cache key
*/
public static final String SYS_ICON_KEY = "sys_icon";
private static final String IOT_DEVICE_VIDEO_PREFIX = "vs_device_video:";
public static String getIotDeviceVideoKey(String deviceCode){
return IOT_DEVICE_VIDEO_PREFIX + deviceCode;
}
private final static String CLIENT_TRANSACTION_CACHE_PREFIX = "IOT_CLIENT_TRANSACTION_CACHE:";
public static String getClientTransactionCacheKey(String ssrc){
return CLIENT_TRANSACTION_CACHE_PREFIX + ssrc;
}
}

View File

@ -1,20 +0,0 @@
package com.dite.znpt.monitor.constant;
/**
* @author yunp
* @since 2022/8/4
* @description 字典类型定义
*/
public class IotDictConstants {
/**
* 设备状态-在线
*/
public static final String IOT_DEVICE_STATUS_ONLINE = "2";
/**
* 设备状态-离线
*/
public static final String IOT_DEVICE_STATUS_OFFLINE = "3";
}

View File

@ -1,113 +0,0 @@
package com.dite.znpt.monitor.constant;
/**
* @author yunp
* @since 2022/8/4
* @description 响应文案定义
*/
public class IotRespMessage {
public static final String UNKNOWN_FAIL = "未知错误";
public static final String ID_NOT_FOUND = "数据不存在";
public static final String PARAMETER_ERROR = "参数有误";
public static final String NO_PERMISSION = "没有访问权限";
public static final String PARENT_AREA_NOT_FOUND = "上级分区不存在";
public static final String CAR_TYPE_HAS_CARS = "该车型下仍有车辆,无法删除";
public static final String CAR_BRAND_HAS_CARS = "该品牌下仍有车辆,无法删除";
public static final String CAR_PLATE_NUMBER_EXIST = "该车牌号车辆已存在";
public static final String CAR_PLATE_NUMBER_NOT_EXIST = "该车牌号车辆不存在";
public static final String CAR_HAS_BIND_TAG_OR_SPEED_MONITOR = "车辆已绑定车载标签或速度检测仪,禁止删除";
public static final String CAR_FREIGHT_NOT_EXIST = "货物不存在";
public static final String CAR_HAS_BIND_ALARM_TEMPLATE = "该车辆已绑定其他告警模板";
public static final String USER_HAS_BIND_ALARM_TEMPLATE = "该人员已绑定其他告警模板";
public static final String REPETITION_ALARM_FOR_AREA = "该厂区分区下已有同类型告警,无法重复添加";
public static final String REPETITION_ALARM_NOTIFY_CONFIG = "已存在相同部门层级的告警消息推送配置";
public static final String DEVICE_TERMINAL_HAS_BEEN_BIND = "该标签卡已被其他人绑定";
public static final String DEVICE_TERMINAL_TYPE_ERROR = "标签卡类型有误";
public static final String DEVICE_TERMINAL_NOT_FOUND_OR_STATUS_ERROR = "标签卡未找到或状态异常";
public static final String DEVICE_CANNOT_EDIT = "设备未启用或已停用才可编辑";
public static final String VIDEO_DEVICE_CANNOT_DELETE = "视频设备禁止删除";
public static final String DEVICE_CANNOT_DELETE = "未启用的设备才可删除";
public static final String DEVICE_HAS_BIND_TO_GROUP = "设备已经绑定至该分组";
public static final String DEVICE_VIDEO_CANNOT_DELETE = "禁止删除在线视频设备";
public static final String DEVICE_VIDEO_CANNOT_SYNC = "禁止更新离线视频设备";
public static final String DEVICE_INACTIVE = "设备未启用";
public static final String CODE_HAS_BEEN_USED = "编号已被占用";
public static final String NAME_HAS_BEEN_USED = "名称已被占用";
public static final String FLAG_HAS_BEEN_USED = "标识已被占用";
public static final String GROUP_HAS_CHILD_CANNOT_REMOVE = "分组有下级分组,无法删除";
public static final String GROUP_HAS_DEVICE_CANNOT_REMOVE = "分组下有绑定设备,无法删除";
public static final String PRODUCT_PUBLISH_CANNOT_DELETE = "该产品已发布,不可删除";
public static final String PRODUCT_HAS_DEVICE_CANNOT_REMOVE = "产品下存在设备关联,需删除设备后进行操作";
public static final String MSG_PROTOCOL_PUBLISH_CANNOT_DELETE = "消息协议未发布,发布协议后操作";
public static final String CATEGORY_CANNOT_DELETE = "该产品分类信息已被产品关联,不可删除";
public static final String SCENE_CANNOT_DELETE = "该场景信息已被产品关联,不可删除";
public static final String SWITCH_PARAM_HAS_BEEN_USED = "该参数在设备服务中只能定义一个";
public static final String CONFIG_CANNOT_DELETE = "该配置已被通知模板关联,不可删除, 请取消关联后重试。";
public static final String TEMPLATE_CANNOT_DELETE = "该通知模板已被场景联动关联,不可删除, 请取消关联后操作。";
public static final String PROTOCOL_CANNOT_DELETE_BY_PUBLISHED = "当前协议状态为已发布,不可删除.";
public static final String PROTOCOL_CANNOT_DELETE_WITH_PRODUCT = "该协议已被产品关联,不可删除,请删除关联后操作!";
public static final String PROTOCOL_CANNOT_UN_PUBLISH = "协议已被产品发布,不可取消!";
public static final String PROTOCOL_TYPE_CANNOT_NULL = "协议类型不能为空";
public static final String PROTOCOL_CLASS_NAME_CANNOT_EMPTY = "协议类型为Jar或者Local类型时必须指定协议类名.";
public static final String PROTOCOL_FILE_PATH_CANNOT_EMPTY = "协议类型为Jar或者Local类型时必须上传或者指定协议文件路径.";
public static final String DATA_ILLEGAL = "数据非法";
public static final String IMPORT_ERROR = "导入出错";
public static final String COMMON_DEVICE_ATTR_DUPLICATE_ERROR = "订阅的通用设备点位全局不唯一";
public static final String PROTOCOL_NOT_EXISTS = "协议不存在";
public static final String RULE_NOT_EXISTS = "上报规则不存在";
public static final String DEVICE_NOT_EXISTS = "设备不存在";
public static final String DATA_DATA_TREND_TIME_TYPE_NOT_EXISTS = "设备数据趋势时间类型不存在";
public static final String DATA_DATA_TREND_DATA_TYPE_NOT_EXISTS = "设备数据趋势数据类型不存在";
public static final String CRON_ERROR = "cron表达式输入错误:";
}

View File

@ -1,32 +0,0 @@
package com.dite.znpt.monitor.constant.dict;
/**
* 摄像头类型
*
* @author huise23
* @since 2023-07-28 15:30:10
*/
public enum CameraType implements ValueAndLabel {
UNKNOWN("0","未知"),
BALLHEAD("1","球机");
private final String value;
private final String label;
CameraType(String value, String label) {
this.value = value;
this.label = label;
}
@Override
public String getValue() {
return value;
}
@Override
public String getLabel() {
return label;
}
}

View File

@ -1,34 +0,0 @@
package com.dite.znpt.monitor.constant.dict;
/**
* 设备状态
*
* @author huise23
* @since 2023-07-28 15:30:10
*/
public enum DeviceStatus implements ValueAndLabel {
INACTIV("1", "未启用"),
ONLINE("2", "在线"),
OFFLINE("3", "离线"),
STOP("4", "停用");
private final String value;
private final String label;
DeviceStatus(String value, String label) {
this.value = value;
this.label = label;
}
@Override
public String getValue() {
return value;
}
@Override
public String getLabel() {
return label;
}
}

View File

@ -1,26 +0,0 @@
package com.dite.znpt.monitor.constant.dict;
public enum SipTransferMode implements ValueAndLabel {
UDP("UDP","UDP"),
TCP("TCP","TCP");
private final String value;
private final String label;
SipTransferMode(String value, String label) {
this.value = value;
this.label = label;
}
@Override
public String getValue() {
return value;
}
@Override
public String getLabel() {
return label;
}
}

View File

@ -1,27 +0,0 @@
package com.dite.znpt.monitor.constant.dict;
public enum StreamTransferMode implements ValueAndLabel {
UDP("UDP","UDP"),
TCP_ACTIVE("TCP-ACTIVE","TCP主动"),
TCP_PASSIVE("TCP-PASSIVE", "TCP被动");
private final String value;
private final String label;
StreamTransferMode(String value, String label) {
this.value = value;
this.label = label;
}
@Override
public String getValue() {
return value;
}
@Override
public String getLabel() {
return label;
}
}

View File

@ -1,14 +0,0 @@
package com.dite.znpt.monitor.constant.dict;
/**
* 字典常量接口
*
* @author huise23
* @since 2023-07-28 15:28:55
*/
public interface ValueAndLabel {
String getValue();
String getLabel();
}

View File

@ -1,32 +0,0 @@
package com.dite.znpt.monitor.constant.dict;
/**
* YesOrNo
*
* @author huise23
* @since 2023-07-28 15:30:10
*/
public enum YesOrNo implements ValueAndLabel {
YES("Y",""),
NO("N", "");
private final String value;
private final String label;
YesOrNo(String value, String label) {
this.value = value;
this.label = label;
}
@Override
public String getValue() {
return value;
}
@Override
public String getLabel() {
return label;
}
}

View File

@ -1,14 +0,0 @@
package com.dite.znpt.monitor.domain;
/**
* @Author: cuizhibin
* @Date: 2023/1/16 14:36:36
* @Description:
*/
public interface CustomFunction<T> {
/**
* 执行的方法
* @return
*/
T get();
}

View File

@ -1,124 +0,0 @@
package com.dite.znpt.monitor.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @Author: huise23
* @Date: 2022/8/11 17:29
* @Description:
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("vs_device_video_channel")
@ApiModel(value="DeviceVideoChannelEntity", description="视频通道表")
public class DeviceVideoChannelEntity implements Serializable {
private static final long serialVersionUID = -4175177624487756818L;
@ApiModelProperty(value = "主键id")
@TableId(value = "channel_id", type = IdType.AUTO)
private Long channelId;
@ApiModelProperty(value = "视频设备id")
private Long videoId;
@ApiModelProperty(value = "通道国标编号")
private String channelCode;
@ApiModelProperty(value = "通道名")
private String channelName;
@ApiModelProperty(value = "生产厂商")
private String manufacture;
@ApiModelProperty(value = "型号")
private String model;
@ApiModelProperty(value = "设备归属")
private String owner;
@ApiModelProperty(value = "行政区域")
private String civilCode;
@ApiModelProperty(value = "警区")
private String block;
@ApiModelProperty(value = "安装位置")
private String address;
@ApiModelProperty(value = "是否有子设备 1有, 0没有")
private int parental;
@ApiModelProperty(value = "父级id")
private String parentId;
@ApiModelProperty(value = "信令安全模式 缺省为0; 0:不采用; 2: S/MIME签名方式; 3: S/ MIME加密签名同时采用方式; 4:数字摘要方式")
private int safetyWay;
@ApiModelProperty(value = "注册方式 缺省为1;1:符合IETFRFC3261标准的认证注册模 式; 2:基于口令的双向认证注册模式; 3:基于数字证书的双向认证注册模式")
private int registerWay;
@ApiModelProperty("证书序列号")
private String certNum;
@ApiModelProperty("证书有效标识 缺省为0;证书有效标识:0:无效1: 有效")
private int certifiable;
@ApiModelProperty("证书无效原因码")
private int errCode;
@ApiModelProperty( "证书终止有效期")
private String endTime;
@ApiModelProperty("保密属性 缺省为0; 0:不涉密, 1:涉密")
private String secrecy;
@ApiModelProperty("IP地址")
private String ipAddress;
@ApiModelProperty("端口号")
private int port;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("摄像头类型")
private String cameraType;
@ApiModelProperty("云台控制")
private String ptzControl;
@ApiModelProperty(value = "状态")
private String status;
@ApiModelProperty("经度")
private double longitude;
@ApiModelProperty("纬度")
private double latitude;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("创建人id")
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("更新人id")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
}

View File

@ -1,97 +0,0 @@
package com.dite.znpt.monitor.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @Author: huise23
* @Date: 2022/8/11 10:24
* @Description:
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("vs_device_video")
@ApiModel(value="DeviceVideoEntity", description="视频设备表")
public class DeviceVideoEntity implements Serializable {
private static final long serialVersionUID = -182441901641147882L;
@ApiModelProperty(value = "主键id")
@TableId(value = "video_id", type = IdType.AUTO)
private Long videoId;
@ApiModelProperty(value = "视频设备国标编码")
private String videoCode;
@ApiModelProperty(value = "视频设备名称")
private String videoName;
@ApiModelProperty(value = "生产厂商")
private String manufacturer;
@ApiModelProperty(value = "型号")
private String model;
@ApiModelProperty(value = "固件版本")
private String firmware;
@ApiModelProperty(value = "传输协议UDP/TCP默认UDP")
private String transport;
@ApiModelProperty(value = "数据流传输模式(默认UDP)")
private String streamMode;
@ApiModelProperty(value = "设备状态")
private String status;
@ApiModelProperty(value = "注册时间")
private LocalDateTime registerTime;
@ApiModelProperty(value = "心跳时间")
private LocalDateTime KeepaliveTime;
@ApiModelProperty("通道个数")
private int channelCount;
@ApiModelProperty(value = "ip")
private String ip;
@ApiModelProperty(value = "端口")
private Integer port;
@ApiModelProperty(value = "地址")
private String hostAddress;
@ApiModelProperty(value = "注册有效期")
private Integer expires;
@ApiModelProperty(value = "符集, 支持 UTF-8 与 GB2312")
private String charset;
@ApiModelProperty(value = "产品id")
private Long productId;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("创建人id")
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("更新人id")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
}

View File

@ -1,35 +0,0 @@
package com.dite.znpt.monitor.domain.entity;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.IdType;
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;
/**
* @Date: 2023/09/05 16:39
* @Description: 监控设备IP配置表实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("vs_ip_config")
@ApiModel(value="VsIpConfigEntity对象", description="监控设备IP配置表")
public class IpConfigEntity implements Serializable {
@ApiModelProperty("${column.comment}")
@TableId(type = IdType.AUTO)
private Long configId;
@ApiModelProperty("ip地址")
private String ip;
@ApiModelProperty("ip地址前三位")
private String ipTopThree;
}

View File

@ -1,14 +0,0 @@
package com.dite.znpt.monitor.domain.req;
import lombok.Data;
import java.util.List;
/**
* @Date:2023/9/5 16:19
* @Description: 视频服务配置新增对象
*/
@Data
public class MonitorConfigAddReq {
private List<String> ipAddresses;
}

View File

@ -1,23 +0,0 @@
package com.dite.znpt.monitor.domain.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 查询视频信息参数
*
* @author huise23
* @since 2024-12-03 14:03:29
*/
@Data
public class VideoInfoReq implements Serializable {
@ApiModelProperty(value = "视频对接方式 1.摄像头直连 2.级联")
private Integer videoConnection;
@ApiModelProperty(value = "级联分隔符(默认/)")
private String cascadeSeparator = "/";
}

View File

@ -1,19 +0,0 @@
package com.dite.znpt.monitor.domain.resp;
import com.dite.znpt.monitor.domain.entity.DeviceVideoEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @Date:2023/9/7 10:26
* @Description:
*/
@Data
public class DeviceVideoResp extends DeviceVideoEntity {
@ApiModelProperty(value = "设备状态label")
private String statusLabel;
@ApiModelProperty(value = "流传输模式label")
private String streamModeLabel;
@ApiModelProperty(value = "传输模式label")
private String transportLabel;
}

View File

@ -1,58 +0,0 @@
package com.dite.znpt.monitor.domain.resp;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 查询视频信息返回信息
*
* @author huise23
* @since 2024-12-03 14:03:29
*/
@Data
public class VideoInfoResp implements Serializable {
@ApiModelProperty(value = "视频设备id")
private Long videoId;
@ApiModelProperty(value = "视频设备名称")
private String videoName;
@ApiModelProperty(value = "通道id")
private Long channelId;
@ApiModelProperty(value = "国标编码")
private String channelCode;
@ApiModelProperty(value = "通道名称")
private String channelName;
@ApiModelProperty(value = "生产厂商")
private String manufacture;
@ApiModelProperty(value = "型号")
private String model;
@ApiModelProperty(value = "安装位置")
private String address;
@ApiModelProperty("IP地址")
private String ipAddress;
@ApiModelProperty("端口号")
private int port;
@ApiModelProperty(value = "云台控制label")
private String ptzControl;
@ApiModelProperty("经度")
private double longitude;
@ApiModelProperty("纬度")
private double latitude;
@ApiModelProperty(value = "状态 DeviceStatus")
private String status;
}

View File

@ -1,34 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: huise23
* @Date: 2022/8/11 18:12
* @Description:
*/
@Data
@ApiModel("视频通道编辑请求")
public class DeviceVideoChannelEditReq implements Serializable {
private static final long serialVersionUID = 719557164910393807L;
@ApiModelProperty(value = "通道名称")
private String channelName;
@ApiModelProperty(value = "安装位置")
private String address;
@ApiModelProperty(value = "摄像头类型")
private String cameraType;
@ApiModelProperty(value = "云台控制Y表示是,N表示否")
private String ptzControl;
@ApiModelProperty(value = "描述")
private String remark;
}

View File

@ -1,55 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: huise23
* @Date: 2022/8/11 18:12
* @Description:
*/
@Data
@ApiModel("视频通道列表响应")
public class DeviceVideoChannelListResp implements Serializable {
private static final long serialVersionUID = -8053965410352257803L;
@ApiModelProperty(value = "主键id")
private Long channelId;
@ApiModelProperty(value = "所属产品id")
private Long productId;
@ApiModelProperty(value = "通道国标编码")
private String channelCode;
@ApiModelProperty(value = "通道名称")
private String channelName;
@ApiModelProperty(value = "安装位置")
private String address;
@ApiModelProperty(value = "摄像头类型label")
private String cameraType;
@ApiModelProperty(value = "摄像头类型")
private String cameraTypeLabel;
@ApiModelProperty(value = "云台控制label")
private String ptzControl;
@ApiModelProperty(value = "云台控制Y表示是,N表示否")
private String ptzControlLabel;
@ApiModelProperty(value = "状态")
private String status;
@ApiModelProperty(value = "状态label")
private String statusLabel;
@ApiModelProperty(value = "描述")
private String remark;
}

View File

@ -1,43 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: huise23
* @Date: 2022/8/11 18:12
* @Description:
*/
@Data
@ApiModel("视频通道响应")
public class DeviceVideoChannelResp implements Serializable {
private static final long serialVersionUID = 1140851083577845760L;
@ApiModelProperty(value = "主键id")
private Long channelId;
@ApiModelProperty(value = "通道国标编码")
private String channelCode;
@ApiModelProperty(value = "通道名称")
private String channelName;
@ApiModelProperty(value = "安装位置")
private String address;
@ApiModelProperty(value = "摄像头类型")
private String cameraType;
@ApiModelProperty(value = "云台控制Y表示是,N表示否")
private String ptzControl;
@ApiModelProperty(value = "状态")
private String status;
@ApiModelProperty(value = "描述")
private String remark;
}

View File

@ -1,29 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: huise23
* @Date: 2022/8/11 18:13
* @Description:
*/
@Data
@ApiModel("视频设备编辑请求参数")
public class DeviceVideoEditReq implements Serializable {
private static final long serialVersionUID = -3387666090991548317L;
@ApiModelProperty(value = "设备名称")
private String videoName;
@ApiModelProperty(value = "所属产品")
private Long productId;
@ApiModelProperty(value = "说明")
private String remark;
}

View File

@ -1,74 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @Author: huise23
* @Date: 2022/8/11 18:13
* @Description:
*/
@Data
@ApiModel("视频设备列表响应")
public class DeviceVideoListResp implements Serializable {
private static final long serialVersionUID = -5568664011265192343L;
@ApiModelProperty(value = "主键id")
private Long videoId;
@ApiModelProperty(value = "视频设备国标编码")
private String videoCode;
@ApiModelProperty(value = "视频设备名称")
private String videoName;
@ApiModelProperty(value = "传输模式")
private String transport;
@ApiModelProperty(value = "传输模式label")
private String transportLabel;
@ApiModelProperty(value = "流传输模式")
private String streamMode;
@ApiModelProperty(value = "流传输模式label")
private String streamModeLabel;
@ApiModelProperty(value = "通道数量")
private Integer channelCount;
@ApiModelProperty(value = "设备状态")
private String status;
@ApiModelProperty(value = "设备状态label")
private String statusLabel;
@ApiModelProperty(value = "设备ip")
private String ip;
@ApiModelProperty(value = "设备端口")
private String port;
@ApiModelProperty(value = "设备地址ip+端口)")
private String hostAddress;
@ApiModelProperty(value = "生产厂商")
private String manufacturer;
@ApiModelProperty(value = "备注")
private String remark;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "心跳时间")
private LocalDateTime keepAliveTime;
}

View File

@ -1,24 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @Author: huise23
* @Date: 2022/8/16 9:34
* @Description:
*/
@Data
@ApiModel("视频设备数量响应")
public class DeviceVideoNumResp {
@ApiModelProperty(value = "设备总数量")
private Long allDevice;
@ApiModelProperty(value = "设备在线数量")
private Long onlineDevice;
@ApiModelProperty(value = "设备离线数量")
private Long offlineDevice;
}

View File

@ -1,77 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.dite.znpt.monitor.media.zlm.dto.ServerConfig;
import com.dite.znpt.monitor.media.zlm.enums.MediaFormatType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @Author: huise23
* @Date: 2022/8/11 10:25
* @Description:
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "StreamMediaFormat对象", description = "流媒体格式")
public class StreamMediaFormat implements Serializable {
private static final long serialVersionUID = -4177962876536716643L;
@ApiModelProperty(value = "流媒体格式")
private String mediaFormat;
@ApiModelProperty(value = "端口")
private Integer port;
@ApiModelProperty(value = "是否开启tls,1表示ture,0表示false")
private String openTls;
@TableField(exist = false)
@ApiModelProperty(value = "WebSocket播放地址")
private String wsUrl;
@TableField(exist = false)
@ApiModelProperty(value = "Http播放地址")
private String httpUrl;
@TableField(exist = false)
@ApiModelProperty(value = "WebSocket播放地址")
private String wssUrl;
@TableField(exist = false)
@ApiModelProperty(value = "Http播放地址")
private String httpsUrl;
@TableField(exist = false)
@ApiModelProperty(value = "相对播放地址")
private String relativePath;
public StreamMediaFormat(String mediaFormat,Integer port,String openTls){
this.mediaFormat = mediaFormat;
this.port = port;
this.openTls = openTls;
}
public void generateUrl(String host, String streamId, ServerConfig config, String mediaRouter) {
if("webrtc".equals(this.mediaFormat)){
this.httpUrl = StrUtil.format("http://{}:{}/index/api/webrtc?app=rtp&stream={}&type=play", host, config.getHttpPort(), streamId);
this.httpsUrl = StrUtil.format("https://{}:{}/index/api/webrtc?app=rtp&stream={}&type=play", host, config.getHttpSslPort(), streamId);
this.relativePath = StrUtil.format("{}/index/api/webrtc?app=rtp&stream={}&type=play", mediaRouter, streamId);
return;
}
String suffix = MediaFormatType.getSuffix(this.mediaFormat);
if (config.getHttpSslPort() != null && config.getHttpSslPort() > 0) {
this.wssUrl = StrUtil.format("wss://{}:{}/rtp/{}{}", host, config.getHttpSslPort(), streamId, suffix);
this.httpsUrl = StrUtil.format("https://{}:{}/rtp/{}{}", host, config.getHttpSslPort(), streamId, suffix);
}
this.wsUrl = StrUtil.format("ws://{}:{}/rtp/{}{}", host, config.getHttpPort(), streamId, suffix);
this.httpUrl = StrUtil.format("http://{}:{}/rtp/{}{}", host, config.getHttpPort(), streamId, suffix);
this.relativePath = StrUtil.format("{}/rtp/{}{}", mediaRouter, streamId, suffix);
}
}

View File

@ -1,28 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: huise23
* @Date: 2022/8/11 14:40
* @Description:
*/
@Data
@ApiModel("流媒体格式请求")
public class StreamMediaFormatReq implements Serializable {
private static final long serialVersionUID = 6627383994019834279L;
@ApiModelProperty(value = "流媒体格式")
private String mediaFormat;
@ApiModelProperty(value = "端口")
private Integer port;
@ApiModelProperty(value = "是否开启TLS,1表示true,0表示false")
private String openTls;
}

View File

@ -1,31 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: huise23
* @Date: 2022/8/11 14:40
* @Description:
*/
@Data
@ApiModel("流媒体格式响应")
public class StreamMediaFormatResp implements Serializable {
private static final long serialVersionUID = -5714327034173930078L;
@ApiModelProperty(value = "流媒体格式主键")
private Long formatId;
@ApiModelProperty(value = "流媒体格式")
private String mediaFormat;
@ApiModelProperty(value = "端口")
private Integer port;
@ApiModelProperty(value = "是否开启TLS,1表示true,0表示false")
private String openTls;
}

View File

@ -1,59 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* @Author: huise23
* @Date: 2022/8/11 14:16
* @Description:
*/
@Data
@ApiModel("流媒体服务配置请求")
public class StreamMediaServerConfigReq implements Serializable {
private static final long serialVersionUID = -1228005085084886474L;
@NotNull(message = "流媒体名称不能为空")
@ApiModelProperty(value = "流媒体名称")
private String mediaName;
@ApiModelProperty(value = "流媒体服务")
private String mediaService;
@ApiModelProperty(value = "公网 HOST")
private String publicHost;
@ApiModelProperty(value = "API HOST")
private String apiHost;
@ApiModelProperty(value = "API 端口")
private Integer apiPort;
@ApiModelProperty(value = "密钥")
private Integer secretKey;
@ApiModelProperty(value = "流ID前缀")
private String streamPrefix;
@ApiModelProperty(value = "RTP IP")
private String rtpHost;
@ApiModelProperty(value = "RTP 端口")
private Integer rtpPort;
@ApiModelProperty(value = "动态端口起始值")
private Integer dynamicPortStart;
@ApiModelProperty(value = "动态端口结束值")
private Integer dynamicPortEnd;
@ApiModelProperty(value = "流媒体格式")
private List<StreamMediaFormatReq> streamMediaFormatReqList;
}

View File

@ -1,60 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @Author: huise23
* @Date: 2022/8/11 14:16
* @Description:
*/
@Data
@ApiModel("流媒体服务配置响应")
public class StreamMediaServerConfigResp implements Serializable {
private static final long serialVersionUID = 3464085768355214710L;
@ApiModelProperty(value = "'流媒体配置主键'")
private Long configId;
@ApiModelProperty(value = "'流媒体名称'")
private String mediaName;
@ApiModelProperty(value = "流媒体服务")
private String mediaService;
@ApiModelProperty(value = "公网 HOST")
private String publicHost;
@ApiModelProperty(value = "API HOST")
private String apiHost;
@ApiModelProperty(value = "API 端口")
private Integer apiPort;
@ApiModelProperty(value = "密钥")
private String secretKey;
@ApiModelProperty(value = "流ID前缀")
private String streamPrefix;
@ApiModelProperty(value = "RTP IP")
private String rtpHost;
@ApiModelProperty(value = "RTP 端口")
private Integer rtpPort;
@ApiModelProperty(value = "动态端口起始值")
private Integer dynamicPortStart;
@ApiModelProperty(value = "动态端口结束值")
private Integer dynamicPortEnd;
@ApiModelProperty(value = "流媒体格式")
private List<StreamMediaFormatResp> streamMediaFormatRespList;
}

View File

@ -1,24 +0,0 @@
package com.dite.znpt.monitor.domain.vo.video;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import java.util.List;
/**
* 视频播放响应
* @author huise23
* @since 2024-11-26 14:03:41
*/
@Data
@Builder
public class VideoPayResp {
@ApiModelProperty(value = "播放方式")
private String mediaType;
@ApiModelProperty(value = "流媒体播放地址")
private List<StreamMediaFormat> streamMediaFormatList;
}

View File

@ -1,55 +0,0 @@
package com.dite.znpt.monitor.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.monitor.domain.entity.DeviceVideoChannelEntity;
import com.dite.znpt.monitor.domain.req.VideoInfoReq;
import com.dite.znpt.monitor.domain.resp.VideoInfoResp;
import com.dite.znpt.monitor.domain.vo.video.DeviceVideoChannelListResp;
import com.dite.znpt.monitor.domain.vo.video.DeviceVideoChannelResp;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Author: huise23
* @Date: 2022/8/11 18:08
* @Description:
*/
public interface DeviceVideoChannelMapper extends BaseMapper<DeviceVideoChannelEntity> {
/**
* 查询视频通道列表
*
* @param videoId 视频id
* @param keyword 插叙条件
* @return {@link List< DeviceVideoChannelListResp>}
*/
List<DeviceVideoChannelListResp> selectDeviceVideoChannel(@Param("videoId") Long videoId, @Param("keyword") String keyword);
/**
* 查询所有视频通道列表
*
* @param keyword 插叙条件
* @return {@link List< DeviceVideoChannelListResp>}
*/
List<DeviceVideoChannelListResp> selectAllDeviceVideoChannel(@Param("keyword") String keyword);
/**
* 查询视频通道详情
*
* @param channelCode 通道code
* @return {@link DeviceVideoChannelResp}
*/
DeviceVideoChannelResp getDeviceVideoChannelDetail(@Param("channelCode") String channelCode);
/**
* 查询通道及视频信息
*
* @param videoInfoReq 查询参数
* @return {@link VideoInfoResp }
* @author huise23
* @since 2024-12-03 13:54:52
*/
List<VideoInfoResp> selectVideoInfoList(VideoInfoReq videoInfoReq);
}

View File

@ -1,24 +0,0 @@
package com.dite.znpt.monitor.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.monitor.domain.entity.DeviceVideoEntity;
import com.dite.znpt.monitor.domain.vo.video.DeviceVideoListResp;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Author: huise23
* @Date: 2022/8/11 18:09
* @Description:
*/
public interface DeviceVideoMapper extends BaseMapper<DeviceVideoEntity> {
/**
* 条件查询视频设备列表
* @param status 是否在线
* @param keyword 设备名称或者编码
* @return {@link List< DeviceVideoListResp>}
*/
List<DeviceVideoListResp> selectDeviceVideoList(@Param("status") String status, @Param("keyword") String keyword, @Param("hostAddress") String hostAddress);
}

View File

@ -1,13 +0,0 @@
package com.dite.znpt.monitor.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.monitor.domain.entity.IpConfigEntity;
/**
* @Date: 2023/09/05 16:39
* @Description: 监控设备IP配置表数据库访问层
*/
public interface IpConfigMapper extends BaseMapper<IpConfigEntity> {
}

View File

@ -1,12 +0,0 @@
package com.dite.znpt.monitor.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.monitor.domain.vo.video.StreamMediaFormat;
/**
* @Author: huise23
* @Date: 2022/8/11 15:00
* @Description:
*/
public interface StreamMediaFormatMapper extends BaseMapper<StreamMediaFormat> {
}

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More