diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserIdentityTypeEnum.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserIdentityTypeEnum.java new file mode 100644 index 000000000..7d4fc26ac --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserIdentityTypeEnum.java @@ -0,0 +1,31 @@ +package com.bsd.pjcloud.admin.api.constant.user; + +import cn.hutool.core.util.ObjectUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 用户身份 + */ +@AllArgsConstructor +@Getter +public enum UserIdentityTypeEnum { + + DEFAULT("DEFAULT", "默认"), + STUDENT("STUDENT", "学生"), + ; + + private final String type; + + private final String description; + + public static UserIdentityTypeEnum valueOfByType(String type) { + if (ObjectUtil.isEmpty(type)) return null; + return Arrays.stream(values()) + .filter(value -> ObjectUtil.equals(type, value.getType())) + .findFirst() + .orElse(null); + } +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserRelationCategoryEnum.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserRelationCategoryEnum.java new file mode 100644 index 000000000..42f945c15 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserRelationCategoryEnum.java @@ -0,0 +1,37 @@ +package com.bsd.pjcloud.admin.api.constant.user; + +import cn.hutool.core.util.ObjectUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 用户关系类型分类 + */ +@AllArgsConstructor +@Getter +public enum UserRelationCategoryEnum { + + FAMILY("family", "家庭关系"), + BUSINESS("business", "业务关系"), + SOCIAL("social", "社交关系"); + + /** + * 分类编码 + */ + private final String category; + + /** + * 分类名称 + */ + private final String description; + + public static UserRelationCategoryEnum valueOfByCategory(String category) { + if (ObjectUtil.isEmpty(category)) return null; + return Arrays.stream(values()) + .filter(value -> ObjectUtil.equals(category, value.getCategory())) + .findFirst() + .orElse(null); + } +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserRelationTypeEnum.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserRelationTypeEnum.java new file mode 100644 index 000000000..ca9d2afc0 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/constant/user/UserRelationTypeEnum.java @@ -0,0 +1,61 @@ +package com.bsd.pjcloud.admin.api.constant.user; + +import cn.hutool.core.util.ObjectUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 用户关系类型 + */ +@AllArgsConstructor +@Getter +public enum UserRelationTypeEnum { + + // 家庭关系 + CHILD_PARENT("CHILD_PARENT", "亲子关系"), + SPOUSE("SPOUSE", "夫妻关系"), + SIBLING("SIBLING", "兄弟姐妹关系"), + GRANDCHILD_GRANDPARENT("GRANDCHILD_GRANDPARENT", "祖孙关系"), + GUARDIAN_WARD("GUARDIAN_WARD", "监护关系"), + RELATIVE("RELATIVE", "亲属关系"), + + // 社交关系 + FRIEND("FRIEND", "朋友关系"), + CLASSMATE("CLASSMATE", "同学关系"), + COLLEAGUE("COLLEAGUE", "同事关系"), + NEIGHBOR("NEIGHBOR", "邻里关系"), + + // 教育关系 + STUDENT_TEACHER("STUDENT_TEACHER", "师生关系"), + + // 工作关系 + SUBORDINATE_LEADER("SUBORDINATE_LEADER", "上下级关系"), + EMPLOYEE_EMPLOYER("EMPLOYEE_EMPLOYER", "雇佣关系"), + + // 客户关系 + CUSTOMER_MANAGER("CUSTOMER_MANAGER", "客户关系"), + CUSTOMER_SERVICE("CUSTOMER_SERVICE", "客服关系"), + + // 其他业务关系 + REFEREE_REFERRER("REFEREE_REFERRER", "推荐关系"), + CONTACT("CONTACT", "联系人关系"), + OTHER("OTHER", "其他关系"); + + /** + * 关系编码 + */ + private final String relationCode; + + /** + * 关系名称 + */ + private final String relationName; + + + public static UserRelationTypeEnum valueOfByType(String relationCode) { + if (ObjectUtil.isEmpty(relationCode)) return null; + return Arrays.stream(values()).filter(v -> ObjectUtil.equals(relationCode, v.getRelationCode())).findFirst().orElse(null); + } +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/UserDTO.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/UserDTO.java index fb5730555..fdeff9f0c 100644 --- a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/UserDTO.java +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/UserDTO.java @@ -19,6 +19,7 @@ package com.bsd.pjcloud.admin.api.dto; +import com.bsd.pjcloud.admin.api.dto.user.SysUserStudentDto; import com.bsd.pjcloud.admin.api.entity.SysUser; import com.bsd.pjcloud.admin.api.vo.base.BaseIsIncludeTreeInterface; import io.swagger.v3.oas.annotations.media.Schema; @@ -54,6 +55,18 @@ public class UserDTO extends SysUser implements BaseIsIncludeTreeInterface { */ private List post; + /** + * 用户身份类型 + */ + @Schema(description = "用户身份类型集合") + private List identityTypes; + + /** + * 学生身份扩展信息 + */ + @Schema(description = "学生身份扩展信息") + private SysUserStudentDto studentInfo; + /** * 新密码 */ diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserRelationCreateDto.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserRelationCreateDto.java new file mode 100644 index 000000000..4df260b12 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserRelationCreateDto.java @@ -0,0 +1,45 @@ +package com.bsd.pjcloud.admin.api.dto.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 为两个已有用户建立关系 + */ +@Data +@Schema(description = "为两个已有用户建立关系") +public class SysUserRelationCreateDto { + + @NotNull(message = "关系主语用户不能为空") + @Schema(description = "关系主语用户ID") + private Long subjectUserId; + + @NotNull(message = "关系对象用户不能为空") + @Schema(description = "关系对象用户ID") + private Long objectUserId; + + @NotNull(message = "关系类型不能为空") + @Schema(description = "关系类型ID") + private Long relationTypeId; + + @Schema(description = "关系生效时间") + private LocalDateTime effectiveTime; + + @Schema(description = "关系失效时间") + private LocalDateTime expireTime; + + @Size(max = 500, message = "关系备注不能超过500个字符") + @Schema(description = "关系备注") + private String remark; + + @AssertTrue(message = "关系失效时间不能早于生效时间") + @Schema(hidden = true) + public boolean isRelationTimeValid() { + return effectiveTime == null || expireTime == null || !expireTime.isBefore(effectiveTime); + } +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserRelationCreateUserDto.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserRelationCreateUserDto.java new file mode 100644 index 000000000..df9040d22 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserRelationCreateUserDto.java @@ -0,0 +1,115 @@ +package com.bsd.pjcloud.admin.api.dto.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 创建用户并建立用户关系 + */ +@Data +@Schema(description = "创建用户并建立用户关系") +public class SysUserRelationCreateUserDto { + + @Schema(description = "关系主语用户ID;为空时由新建用户作为关系主语") + private Long subjectUserId; + + @Schema(description = "关系对象用户ID;为空时由新建用户作为关系对象") + private Long objectUserId; + + @NotNull(message = "关系类型不能为空") + @Schema(description = "关系类型ID") + private Long relationTypeId; + + @Schema(description = "关系生效时间") + private LocalDateTime effectiveTime; + + @Schema(description = "关系失效时间") + private LocalDateTime expireTime; + + @Size(max = 500, message = "关系备注不能超过500个字符") + @Schema(description = "关系备注") + private String remark; + + @NotBlank(message = "用户名不能为空") + @Size(min = 5, max = 60, message = "用户名长度必须介于5到60个字符之间") + @Pattern(regexp = "^[^\\u4e00-\\u9fa5]+$", message = "用户名不能包含中文") + @Schema(description = "用户名") + private String username; + + @NotBlank(message = "密码不能为空") + @Size(min = 6, max = 20, message = "密码长度必须介于6到20个字符之间") + @Schema(description = "密码") + private String password; + + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") + @Schema(description = "手机号") + private String phone; + + @NotBlank(message = "姓名不能为空") + @Size(max = 64, message = "姓名不能超过64个字符") + @Schema(description = "姓名") + private String name; + + @Size(max = 64, message = "昵称不能超过64个字符") + @Schema(description = "昵称") + private String nickname; + + @Email(message = "邮箱格式不正确") + @Size(max = 128, message = "邮箱不能超过128个字符") + @Schema(description = "邮箱") + private String email; + + @Size(max = 255, message = "头像地址不能超过255个字符") + @Schema(description = "头像") + private String avatar; + + @Schema(description = "所属部门ID") + private Long deptId; + + @Schema(description = "角色ID集合,为空时使用默认角色") + private List role; + + @Schema(description = "岗位ID集合") + private List post; + + @Min(value = 0, message = "性别值不正确") + @Max(value = 2, message = "性别值不正确") + @Schema(description = "性别:0未知,1男,2女") + private Integer gender; + + @Size(max = 32, message = "编制类型不能超过32个字符") + @Schema(description = "编制类型") + private String staffingType; + + @Schema(description = "用户状态:0正常,9锁定") + private String lockFlag; + + @Schema(description = "用户身份类型集合") + private List identityTypes; + + @Schema(description = "学生身份扩展信息") + private SysUserStudentDto studentInfo; + + @AssertTrue(message = "关系主语用户和关系对象用户必须且只能填写一个") + @Schema(hidden = true) + public boolean isRelationEndpointValid() { + return (subjectUserId == null) != (objectUserId == null); + } + + @AssertTrue(message = "关系失效时间不能早于生效时间") + @Schema(hidden = true) + public boolean isRelationTimeValid() { + return effectiveTime == null || expireTime == null || !expireTime.isBefore(effectiveTime); + } +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserStudentDto.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserStudentDto.java new file mode 100644 index 000000000..b73a45c45 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/dto/user/SysUserStudentDto.java @@ -0,0 +1,24 @@ +package com.bsd.pjcloud.admin.api.dto.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 学生身份扩展信息 + */ +@Data +@Schema(description = "学生身份扩展信息") +public class SysUserStudentDto { + + @Schema(description = "学号") + private String studentNo; + + @Schema(description = "学校名称") + private String schoolName; + + @Schema(description = "班级名称") + private String className; + + @Schema(description = "其他非核心扩展信息") + private String extJson; +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserIdentityEntity.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserIdentityEntity.java new file mode 100755 index 000000000..3a42b8b36 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserIdentityEntity.java @@ -0,0 +1,39 @@ +package com.bsd.pjcloud.admin.api.entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 用户身份表 + */ +@Data +@TableName("sys_user_identity") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "用户身份表") +public class SysUserIdentityEntity extends Model { + + /** + * 用户ID + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "用户ID") + private Long userId; + + /** + * 身份类型:STUDENT学生、TEACHER教师等 + */ + @Schema(description = "身份类型:STUDENT学生、TEACHER教师等") + private String identityType; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建时间") + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserRelationEntity.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserRelationEntity.java new file mode 100755 index 000000000..ee86721d8 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserRelationEntity.java @@ -0,0 +1,106 @@ +package com.bsd.pjcloud.admin.api.entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.bsd.pjcloud.common.core.util.TenantTable; + +import java.time.LocalDateTime; + +/** + * 用户多对多关系表 + */ +@Data +@TenantTable +@TableName("sys_user_relation") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "用户多对多关系表") +public class SysUserRelationEntity extends Model { + + /** + * 关系ID + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "关系ID") + private Long relationId; + + /** + * 主语用户ID + */ + @Schema(description = "主语用户ID") + private Long subjectUserId; + + /** + * 对象用户ID + */ + @Schema(description = "对象用户ID") + private Long objectUserId; + + /** + * 关系类型ID + */ + @Schema(description = "关系类型ID") + private Long relationTypeId; + + /** + * 关系生效时间 + */ + @Schema(description = "关系生效时间") + private LocalDateTime effectiveTime; + + /** + * 关系失效时间 + */ + @Schema(description = "关系失效时间") + private LocalDateTime expireTime; + + /** + * 备注 + */ + @Schema(description = "备注") + private String remark; + + /** + * 创建人 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建时间") + private LocalDateTime createTime; + + /** + * 修改人 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改人") + private String updateBy; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改时间") + private LocalDateTime updateTime; + + /** + * 删除标记,0未删除,1已删除 + */ + @TableLogic + @TableField(fill = FieldFill.INSERT) + @Schema(description = "删除标记,0未删除,1已删除") + private String delFlag; + + /** + * 所属租户ID + */ + @Schema(description = "所属租户ID") + private Long tenantId; +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserRelationTypeEntity.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserRelationTypeEntity.java new file mode 100755 index 000000000..a81037a49 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserRelationTypeEntity.java @@ -0,0 +1,124 @@ +package com.bsd.pjcloud.admin.api.entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.bsd.pjcloud.common.core.util.TenantTable; + +import java.time.LocalDateTime; + +/** + * 用户关系类型表 + */ +@Data +@TenantTable +@TableName("sys_user_relation_type") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "用户关系类型表") +public class SysUserRelationTypeEntity extends Model { + + /** + * 关系类型 + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "关系类型") + private Long relationTypeId; + + /** + * 关系编码 + */ + @Schema(description = "关系编码") + private String relationCode; + + /** + * 关系名称 + */ + @Schema(description = "关系名称") + private String relationName; + + /** + * 主语一方称呼 + */ + @Schema(description = "主语一方称呼") + private String subjectRoleName; + + /** + * 对象一方称呼 + */ + @Schema(description = "对象一方称呼") + private String objectRoleName; + + /** + * 分类:family、business、social + */ + @Schema(description = "分类:family、business、social") + private String category; + + /** + * 是否有方向:0否,1是 + */ + @Schema(description = "是否有方向:0否,1是") + private String directedFlag; + + /** + * 排序 + */ + @Schema(description = "排序") + private Integer sortOrder; + + /** + * 状态:0正常,1停用 + */ + @Schema(description = "状态:0正常,1停用") + private String status; + + /** + * 备注 + */ + @Schema(description = "备注") + private String remark; + + /** + * 创建人 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建时间") + private LocalDateTime createTime; + + /** + * 修改人 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改人") + private String updateBy; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改时间") + private LocalDateTime updateTime; + + /** + * 删除标记 + */ + @TableLogic + @TableField(fill = FieldFill.INSERT) + @Schema(description = "删除标记") + private String delFlag; + + /** + * 所属租户ID + */ + @Schema(description = "所属租户ID") + private Long tenantId; +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserStudentEntity.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserStudentEntity.java new file mode 100755 index 000000000..43c14c77b --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/user/SysUserStudentEntity.java @@ -0,0 +1,72 @@ +package com.bsd.pjcloud.admin.api.entity.user; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.bsd.pjcloud.common.core.util.TenantTable; + +import java.time.LocalDateTime; + +/** + * 学生用户扩展信息表 + */ +@Data +@TenantTable +@TableName("sys_user_student") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "学生用户扩展信息表") +public class SysUserStudentEntity extends Model { + + /** + * 用户ID + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "用户ID") + private Long userId; + + /** + * 学号 + */ + @Schema(description = "学号") + private String studentNo; + + /** + * 学校名称 + */ + @Schema(description = "学校名称") + private String schoolName; + + /** + * 班级名称 + */ + @Schema(description = "班级名称") + private String className; + + /** + * 其他非核心扩展信息 + */ + @Schema(description = "其他非核心扩展信息") + private String extJson; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建时间") + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description = "修改时间") + private LocalDateTime updateTime; + + /** + * 所属租户ID + */ + @Schema(description = "所属租户ID") + private Long tenantId; +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/UserVO.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/UserVO.java index b0e5fd8b1..e7bb7254b 100644 --- a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/UserVO.java +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/UserVO.java @@ -19,6 +19,7 @@ package com.bsd.pjcloud.admin.api.vo; +import com.bsd.pjcloud.admin.api.dto.user.SysUserStudentDto; import com.bsd.pjcloud.admin.api.vo.base.BaseFacesInterface; import com.fasterxml.jackson.annotation.JsonIgnore; import com.bsd.pjcloud.admin.api.entity.SysPost; @@ -211,6 +212,18 @@ public class UserVO implements BaseFacesInterface, Serializable { */ private List postList; + /** + * 用户身份类型 + */ + @Schema(description = "用户身份类型集合") + private List identityTypes; + + /** + * 学生身份扩展信息 + */ + @Schema(description = "学生身份扩展信息") + private SysUserStudentDto studentInfo; + /** * 昵称 */ diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/user/SysUserRelationGraphVo.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/user/SysUserRelationGraphVo.java new file mode 100644 index 000000000..c536d15e0 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/user/SysUserRelationGraphVo.java @@ -0,0 +1,106 @@ +package com.bsd.pjcloud.admin.api.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +/** + * 用户关系图谱 + */ +@Data +@Schema(description = "用户关系图谱") +public class SysUserRelationGraphVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "图谱节点ID,根节点为0,其他节点使用关系ID") + private Long nodeId; + + @Schema(description = "父节点ID") + private Long parentNodeId; + + @Schema(description = "是否根节点") + private Boolean root; + + @Schema(description = "是否为已出现用户的重复引用节点,重复节点不再继续展开") + private Boolean repeated; + + @Schema(description = "用户ID") + private Long userId; + + @Schema(description = "用户名") + private String username; + + @Schema(description = "姓名") + private String name; + + @Schema(description = "昵称") + private String nickname; + + @Schema(description = "图谱展示名称") + private String displayName; + + @Schema(description = "头像") + private String avatar; + + @Schema(description = "性别:0未知,1男,2女") + private Integer gender; + + @Schema(description = "图谱中的用户数量,仅根节点返回,重复用户不重复计数") + private Integer userCount; + + @Schema(description = "图谱中的关系数量,仅根节点返回") + private Integer relationCount; + + @Schema(description = "关系ID,根节点为空") + private Long relationId; + + @Schema(description = "关系主语用户ID") + private Long subjectUserId; + + @Schema(description = "关系对象用户ID") + private Long objectUserId; + + @Schema(description = "关系类型ID") + private Long relationTypeId; + + @Schema(description = "关系编码") + private String relationCode; + + @Schema(description = "关系名称") + private String relationName; + + @Schema(description = "关系分类") + private String category; + + @Schema(description = "是否有方向:0否,1是") + private String directedFlag; + + @Schema(description = "当前树边方向:subject-to-object或object-to-subject") + private String relationDirection; + + @Schema(description = "当前用户相对于父节点用户的角色,例如老师、监护人、学生") + private String userRoleName; + + @Schema(description = "父节点用户相对于当前用户的角色") + private String parentRoleName; + + @Schema(description = "完整关系描述,例如张老师是李同学的老师") + private String relationDescription; + + @Schema(description = "关系生效时间") + private LocalDateTime effectiveTime; + + @Schema(description = "关系失效时间") + private LocalDateTime expireTime; + + @Schema(description = "关系备注") + private String remark; + + @Schema(description = "下级关系节点") + private List children = new ArrayList<>(); +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/user/SysUserRelationController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/user/SysUserRelationController.java new file mode 100755 index 000000000..03a540719 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/user/SysUserRelationController.java @@ -0,0 +1,67 @@ +package com.bsd.pjcloud.admin.controller.user; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.admin.api.dto.user.SysUserRelationCreateUserDto; +import com.bsd.pjcloud.admin.api.dto.user.SysUserRelationCreateDto; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationEntity; +import com.bsd.pjcloud.admin.api.vo.user.SysUserRelationGraphVo; +import com.bsd.pjcloud.admin.service.SysUserRelationService; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.http.HttpHeaders; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + * 用户多对多关系表 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/sysUserRelation") +@Tag(description = "sysUserRelation", name = "用户多对多关系表管理") +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class SysUserRelationController { + + private final SysUserRelationService sysUserRelationService; + + /** + * 查询用户关系图谱 + */ + @Operation(summary = "关系图谱", description = "以指定用户为根节点查询用户关系树") + @GetMapping("/graph/{userId}") + // @PreAuthorize("@pms.hasPermission('dzc_sysUserRelation_view')") + public R getRelationGraph(@PathVariable Long userId) { + return R.ok(sysUserRelationService.getRelationGraph(userId)); + } + + /** + * 创建用户并建立关系,新用户可作为关系主语或关系对象 + */ + @Operation(summary = "创建用户并建立关系", description = "创建用户且直接审核通过,再建立用户关系") + @SysLog("创建用户并建立关系") + @PostMapping("/create-user") + // @PreAuthorize("@pms.hasPermission('dzc_sysUserRelation_add')") + public R createUserAndRelation(@Valid @RequestBody SysUserRelationCreateUserDto dto) { + return R.ok(sysUserRelationService.createUserAndRelation(dto)); + } + + /** + * 为两个已有用户建立关系 + */ + @Operation(summary = "建立用户关系", description = "为两个已经存在的用户建立关系") + @SysLog("建立用户关系") + @PostMapping("/create") + // @PreAuthorize("@pms.hasPermission('dzc_sysUserRelation_add')") + public R createRelation(@Valid @RequestBody SysUserRelationCreateDto dto) { + return R.ok(sysUserRelationService.createRelation(dto)); + } + +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/user/SysUserRelationTypeController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/user/SysUserRelationTypeController.java new file mode 100755 index 000000000..8d1b9d951 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/user/SysUserRelationTypeController.java @@ -0,0 +1,87 @@ +package com.bsd.pjcloud.admin.controller.user; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationTypeEntity; +import com.bsd.pjcloud.admin.service.SysUserRelationTypeService; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.http.HttpHeaders; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + + +/** + * 用户关系类型表 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/sysUserRelationType") +@Tag(description = "sysUserRelationType", name = "用户关系类型表管理") +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class SysUserRelationTypeController { + + private final SysUserRelationTypeService sysUserRelationTypeService; + + /** + * 分页查询 + */ + @Operation(summary = "分页查询", description = "分页查询") + @GetMapping("/page") + @PreAuthorize("@pms.hasPermission('dzc_sysUserRelationType_view')") + public R getSysUserRelationTypePage(@ParameterObject Page page, @ParameterObject SysUserRelationTypeEntity sysUserRelationType) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + return R.ok(sysUserRelationTypeService.page(page, wrapper)); + } + + /** + * 通过id查询用户关系类型表 + */ + @Operation(summary = "通过id查询", description = "通过id查询") + @GetMapping("/{relationTypeId}") + @PreAuthorize("@pms.hasPermission('dzc_sysUserRelationType_view')") + public R getById(@PathVariable("relationTypeId") Long relationTypeId) { + return R.ok(sysUserRelationTypeService.getById(relationTypeId)); + } + + /** + * 新增用户关系类型表 + */ + @Operation(summary = "新增用户关系类型表", description = "新增用户关系类型表") + @SysLog("新增用户关系类型表") + @PostMapping + @PreAuthorize("@pms.hasPermission('dzc_sysUserRelationType_add')") + public R save(@RequestBody SysUserRelationTypeEntity dto) { + return R.ok(sysUserRelationTypeService.create(dto)); + } + + /** + * 修改用户关系类型表 + */ + @Operation(summary = "修改用户关系类型表", description = "修改用户关系类型表") + @SysLog("修改用户关系类型表") + @PutMapping + @PreAuthorize("@pms.hasPermission('dzc_sysUserRelationType_edit')") + public R updateById(@RequestBody SysUserRelationTypeEntity dto) { + return R.ok(sysUserRelationTypeService.edit(dto)); + } + + /** + * 通过id删除用户关系类型表 + */ + @Operation(summary = "通过id删除用户关系类型表", description = "通过id删除用户关系类型表") + @SysLog("通过id删除用户关系类型表") + @DeleteMapping + @PreAuthorize("@pms.hasPermission('dzc_sysUserRelationType_del')") + public R removeById(@RequestBody Long[] ids) { + sysUserRelationTypeService.delById(CollUtil.toList(ids)); + return R.ok(); + } +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserIdentityMapper.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserIdentityMapper.java new file mode 100755 index 000000000..b5f6098b9 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserIdentityMapper.java @@ -0,0 +1,10 @@ +package com.bsd.pjcloud.admin.mapper.user; + +import com.bsd.pjcloud.admin.api.entity.user.SysUserIdentityEntity; +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysUserIdentityMapper extends PjcloudBaseMapper { + +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserRelationMapper.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserRelationMapper.java new file mode 100755 index 000000000..6260e5617 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserRelationMapper.java @@ -0,0 +1,10 @@ +package com.bsd.pjcloud.admin.mapper.user; + +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationEntity; +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysUserRelationMapper extends PjcloudBaseMapper { + +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserRelationTypeMapper.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserRelationTypeMapper.java new file mode 100755 index 000000000..6c17a8f48 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserRelationTypeMapper.java @@ -0,0 +1,10 @@ +package com.bsd.pjcloud.admin.mapper.user; + +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationTypeEntity; +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysUserRelationTypeMapper extends PjcloudBaseMapper { + +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserStudentMapper.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserStudentMapper.java new file mode 100755 index 000000000..2407cfa0c --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/user/SysUserStudentMapper.java @@ -0,0 +1,10 @@ +package com.bsd.pjcloud.admin.mapper.user; + +import com.bsd.pjcloud.admin.api.entity.user.SysUserStudentEntity; +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysUserStudentMapper extends PjcloudBaseMapper { + +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserIdentityService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserIdentityService.java new file mode 100755 index 000000000..a44f311fd --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserIdentityService.java @@ -0,0 +1,24 @@ +package com.bsd.pjcloud.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.admin.api.dto.UserDTO; +import com.bsd.pjcloud.admin.api.entity.user.SysUserIdentityEntity; +import com.bsd.pjcloud.admin.api.vo.UserVO; + +public interface SysUserIdentityService extends IService { + + /** + * 校验并规范化用户身份请求参数 + */ + void validateDto(UserDTO userDto); + + /** + * 保存用户身份及对应扩展信息 + */ + void saveUserIdentity(Long userId, UserDTO userDto); + + /** + * 填充用户身份及对应扩展信息 + */ + void fillUserIdentity(UserVO userVo); +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserRelationService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserRelationService.java new file mode 100755 index 000000000..255917f5c --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserRelationService.java @@ -0,0 +1,34 @@ +package com.bsd.pjcloud.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.admin.api.dto.user.SysUserRelationCreateUserDto; +import com.bsd.pjcloud.admin.api.dto.user.SysUserRelationCreateDto; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationEntity; +import com.bsd.pjcloud.admin.api.vo.user.SysUserRelationGraphVo; + +public interface SysUserRelationService extends IService { + + /** + * 查询用户关系图谱 + * + * @param userId 根用户ID + * @return 用户关系图谱 + */ + SysUserRelationGraphVo getRelationGraph(Long userId); + + /** + * 创建用户并建立关系,新用户作为关系主语 + * + * @param dto 用户及关系信息 + * @return 新用户ID + */ + Long createUserAndRelation(SysUserRelationCreateUserDto dto); + + /** + * 为两个已有用户建立关系 + * + * @param dto 关系信息 + * @return 关系ID + */ + Long createRelation(SysUserRelationCreateDto dto); +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserRelationTypeService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserRelationTypeService.java new file mode 100755 index 000000000..de6445a3d --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserRelationTypeService.java @@ -0,0 +1,24 @@ +package com.bsd.pjcloud.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationTypeEntity; + +import java.util.ArrayList; + +public interface SysUserRelationTypeService extends IService { + + /** + * 新增用户关系类型表 + */ + Long create(SysUserRelationTypeEntity dto); + + /** + * 修改用户关系类型表 + */ + Long edit(SysUserRelationTypeEntity dto); + + /** + * 通过id删除用户关系类型表 + */ + void delById(ArrayList ids); +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java index 0f2f66436..cbab997a8 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java @@ -111,6 +111,14 @@ public interface SysUserService extends IService { */ Long saveUser(UserDTO userDto); + /** + * 保存用户信息并直接审核通过 + * + * @param userDto DTO 对象 + * @return 用户ID + */ + Long saveUserWithoutAudit(UserDTO userDto); + /** * 查询全部的用户 * diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserStudentService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserStudentService.java new file mode 100755 index 000000000..531c88f66 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserStudentService.java @@ -0,0 +1,12 @@ +package com.bsd.pjcloud.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.admin.api.entity.user.SysUserStudentEntity; + +public interface SysUserStudentService extends IService { + + /** + * 判断学号是否已被其他用户使用 + */ + boolean existsStudentNo(Long userId, String studentNo); +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java index b63c72b95..e18aef320 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java @@ -37,6 +37,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bsd.pjcloud.admin.api.constant.UserExpireEnum; import com.bsd.pjcloud.admin.api.constant.UserStaffingTypeEnum; import com.bsd.pjcloud.admin.api.constant.UserStateEnum; +import com.bsd.pjcloud.admin.api.constant.user.UserIdentityTypeEnum; import com.bsd.pjcloud.admin.api.dto.ForgotPasswordDTO; import com.bsd.pjcloud.admin.api.dto.SysUserFaceDto; import com.bsd.pjcloud.admin.api.dto.UserDTO; @@ -123,6 +124,8 @@ public class SysUserServiceImpl extends ServiceImpl impl private final SysUserTagService sysUserTagService; + private final SysUserIdentityService sysUserIdentityService; + @Lazy private final SysUserFaceService sysUserFaceService; private final SysUserFaceMapper sysUserFaceMapper; @@ -165,12 +168,26 @@ public class SysUserServiceImpl extends ServiceImpl impl @Override @Transactional(rollbackFor = Exception.class) public Long saveUser(UserDTO userDto) { + return saveUser(userDto, false); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long saveUserWithoutAudit(UserDTO userDto) { + return saveUser(userDto, true); + } + + private Long saveUser(UserDTO userDto, boolean skipAudit) { + sysUserIdentityService.validateDto(userDto); SysUser sysUser = new SysUser(); BeanUtils.copyProperties(userDto, sysUser); // 判断是否为部门管理员 PjcloudUser applyUser = SecurityUtils.getUser(); boolean isDeptAdmin = false; - if (null != applyUser) { + if (skipAudit) { + sysUser.setProcessStatus(TaskCheckStatusEnum.RESULT.getCode()); + sysUser.setProcessTime(LocalDateTime.now()); + } else if (null != applyUser) { isDeptAdmin = sysRoleService.isDeptAdmin(applyUser.getId()); if (isDeptAdmin) { List defaultRoles = sysRoleService.findRolesByCodes(List.of(CommonRoleConstant.DEFAULT_USER, CommonRoleConstant.AUTO_CREATE_WALLET)); @@ -194,6 +211,7 @@ public class SysUserServiceImpl extends ServiceImpl impl sysUser.setPasswordModifyTime(LocalDateTime.now()); sysUser.setPasswordExpireFlag(UserExpireEnum.EXPIRE.getCode()); baseMapper.insert(sysUser); + sysUserIdentityService.saveUserIdentity(sysUser.getUserId(), userDto); // 保存用户岗位信息 Optional.ofNullable(userDto.getPost()).ifPresent(posts -> { posts.stream().map(postId -> { @@ -221,7 +239,7 @@ public class SysUserServiceImpl extends ServiceImpl impl return userRole; }).forEach(sysUserRoleMapper::insert); - if (isDeptAdmin) { + if (isDeptAdmin && !skipAudit) { getSelf().applyFlow(sysUser); } else { // 创建用户默认钱包、保证线程header @@ -345,7 +363,9 @@ public class SysUserServiceImpl extends ServiceImpl impl */ @Override public UserVO selectUserVoById(Long id) { - return baseMapper.getUserVoById(id); + UserVO userVo = baseMapper.getUserVoById(id); + sysUserIdentityService.fillUserIdentity(userVo); + return userVo; } /** @@ -405,6 +425,7 @@ public class SysUserServiceImpl extends ServiceImpl impl @Audit(name = "用户更新", spel = "@sysUserMapper.selectById(#userDto.userId)") @CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username") public Boolean updateUser(UserDTO userDto) { + sysUserIdentityService.validateDto(userDto); // 更新用户表信息 SysUser sysUser = new SysUser(); BeanUtils.copyProperties(userDto, sysUser); @@ -423,6 +444,14 @@ public class SysUserServiceImpl extends ServiceImpl impl this.updateById(sysUser); + if (userDto.getIdentityTypes() != null + && !userDto.getIdentityTypes().contains(UserIdentityTypeEnum.DEFAULT.getType())) { + baseMapper.update(null, Wrappers.lambdaUpdate() + .eq(SysUser::getUserId, userDto.getUserId()) + .set(SysUser::getPhone, null)); + } + sysUserIdentityService.saveUserIdentity(userDto.getUserId(), userDto); + // 更新用户角色表 if (userDto.getRole() != null) { sysUserRoleMapper.delete(Wrappers.lambdaQuery().eq(SysUserRole::getUserId, userDto.getUserId())); diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserIdentityServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserIdentityServiceImpl.java new file mode 100755 index 000000000..def199f9c --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserIdentityServiceImpl.java @@ -0,0 +1,156 @@ +package com.bsd.pjcloud.admin.service.impl.user; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.admin.api.constant.user.UserIdentityTypeEnum; +import com.bsd.pjcloud.admin.api.dto.UserDTO; +import com.bsd.pjcloud.admin.api.dto.user.SysUserStudentDto; +import com.bsd.pjcloud.admin.api.entity.SysUser; +import com.bsd.pjcloud.admin.api.entity.user.SysUserIdentityEntity; +import com.bsd.pjcloud.admin.api.entity.user.SysUserStudentEntity; +import com.bsd.pjcloud.admin.api.vo.UserVO; +import com.bsd.pjcloud.admin.mapper.SysUserMapper; +import com.bsd.pjcloud.admin.mapper.user.SysUserIdentityMapper; +import com.bsd.pjcloud.admin.service.SysUserIdentityService; +import com.bsd.pjcloud.admin.service.SysUserStudentService; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + * 用户身份表 + */ +@Service +@RequiredArgsConstructor +public class SysUserIdentityServiceImpl extends ServiceImpl implements SysUserIdentityService { + + private static final int STUDENT_NO_MAX_LENGTH = 255; + + private static final String PHONE_PATTERN = "^1[3-9]\\d{9}$"; + + private final SysUserStudentService sysUserStudentService; + + private final SysUserMapper sysUserMapper; + + @Override + public void validateDto(UserDTO userDto) { + if (userDto.getIdentityTypes() == null) { + return; + } + if (CollUtil.isEmpty(userDto.getIdentityTypes())) { + throw new IllegalArgumentException("用户身份不能为空"); + } + + Set identityTypes = new LinkedHashSet<>(); + for (String identityType : userDto.getIdentityTypes()) { + String normalizedType = StrUtil.trim(identityType); + if (UserIdentityTypeEnum.valueOfByType(normalizedType) == null) { + throw new IllegalArgumentException("用户身份类型不正确"); + } + if (!identityTypes.add(normalizedType)) { + throw new IllegalArgumentException("用户身份不能重复"); + } + } + userDto.setIdentityTypes(List.copyOf(identityTypes)); + + if (identityTypes.contains(UserIdentityTypeEnum.DEFAULT.getType())) { + validateDefaultIdentity(userDto); + } else { + userDto.setPhone(null); + } + + if (!identityTypes.contains(UserIdentityTypeEnum.STUDENT.getType())) { + userDto.setStudentInfo(null); + return; + } + validateStudentInfo(userDto); + } + + @Override + public void saveUserIdentity(Long userId, UserDTO userDto) { + if (userDto.getIdentityTypes() == null) { + return; + } + + remove(Wrappers.lambdaQuery() + .eq(SysUserIdentityEntity::getUserId, userId)); + List identities = userDto.getIdentityTypes().stream() + .map(identityType -> { + SysUserIdentityEntity identity = new SysUserIdentityEntity(); + identity.setUserId(userId); + identity.setIdentityType(identityType); + return identity; + }) + .toList(); + saveBatch(identities); + + if (!userDto.getIdentityTypes().contains(UserIdentityTypeEnum.STUDENT.getType())) { + sysUserStudentService.removeById(userId); + return; + } + SysUserStudentEntity student = new SysUserStudentEntity(); + BeanUtils.copyProperties(userDto.getStudentInfo(), student); + student.setUserId(userId); + sysUserStudentService.saveOrUpdate(student); + } + + @Override + public void fillUserIdentity(UserVO userVo) { + if (userVo == null || userVo.getUserId() == null) { + return; + } + List identityTypes = list(Wrappers.lambdaQuery() + .eq(SysUserIdentityEntity::getUserId, userVo.getUserId())) + .stream() + .map(SysUserIdentityEntity::getIdentityType) + .toList(); + userVo.setIdentityTypes(identityTypes); + + if (!identityTypes.contains(UserIdentityTypeEnum.STUDENT.getType())) { + return; + } + SysUserStudentEntity student = sysUserStudentService.getById(userVo.getUserId()); + if (student != null) { + SysUserStudentDto studentInfo = new SysUserStudentDto(); + BeanUtils.copyProperties(student, studentInfo); + userVo.setStudentInfo(studentInfo); + } + } + + private void validateStudentInfo(UserDTO userDto) { + SysUserStudentDto studentInfo = userDto.getStudentInfo(); + if (studentInfo == null || StrUtil.isBlank(studentInfo.getStudentNo())) { + throw new IllegalArgumentException("学号不能为空"); + } + String studentNo = studentInfo.getStudentNo().trim(); + if (studentNo.length() > STUDENT_NO_MAX_LENGTH) { + throw new IllegalArgumentException("学号不能超过255个字符"); + } + if (sysUserStudentService.existsStudentNo(userDto.getUserId(), studentNo)) { + throw new IllegalArgumentException("学号已存在"); + } + studentInfo.setStudentNo(studentNo); + } + + private void validateDefaultIdentity(UserDTO userDto) { + if (StrUtil.isBlank(userDto.getPhone())) { + SysUser currentUser = userDto.getUserId() == null ? null : sysUserMapper.selectById(userDto.getUserId()); + if (currentUser == null || StrUtil.isBlank(currentUser.getPhone())) { + throw new IllegalArgumentException("手机号不能为空"); + } + return; + } + String phone = userDto.getPhone().trim(); + if (!phone.matches(PHONE_PATTERN)) { + throw new IllegalArgumentException("手机号格式不正确"); + } + userDto.setPhone(phone); + } + +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserRelationServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserRelationServiceImpl.java new file mode 100755 index 000000000..bc246aace --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserRelationServiceImpl.java @@ -0,0 +1,386 @@ +package com.bsd.pjcloud.admin.service.impl.user; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.admin.api.dto.UserDTO; +import com.bsd.pjcloud.admin.api.dto.user.SysUserRelationCreateUserDto; +import com.bsd.pjcloud.admin.api.dto.user.SysUserRelationCreateDto; +import com.bsd.pjcloud.admin.api.entity.SysUser; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationEntity; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationTypeEntity; +import com.bsd.pjcloud.admin.api.vo.user.SysUserRelationGraphVo; +import com.bsd.pjcloud.admin.mapper.user.SysUserRelationMapper; +import com.bsd.pjcloud.admin.service.SysUserRelationService; +import com.bsd.pjcloud.admin.service.SysUserRelationTypeService; +import com.bsd.pjcloud.admin.service.SysUserService; +import com.bsd.pjcloud.common.core.constant.CommonConstants; +import com.bsd.pjcloud.common.core.exception.ErrorCodes; +import com.bsd.pjcloud.common.core.util.MsgUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 用户多对多关系表 + */ +@Service +@RequiredArgsConstructor +public class SysUserRelationServiceImpl extends ServiceImpl implements SysUserRelationService { + + private static final Long TREE_ROOT_PARENT_ID = -1L; + + private static final Long TREE_ROOT_NODE_ID = 0L; + + private final SysUserService sysUserService; + + private final SysUserRelationTypeService sysUserRelationTypeService; + + @Override + public SysUserRelationGraphVo getRelationGraph(Long userId) { + SysUser rootUser = sysUserService.getById(userId); + if (rootUser == null) { + throw new RuntimeException("用户不存在"); + } + RelationGraphData graphData = collectRelationGraph(userId); + Map userMap = sysUserService.listByIds(graphData.userIds).stream() + .collect(Collectors.toMap(SysUser::getUserId, Function.identity(), (first, second) -> first)); + Map relationTypeMap = graphData.relationTypeIds.isEmpty() + ? Map.of() + : sysUserRelationTypeService.listByIds(graphData.relationTypeIds).stream() + .collect(Collectors.toMap(SysUserRelationTypeEntity::getRelationTypeId, + Function.identity(), (first, second) -> first)); + + Map nodeMap = graphData.nodes.stream() + .map(node -> buildGraphNode(node, userMap, relationTypeMap)) + .collect(Collectors.toMap(SysUserRelationGraphVo::getNodeId, Function.identity())); + SysUserRelationGraphVo rootNode = nodeMap.get(TREE_ROOT_NODE_ID); + graphData.nodes.stream() + .filter(node -> !Objects.equals(node.nodeId, TREE_ROOT_NODE_ID)) + .forEach(node -> { + SysUserRelationGraphVo parentNode = nodeMap.get(node.parentNodeId); + SysUserRelationGraphVo currentNode = nodeMap.get(node.nodeId); + if (parentNode != null && currentNode != null) { + parentNode.getChildren().add(currentNode); + } + }); + rootNode.setUserCount(graphData.userIds.size()); + rootNode.setRelationCount(graphData.relationIds.size()); + return rootNode; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createUserAndRelation(SysUserRelationCreateUserDto dto) { + validateCreateUserAndRelation(dto); + + UserDTO userDto = new UserDTO(); + BeanUtils.copyProperties(dto, userDto); + Long newUserId = sysUserService.saveUserWithoutAudit(userDto); + Long subjectUserId = dto.getSubjectUserId() == null ? newUserId : dto.getSubjectUserId(); + Long objectUserId = dto.getObjectUserId() == null ? newUserId : dto.getObjectUserId(); + SysUserRelationTypeEntity relationType = validateRelation( + subjectUserId, objectUserId, dto.getRelationTypeId()); + validateRelationNotExists(subjectUserId, objectUserId, relationType); + + SysUserRelationEntity relation = new SysUserRelationEntity(); + relation.setSubjectUserId(subjectUserId); + relation.setObjectUserId(objectUserId); + relation.setRelationTypeId(dto.getRelationTypeId()); + relation.setEffectiveTime(dto.getEffectiveTime()); + relation.setExpireTime(dto.getExpireTime()); + relation.setRemark(dto.getRemark()); + save(relation); + return newUserId; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createRelation(SysUserRelationCreateDto dto) { + SysUserRelationTypeEntity relationType = validateRelation( + dto.getSubjectUserId(), dto.getObjectUserId(), dto.getRelationTypeId()); + validateRelationNotExists(dto.getSubjectUserId(), dto.getObjectUserId(), relationType); + + SysUserRelationEntity relation = new SysUserRelationEntity(); + BeanUtils.copyProperties(dto, relation); + save(relation); + return relation.getRelationId(); + } + + private void validateCreateUserAndRelation(SysUserRelationCreateUserDto dto) { + Long existingUserId = dto.getSubjectUserId() == null ? dto.getObjectUserId() : dto.getSubjectUserId(); + validateExistingUserAndRelationType(existingUserId, dto.getRelationTypeId()); + boolean usernameExists = sysUserService.exists(Wrappers.lambdaQuery() + .eq(SysUser::getUsername, dto.getUsername())); + if (usernameExists) { + throw new RuntimeException(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERNAME_EXISTING, dto.getUsername())); + } + if (StrUtil.isNotBlank(dto.getPhone())) { + boolean phoneExists = sysUserService.exists(Wrappers.lambdaQuery() + .eq(SysUser::getPhone, dto.getPhone())); + if (phoneExists) { + throw new RuntimeException(MsgUtils.getMessage(ErrorCodes.SYS_USER_PHONE_EXISTING, dto.getPhone())); + } + } + } + + private SysUserRelationTypeEntity validateRelation(Long subjectUserId, Long objectUserId, Long relationTypeId) { + if (Objects.equals(subjectUserId, objectUserId)) { + throw new RuntimeException("不能与自己建立用户关系"); + } + if (sysUserService.getById(subjectUserId) == null) { + throw new RuntimeException("关系主语用户不存在"); + } + return validateObjectUserAndRelationType(objectUserId, relationTypeId); + } + + private SysUserRelationTypeEntity validateObjectUserAndRelationType(Long objectUserId, Long relationTypeId) { + SysUserRelationTypeEntity relationType = validateExistingUserAndRelationType(objectUserId, relationTypeId); + return relationType; + } + + private SysUserRelationTypeEntity validateExistingUserAndRelationType(Long userId, Long relationTypeId) { + if (sysUserService.getById(userId) == null) { + throw new RuntimeException("关联用户不存在"); + } + SysUserRelationTypeEntity relationType = sysUserRelationTypeService.getById(relationTypeId); + if (relationType == null || !CommonConstants.STATUS_NORMAL.equals(relationType.getStatus())) { + throw new RuntimeException("关系类型不存在或已停用"); + } + return relationType; + } + + private void validateRelationNotExists(Long subjectUserId, Long objectUserId, + SysUserRelationTypeEntity relationType) { + boolean directed = "1".equals(relationType.getDirectedFlag()); + boolean exists = exists(Wrappers.lambdaQuery() + .eq(SysUserRelationEntity::getRelationTypeId, relationType.getRelationTypeId()) + .and(wrapper -> wrapper + .nested(current -> current.eq(SysUserRelationEntity::getSubjectUserId, subjectUserId) + .eq(SysUserRelationEntity::getObjectUserId, objectUserId)) + .or(!directed, reverse -> reverse + .eq(SysUserRelationEntity::getSubjectUserId, objectUserId) + .eq(SysUserRelationEntity::getObjectUserId, subjectUserId)))); + if (exists) { + throw new RuntimeException("所选用户之间已存在该类型的关系"); + } + } + + private RelationGraphData collectRelationGraph(Long rootUserId) { + RelationGraphData graphData = new RelationGraphData(); + graphData.userIds.add(rootUserId); + graphData.nodes.add(RelationGraphNode.root(rootUserId)); + + Set expandedUserIds = new HashSet<>(); + List currentLevel = List.of(new RelationNodeContext(TREE_ROOT_NODE_ID, rootUserId)); + while (!currentLevel.isEmpty()) { + List expandableNodes = new ArrayList<>(); + Set expandableUserIds = new LinkedHashSet<>(); + for (RelationNodeContext context : currentLevel) { + if (expandedUserIds.add(context.userId)) { + expandableNodes.add(context); + expandableUserIds.add(context.userId); + } + } + if (expandableNodes.isEmpty()) { + break; + } + + Map> relationMap = listRelations(expandableUserIds).stream() + .flatMap(relation -> Stream.of(relation.getSubjectUserId(), relation.getObjectUserId()) + .filter(Objects::nonNull) + .map(relationUserId -> Map.entry(relationUserId, relation))) + .collect(Collectors.groupingBy(Map.Entry::getKey, + Collectors.mapping(Map.Entry::getValue, Collectors.toList()))); + + List nextLevel = new ArrayList<>(); + for (RelationNodeContext context : expandableNodes) { + for (SysUserRelationEntity relation : relationMap.getOrDefault(context.userId, List.of())) { + boolean parentIsSubject = Objects.equals(context.userId, relation.getSubjectUserId()); + Long childUserId = parentIsSubject ? relation.getObjectUserId() : relation.getSubjectUserId(); + if (childUserId == null || Objects.equals(childUserId, context.userId)) { + continue; + } + if (!graphData.relationIds.add(relation.getRelationId())) { + continue; + } + + boolean repeated = !graphData.userIds.add(childUserId); + if (relation.getRelationTypeId() != null) { + graphData.relationTypeIds.add(relation.getRelationTypeId()); + } + graphData.nodes.add(RelationGraphNode.child( + relation.getRelationId(), context.nodeId, context.userId, childUserId, + relation, parentIsSubject, repeated)); + nextLevel.add(new RelationNodeContext(relation.getRelationId(), childUserId)); + } + } + currentLevel = nextLevel; + } + return graphData; + } + + private List listRelations(Set userIds) { + return list(Wrappers.lambdaQuery() + .and(wrapper -> wrapper.in(SysUserRelationEntity::getSubjectUserId, userIds) + .or() + .in(SysUserRelationEntity::getObjectUserId, userIds))); + } + + private SysUserRelationGraphVo buildGraphNode(RelationGraphNode node, Map userMap, + Map relationTypeMap) { + SysUser user = userMap.get(node.userId); + SysUserRelationEntity relation = node.relation; + SysUserRelationTypeEntity relationType = relation == null + ? null : relationTypeMap.get(relation.getRelationTypeId()); + + SysUserRelationGraphVo graphNode = new SysUserRelationGraphVo(); + graphNode.setNodeId(node.nodeId); + graphNode.setParentNodeId(node.parentNodeId); + graphNode.setRoot(relation == null); + graphNode.setRepeated(node.repeated); + graphNode.setUserId(node.userId); + graphNode.setUsername(user == null ? null : user.getUsername()); + graphNode.setName(user == null ? null : user.getName()); + graphNode.setNickname(user == null ? null : user.getNickname()); + graphNode.setDisplayName(getUserDisplayName(user, node.userId)); + graphNode.setAvatar(user == null ? null : user.getAvatar()); + graphNode.setGender(user == null ? null : user.getGender()); + if (relation != null) { + String userRoleName = getUserRoleName(relationType, node.parentIsSubject); + graphNode.setRelationId(relation.getRelationId()); + graphNode.setSubjectUserId(relation.getSubjectUserId()); + graphNode.setObjectUserId(relation.getObjectUserId()); + graphNode.setRelationTypeId(relation.getRelationTypeId()); + graphNode.setEffectiveTime(relation.getEffectiveTime()); + graphNode.setExpireTime(relation.getExpireTime()); + graphNode.setRemark(relation.getRemark()); + graphNode.setRelationDirection(node.parentIsSubject ? "subject-to-object" : "object-to-subject"); + graphNode.setRelationCode(relationType == null ? null : relationType.getRelationCode()); + graphNode.setRelationName(relationType == null ? null : relationType.getRelationName()); + graphNode.setCategory(relationType == null ? null : relationType.getCategory()); + graphNode.setDirectedFlag(relationType == null ? null : relationType.getDirectedFlag()); + graphNode.setUserRoleName(userRoleName); + graphNode.setParentRoleName(getParentRoleName(relationType, node.parentIsSubject)); + graphNode.setRelationDescription(buildRelationDescription( + user, node.userId, userMap.get(node.parentUserId), node.parentUserId, + userRoleName, relationType)); + } + return graphNode; + } + + private String getUserDisplayName(SysUser user, Long userId) { + if (user == null) { + return String.valueOf(userId); + } + if (StrUtil.isNotBlank(user.getName())) { + return user.getName(); + } + if (StrUtil.isNotBlank(user.getNickname())) { + return user.getNickname(); + } + return StrUtil.blankToDefault(user.getUsername(), String.valueOf(userId)); + } + + private String getUserRoleName(SysUserRelationTypeEntity relationType, boolean parentIsSubject) { + if (relationType == null) { + return null; + } + return parentIsSubject ? relationType.getObjectRoleName() : relationType.getSubjectRoleName(); + } + + private String getParentRoleName(SysUserRelationTypeEntity relationType, boolean parentIsSubject) { + if (relationType == null) { + return null; + } + return parentIsSubject ? relationType.getSubjectRoleName() : relationType.getObjectRoleName(); + } + + private String buildRelationDescription(SysUser user, Long userId, SysUser parentUser, Long parentUserId, + String userRoleName, SysUserRelationTypeEntity relationType) { + String userName = getUserDisplayName(user, userId); + String parentUserName = getUserDisplayName(parentUser, parentUserId); + if (StrUtil.isNotBlank(userRoleName)) { + return userName + "是" + parentUserName + "的" + userRoleName; + } + if (relationType != null && StrUtil.isNotBlank(relationType.getRelationName())) { + return userName + "与" + parentUserName + "的关系是" + relationType.getRelationName(); + } + return userName + "与" + parentUserName + "存在用户关系"; + } + + private static class RelationGraphData { + + private final List nodes = new ArrayList<>(); + + private final Set userIds = new LinkedHashSet<>(); + + private final Set relationIds = new HashSet<>(); + + private final Set relationTypeIds = new HashSet<>(); + } + + private static class RelationGraphNode { + + private final Long nodeId; + + private final Long parentNodeId; + + private final Long parentUserId; + + private final Long userId; + + private final SysUserRelationEntity relation; + + private final boolean parentIsSubject; + + private final boolean repeated; + + private RelationGraphNode(Long nodeId, Long parentNodeId, Long parentUserId, Long userId, + SysUserRelationEntity relation, boolean parentIsSubject, boolean repeated) { + this.nodeId = nodeId; + this.parentNodeId = parentNodeId; + this.parentUserId = parentUserId; + this.userId = userId; + this.relation = relation; + this.parentIsSubject = parentIsSubject; + this.repeated = repeated; + } + + private static RelationGraphNode root(Long userId) { + return new RelationGraphNode(TREE_ROOT_NODE_ID, TREE_ROOT_PARENT_ID, null, + userId, null, false, false); + } + + private static RelationGraphNode child(Long nodeId, Long parentNodeId, Long parentUserId, Long userId, + SysUserRelationEntity relation, boolean parentIsSubject, + boolean repeated) { + return new RelationGraphNode(nodeId, parentNodeId, parentUserId, + userId, relation, parentIsSubject, repeated); + } + } + + private static class RelationNodeContext { + + private final Long nodeId; + + private final Long userId; + + private RelationNodeContext(Long nodeId, Long userId) { + this.nodeId = nodeId; + this.userId = userId; + } + } +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserRelationTypeServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserRelationTypeServiceImpl.java new file mode 100755 index 000000000..e039f911e --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserRelationTypeServiceImpl.java @@ -0,0 +1,86 @@ +package com.bsd.pjcloud.admin.service.impl.user; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationEntity; +import com.bsd.pjcloud.admin.api.entity.user.SysUserRelationTypeEntity; +import com.bsd.pjcloud.admin.mapper.user.SysUserRelationMapper; +import com.bsd.pjcloud.admin.mapper.user.SysUserRelationTypeMapper; +import com.bsd.pjcloud.admin.service.SysUserRelationTypeService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; + +/** + * 用户关系类型表 + */ +@Service +@RequiredArgsConstructor +public class SysUserRelationTypeServiceImpl extends ServiceImpl implements SysUserRelationTypeService { + + private final SysUserRelationMapper sysUserRelationMapper; + + /** + * 新增用户关系类型表 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Long create(SysUserRelationTypeEntity dto) { + validateUnique(dto, null); + baseMapper.insert(dto); + return dto.getRelationTypeId(); + } + + /** + * 修改用户关系类型表 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Long edit(SysUserRelationTypeEntity dto) { + if (dto.getRelationTypeId() == null) { + throw new IllegalArgumentException("关系类型ID不能为空"); + } + if (getById(dto.getRelationTypeId()) == null) { + throw new IllegalArgumentException("用户关系类型不存在"); + } + validateUnique(dto, dto.getRelationTypeId()); + baseMapper.updateById(dto); + return dto.getRelationTypeId(); + } + + /** + * 通过id删除用户关系类型表 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void delById(ArrayList ids) { + if (ids == null || ids.isEmpty()) { + return; + } + Long relationCount = sysUserRelationMapper.selectCount(Wrappers.lambdaQuery() + .in(SysUserRelationEntity::getRelationTypeId, ids)); + if (relationCount != null && relationCount > 0) { + throw new IllegalStateException("所选关系类型已被用户关系引用,无法删除"); + } + removeBatchByIds(ids); + } + + private void validateUnique(SysUserRelationTypeEntity dto, Long excludeId) { + if (dto.getRelationTypeId() != null) { + Long relationTypeIdCount = baseMapper.selectCount(Wrappers.lambdaQuery() + .eq(SysUserRelationTypeEntity::getRelationTypeId, dto.getRelationTypeId()) + .ne(excludeId != null, SysUserRelationTypeEntity::getRelationTypeId, excludeId)); + if (relationTypeIdCount != null && relationTypeIdCount > 0) { + throw new IllegalArgumentException("关系类型ID不能重复"); + } + } + Long categoryCount = baseMapper.selectCount(Wrappers.lambdaQuery() + .eq(SysUserRelationTypeEntity::getCategory, dto.getCategory()) + .ne(excludeId != null, SysUserRelationTypeEntity::getRelationTypeId, excludeId)); + if (categoryCount != null && categoryCount > 0) { + throw new IllegalArgumentException("关系分类不能重复"); + } + } +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserStudentServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserStudentServiceImpl.java new file mode 100755 index 000000000..10d8a4a73 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/user/SysUserStudentServiceImpl.java @@ -0,0 +1,26 @@ +package com.bsd.pjcloud.admin.service.impl.user; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.admin.api.entity.user.SysUserStudentEntity; +import com.bsd.pjcloud.admin.mapper.user.SysUserStudentMapper; +import com.bsd.pjcloud.admin.service.SysUserStudentService; +import org.springframework.stereotype.Service; + +/** + * 学生用户扩展信息表 + */ +@Service +public class SysUserStudentServiceImpl extends ServiceImpl implements SysUserStudentService { + + @Override + public boolean existsStudentNo(Long userId, String studentNo) { + if (StrUtil.isBlank(studentNo)) { + return false; + } + return exists(Wrappers.lambdaQuery() + .eq(SysUserStudentEntity::getStudentNo, studentNo.trim()) + .ne(userId != null, SysUserStudentEntity::getUserId, userId)); + } +} diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserIdentityMapper.xml b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserIdentityMapper.xml new file mode 100755 index 000000000..736b84ddc --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserIdentityMapper.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserRelationMapper.xml b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserRelationMapper.xml new file mode 100755 index 000000000..3eb2e58cd --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserRelationMapper.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserRelationTypeMapper.xml b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserRelationTypeMapper.xml new file mode 100755 index 000000000..d9b46ecf5 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserRelationTypeMapper.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserStudentMapper.xml b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserStudentMapper.xml new file mode 100755 index 000000000..24ea97f88 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/user/SysUserStudentMapper.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file