init: UserBaseService (backend + deploy + scripts)
ci-userbase-service / build-and-push (push) Successful in 40s

This commit is contained in:
chenxing
2026-08-10 14:50:22 +08:00
commit 4ec19486e0
234 changed files with 15604 additions and 0 deletions
@@ -0,0 +1,34 @@
package com.yunhai.userbase.model;
/**
* @program: QualityEvaluate
* @description: 系统字典类
* @author: chenx
* @create: 2023-05-15 17:17
**/
public class BaseDict {
public Integer k;
public String v;
public int getK() {
return this.k;
}
public void setK(int k) {
this.k = k;
}
public String getV() {
return this.v;
}
public void setV(String v) {
this.v = v;
}
public BaseDict(Integer k, String v) {
this.k = k;
this.v = v;
}
}
@@ -0,0 +1,16 @@
package com.yunhai.userbase.model;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/21 21:41
* @description
*/
@Data
public class BasePageQuery {
private int pageIndex = 1;
private int pageSize = 10;
/** 通用模糊搜索关键词 */
private String keyword;
}
@@ -0,0 +1,39 @@
package com.yunhai.userbase.model;
import lombok.Data;
import java.util.List;
/**
* 统一分页响应外壳。<br>
* 由 Controller 层负责装配(见 {@link com.yunhai.userbase.utils.PageUtils#toResult}),
* Service 层仍返回 Spring Data 的 {@link org.springframework.data.domain.Page},保持与传输协议解耦。<br>
*
* @author chenx
* @date 2026/7/21 21:40
* @description 统一分页响应外壳
*/
@Data
public class BasePageResult<T> {
/** 总记录数 */
private int total;
/** 当前页数据 */
private List<T> content;
/** 当前页码(从 1 起,与 {@link BasePageQuery#getPageIndex()} 约定一致) */
private int pageIndex;
/** 每页条数 */
private int pageSize;
/** 总页数 */
private int totalPages;
/** 是否还有下一页 */
private boolean hasNext;
public BasePageResult(List<T> content, int total, int pageIndex, int pageSize, int totalPages, boolean hasNext) {
this.content = content;
this.total = total;
this.pageIndex = pageIndex;
this.pageSize = pageSize;
this.totalPages = totalPages;
this.hasNext = hasNext;
}
}
@@ -0,0 +1,19 @@
package com.yunhai.userbase.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class BaseTree {
public Integer id;
public String name;
public Integer pid ;
public Integer type;
public List<BaseTree> children;
}
@@ -0,0 +1,33 @@
package com.yunhai.userbase.model.Excel;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chenx
* @date 2026/1/19 19:45
* @description 教材导入
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExcelKnowledge {
@Excel(name = "第一层", width = 20)
private String first;
@Excel(name = "第二层", width = 20)
private String second;
@Excel(name = "第三层", width =20)
private String third;
@Excel(name = "第四层", width = 20)
private String fourth;
@Excel(name = "第五层", width = 20)
private String five;
}
@@ -0,0 +1,28 @@
package com.yunhai.userbase.model.Excel;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
/**
* @program: ResearchLearn
* @description: 导入研学活动填报实体类
* @author: chenx
* @create: 2023-07-21 14:12
**/
@Data
public class ExcelResearchFill {
@Excel(name = "年级")
private String gradeName;
@Excel(name = "班级")
private String className;
@Excel(name = "姓名")
private String stuName;
@Excel(name = "研学/活动名称")
private String researchName;
}
@@ -0,0 +1,29 @@
package com.yunhai.userbase.model;
import com.bestsch.openapi.UserSysRole;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
*功能描述 :操作人信息
* @author chenx
* @date 2026/1/5 13:31
* @description
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Operator {
private Integer userId;
private Integer schoolSid;
private Integer roleId;
private Date createTime=new Date();
public static Operator of(UserSysRole curRole){
return new Operator(curRole.getUserId(),curRole.getSchId(),curRole.getRoleId(),new Date());
}
}
@@ -0,0 +1,72 @@
package com.yunhai.userbase.model;
import org.apache.commons.lang3.StringUtils;
public class Page<U> {
private int current;
private int pageSize;
private long count;
public Page() {
}
public int getCurrent() {
return this.current;
}
public void setCurrent(int current) {
this.current = current;
}
public int getPageSize() {
return this.pageSize == 0 ? 10 : this.pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public void setPageSize(String pageSize) {
if (!StringUtils.isEmpty(pageSize) && StringUtils.isNumeric(pageSize)) {
this.pageSize = Integer.valueOf(pageSize);
}
}
public long getCount() {
return this.count;
}
public void setCount(long count) {
this.count = count;
}
public int getPageCount() {
return this.getPageSize() != 0 ? (int)Math.ceil((double)this.count / (double)this.getPageSize()) : 0;
}
public int getStartIndex() {
return (this.getCurrent() - 1) * this.getPageSize();
}
public void setCurrent(String current) {
if (!StringUtils.isEmpty(current) && StringUtils.isNumeric(current)) {
this.current = Integer.valueOf(current);
}
}
public void setCount(String count) {
if (!StringUtils.isEmpty(count) && StringUtils.isNumeric(count)) {
this.count = Long.valueOf(count);
}
}
public int getEndIndex() {
return this.getStartIndex() + this.getPageSize();
}
}
@@ -0,0 +1,16 @@
package com.yunhai.userbase.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StartEndDate {
private Date startDate;
private Date endDate;
}
@@ -0,0 +1,18 @@
package com.yunhai.userbase.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Tree {
private String label;
private String value;
private Integer type = 0;
private List<Tree> children;
}
@@ -0,0 +1,37 @@
package com.yunhai.userbase.model.appauthz;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 应用授权查询的扁平投影行(含 categoryId 供分组)。<br>
* 仅取授权列表所需字段,避免加载 appSecret 等无关大字段。<br>
*
* @author chenx
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AppAuthzAppRow {
/**
* 应用类型ID(分组键)。<br>
*/
private Integer categoryId;
/**
* 应用ID。<br>
*/
private Integer id;
/**
* 应用名称。<br>
*/
private String name;
/**
* 应用图标(pcIcon)。<br>
*/
private String icon;
}
@@ -0,0 +1,48 @@
package com.yunhai.userbase.model.appauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 应用授权视图:应用类型 + 该类型下的应用列表。<br>
*
* @author chenx
*/
@Data
public class AppAuthzCategoryVo {
/**
* 应用类型ID。<br>
*/
private Integer id;
/**
* 应用类型名称。<br>
*/
private String name;
/**
* 该类型下的应用列表。<br>
*/
private List<AppItem> app = new ArrayList<>();
/**
* 授权用的应用精简项(id/name/icon)。<br>
*/
@Data
public static class AppItem {
/**
* 应用ID。<br>
*/
private Integer id;
/**
* 应用名称。<br>
*/
private String name;
}
}
@@ -0,0 +1,13 @@
package com.yunhai.userbase.model.appcategory;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/15 22:35
* @description
*/
@Data
public class AppCategoryQuery {
private String name;
}
@@ -0,0 +1,22 @@
package com.yunhai.userbase.model.appcategory;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.yunhai.userbase.common.validation.ValidationGroups;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/15 22:35
* @description
*/
@Data
public class AppCategoryRequest {
@NotNull(groups = ValidationGroups.Update.class, message = "编辑时ID不能为空")
private Integer id;
@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "类别名称不能为空")
private String name;
private Integer sortNo;
}
@@ -0,0 +1,15 @@
package com.yunhai.userbase.model.appcategory;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/15 22:35
* @description
*/
@Data
public class AppCategoryVo {
private Integer id;
private String name;
private Integer sortNo;
}
@@ -0,0 +1,22 @@
package com.yunhai.userbase.model.application;
import lombok.Data;
/**
* 应用信息查询条件。<br>
* 用于列表查询时封装前端传入的筛选参数。<br>
*
* @author chenx
*/
@Data
public class ApplicationInfoQuery {
/**
* 应用名称,用于模糊匹配。<br>
*/
private String name;
/**
* 应用类别ID,用于精确筛选。<br>
*/
private Integer categoryId;
}
@@ -0,0 +1,76 @@
package com.yunhai.userbase.model.application;
import com.yunhai.userbase.common.validation.ValidationGroups;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 应用信息新增/修改入参。<br>
* 用于接收前端提交的应用数据,并按分组做参数校验。<br>
* 说明:appKey/appSecret 为系统生成字段,不在此入参中暴露。<br>
*
* @author chenx
*/
@Data
public class ApplicationInfoRequest {
/**
* 主键ID,编辑时必填。<br>
*/
@NotNull(groups = ValidationGroups.Update.class, message = "编辑时ID不能为空")
private Integer id;
/**
* 应用名称,新增与编辑均必填。<br>
*/
@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "应用名称不能为空")
private String name;
/**
* 应用类别ID,新增与编辑均必填。<br>
*/
@NotNull(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "应用类别不能为空")
private Integer categoryId;
/**
* 应用描述。<br>
*/
private String desc;
/**
* 应用前端类型列表。<br>
*/
private List<Integer> clients;
/**
* PC应用访问地址。<br>
*/
private String pcUrl;
/**
* PC应用图标地址。<br>
*/
private String pcIcon;
/**
* App访问地址(移动端主地址)。<br>
*/
private String appUrl;
/**
* App应用图标地址。<br>
*/
private String appIcon;
/**
* 公众号应用地址。<br>
*/
private String officialAccountUrl;
/**
* 钉钉应用地址。<br>
*/
private String dingtalkUrl;
}
@@ -0,0 +1,34 @@
package com.yunhai.userbase.model.application;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 应用信息返回视图。<br>
* 用于接口返回给前端的应用数据。<br>
*
* @author chenx
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ApplicationInfoSortVo {
/**
* 主键ID。<br>
*/
private Integer id;
/**
* 应用名称。<br>
*/
private String name;
/**
* 排序号,仅在同一个应用类型内有效;未排序时为 null。<br>
*/
private Integer sortNo;
}
@@ -0,0 +1,84 @@
package com.yunhai.userbase.model.application;
import lombok.Data;
import java.util.List;
/**
* 应用信息返回视图。
* 用于接口返回给前端的应用数据。
*
* @author chenx
*/
@Data
public class ApplicationInfoVo {
/**
* 主键ID。<br>
*/
private Integer id;
/**
* 应用名称。<br>
*/
private String name;
/**
* 应用类别ID。<br>
*/
private Integer categoryId;
/**
* 排序号,仅在同一个应用类型内有效;未排序时为 null。<br>
*/
private Integer sortNo;
/**
* 应用描述。<br>
*/
private String desc;
/**
* 系统生成的唯一标识(appKey),整型,从100000起自增。<br>
*/
private Integer appKey;
/**
* 密钥(appSecret),与数据库 app_secret 字段一致,字符串类型。<br>
*/
private String appSecret;
/**
* 应用前端类型列表。<br>
*/
private List<Integer> clients;
/**
* PC应用访问地址。<br>
*/
private String pcUrl;
/**
* PC应用图标地址。<br>
*/
private String pcIcon;
/**
* App访问地址。<br>
*/
private String appUrl;
/**
* App应用图标地址。<br>
*/
private String appIcon;
/**
* 公众号应用地址。<br>
*/
private String officialAccountUrl;
/**
* 钉钉应用地址。<br>
*/
private String dingtalkUrl;
}
@@ -0,0 +1,18 @@
package com.yunhai.userbase.model.appmodule;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/22
* @description 应用模块查询条件。<br>
*/
@Data
public class AppModuleQuery {
/** 所属应用ID(按应用过滤模块树)。<br> */
private Integer appId;
/** 模块名称(模糊匹配)。<br> */
private String name;
/** 父模块ID(传入则以该模块为根,递归返回其完整子树;不传则顶层只显示 level-1 根模块)。<br> */
private Integer parentId;
}
@@ -0,0 +1,36 @@
package com.yunhai.userbase.model.appmodule;
import com.yunhai.userbase.common.validation.ValidationGroups;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author chenx
* @date 2026/7/22
* @description 应用模块请求体。<br>
*/
@Data
public class AppModuleRequest {
@NotNull(groups = ValidationGroups.Update.class, message = "编辑时ID不能为空")
private Integer id;
/** 所属应用ID(创建时必填,创建后不可改)。<br> */
@NotNull(groups = ValidationGroups.Create.class, message = "所属应用不能为空")
private Integer appId;
/** 父模块ID;根模块传 null。<br> */
private Integer parentId;
@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "模块名称不能为空")
private String name;
@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "自定义ID不能为空")
private String customId;
/** 模块路径(前端路由/资源路径)。<br> */
private String path;
private Integer sortNo;
}
@@ -0,0 +1,25 @@
package com.yunhai.userbase.model.appmodule;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author chenx
* @date 2026/7/22
* @description 应用模块视图(树形,children 递归存放子模块)。<br>
*/
@Data
public class AppModuleVo {
private Integer id;
private Integer appId;
private Integer parentId;
private String name;
private String customId;
private String path;
private Integer level;
private Integer sortNo;
/** 子模块(递归);默认空列表,避免 JSON 序列化出现 null。 */
private List<AppModuleVo> children = new ArrayList<>();
}
@@ -0,0 +1,34 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 角色授权页应用节点视图:应用信息 + 其下模块权限树。<br>
* 普通角色只返回其所属应用;全应用角色返回系统全部应用。<br>
*
* @author chenx
*/
@Data
public class AppRoleAuthzAppVo {
/** 应用ID。 */
private Integer id;
/** 应用名称。 */
private String name;
/** 应用唯一标识 appKey。 */
private Integer appKey;
/** PC 应用图标地址。 */
private String pcIcon;
/** 排序号。 */
private Integer sortNo;
/** 该应用下的模块权限树(含勾选回显)。 */
private List<AppRoleAuthzModuleVo> modules = new ArrayList<>();
}
@@ -0,0 +1,42 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 角色授权页模块节点视图(树形):模块信息 + 该角色勾选状态。<br>
*
* @author chenx
*/
@Data
public class AppRoleAuthzModuleVo {
/** 模块ID。 */
private Integer id;
/** 父模块ID;根模块为 null。 */
private Integer parentId;
/** 模块名称。 */
private String name;
/** 自定义ID(应用内唯一业务编码)。 */
private String customId;
/** 模块路径。 */
private String path;
/** 层级(根=1)。 */
private Integer level;
/** 排序号。 */
private Integer sortNo;
/** 该角色是否已勾选该模块(sys_app_role_module_rel 存在记录即勾选)。 */
private Boolean checked = Boolean.FALSE;
/** 子模块(递归);默认空列表,避免 JSON 序列化出现 null。 */
private List<AppRoleAuthzModuleVo> children = new ArrayList<>();
}
@@ -0,0 +1,27 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 角色模块授权保存入参(全量覆盖)。<br>
* moduleIds 为该角色本次勾选的模块ID全量列表;传空列表即清空该角色全部模块授权。<br>
*
* @author chenx
*/
@Data
public class AppRoleModuleAssignRequest {
/**
* 角色ID。<br>
*/
@NotNull(message = "角色ID不能为空")
private Integer roleId;
/**
* 勾选的模块ID全量列表。<br>
*/
private List<Integer> moduleIds;
}
@@ -0,0 +1,27 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 角色绑定用户保存入参(全量覆盖,角色维度)。<br>
* userIds 为该角色本次绑定的用户ID全量列表;传空列表即解绑该角色全部用户。<br>
*
* @author chenx
*/
@Data
public class AppRoleUserBindRequest {
/**
* 角色ID。<br>
*/
@NotNull(message = "角色ID不能为空")
private Integer roleId;
/**
* 绑定的用户ID全量列表。<br>
*/
private List<Integer> userIds;
}
@@ -0,0 +1,21 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
/**
* 角色已绑定用户列表项视图。<br>
*
* @author chenx
*/
@Data
public class AppRoleUserVo {
/** 用户ID。 */
private Integer id;
/** 账号。 */
private String account;
/** 真实姓名。 */
private String realName;
}
@@ -0,0 +1,24 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
/**
* 业务角色列表查询条件。<br>
*
* @author chenx
*/
@Data
public class SysAppRoleQuery {
/** 角色名称(模糊匹配)。 */
private String name;
/** 所属应用ID(精确匹配,仅命中普通角色)。 */
private Integer appId;
/** 是否全应用角色。 */
private Boolean allAppFlag;
/** 是否禁用。 */
private Boolean disabled;
}
@@ -0,0 +1,50 @@
package com.yunhai.userbase.model.approle;
import com.yunhai.userbase.common.validation.ValidationGroups;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 业务角色新增/修改入参。<br>
* 普通角色:allAppFlag=false 且 appId 必填;全应用角色:allAppFlag=true 且 appId 必须为空(服务层校验)。<br>
*
* @author chenx
*/
@Data
public class SysAppRoleRequest {
/**
* 主键ID,编辑时必填。<br>
*/
@NotNull(groups = ValidationGroups.Update.class, message = "编辑时ID不能为空")
private Integer id;
/**
* 角色名称,新增与编辑均必填。<br>
*/
@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "角色名称不能为空")
private String name;
/**
* 所属应用ID;普通角色必填,全应用角色必须为空(appId 与 allAppFlag 的匹配关系在服务层校验)。<br>
*/
private Integer appId;
/**
* 是否全应用角色,新增与编辑均必填。<br>
*/
@NotNull(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "角色类型不能为空")
private Boolean allAppFlag;
/**
* 角色备注。<br>
*/
private String remark;
/**
* 是否禁用;空值按不禁用处理。<br>
*/
private Boolean disabled;
}
@@ -0,0 +1,33 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
/**
* 业务角色列表项视图。<br>
*
* @author chenx
*/
@Data
public class SysAppRoleVo {
/** 角色ID。 */
private Integer id;
/** 角色名称。 */
private String name;
/** 所属应用ID;全应用角色为 null。 */
private Integer appId;
/** 所属应用名称;全应用角色为 null。 */
private String appName;
/** 是否全应用角色。 */
private Boolean allAppFlag;
/** 角色备注。 */
private String remark;
/** 是否禁用。 */
private Boolean disabled;
}
@@ -0,0 +1,27 @@
package com.yunhai.userbase.model.approle;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 用户绑定角色保存入参(全量覆盖,用户维度)。<br>
* roleIds 为该用户本次绑定的角色ID全量列表;传空列表即解绑该用户全部角色。<br>
*
* @author chenx
*/
@Data
public class UserAppRoleBindRequest {
/**
* 用户ID。<br>
*/
@NotNull(message = "用户ID不能为空")
private Integer userId;
/**
* 绑定的角色ID全量列表。<br>
*/
private List<Integer> roleIds;
}
@@ -0,0 +1,23 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author chenx
* @date 2026/7/23
* @description 应用开通保存请求(功能1,全量覆盖式)。<br>
* 前端传递组ID与勾选的应用ID列表;appIds 为空或空列表代表取消该组全部应用开通。<br>
*/
@Data
public class GroupAppAssignRequest {
/** 组ID。<br> */
@NotNull(message = "组ID不能为空")
private Integer groupId;
/** 勾选的应用ID列表(全量);为空代表全部取消开通。<br> */
private List<Integer> appIds;
}
@@ -0,0 +1,30 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/23
* @description 应用开通视图(功能1):系统全量应用 + 该组是否已开通。<br>
*/
@Data
public class GroupAppVo {
/** 应用ID。<br> */
private Integer id;
/** 应用名称。<br> */
private String name;
/** 应用类别ID。<br> */
private Integer categoryId;
/** 应用唯一标识 appKey。<br> */
private Integer appKey;
/** PC应用图标地址。<br> */
private String pcIcon;
/** 该组是否已开通(用于复选框回显)。<br> */
private Boolean checked = Boolean.FALSE;
}
@@ -0,0 +1,35 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author chenx
* @date 2026/7/23
* @description 组授权应用视图(功能2):该组已开通的应用 + 其下模块权限树。<br>
*/
@Data
public class GroupAuthzAppVo {
/** 应用ID。<br> */
private Integer id;
/** 应用名称。<br> */
private String name;
/** 应用唯一标识 appKey。<br> */
private Integer appKey;
/** PC应用图标地址。<br> */
private String pcIcon;
/** 应用类型ID;用于按应用分类分组展示组授权面板。<br> */
private Integer categoryId;
private Integer sortNo;
/** 该应用下的模块权限树;默认空列表,避免 JSON 序列化出现 null。 */
private List<GroupAuthzModuleVo> modules = new ArrayList<>();
}
@@ -0,0 +1,25 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 组授权分类视图:按应用类型分组后,每个分类下挂载已开通的应用及其模块权限树。<br>
*
* @author chenx
* @date 2026/7/23
*/
@Data
public class GroupAuthzCategoryVo {
/** 应用类型ID。 */
private Integer id;
/** 应用类型名称。 */
private String name;
/** 该分类下已开通的应用列表(含模块权限树)。 */
private List<GroupAuthzAppVo> apps = new ArrayList<>();
}
@@ -0,0 +1,45 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author chenx
* @date 2026/7/23
* @description 组授权模块节点视图(功能2,树形):模块信息 + 该组勾选状态与子组继承开关。<br>
*/
@Data
public class GroupAuthzModuleVo {
/** 模块ID。<br> */
private Integer id;
/** 父模块ID;根模块为 null。<br> */
private Integer parentId;
/** 模块名称。<br> */
private String name;
/** 自定义ID(应用内唯一业务编码)。<br> */
private String customId;
/** 模块路径。<br> */
private String path;
/** 层级(根=1)。<br> */
private Integer level;
/** 排序号。<br> */
private Integer sortNo;
/** 该组是否已勾选该模块(sys_group_module_perm 存在记录即勾选)。<br> */
private Boolean checked = Boolean.FALSE;
/** 是否子组继承(仅 checked=true 时有意义)。<br> */
private Boolean inheritFlag = Boolean.FALSE;
/** 子模块(递归);默认空列表,避免 JSON 序列化出现 null。 */
private List<GroupAuthzModuleVo> children = new ArrayList<>();
}
@@ -0,0 +1,47 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 组模块授权单项(增量式:对某个组的「某应用下的某模块」做追加/删除)。<br>
* 与 GroupModulePermRequest(全量覆盖式 SaveModulePerms)互为补充:本类用于单条/批量增量操作,<br>
* 由前端「组授权」面板逐条勾选或取消时提交。<br>
* <br>
* 字段语义(务必与前端对齐):<br>
* - groupId:目标组ID<br>
* - appId:应用ID(被授权的模块必须属于该应用,越权写别的应用的模块会被拒绝)<br>
* - moduleId:模块ID;传 0 表示「该应用下的全部模块」(前端勾选应用根/整应用时用)<br>
* - mode:操作模式,取值见 SysModeEnum —— 0=追加(APPEND,授予授权) / 2=删除(DELETE,取消授权);1=覆盖 不适用于单条增量,会被拒绝<br>
* - isAll:是否对子组继承,直接映射现有 sys_group_module_perm.inherit_flag 列 —— 1=子孙组自动继承 / 0=仅本组生效<br>
*
* @author chenx
*/
@Data
public class GroupModuleAuthzItem {
/** 目标组ID。 */
@NotNull(message = "组ID不能为空")
private Integer groupId;
/** 应用ID(模块必须属于该应用)。 */
@NotNull(message = "应用ID不能为空")
private Integer appId;
/**
* 模块ID;传 0 表示「该应用下全部模块」。<br>
* 注意:后端不会向 sys_group_module_perm 写入 module_id=0 的伪记录,<br>
* 而是把 0 展开为应用下每个真实模块各写一条权限记录。
*/
@NotNull(message = "模块ID不能为空(整应用传 0)")
private Integer moduleId;
/** 操作模式:0=追加 / 2=删除(1=覆盖不适用)。 */
@NotNull(message = "操作模式不能为空(0=追加/2=删除)")
private Integer mode;
/** 是否对子组继承:1=子孙组继承 / 0=仅本组。映射 inherit_flag。 */
@NotNull(message = "isAll不能为空(0=仅本组/1=子组继承)")
private Integer isAll;
}
@@ -0,0 +1,38 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author chenx
* @date 2026/7/23
* @description 组授权保存请求(功能2,全量覆盖式)。<br>
* perms 为该组当前勾选的模块权限全量列表:有旧记录则更新 inheritFlag,无则新增,<br>
* 不在列表中的旧记录物理删除(即取消勾选)。<br>
*/
@Data
public class GroupModulePermRequest {
/** 组ID。<br> */
@NotNull(message = "组ID不能为空")
private Integer groupId;
/** 勾选的模块权限全量列表;为空代表全部取消勾选。<br> */
@Valid
private List<ModulePermItem> perms;
/** 单个模块权限项。<br> */
@Data
public static class ModulePermItem {
/** 模块ID。<br> */
@NotNull(message = "模块ID不能为空")
private Integer moduleId;
/** 是否子组继承;不传默认 false。<br> */
private Boolean inheritFlag;
}
}
@@ -0,0 +1,38 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 学校组应用授权增量请求(对应前端点击单个应用多选框勾选/取消时提交)。<br>
* 与 {@link GroupAppAssignRequest}(全量覆盖式 AssignApps)互为补充:本类用于「单条」增量开通或取消应用,<br>
* 前端一次只传一个应用ID(逐次点击触发),因此 appid 为单个 Integer,而非集合/逗号串。<br>
* <br>
* 字段语义(务必与前端对齐):<br>
* - schid:目标学校组ID(即左侧树点击的 nodeId)<br>
* - appid:单个应用ID(每次只传一个)<br>
* - mode:操作模式,取值见 SysModeEnum —— 0=追加(APPEND,开通应用) / 2=删除(DELETE,取消开通);1=覆盖 不适用于单条增量,会被拒绝<br>
* <br>
* <b>设计说明</b>:每次请求只携带一个 appid,控制器/服务均不再做多值解析;逐次点击即多次提交。
*
* @author chenx
*/
@Data
public class SchoolAppAuthzRequest {
/** 目标学校组ID(左侧树节点 nodeId)。 */
@NotNull(message = "组ID不能为空")
private Integer schid;
/**
* 单个应用ID。<br>
* 前端逐次点击应用多选框触发,每次只传一个应用ID,故为 Integer 而非集合/字符串。
*/
@NotNull(message = "应用ID不能为空")
private Integer appid;
/** 操作模式:0=追加 / 2=删除(1=覆盖不适用)。 */
@NotNull(message = "操作模式不能为空(0=追加/2=删除)")
private Integer mode;
}
@@ -0,0 +1,29 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 权限一览:用户所属部门树节点(左侧上方「所属部门」区域)。<br>
* 树仅由「用户直接归属的组 + 其全部祖先组」构成(如:云平台-学校中学-语文组),
* 不包含无关的兄弟/子孙节点。<br>
*
* @author chenx
*/
@Data
public class UserGroupNodeVo {
/** 组ID。 */
private Integer id;
/** 组名称。 */
private String name;
/** 是否用户直接归属的组(叶子高亮用);祖先组为 false。 */
private Boolean own;
/** 子节点(仅含祖先链上的节点)。 */
private List<UserGroupNodeVo> children = new ArrayList<>();
}
@@ -0,0 +1,32 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 权限一览:用户已授权应用节点。<br>
* 父节点为 {@link UserPermissionCategoryVo},子节点为 {@link UserPermissionModuleVo}。
*/
@Data
public class UserPermissionAppVo {
/** 应用ID。 */
private Integer id;
/** 应用名称。 */
private String name;
/** 应用唯一标识 appKey。 */
private Integer appKey;
/** PC 应用图标地址。 */
private String pcIcon;
/** 排序号。 */
private Integer sortNo;
/** 该应用下已授权的模块树。 */
private List<UserPermissionModuleVo> modules = new ArrayList<>();
}
@@ -0,0 +1,26 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 权限一览:用户已授权应用分类节点。<br>
* 一级子节点为 {@link UserPermissionAppVo}。
*/
@Data
public class UserPermissionCategoryVo {
/** 分类ID。 */
private Integer id;
/** 分类名称。 */
private String name;
/** 排序号。 */
private Integer sortNo;
/** 该分类下已授权的应用列表。 */
private List<UserPermissionAppVo> apps = new ArrayList<>();
}
@@ -0,0 +1,38 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 权限一览:用户已授权模块节点(递归树)。<br>
* 仅包含有权限的模块,无权限的模块及其子节点均不显示。
*/
@Data
public class UserPermissionModuleVo {
/** 模块ID。 */
private Integer id;
/** 父模块ID;根模块为 null。 */
private Integer parentId;
/** 模块名称。 */
private String name;
/** 自定义ID(应用内唯一业务编码)。 */
private String customId;
/** 模块路径。 */
private String path;
/** 层级(根=1)。 */
private Integer level;
/** 排序号。 */
private Integer sortNo;
/** 子模块(递归)。 */
private List<UserPermissionModuleVo> children = new ArrayList<>();
}
@@ -0,0 +1,25 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
/**
* 权限一览:用户列表项(组下用户或全局搜索用户)。<br>
*/
@Data
public class UserPermissionUserVo {
/** 用户ID。 */
private Integer id;
/** 账号。 */
private String account;
/** 真实姓名。 */
private String realName;
/** 是否主归属:1=本职主学校/部门,0=兼职兼任。 */
private Integer isMain;
/** 用户所属部门/组织路径,如 /上海市仙霞高级中学/教师/行政。 */
private String groupPath;
}
@@ -0,0 +1,30 @@
package com.yunhai.userbase.model.groupauthz;
import lombok.Data;
/**
* 权限一览:用户所属业务角色列表项(中间下方「所属角色」区域)。<br>
*
* @author chenx
*/
@Data
public class UserRoleVo {
/** 角色ID。 */
private Integer id;
/** 角色名称。 */
private String name;
/** 是否全应用角色。 */
private Boolean allAppFlag;
/** 所属应用ID;全应用角色为 null。 */
private Integer appId;
/** 所属应用名称;全应用角色为 null。 */
private String appName;
/** 是否禁用(禁用角色仍展示,但不参与权限计算)。 */
private Boolean disabled;
}
@@ -0,0 +1,77 @@
package com.yunhai.userbase.model.oplog;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 操作日志列表项视图。<br>
* 不含 response_data(响应结果),列表不展示,需通过下载接口单独获取。<br>
*
* @author chenx
* @date 2026/7/28
*/
@Data
public class SysOperationLogListVo {
/** 主键 */
private Long id;
/** 日志级别 1-重要 2-次要 3-一般 */
private Integer logLevel;
/** 操作用户ID */
private Long userId;
/** 操作用户名 */
private String username;
/** 请求IP */
private String requestIp;
/** 请求路径 */
private String requestUri;
/** 请求方法 GET/POST/PUT/DELETE */
private String requestMethod;
/** 操作类型 DELETE/CREATE/UPDATE/QUERY */
private String operationType;
/** 类名.方法名 */
private String classMethod;
/** 请求参数JSON */
private String requestParams;
/** HTTP 状态码 */
private Integer statusCode;
/** 耗时(ms) */
private Long costTime;
/** 浏览器UA */
private String userAgent;
/** 错误信息 */
private String errorMsg;
/** 操作时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
/**
* 全参构造,顺序需与 {@code SysOperationLog} 的列表投影字段一致。<br>
* 用于 JPA Criteria {@code cb.construct} 投影查询。<br>
*/
public SysOperationLogListVo(Long id, Integer logLevel, Long userId, String username,
String requestIp, String requestUri, String requestMethod,
String operationType, String classMethod, String requestParams,
Integer statusCode, Long costTime, String userAgent,
String errorMsg, LocalDateTime createTime) {
this.id = id;
this.logLevel = logLevel;
this.userId = userId;
this.username = username;
this.requestIp = requestIp;
this.requestUri = requestUri;
this.requestMethod = requestMethod;
this.operationType = operationType;
this.classMethod = classMethod;
this.requestParams = requestParams;
this.statusCode = statusCode;
this.costTime = costTime;
this.userAgent = userAgent;
this.errorMsg = errorMsg;
this.createTime = createTime;
}
}
@@ -0,0 +1,59 @@
package com.yunhai.userbase.model.oplog;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* 操作日志查询条件。<br>
* 覆盖时间、用户、URI、级别、IP 等高频查询场景,与表索引前缀对齐。<br>
*
* @author chenx
* @date 2026/7/28
*/
@Data
public class SysOperationLogQuery {
/** 日志级别(1-重要 2-次要 3-一般) */
private Integer logLevel;
/** 操作用户ID */
private Long userId;
/** 操作用户名(模糊) */
private String username;
/** 请求路径(模糊) */
private String requestUri;
/** 请求IP(模糊) */
private String requestIp;
/** 操作类型 DELETE/CREATE/UPDATE/QUERY */
private String operationType;
/** HTTP 状态码 */
private Integer statusCode;
/**
* 成功/失败筛选。<br>
* true=仅 HTTP 200(成功),false=非 200(失败)。
*/
private Boolean success;
/**
* 关键字,同时匹配接口名称(requestUri)与用户名(username)。<br>
* 前端单输入框搜索这两个字段。
*/
private String keyword;
/** 操作起始时间(含) */
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime;
/** 操作结束时间(含) */
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
}
@@ -0,0 +1,33 @@
package com.yunhai.userbase.model.other;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: UserProfile
* @description: 接口日志操作应用详情
* @author: chenx
* @create: 2024-07-05 12:34
**/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class OperationDetailsModel {
private Integer id;//应用id
private String name;//应用名称
private Long time;//requestTime
private String url;
private String errorMsg;
@JsonIgnore
private Integer indicatorId;
@JsonIgnore
private String resultMsg;
@JsonIgnore
private Double computeScore;//计算后的分数
}
@@ -0,0 +1,25 @@
package com.yunhai.userbase.model.other;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: UserProfile
* @description: 用户当前角色信息
* @author: chenx
* @create: 2024-07-09 17:30
**/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class RoleInfoModel {
private Integer roleId;
private String roleName;
private Integer schId;
private String schName;
private Integer childId;
private String childName;
}
@@ -0,0 +1,22 @@
package com.yunhai.userbase.model.other;
import lombok.Data;
/**
* @author chenx
* @date 2025/12/25 21:28
* @description 学校学制年级实体
*/
@Data
public class SchLenGradeModel {
private Integer gradeId;
private String gradeName;
private Integer stage;
public SchLenGradeModel(Integer gradeId, String gradeName, Integer stage) {
this.gradeId = gradeId;
this.gradeName = gradeName;
this.stage = stage;
}
}
@@ -0,0 +1,19 @@
package com.yunhai.userbase.model.other;
import com.yunhai.userbase.enums.SchoolStage;
import lombok.Data;
import java.util.List;
/**
* @author chenx
* @date 2025/12/25 17:44
* @description 学校学段学制年级实体
*/
@Data
public class SchLenLevelModel {
private SchoolStage stage;
private List<SchLenGradeModel> grades;
}
@@ -0,0 +1,26 @@
package com.yunhai.userbase.model.other;
import com.yunhai.userbase.enums.UserType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: UserProfile
* @description: 用户信息
* @author: chenx
* @create: 2024-07-09 17:30
**/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class UserInfoModel {
private Integer userId;
private String userName;
private Integer schId;
private Integer groupId;
private String photo;
private UserType userType;
}
@@ -0,0 +1,20 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
/**
* @Description: 学年学期
* @Author: chenx
* @Date: 2023/9/5
*/
@Data
public class AcademicYear {
public Integer id;
public String name;
public Integer year;
public Integer semester;
public String startDate;
public String endDate;
public String intervalDate;//日期区间
}
@@ -0,0 +1,25 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
import java.util.Date;
/**
* @Description: 班级管理学年学期序列化
* @Author: chenx
* @Date: 2023/9/5
*/
@Data
public class AcademicYearSeq {
private int id;
private String name;
private Date startDate;
private Date endDate;
private Date progressionDate;
private int year;
private Date firstSemesterStartDate;
private Date firstSemesterEndDate;
private Date secondSemesterStartDate;
private Date secondSemesterEndDate;
}
@@ -0,0 +1,18 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
/**
* @author chenx
* @date 2025/12/30 19:31
* @description 学校列表
*/
@Data
public class BaseSchool {
private String SchSerID;
private int Type;
private String PID;
private int ID;
private String Name;
}
@@ -0,0 +1,22 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
/**
* @Description: 班级管理接口序列化 :GetClaArrStulist
* @Author: chenx
* @Date: 2023/6/8
*/
@Data
public class GradeClassStu {
private Integer gradeId;
private String gradeName;
private Integer classId;
private String className;
private Integer stuId;
private String stuName;
private String CardID;//学号
private Integer StuSex;//性别
private String StuPhoto;
}
@@ -0,0 +1,15 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
@Data
public class SchClass {
public String SchSerID;
public int SchID;
public String GradeName;
public String ClassName;
public String ClassID;
public int GradeID;
public int CID;
}
@@ -0,0 +1,12 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
@Data
public class SchClassModel {
public Integer classID;
public Integer gradeID;
public String gradeName;
public String className;
}
@@ -0,0 +1,23 @@
package com.yunhai.userbase.model.serialize;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
* @author chenx
* @date 2025/12/25 15:56
* @description 学校学制年级信息
*/
@Data
public class SchLenLevel {
private Integer code;
@JSONField(name = "OwnerId")
private Integer ownerId;
private String sx;
@JSONField(name = "Id")
private Integer id;
private Integer levell;
@JSONField(name = "Name")
private String name;
}
@@ -0,0 +1,35 @@
package com.yunhai.userbase.model.serialize;
/**
* @program: ResearchLearn
* @description: 全部教师信息
* @author: chenx
* @create: 2024-06-07 10:16
**/
import lombok.Data;
@Data
public class SchTeaInfo {
private String SchSerID;
private String Teapolitical;
private String TeaWorkStart;
private String Account;
private String role;
private Integer TeaSex;
private String IsLeadingMiddle;
private String TeaOriginPlace;
private String Photo;
private String TeaIDCard;
private String Name;
private Integer GroupID;
private String SchName;
private String TeaTeachStart;
private String TeaSerID;
private Integer UserID;
private String TeaNation;
private String Tel;
private String TeaWorkType;
private Integer TeaNo;
private String TeaBirth;
}
@@ -0,0 +1,29 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
/**
* @program: QualityEvaluate
* @description: 获取班级列表的学生信息序列化
* @author: chenx
* @create: 2023-08-21 10:27
**/
@Data
public class StuInfo {
private String SchSerID;
private String Account;
private String StuStatus;
private String invitecode;
private int StuSex;
private String ClassID;
private String CardID;
private String ClassStuID;
private String StuPhoto;
private long GroupID;
private String StuName;
private long UserStuSerID;
private boolean Graduated;
private String StuIDCard;
private String StuCurrentTel;
}
@@ -0,0 +1,31 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
import java.util.Date;
/**
* @program: QualityEvaluate
* @description: 获取单个学生信息序列化
* @author: chenx
* @create: 2023-09-06 14:46
**/
@Data
public class StuInfo2 {
private int status_code;
private String idCard;
private int sex;
private String photo;
private int IsGraduation;
private Date birth;
private String ClaName;
private String stuName;
private String SchName;
private String studentId;
private long classId;
private String GradeName;
private long UserStuSerID;
private String ClassName;
private int IsDelete;
}
@@ -0,0 +1,13 @@
package com.yunhai.userbase.model.serialize;
import lombok.Data;
@Data
public class TeaFirstClass {
public String gradeName;
public int gradeId ;
public String alias;
public String className ;
public String name ;
public int id ;
}
@@ -0,0 +1,48 @@
package com.yunhai.userbase.model.sysgroup;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author chenx
* @date 2026/7/23
* @description 系统组批量新增请求:在指定父组下,按 items 列表逐个创建子组。<br>
* 请求体示例:<br>
* {<br>
* "pid": 11285,<br>
* "type": 4,<br>
* "items": [<br>
* { "name": "高一1班" },<br>
* { "name": "高一2班" }<br>
* ]<br>
* }
*/
@Data
public class SysGroupBatchRequest {
/** 父组ID(待生成子组的挂载点,必须存在)。 */
@NotNull(message = "父组ID不能为空")
private Integer pid;
/** 组类型(GroupTypeEnum.key,如 4=班级组)。 */
@NotNull(message = "组类型不能为空")
private Integer type;
/** 待新增的子组列表,每一项仅需提供 name。 */
@NotEmpty(message = "批量新增的子组列表不能为空")
@Valid
private List<BatchItem> items;
/** 批量新增的单项。 */
@Data
public static class BatchItem {
/** 子组名称。 */
@javax.validation.constraints.NotBlank(message = "组名称不能为空")
private String name;
}
}
@@ -0,0 +1,23 @@
package com.yunhai.userbase.model.sysgroup;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author chenx
* @date 2026/7/22
* @description 移动组请求:将 moveId 节点移动到 pid 节点下。<br>
* 不支持移动到自身或自身后代下(环检测)。
*/
@Data
public class SysGroupMoveRequest {
/** 待移动节点ID。 */
@NotNull(message = "待移动节点ID不能为空")
private Integer moveId;
/** 目标父节点ID(移动后的挂载点,必须存在)。 */
@NotNull(message = "目标父节点ID不能为空")
private Integer pid;
}
@@ -0,0 +1,15 @@
package com.yunhai.userbase.model.sysgroup;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/20 16:00
* @description 系统组查询条件
*/
@Data
public class SysGroupQuery {
private String name;
private Integer parentId;
}
@@ -0,0 +1,31 @@
package com.yunhai.userbase.model.sysgroup;
import com.yunhai.userbase.common.validation.ValidationGroups;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotBlank;
/**
* @author chenx
* @date 2026/7/20 16:00
* @description 系统组新增/编辑请求
*/
@Data
public class SysGroupRequest {
// ID 通过路径参数传递,body 无需携带,故不在校验组内强制
private Integer id;
@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "组名称不能为空")
private String name;
// 新增时必填;编辑不通过此字段移动节点(移动请走 Move 接口),故编辑时可选
@NotNull(groups = ValidationGroups.Create.class, message = "上级组ID不能为空")
private Integer parentId;
// 新增时必填;编辑时可选(仅当需要变更类型时传入)
@NotNull(groups = ValidationGroups.Create.class, message = "组类型不能为空")
private Integer type;
private Integer sort;
}
@@ -0,0 +1,24 @@
package com.yunhai.userbase.model.sysgroup;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author chenx
* @date 2026/7/22
* @description 子组排序请求:将 pid 的直接子节点按给定 ids 顺序重新排列并落库。<br>
* ids 必须全部是 pid 下一级的直接子节点,否则报错。
*/
@Data
public class SysGroupSortRequest {
/** 父组ID。 */
@NotNull(message = "父组ID不能为空")
private Integer pid;
/** 期望的、pid 直接子节点有序 ID 列表(按传入顺序生效)。 */
@NotNull(message = "子节点ID列表不能为空")
private List<Integer> ids;
}
@@ -0,0 +1,21 @@
package com.yunhai.userbase.model.sysgroup;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author chenx
* @date 2026/7/20 16:00
* @description 系统组返回对象(树形:children 递归存放子组)。<br>
*/
@Data
public class SysGroupVo {
private Integer id;
private String name;
private Integer type;
private Integer sort;
/** 子组(递归);默认空列表,避免 JSON 序列化出现 null。 */
private List<SysGroupVo> children = new ArrayList<>();
}
@@ -0,0 +1,27 @@
package com.yunhai.userbase.model.sysuser;
import lombok.Data;
/**
* @author chenx
* @date 2026/7/20 16:14
* @description 系统用户列表查询条件
*/
@Data
public class SysUserQuery {
/** 分组ID(列表以某个组节点为上下文查询其下用户) */
private Integer groupId;
/**
* 是否包含子组用户:0=仅查询该节点下的用户;1=查询该节点及其所有子孙组下的用户。<br>
* 默认 0。<br>
*/
private Integer withSub = 0;
/** 关键字:同时匹配账号、姓名、身份证(模糊)与手机号(精确) */
private String name;
/** 启用状态过滤(可选);对应实体 disabled 字段(StatusEnum key:0=正常/未禁用,1=禁用) */
private Integer disabled;
}
@@ -0,0 +1,43 @@
package com.yunhai.userbase.model.sysuser;
import com.yunhai.userbase.common.validation.ValidationGroups;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.List;
/**
* @author chenx
* @date 2026/7/20 16:14
* @description 系统用户新增/编辑请求
*/
@Data
public class SysUserRequest {
@NotNull(groups = ValidationGroups.Update.class, message = "编辑时ID不能为空")
private Integer id;
/** 所属分组ID,新增时必填(用户创建后写入组用户关联表) */
@NotNull(groups = ValidationGroups.Create.class, message = "所属分组不能为空")
private Integer groupId;
@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class}, message = "账号不能为空")
private String account;
@NotBlank(groups = ValidationGroups.Create.class, message = "密码不能为空")
private String password;
/** 确认密码:与 password 一致性由 Service 校验(编辑时若不修改密码可不传) */
private String confirmPassword;
private String realName;
private String phone;
private LocalDate birthday;
private String idcard;
private String profilePicture;
private List<Integer> roles;
/** 启用状态:对应 StatusEnum 的 key(0=正常/未禁用,1=禁用);不传则默认启用 */
private Integer disabled;
private Boolean expired;
}
@@ -0,0 +1,31 @@
package com.yunhai.userbase.model.sysuser;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author chenx
* @date 2026/7/20 16:14
* @description 系统用户返回对象
*/
@Data
public class SysUserVo {
private Integer id;
private String account;
private LocalDate birthday;
private String realName;
private String phone;
private String idcard;
private String profilePicture;
private List<Integer> roles;
/** 启用状态:StatusEnum 的 key(0=正常/未禁用,1=禁用) */
private Integer disabled;
/** 用户类型:UserTypeEnum 的 key(0=普通用户,1=超级管理员,2=学校管理员) */
private Integer type;
private Boolean expired;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}