This commit is contained in:
2025-11-11 22:03:30 +08:00
parent 685bb0cebd
commit ff88c2c04a
947 changed files with 122829 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
package com.klp.system.domain;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 系统访问记录表 sys_logininfor
*
* @author Lion Li
*/
@Data
@TableName("sys_logininfor")
@ExcelIgnoreUnannotated
public class SysLogininfor implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@ExcelProperty(value = "序号")
@TableId(value = "info_id")
private Long infoId;
/**
* 用户账号
*/
@ExcelProperty(value = "用户账号")
private String userName;
/**
* 登录状态 0成功 1失败
*/
@ExcelProperty(value = "登录状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_common_status")
private String status;
/**
* 登录IP地址
*/
@ExcelProperty(value = "登录地址")
private String ipaddr;
/**
* 登录地点
*/
@ExcelProperty(value = "登录地点")
private String loginLocation;
/**
* 浏览器类型
*/
@ExcelProperty(value = "浏览器")
private String browser;
/**
* 操作系统
*/
@ExcelProperty(value = "操作系统")
private String os;
/**
* 提示消息
*/
@ExcelProperty(value = "提示消息")
private String msg;
/**
* 访问时间
*/
@ExcelProperty(value = "访问时间")
private Date loginTime;
/**
* 请求参数
*/
@TableField(exist = false)
private Map<String, Object> params = new HashMap<>();
}

View File

@@ -0,0 +1,50 @@
package com.klp.system.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* OSS对象存储对象
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_oss")
public class SysOss extends BaseEntity {
/**
* 对象存储主键
*/
@TableId(value = "oss_id")
private Long ossId;
/**
* 文件名
*/
private String fileName;
/**
* 原名
*/
private String originalName;
/**
* 文件后缀名
*/
private String fileSuffix;
/**
* URL地址
*/
private String url;
/**
* 服务商
*/
private String service;
}

View File

@@ -0,0 +1,89 @@
package com.klp.system.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 对象存储配置对象 sys_oss_config
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_oss_config")
public class SysOssConfig extends BaseEntity {
/**
* 主建
*/
@TableId(value = "oss_config_id")
private Long ossConfigId;
/**
* 配置key
*/
private String configKey;
/**
* accessKey
*/
private String accessKey;
/**
* 秘钥
*/
private String secretKey;
/**
* 桶名称
*/
private String bucketName;
/**
* 前缀
*/
private String prefix;
/**
* 访问站点
*/
private String endpoint;
/**
* 自定义域名
*/
private String domain;
/**
* 是否https0否 1是
*/
private String isHttps;
/**
* 域
*/
private String region;
/**
* 是否默认0=是,1=否)
*/
private String status;
/**
* 扩展字段
*/
private String ext1;
/**
* 备注
*/
private String remark;
/**
* 桶权限类型(0private 1public 2custom)
*/
private String accessPolicy;
}

View File

@@ -0,0 +1,78 @@
package com.klp.system.domain;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 岗位表 sys_post
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_post")
@ExcelIgnoreUnannotated
public class SysPost extends BaseEntity {
/**
* 岗位序号
*/
@ExcelProperty(value = "岗位序号")
@TableId(value = "post_id")
private Long postId;
/**
* 岗位编码
*/
@ExcelProperty(value = "岗位编码")
@NotBlank(message = "岗位编码不能为空")
@Size(min = 0, max = 64, message = "岗位编码长度不能超过{max}个字符")
private String postCode;
/**
* 岗位名称
*/
@ExcelProperty(value = "岗位名称")
@NotBlank(message = "岗位名称不能为空")
@Size(min = 0, max = 50, message = "岗位名称长度不能超过{max}个字符")
private String postName;
/**
* 岗位排序
*/
@ExcelProperty(value = "岗位排序")
@NotNull(message = "显示顺序不能为空")
private Integer postSort;
/**
* 状态0正常 1停用
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_normal_disable")
private String status;
/**
* 备注
*/
private String remark;
/**
* 用户是否存在此岗位标识 默认不存在
*/
@TableField(exist = false)
private boolean flag = false;
}

View File

@@ -0,0 +1,29 @@
package com.klp.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 角色和部门关联 sys_role_dept
*
* @author Lion Li
*/
@Data
@TableName("sys_role_dept")
public class SysRoleDept {
/**
* 角色ID
*/
@TableId(type = IdType.INPUT)
private Long roleId;
/**
* 部门ID
*/
private Long deptId;
}

View File

@@ -0,0 +1,54 @@
package com.klp.system.domain;
import lombok.Data;
/**
* 当前在线会话
*
* @author Lion Li
*/
@Data
public class SysUserOnline {
/**
* 会话编号
*/
private String tokenId;
/**
* 部门名称
*/
private String deptName;
/**
* 用户名称
*/
private String userName;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地址
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 登录时间
*/
private Long loginTime;
}

View File

@@ -0,0 +1,29 @@
package com.klp.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 用户和岗位关联 sys_user_post
*
* @author Lion Li
*/
@Data
@TableName("sys_user_post")
public class SysUserPost {
/**
* 用户ID
*/
@TableId(type = IdType.INPUT)
private Long userId;
/**
* 岗位ID
*/
private Long postId;
}

View File

@@ -0,0 +1,29 @@
package com.klp.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 用户和角色关联 sys_user_role
*
* @author Lion Li
*/
@Data
@TableName("sys_user_role")
public class SysUserRole {
/**
* 用户ID
*/
@TableId(type = IdType.INPUT)
private Long userId;
/**
* 角色ID
*/
private Long roleId;
}

View File

@@ -0,0 +1,46 @@
package com.klp.system.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* OSS对象存储分页查询对象 sys_oss
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SysOssBo extends BaseEntity {
/**
* ossId
*/
private Long ossId;
/**
* 文件名
*/
private String fileName;
/**
* 原名
*/
private String originalName;
/**
* 文件后缀名
*/
private String fileSuffix;
/**
* URL地址
*/
private String url;
/**
* 服务商
*/
private String service;
}

View File

@@ -0,0 +1,107 @@
package com.klp.system.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 对象存储配置业务对象 sys_oss_config
*
* @author Lion Li
* @author 孤舟烟雨
* @date 2021-08-13
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SysOssConfigBo extends BaseEntity {
/**
* 主建
*/
@NotNull(message = "主建不能为空", groups = {EditGroup.class})
private Long ossConfigId;
/**
* 配置key
*/
@NotBlank(message = "配置key不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(min = 2, max = 100, message = "configKey长度必须介于{min}和{max} 之间")
private String configKey;
/**
* accessKey
*/
@NotBlank(message = "accessKey不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(min = 2, max = 100, message = "accessKey长度必须介于{min}和{max} 之间")
private String accessKey;
/**
* 秘钥
*/
@NotBlank(message = "secretKey不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(min = 2, max = 100, message = "secretKey长度必须介于{min}和{max} 之间")
private String secretKey;
/**
* 桶名称
*/
@NotBlank(message = "桶名称不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(min = 2, max = 100, message = "bucketName长度必须介于{min}和{max}之间")
private String bucketName;
/**
* 前缀
*/
private String prefix;
/**
* 访问站点
*/
@NotBlank(message = "访问站点不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(min = 2, max = 100, message = "endpoint长度必须介于{min}和{max}之间")
private String endpoint;
/**
* 自定义域名
*/
private String domain;
/**
* 是否httpsY=是,N=否)
*/
private String isHttps;
/**
* 是否默认0=是,1=否)
*/
private String status;
/**
* 域
*/
private String region;
/**
* 扩展字段
*/
private String ext1;
/**
* 备注
*/
private String remark;
/**
* 桶权限类型(0private 1public 2custom)
*/
@NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class})
private String accessPolicy;
}

View File

@@ -0,0 +1,61 @@
package com.klp.system.domain.vo;
import com.klp.common.utils.StringUtils;
import lombok.Data;
/**
* 路由显示信息
*
* @author klp
*/
@Data
public class MetaVo {
/**
* 设置该路由在侧边栏和面包屑中展示的名字
*/
private String title;
/**
* 设置该路由的图标对应路径src/assets/icons/svg
*/
private String icon;
/**
* 设置为true则不会被 <keep-alive>缓存
*/
private boolean noCache;
/**
* 内链地址http(s)://开头)
*/
private String link;
public MetaVo(String title, String icon) {
this.title = title;
this.icon = icon;
}
public MetaVo(String title, String icon, boolean noCache) {
this.title = title;
this.icon = icon;
this.noCache = noCache;
}
public MetaVo(String title, String icon, String link) {
this.title = title;
this.icon = icon;
this.link = link;
}
public MetaVo(String title, String icon, boolean noCache, String link) {
this.title = title;
this.icon = icon;
this.noCache = noCache;
if (StringUtils.ishttp(link)) {
this.link = link;
}
}
}

View File

@@ -0,0 +1,90 @@
package com.klp.system.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import lombok.Data;
/**
* 对象存储配置视图对象 sys_oss_config
*
* @author Lion Li
* @author 孤舟烟雨
* @date 2021-08-13
*/
@Data
@ExcelIgnoreUnannotated
public class SysOssConfigVo {
private static final long serialVersionUID = 1L;
/**
* 主建
*/
private Long ossConfigId;
/**
* 配置key
*/
private String configKey;
/**
* accessKey
*/
private String accessKey;
/**
* 秘钥
*/
private String secretKey;
/**
* 桶名称
*/
private String bucketName;
/**
* 前缀
*/
private String prefix;
/**
* 访问站点
*/
private String endpoint;
/**
* 自定义域名
*/
private String domain;
/**
* 是否httpsY=是,N=否)
*/
private String isHttps;
/**
* 域
*/
private String region;
/**
* 是否默认0=是,1=否)
*/
private String status;
/**
* 扩展字段
*/
private String ext1;
/**
* 备注
*/
private String remark;
/**
* 桶权限类型(0private 1public 2custom)
*/
private String accessPolicy;
}

View File

@@ -0,0 +1,91 @@
package com.klp.system.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 用户对象导出VO
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class SysUserExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@ExcelProperty(value = "用户序号")
private Long userId;
/**
* 用户账号
*/
@ExcelProperty(value = "登录名称")
private String userName;
/**
* 用户昵称
*/
@ExcelProperty(value = "用户名称")
private String nickName;
/**
* 用户邮箱
*/
@ExcelProperty(value = "用户邮箱")
private String email;
/**
* 手机号码
*/
@ExcelProperty(value = "手机号码")
private String phonenumber;
/**
* 用户性别
*/
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_user_sex")
private String sex;
/**
* 帐号状态0正常 1停用
*/
@ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_normal_disable")
private String status;
/**
* 最后登录IP
*/
@ExcelProperty(value = "最后登录IP")
private String loginIp;
/**
* 最后登录时间
*/
@ExcelProperty(value = "最后登录时间")
private Date loginDate;
/**
* 部门名称
*/
@ExcelProperty(value = "部门名称")
private String deptName;
/**
* 负责人
*/
@ExcelProperty(value = "部门负责人")
private String leader;
}

View File

@@ -0,0 +1,73 @@
package com.klp.system.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 用户对象导入VO
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
// @Accessors(chain = true) // 导入不允许使用 会找不到set方法
public class SysUserImportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@ExcelProperty(value = "用户序号")
private Long userId;
/**
* 部门ID
*/
@ExcelProperty(value = "部门编号")
private Long deptId;
/**
* 用户账号
*/
@ExcelProperty(value = "登录名称")
private String userName;
/**
* 用户昵称
*/
@ExcelProperty(value = "用户名称")
private String nickName;
/**
* 用户邮箱
*/
@ExcelProperty(value = "用户邮箱")
private String email;
/**
* 手机号码
*/
@ExcelProperty(value = "手机号码")
private String phonenumber;
/**
* 用户性别
*/
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_user_sex")
private String sex;
/**
* 帐号状态0正常 1停用
*/
@ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_normal_disable")
private String status;
}

View File

@@ -0,0 +1,13 @@
package com.klp.system.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.system.domain.SysConfig;
/**
* 参数配置 数据层
*
* @author Lion Li
*/
public interface SysConfigMapper extends BaseMapperPlus<SysConfigMapper, SysConfig, SysConfig> {
}

View File

@@ -0,0 +1,40 @@
package com.klp.system.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.klp.common.annotation.DataColumn;
import com.klp.common.annotation.DataPermission;
import com.klp.common.core.domain.entity.SysDept;
import com.klp.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 部门管理 数据层
*
* @author Lion Li
*/
public interface SysDeptMapper extends BaseMapperPlus<SysDeptMapper, SysDept, SysDept> {
/**
* 查询部门管理数据
*
* @param queryWrapper 查询条件
* @return 部门信息集合
*/
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id")
})
List<SysDept> selectDeptList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
/**
* 根据角色ID查询部门树信息
*
* @param roleId 角色ID
* @param deptCheckStrictly 部门树选择项是否关联显示
* @return 选中部门列表
*/
List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
}

View File

@@ -0,0 +1,24 @@
package com.klp.system.mapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.klp.common.constant.UserConstants;
import com.klp.common.core.domain.entity.SysDictData;
import com.klp.common.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* 字典表 数据层
*
* @author Lion Li
*/
public interface SysDictDataMapper extends BaseMapperPlus<SysDictDataMapper, SysDictData, SysDictData> {
default List<SysDictData> selectDictDataByType(String dictType) {
return selectList(
new LambdaQueryWrapper<SysDictData>()
.eq(SysDictData::getStatus, UserConstants.DICT_NORMAL)
.eq(SysDictData::getDictType, dictType)
.orderByAsc(SysDictData::getDictSort));
}
}

View File

@@ -0,0 +1,82 @@
package com.klp.system.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.klp.common.constant.UserConstants;
import com.klp.common.core.domain.entity.SysMenu;
import com.klp.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 菜单表 数据层
*
* @author Lion Li
*/
public interface SysMenuMapper extends BaseMapperPlus<SysMenuMapper, SysMenu, SysMenu> {
/**
* 根据用户所有权限
*
* @return 权限列表
*/
List<String> selectMenuPerms();
/**
* 根据用户查询系统菜单列表
*
* @param queryWrapper 查询条件
* @return 菜单列表
*/
List<SysMenu> selectMenuListByUserId(@Param(Constants.WRAPPER) Wrapper<SysMenu> queryWrapper);
/**
* 根据用户ID查询权限
*
* @param userId 用户ID
* @return 权限列表
*/
List<String> selectMenuPermsByUserId(Long userId);
/**
* 根据角色ID查询权限
*
* @param roleId 角色ID
* @return 权限列表
*/
List<String> selectMenuPermsByRoleId(Long roleId);
/**
* 根据用户ID查询菜单
*
* @return 菜单列表
*/
default List<SysMenu> selectMenuTreeAll() {
LambdaQueryWrapper<SysMenu> lqw = new LambdaQueryWrapper<SysMenu>()
.in(SysMenu::getMenuType, UserConstants.TYPE_DIR, UserConstants.TYPE_MENU)
.eq(SysMenu::getStatus, UserConstants.MENU_NORMAL)
.orderByAsc(SysMenu::getParentId)
.orderByAsc(SysMenu::getOrderNum);
return this.selectList(lqw);
}
/**
* 根据用户ID查询菜单
*
* @param userId 用户ID
* @return 菜单列表
*/
List<SysMenu> selectMenuTreeByUserId(Long userId);
/**
* 根据角色ID查询菜单树信息
*
* @param roleId 角色ID
* @param menuCheckStrictly 菜单树选择项是否关联显示
* @return 选中菜单列表
*/
List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
}

View File

@@ -0,0 +1,13 @@
package com.klp.system.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.system.domain.SysNotice;
/**
* 通知公告表 数据层
*
* @author Lion Li
*/
public interface SysNoticeMapper extends BaseMapperPlus<SysNoticeMapper, SysNotice, SysNotice> {
}

View File

@@ -0,0 +1,13 @@
package com.klp.system.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.system.domain.SysOperLog;
/**
* 操作日志 数据层
*
* @author Lion Li
*/
public interface SysOperLogMapper extends BaseMapperPlus<SysOperLogMapper, SysOperLog, SysOperLog> {
}

View File

@@ -0,0 +1,16 @@
package com.klp.system.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.system.domain.SysOssConfig;
import com.klp.system.domain.vo.SysOssConfigVo;
/**
* 对象存储配置Mapper接口
*
* @author Lion Li
* @author 孤舟烟雨
* @date 2021-08-13
*/
public interface SysOssConfigMapper extends BaseMapperPlus<SysOssConfigMapper, SysOssConfig, SysOssConfigVo> {
}

View File

@@ -0,0 +1,13 @@
package com.klp.system.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.system.domain.SysOss;
import com.klp.system.domain.vo.SysOssVo;
/**
* 文件上传 数据层
*
* @author Lion Li
*/
public interface SysOssMapper extends BaseMapperPlus<SysOssMapper, SysOss, SysOssVo> {
}

View File

@@ -0,0 +1,13 @@
package com.klp.system.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.system.domain.SysRoleMenu;
/**
* 角色与菜单关联表 数据层
*
* @author Lion Li
*/
public interface SysRoleMenuMapper extends BaseMapperPlus<SysRoleMenuMapper, SysRoleMenu, SysRoleMenu> {
}

View File

@@ -0,0 +1,13 @@
package com.klp.system.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.system.domain.SysUserPost;
/**
* 用户与岗位关联表 数据层
*
* @author Lion Li
*/
public interface SysUserPostMapper extends BaseMapperPlus<SysUserPostMapper, SysUserPost, SysUserPost> {
}

View File

@@ -0,0 +1,41 @@
package com.klp.system.runner;
import com.klp.common.config.KLPConfig;
import com.klp.system.service.ISysConfigService;
import com.klp.system.service.ISysDictTypeService;
import com.klp.system.service.ISysOssConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 初始化 system 模块对应业务数据
*
* @author Lion Li
*/
@Slf4j
@RequiredArgsConstructor
@Component
public class SystemApplicationRunner implements ApplicationRunner {
private final KLPConfig ruoyiConfig;
private final ISysConfigService configService;
private final ISysDictTypeService dictTypeService;
private final ISysOssConfigService ossConfigService;
@Override
public void run(ApplicationArguments args) throws Exception {
ossConfigService.init();
log.info("初始化OSS配置成功");
if (ruoyiConfig.isCacheLazy()) {
return;
}
configService.loadingConfigCache();
log.info("加载参数缓存数据成功");
dictTypeService.loadingDictCache();
log.info("加载字典缓存数据成功");
}
}

View File

@@ -0,0 +1,26 @@
package com.klp.system.service;
/**
* 通用 数据权限 服务
*
* @author Lion Li
*/
public interface ISysDataScopeService {
/**
* 获取角色自定义权限
*
* @param roleId 角色id
* @return 部门id组
*/
String getRoleCustom(Long roleId);
/**
* 获取部门及以下权限
*
* @param deptId 部门id
* @return 部门id组
*/
String getDeptAndChild(Long deptId);
}

View File

@@ -0,0 +1,66 @@
package com.klp.system.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.entity.SysDictData;
import com.klp.common.core.page.TableDataInfo;
import java.util.List;
/**
* 字典 业务层
*
* @author Lion Li
*/
public interface ISysDictDataService {
TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData, PageQuery pageQuery);
/**
* 根据条件分页查询字典数据
*
* @param dictData 字典数据信息
* @return 字典数据集合信息
*/
List<SysDictData> selectDictDataList(SysDictData dictData);
/**
* 根据字典类型和字典键值查询字典数据信息
*
* @param dictType 字典类型
* @param dictValue 字典键值
* @return 字典标签
*/
String selectDictLabel(String dictType, String dictValue);
/**
* 根据字典数据ID查询信息
*
* @param dictCode 字典数据ID
* @return 字典数据
*/
SysDictData selectDictDataById(Long dictCode);
/**
* 批量删除字典数据信息
*
* @param dictCodes 需要删除的字典数据ID
*/
void deleteDictDataByIds(Long[] dictCodes);
/**
* 新增保存字典数据信息
*
* @param dictData 字典数据信息
* @return 结果
*/
List<SysDictData> insertDictData(SysDictData dictData);
/**
* 修改保存字典数据信息
*
* @param dictData 字典数据信息
* @return 结果
*/
List<SysDictData> updateDictData(SysDictData dictData);
}

View File

@@ -0,0 +1,46 @@
package com.klp.system.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.system.domain.SysLogininfor;
import java.util.List;
/**
* 系统访问日志情况信息 服务层
*
* @author Lion Li
*/
public interface ISysLogininforService {
TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor, PageQuery pageQuery);
/**
* 新增系统登录日志
*
* @param logininfor 访问日志对象
*/
void insertLogininfor(SysLogininfor logininfor);
/**
* 查询系统登录日志集合
*
* @param logininfor 访问日志对象
* @return 登录记录集合
*/
List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
/**
* 批量删除系统登录日志
*
* @param infoIds 需要删除的登录日志ID
* @return 结果
*/
int deleteLogininforByIds(Long[] infoIds);
/**
* 清空系统登录日志
*/
void cleanLogininfor();
}

View File

@@ -0,0 +1,66 @@
package com.klp.system.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.system.domain.SysNotice;
import java.util.List;
/**
* 公告 服务层
*
* @author Lion Li
*/
public interface ISysNoticeService {
TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice, PageQuery pageQuery);
/**
* 查询公告信息
*
* @param noticeId 公告ID
* @return 公告信息
*/
SysNotice selectNoticeById(Long noticeId);
/**
* 查询公告列表
*
* @param notice 公告信息
* @return 公告集合
*/
List<SysNotice> selectNoticeList(SysNotice notice);
/**
* 新增公告
*
* @param notice 公告信息
* @return 结果
*/
int insertNotice(SysNotice notice);
/**
* 修改公告
*
* @param notice 公告信息
* @return 结果
*/
int updateNotice(SysNotice notice);
/**
* 删除公告信息
*
* @param noticeId 公告ID
* @return 结果
*/
int deleteNoticeById(Long noticeId);
/**
* 批量删除公告信息
*
* @param noticeIds 需要删除的公告ID
* @return 结果
*/
int deleteNoticeByIds(Long[] noticeIds);
}

View File

@@ -0,0 +1,211 @@
package com.klp.system.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.common.core.page.TableDataInfo;
import java.util.List;
/**
* 用户 业务层
*
* @author Lion Li
*/
public interface ISysUserService {
TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery);
/**
* 根据条件分页查询用户列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
List<SysUser> selectUserList(SysUser user);
/**
* 根据条件分页查询已分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery);
/**
* 根据条件分页查询未分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery);
/**
* 通过用户名查询用户
*
* @param userName 用户名
* @return 用户对象信息
*/
SysUser selectUserByUserName(String userName);
/**
* 通过手机号查询用户
*
* @param phonenumber 手机号
* @return 用户对象信息
*/
SysUser selectUserByPhonenumber(String phonenumber);
/**
* 通过用户ID查询用户
*
* @param userId 用户ID
* @return 用户对象信息
*/
SysUser selectUserById(Long userId);
/**
* 根据用户ID查询用户所属角色组
*
* @param userName 用户名
* @return 结果
*/
String selectUserRoleGroup(String userName);
/**
* 根据用户ID查询用户所属岗位组
*
* @param userName 用户名
* @return 结果
*/
String selectUserPostGroup(String userName);
/**
* 校验用户名称是否唯一
*
* @param user 用户信息
* @return 结果
*/
boolean checkUserNameUnique(SysUser user);
/**
* 校验手机号码是否唯一
*
* @param user 用户信息
* @return 结果
*/
boolean checkPhoneUnique(SysUser user);
/**
* 校验email是否唯一
*
* @param user 用户信息
* @return 结果
*/
boolean checkEmailUnique(SysUser user);
/**
* 校验用户是否允许操作
*
* @param user 用户信息
*/
void checkUserAllowed(SysUser user);
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
void checkUserDataScope(Long userId);
/**
* 新增用户信息
*
* @param user 用户信息
* @return 结果
*/
int insertUser(SysUser user);
/**
* 注册用户信息
*
* @param user 用户信息
* @return 结果
*/
boolean registerUser(SysUser user);
/**
* 修改用户信息
*
* @param user 用户信息
* @return 结果
*/
int updateUser(SysUser user);
/**
* 用户授权角色
*
* @param userId 用户ID
* @param roleIds 角色组
*/
void insertUserAuth(Long userId, Long[] roleIds);
/**
* 修改用户状态
*
* @param user 用户信息
* @return 结果
*/
int updateUserStatus(SysUser user);
/**
* 修改用户基本信息
*
* @param user 用户信息
* @return 结果
*/
int updateUserProfile(SysUser user);
/**
* 修改用户头像
*
* @param userName 用户名
* @param avatar 头像地址
* @return 结果
*/
boolean updateUserAvatar(String userName, String avatar);
/**
* 重置用户密码
*
* @param user 用户信息
* @return 结果
*/
int resetPwd(SysUser user);
/**
* 重置用户密码
*
* @param userName 用户名
* @param password 密码
* @return 结果
*/
int resetUserPwd(String userName, String password);
/**
* 通过用户ID删除用户
*
* @param userId 用户ID
* @return 结果
*/
int deleteUserById(Long userId);
/**
* 批量删除用户信息
*
* @param userIds 需要删除的用户ID
* @return 结果
*/
int deleteUserByIds(Long[] userIds);
}

View File

@@ -0,0 +1,332 @@
package com.klp.system.service;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.klp.common.constant.CacheConstants;
import com.klp.common.constant.Constants;
import com.klp.common.core.domain.event.LogininforEvent;
import com.klp.common.core.domain.dto.RoleDTO;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.common.core.domain.model.LoginUser;
import com.klp.common.core.domain.model.XcxLoginUser;
import com.klp.common.enums.DeviceType;
import com.klp.common.enums.LoginType;
import com.klp.common.enums.UserStatus;
import com.klp.common.exception.user.CaptchaException;
import com.klp.common.exception.user.CaptchaExpireException;
import com.klp.common.exception.user.UserException;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.DateUtils;
import com.klp.common.utils.MessageUtils;
import com.klp.common.utils.ServletUtils;
import com.klp.common.utils.StringUtils;
import com.klp.common.utils.redis.RedisUtils;
import com.klp.common.utils.spring.SpringUtils;
import com.klp.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.List;
import java.util.function.Supplier;
/**
* 登录校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Slf4j
@Service
public class SysLoginService {
private final SysUserMapper userMapper;
private final ISysConfigService configService;
private final SysPermissionService permissionService;
@Value("${user.password.maxRetryCount}")
private Integer maxRetryCount;
@Value("${user.password.lockTime}")
private Integer lockTime;
/**
* 登录验证
*
* @param username 用户名
* @param password 密码
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public String login(String username, String password, String code, String uuid) {
boolean captchaEnabled = configService.selectCaptchaEnabled();
// 验证码开关
if (captchaEnabled) {
validateCaptcha(username, code, uuid);
}
SysUser user = loadUserByUsername(username);
checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, user.getPassword()));
// 此处可根据登录用户的数据不同 自行创建 loginUser
LoginUser loginUser = buildLoginUser(user);
// 生成token
LoginHelper.loginByDevice(loginUser, DeviceType.PC);
recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
recordLoginInfo(user.getUserId(), username);
return StpUtil.getTokenValue();
}
public String smsLogin(String phonenumber, String smsCode) {
// 通过手机号查找用户
SysUser user = loadUserByPhonenumber(phonenumber);
checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode));
// 此处可根据登录用户的数据不同 自行创建 loginUser
LoginUser loginUser = buildLoginUser(user);
// 生成token
LoginHelper.loginByDevice(loginUser, DeviceType.APP);
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
recordLoginInfo(user.getUserId(), user.getUserName());
return StpUtil.getTokenValue();
}
public String emailLogin(String email, String emailCode) {
// 通过手机号查找用户
SysUser user = loadUserByEmail(email);
checkLogin(LoginType.EMAIL, user.getUserName(), () -> !validateEmailCode(email, emailCode));
// 此处可根据登录用户的数据不同 自行创建 loginUser
LoginUser loginUser = buildLoginUser(user);
// 生成token
LoginHelper.loginByDevice(loginUser, DeviceType.APP);
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
recordLoginInfo(user.getUserId(), user.getUserName());
return StpUtil.getTokenValue();
}
public String xcxLogin(String xcxCode) {
// xcxCode 为 小程序调用 wx.login 授权后获取
// todo 以下自行实现
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
String openid = "";
SysUser user = loadUserByOpenid(openid);
// 此处可根据登录用户的数据不同 自行创建 loginUser
XcxLoginUser loginUser = new XcxLoginUser();
loginUser.setUserId(user.getUserId());
loginUser.setUsername(user.getUserName());
loginUser.setUserType(user.getUserType());
loginUser.setOpenid(openid);
// 生成token
LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
recordLoginInfo(user.getUserId(), user.getUserName());
return StpUtil.getTokenValue();
}
/**
* 退出登录
*/
public void logout() {
try {
LoginUser loginUser = LoginHelper.getLoginUser();
StpUtil.logout();
recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
} catch (NotLoginException ignored) {
}
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
*/
private void recordLogininfor(String username, String status, String message) {
LogininforEvent logininforEvent = new LogininforEvent();
logininforEvent.setUsername(username);
logininforEvent.setStatus(status);
logininforEvent.setMessage(message);
logininforEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforEvent);
}
/**
* 校验短信验证码
*/
private boolean validateSmsCode(String phonenumber, String smsCode) {
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
if (StringUtils.isBlank(code)) {
recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
return code.equals(smsCode);
}
/**
* 校验邮箱验证码
*/
private boolean validateEmailCode(String email, String emailCode) {
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + email);
if (StringUtils.isBlank(code)) {
recordLogininfor(email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
return code.equals(emailCode);
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
*/
public void validateCaptcha(String username, String code, String uuid) {
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
String captcha = RedisUtils.getCacheObject(verifyKey);
RedisUtils.deleteObject(verifyKey);
if (captcha == null) {
recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha)) {
recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
throw new CaptchaException();
}
}
private SysUser loadUserByUsername(String username) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserName, SysUser::getStatus)
.eq(SysUser::getUserName, username));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", username);
throw new UserException("user.blocked", username);
}
return userMapper.selectUserByUserName(username);
}
private SysUser loadUserByPhonenumber(String phonenumber) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getPhonenumber, SysUser::getStatus)
.eq(SysUser::getPhonenumber, phonenumber));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", phonenumber);
throw new UserException("user.not.exists", phonenumber);
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", phonenumber);
throw new UserException("user.blocked", phonenumber);
}
return userMapper.selectUserByPhonenumber(phonenumber);
}
private SysUser loadUserByEmail(String email) {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getPhonenumber, SysUser::getStatus)
.eq(SysUser::getEmail, email));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", email);
throw new UserException("user.not.exists", email);
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", email);
throw new UserException("user.blocked", email);
}
return userMapper.selectUserByEmail(email);
}
private SysUser loadUserByOpenid(String openid) {
// 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
// todo 自行实现 userService.selectUserByOpenid(openid);
SysUser user = new SysUser();
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", openid);
// todo 用户不存在 业务逻辑自行实现
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", openid);
// todo 用户已被停用 业务逻辑自行实现
}
return user;
}
/**
* 构建登录用户
*/
private LoginUser buildLoginUser(SysUser user) {
LoginUser loginUser = new LoginUser();
loginUser.setUserId(user.getUserId());
loginUser.setDeptId(user.getDeptId());
loginUser.setUsername(user.getUserName());
loginUser.setNickName(user.getNickName());
loginUser.setUserType(user.getUserType());
loginUser.setMenuPermission(permissionService.getMenuPermission(user));
loginUser.setRolePermission(permissionService.getRolePermission(user));
loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
loginUser.setRoles(roles);
return loginUser;
}
/**
* 记录登录信息
*
* @param userId 用户ID
*/
public void recordLoginInfo(Long userId, String username) {
SysUser sysUser = new SysUser();
sysUser.setUserId(userId);
sysUser.setLoginIp(ServletUtils.getClientIP());
sysUser.setLoginDate(DateUtils.getNowDate());
sysUser.setUpdateBy(username);
userMapper.updateById(sysUser);
}
/**
* 登录校验
*/
private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
String loginFail = Constants.LOGIN_FAIL;
// 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip)
Integer errorNumber = RedisUtils.getCacheObject(errorKey);
// 锁定时间内登录 则踢出
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
}
if (supplier.get()) {
// 是否第一次
errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
// 达到规定错误次数 则锁定登录
if (errorNumber.equals(maxRetryCount)) {
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
} else {
// 未达到规定错误次数 则递增
RedisUtils.setCacheObject(errorKey, errorNumber);
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
}
}
// 登录成功 清空错误次数
RedisUtils.deleteObject(errorKey);
}
}

View File

@@ -0,0 +1,101 @@
package com.klp.system.service;
import cn.dev33.satoken.secure.BCrypt;
import com.klp.common.constant.CacheConstants;
import com.klp.common.constant.Constants;
import com.klp.common.core.domain.event.LogininforEvent;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.common.core.domain.model.RegisterBody;
import com.klp.common.enums.UserType;
import com.klp.common.exception.user.CaptchaException;
import com.klp.common.exception.user.CaptchaExpireException;
import com.klp.common.exception.user.UserException;
import com.klp.common.utils.MessageUtils;
import com.klp.common.utils.ServletUtils;
import com.klp.common.utils.StringUtils;
import com.klp.common.utils.redis.RedisUtils;
import com.klp.common.utils.spring.SpringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* 注册校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service
public class SysRegisterService {
private final ISysUserService userService;
private final ISysConfigService configService;
/**
* 注册
*/
public void register(RegisterBody registerBody) {
String username = registerBody.getUsername();
String password = registerBody.getPassword();
// 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
boolean captchaEnabled = configService.selectCaptchaEnabled();
// 验证码开关
if (captchaEnabled) {
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
}
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(BCrypt.hashpw(password));
sysUser.setUserType(userType);
if (!userService.checkUserNameUnique(sysUser)) {
throw new UserException("user.register.save.error", username);
}
boolean regFlag = userService.registerUser(sysUser);
if (!regFlag) {
throw new UserException("user.register.error");
}
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
*/
public void validateCaptcha(String username, String code, String uuid) {
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
String captcha = RedisUtils.getCacheObject(verifyKey);
RedisUtils.deleteObject(verifyKey);
if (captcha == null) {
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha)) {
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
throw new CaptchaException();
}
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
private void recordLogininfor(String username, String status, String message) {
LogininforEvent logininforEvent = new LogininforEvent();
logininforEvent.setUsername(username);
logininforEvent.setStatus(status);
logininforEvent.setMessage(message);
logininforEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforEvent);
}
}

View File

@@ -0,0 +1,227 @@
package com.klp.system.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.constant.CacheNames;
import com.klp.common.constant.UserConstants;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.service.ConfigService;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import com.klp.common.utils.redis.CacheUtils;
import com.klp.common.utils.spring.SpringUtils;
import com.klp.system.domain.SysConfig;
import com.klp.system.mapper.SysConfigMapper;
import com.klp.system.service.ISysConfigService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 参数配置 服务层实现
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service
public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
private final SysConfigMapper baseMapper;
@Override
public TableDataInfo<SysConfig> selectPageConfigList(SysConfig config, PageQuery pageQuery) {
Map<String, Object> params = config.getParams();
LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
.like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
.eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
.like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
Page<SysConfig> page = baseMapper.selectPage(pageQuery.build(), lqw);
return TableDataInfo.build(page);
}
/**
* 查询参数配置信息
*
* @param configId 参数配置ID
* @return 参数配置信息
*/
@Override
@DS("master")
public SysConfig selectConfigById(Long configId) {
return baseMapper.selectById(configId);
}
/**
* 根据键名查询参数配置信息
*
* @param configKey 参数key
* @return 参数键值
*/
@Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey")
@Override
public String selectConfigByKey(String configKey) {
SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
.eq(SysConfig::getConfigKey, configKey));
if (ObjectUtil.isNotNull(retConfig)) {
return retConfig.getConfigValue();
}
return StringUtils.EMPTY;
}
/**
* 获取验证码开关
*
* @return true开启false关闭
*/
@Override
public boolean selectCaptchaEnabled() {
String captchaEnabled = SpringUtils.getAopProxy(this).selectConfigByKey("sys.account.captchaEnabled");
if (StringUtils.isEmpty(captchaEnabled)) {
return true;
}
return Convert.toBool(captchaEnabled);
}
/**
* 查询参数配置列表
*
* @param config 参数配置信息
* @return 参数配置集合
*/
@Override
public List<SysConfig> selectConfigList(SysConfig config) {
Map<String, Object> params = config.getParams();
LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
.like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
.eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
.like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
return baseMapper.selectList(lqw);
}
/**
* 新增参数配置
*
* @param config 参数配置信息
* @return 结果
*/
@CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey")
@Override
public String insertConfig(SysConfig config) {
int row = baseMapper.insert(config);
if (row > 0) {
return config.getConfigValue();
}
throw new ServiceException("操作失败");
}
/**
* 修改参数配置
*
* @param config 参数配置信息
* @return 结果
*/
@CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey")
@Override
public String updateConfig(SysConfig config) {
int row = 0;
if (config.getConfigId() != null) {
SysConfig temp = baseMapper.selectById(config.getConfigId());
if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
CacheUtils.evict(CacheNames.SYS_CONFIG, temp.getConfigKey());
}
row = baseMapper.updateById(config);
} else {
row = baseMapper.update(config, new LambdaQueryWrapper<SysConfig>()
.eq(SysConfig::getConfigKey, config.getConfigKey()));
}
if (row > 0) {
return config.getConfigValue();
}
throw new ServiceException("操作失败");
}
/**
* 批量删除参数信息
*
* @param configIds 需要删除的参数ID
*/
@Override
public void deleteConfigByIds(Long[] configIds) {
for (Long configId : configIds) {
SysConfig config = selectConfigById(configId);
if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
}
CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey());
}
baseMapper.deleteBatchIds(Arrays.asList(configIds));
}
/**
* 加载参数缓存数据
*/
@Override
public void loadingConfigCache() {
List<SysConfig> configsList = selectConfigList(new SysConfig());
configsList.forEach(config ->
CacheUtils.put(CacheNames.SYS_CONFIG, config.getConfigKey(), config.getConfigValue()));
}
/**
* 清空参数缓存数据
*/
@Override
public void clearConfigCache() {
CacheUtils.clear(CacheNames.SYS_CONFIG);
}
/**
* 重置参数缓存数据
*/
@Override
public void resetConfigCache() {
clearConfigCache();
loadingConfigCache();
}
/**
* 校验参数键名是否唯一
*
* @param config 参数配置信息
* @return 结果
*/
@Override
public boolean checkConfigKeyUnique(SysConfig config) {
long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId();
SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, config.getConfigKey()));
if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) {
return false;
}
return true;
}
/**
* 根据参数 key 获取参数值
*
* @param configKey 参数 key
* @return 参数值
*/
@Override
public String getConfigValue(String configKey) {
return SpringUtils.getAopProxy(this).selectConfigByKey(configKey);
}
}

View File

@@ -0,0 +1,61 @@
package com.klp.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.klp.common.core.domain.entity.SysDept;
import com.klp.common.helper.DataBaseHelper;
import com.klp.common.utils.StreamUtils;
import com.klp.system.domain.SysRoleDept;
import com.klp.system.mapper.SysDeptMapper;
import com.klp.system.mapper.SysRoleDeptMapper;
import com.klp.system.service.ISysDataScopeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 数据权限 实现
* <p>
* 注意: 此Service内不允许调用标注`数据权限`注解的方法
* 例如: deptMapper.selectList 此 selectList 方法标注了`数据权限`注解 会出现循环解析的问题
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service("sdss")
public class SysDataScopeServiceImpl implements ISysDataScopeService {
private final SysRoleDeptMapper roleDeptMapper;
private final SysDeptMapper deptMapper;
@Override
public String getRoleCustom(Long roleId) {
List<SysRoleDept> list = roleDeptMapper.selectList(
new LambdaQueryWrapper<SysRoleDept>()
.select(SysRoleDept::getDeptId)
.eq(SysRoleDept::getRoleId, roleId));
if (CollUtil.isNotEmpty(list)) {
return StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId()));
}
return null;
}
@Override
public String getDeptAndChild(Long deptId) {
List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
.select(SysDept::getDeptId)
.apply(DataBaseHelper.findInSet(deptId, "ancestors")));
List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
ids.add(deptId);
List<SysDept> list = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
.select(SysDept::getDeptId)
.in(SysDept::getDeptId, ids));
if (CollUtil.isNotEmpty(list)) {
return StreamUtils.join(list, d -> Convert.toStr(d.getDeptId()));
}
return null;
}
}

View File

@@ -0,0 +1,282 @@
package com.klp.system.service.impl;
import cn.dev33.satoken.context.SaHolder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.constant.CacheConstants;
import com.klp.common.constant.CacheNames;
import com.klp.common.constant.UserConstants;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.entity.SysDictData;
import com.klp.common.core.domain.entity.SysDictType;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.service.DictService;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StreamUtils;
import com.klp.common.utils.StringUtils;
import com.klp.common.utils.redis.CacheUtils;
import com.klp.common.utils.spring.SpringUtils;
import com.klp.system.mapper.SysDictDataMapper;
import com.klp.system.mapper.SysDictTypeMapper;
import com.klp.system.service.ISysDictTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 字典 业务层处理
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service
public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService {
private final SysDictTypeMapper baseMapper;
private final SysDictDataMapper dictDataMapper;
@Override
public TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType, PageQuery pageQuery) {
Map<String, Object> params = dictType.getParams();
LambdaQueryWrapper<SysDictType> lqw = new LambdaQueryWrapper<SysDictType>()
.like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
.eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
.like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime"));
Page<SysDictType> page = baseMapper.selectPage(pageQuery.build(), lqw);
return TableDataInfo.build(page);
}
/**
* 根据条件分页查询字典类型
*
* @param dictType 字典类型信息
* @return 字典类型集合信息
*/
@Override
public List<SysDictType> selectDictTypeList(SysDictType dictType) {
Map<String, Object> params = dictType.getParams();
return baseMapper.selectList(new LambdaQueryWrapper<SysDictType>()
.like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
.eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
.like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime")));
}
/**
* 根据所有字典类型
*
* @return 字典类型集合信息
*/
@Override
public List<SysDictType> selectDictTypeAll() {
return baseMapper.selectList();
}
/**
* 根据字典类型查询字典数据
*
* @param dictType 字典类型
* @return 字典数据集合信息
*/
@Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
@Override
public List<SysDictData> selectDictDataByType(String dictType) {
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType);
if (CollUtil.isNotEmpty(dictDatas)) {
return dictDatas;
}
return null;
}
/**
* 根据字典类型ID查询信息
*
* @param dictId 字典类型ID
* @return 字典类型
*/
@Override
public SysDictType selectDictTypeById(Long dictId) {
return baseMapper.selectById(dictId);
}
/**
* 根据字典类型查询信息
*
* @param dictType 字典类型
* @return 字典类型
*/
@Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
@Override
public SysDictType selectDictTypeByType(String dictType) {
return baseMapper.selectById(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getDictType, dictType));
}
/**
* 批量删除字典类型信息
*
* @param dictIds 需要删除的字典ID
*/
@Override
public void deleteDictTypeByIds(Long[] dictIds) {
for (Long dictId : dictIds) {
SysDictType dictType = selectDictTypeById(dictId);
if (dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
.eq(SysDictData::getDictType, dictType.getDictType()))) {
throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
}
CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType());
}
baseMapper.deleteBatchIds(Arrays.asList(dictIds));
}
/**
* 加载字典缓存数据
*/
@Override
public void loadingDictCache() {
List<SysDictData> dictDataList = dictDataMapper.selectList(
new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getStatus, UserConstants.DICT_NORMAL));
Map<String, List<SysDictData>> dictDataMap = StreamUtils.groupByKey(dictDataList, SysDictData::getDictType);
dictDataMap.forEach((k,v) -> {
List<SysDictData> dictList = StreamUtils.sorted(v, Comparator.comparing(SysDictData::getDictSort));
CacheUtils.put(CacheNames.SYS_DICT, k, dictList);
});
}
/**
* 清空字典缓存数据
*/
@Override
public void clearDictCache() {
CacheUtils.clear(CacheNames.SYS_DICT);
}
/**
* 重置字典缓存数据
*/
@Override
public void resetDictCache() {
clearDictCache();
loadingDictCache();
}
/**
* 新增保存字典类型信息
*
* @param dict 字典类型信息
* @return 结果
*/
@CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType")
@Override
public List<SysDictData> insertDictType(SysDictType dict) {
int row = baseMapper.insert(dict);
if (row > 0) {
return new ArrayList<>();
}
throw new ServiceException("操作失败");
}
/**
* 修改保存字典类型信息
*
* @param dict 字典类型信息
* @return 结果
*/
@CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType")
@Override
@Transactional(rollbackFor = Exception.class)
public List<SysDictData> updateDictType(SysDictType dict) {
SysDictType oldDict = baseMapper.selectById(dict.getDictId());
dictDataMapper.update(null, new LambdaUpdateWrapper<SysDictData>()
.set(SysDictData::getDictType, dict.getDictType())
.eq(SysDictData::getDictType, oldDict.getDictType()));
int row = baseMapper.updateById(dict);
if (row > 0) {
CacheUtils.evict(CacheNames.SYS_DICT, oldDict.getDictType());
return dictDataMapper.selectDictDataByType(dict.getDictType());
}
throw new ServiceException("操作失败");
}
/**
* 校验字典类型称是否唯一
*
* @param dict 字典类型
* @return 结果
*/
@Override
public boolean checkDictTypeUnique(SysDictType dict) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDictType>()
.eq(SysDictType::getDictType, dict.getDictType())
.ne(ObjectUtil.isNotNull(dict.getDictId()), SysDictType::getDictId, dict.getDictId()));
return !exist;
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
@SuppressWarnings("unchecked cast")
@Override
public String getDictLabel(String dictType, String dictValue, String separator) {
// 优先从本地缓存获取
List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
if (ObjectUtil.isNull(datas)) {
datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
}
Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictValue, SysDictData::getDictLabel);
if (StringUtils.containsAny(dictValue, separator)) {
return Arrays.stream(dictValue.split(separator))
.map(v -> map.getOrDefault(v, StringUtils.EMPTY))
.collect(Collectors.joining(separator));
} else {
return map.getOrDefault(dictValue, StringUtils.EMPTY);
}
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
@SuppressWarnings("unchecked cast")
@Override
public String getDictValue(String dictType, String dictLabel, String separator) {
// 优先从本地缓存获取
List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
if (ObjectUtil.isNull(datas)) {
datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
}
Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictLabel, SysDictData::getDictValue);
if (StringUtils.containsAny(dictLabel, separator)) {
return Arrays.stream(dictLabel.split(separator))
.map(l -> map.getOrDefault(l, StringUtils.EMPTY))
.collect(Collectors.joining(separator));
} else {
return map.getOrDefault(dictLabel, StringUtils.EMPTY);
}
}
}

View File

@@ -0,0 +1,155 @@
package com.klp.system.service.impl;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.constant.Constants;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.event.LogininforEvent;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.utils.ServletUtils;
import com.klp.common.utils.StringUtils;
import com.klp.common.utils.ip.AddressUtils;
import com.klp.system.domain.SysLogininfor;
import com.klp.system.mapper.SysLogininforMapper;
import com.klp.system.service.ISysLogininforService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 系统访问日志情况信息 服务层处理
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Slf4j
@Service
public class SysLogininforServiceImpl implements ISysLogininforService {
private final SysLogininforMapper baseMapper;
/**
* 记录登录信息
*
* @param logininforEvent 登录事件
*/
@Async
@EventListener
public void recordLogininfor(LogininforEvent logininforEvent) {
HttpServletRequest request = logininforEvent.getRequest();
final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
final String ip = ServletUtils.getClientIP(request);
String address = AddressUtils.getRealAddressByIP(ip);
StringBuilder s = new StringBuilder();
s.append(getBlock(ip));
s.append(address);
s.append(getBlock(logininforEvent.getUsername()));
s.append(getBlock(logininforEvent.getStatus()));
s.append(getBlock(logininforEvent.getMessage()));
// 打印信息到日志
log.info(s.toString(), logininforEvent.getArgs());
// 获取客户端操作系统
String os = userAgent.getOs().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
// 封装对象
SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(logininforEvent.getUsername());
logininfor.setIpaddr(ip);
logininfor.setLoginLocation(address);
logininfor.setBrowser(browser);
logininfor.setOs(os);
logininfor.setMsg(logininforEvent.getMessage());
// 日志状态
if (StringUtils.equalsAny(logininforEvent.getStatus(), Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
logininfor.setStatus(Constants.SUCCESS);
} else if (Constants.LOGIN_FAIL.equals(logininforEvent.getStatus())) {
logininfor.setStatus(Constants.FAIL);
}
// 插入数据
insertLogininfor(logininfor);
}
private String getBlock(Object msg) {
if (msg == null) {
msg = "";
}
return "[" + msg.toString() + "]";
}
@Override
public TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor, PageQuery pageQuery) {
Map<String, Object> params = logininfor.getParams();
LambdaQueryWrapper<SysLogininfor> lqw = new LambdaQueryWrapper<SysLogininfor>()
.like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
.eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
.like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"));
if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
pageQuery.setOrderByColumn("info_id");
pageQuery.setIsAsc("desc");
}
Page<SysLogininfor> page = baseMapper.selectPage(pageQuery.build(), lqw);
return TableDataInfo.build(page);
}
/**
* 新增系统登录日志
*
* @param logininfor 访问日志对象
*/
@Override
public void insertLogininfor(SysLogininfor logininfor) {
logininfor.setLoginTime(new Date());
baseMapper.insert(logininfor);
}
/**
* 查询系统登录日志集合
*
* @param logininfor 访问日志对象
* @return 登录记录集合
*/
@Override
public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor) {
Map<String, Object> params = logininfor.getParams();
return baseMapper.selectList(new LambdaQueryWrapper<SysLogininfor>()
.like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
.eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
.like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"))
.orderByDesc(SysLogininfor::getInfoId));
}
/**
* 批量删除系统登录日志
*
* @param infoIds 需要删除的登录日志ID
* @return 结果
*/
@Override
public int deleteLogininforByIds(Long[] infoIds) {
return baseMapper.deleteBatchIds(Arrays.asList(infoIds));
}
/**
* 清空系统登录日志
*/
@Override
public void cleanLogininfor() {
baseMapper.delete(new LambdaQueryWrapper<>());
}
}

View File

@@ -0,0 +1,177 @@
package com.klp.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import com.klp.system.domain.SysPost;
import com.klp.system.domain.SysUserPost;
import com.klp.system.mapper.SysPostMapper;
import com.klp.system.mapper.SysUserPostMapper;
import com.klp.system.service.ISysPostService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
/**
* 岗位信息 服务层处理
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service
public class SysPostServiceImpl implements ISysPostService {
private final SysPostMapper baseMapper;
private final SysUserPostMapper userPostMapper;
@Override
public TableDataInfo<SysPost> selectPagePostList(SysPost post, PageQuery pageQuery) {
LambdaQueryWrapper<SysPost> lqw = new LambdaQueryWrapper<SysPost>()
.like(StringUtils.isNotBlank(post.getPostCode()), SysPost::getPostCode, post.getPostCode())
.eq(StringUtils.isNotBlank(post.getStatus()), SysPost::getStatus, post.getStatus())
.like(StringUtils.isNotBlank(post.getPostName()), SysPost::getPostName, post.getPostName());
Page<SysPost> page = baseMapper.selectPage(pageQuery.build(), lqw);
return TableDataInfo.build(page);
}
/**
* 查询岗位信息集合
*
* @param post 岗位信息
* @return 岗位信息集合
*/
@Override
public List<SysPost> selectPostList(SysPost post) {
return baseMapper.selectList(new LambdaQueryWrapper<SysPost>()
.like(StringUtils.isNotBlank(post.getPostCode()), SysPost::getPostCode, post.getPostCode())
.eq(StringUtils.isNotBlank(post.getStatus()), SysPost::getStatus, post.getStatus())
.like(StringUtils.isNotBlank(post.getPostName()), SysPost::getPostName, post.getPostName()));
}
/**
* 查询所有岗位
*
* @return 岗位列表
*/
@Override
public List<SysPost> selectPostAll() {
return baseMapper.selectList();
}
/**
* 通过岗位ID查询岗位信息
*
* @param postId 岗位ID
* @return 角色对象信息
*/
@Override
public SysPost selectPostById(Long postId) {
return baseMapper.selectById(postId);
}
/**
* 根据用户ID获取岗位选择框列表
*
* @param userId 用户ID
* @return 选中岗位ID列表
*/
@Override
public List<Long> selectPostListByUserId(Long userId) {
return baseMapper.selectPostListByUserId(userId);
}
/**
* 校验岗位名称是否唯一
*
* @param post 岗位信息
* @return 结果
*/
@Override
public boolean checkPostNameUnique(SysPost post) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>()
.eq(SysPost::getPostName, post.getPostName())
.ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId()));
return !exist;
}
/**
* 校验岗位编码是否唯一
*
* @param post 岗位信息
* @return 结果
*/
@Override
public boolean checkPostCodeUnique(SysPost post) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>()
.eq(SysPost::getPostCode, post.getPostCode())
.ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId()));
return !exist;
}
/**
* 通过岗位ID查询岗位使用数量
*
* @param postId 岗位ID
* @return 结果
*/
@Override
public long countUserPostById(Long postId) {
return userPostMapper.selectCount(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId, postId));
}
/**
* 删除岗位信息
*
* @param postId 岗位ID
* @return 结果
*/
@Override
public int deletePostById(Long postId) {
return baseMapper.deleteById(postId);
}
/**
* 批量删除岗位信息
*
* @param postIds 需要删除的岗位ID
* @return 结果
*/
@Override
public int deletePostByIds(Long[] postIds) {
for (Long postId : postIds) {
SysPost post = selectPostById(postId);
if (countUserPostById(postId) > 0) {
throw new ServiceException(String.format("%1$s已分配,不能删除", post.getPostName()));
}
}
return baseMapper.deleteBatchIds(Arrays.asList(postIds));
}
/**
* 新增保存岗位信息
*
* @param post 岗位信息
* @return 结果
*/
@Override
public int insertPost(SysPost post) {
return baseMapper.insert(post);
}
/**
* 修改保存岗位信息
*
* @param post 岗位信息
* @return 结果
*/
@Override
public int updatePost(SysPost post) {
return baseMapper.updateById(post);
}
}

View File

@@ -0,0 +1,26 @@
package com.klp.system.service.impl;
import com.klp.common.core.service.SensitiveService;
import com.klp.common.helper.LoginHelper;
import org.springframework.stereotype.Service;
/**
* 脱敏服务
* 默认管理员不过滤
* 需自行根据业务重写实现
*
* @author Lion Li
* @version 3.6.0
*/
@Service
public class SysSensitiveServiceImpl implements SensitiveService {
/**
* 是否脱敏
*/
@Override
public boolean isSensitive() {
return !LoginHelper.isAdmin();
}
}

View File

@@ -0,0 +1,493 @@
package com.klp.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.constant.CacheNames;
import com.klp.common.constant.UserConstants;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.entity.SysDept;
import com.klp.common.core.domain.entity.SysRole;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.service.UserService;
import com.klp.common.exception.ServiceException;
import com.klp.common.helper.DataBaseHelper;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.StreamUtils;
import com.klp.common.utils.StringUtils;
import com.klp.system.domain.SysPost;
import com.klp.system.domain.SysUserPost;
import com.klp.system.domain.SysUserRole;
import com.klp.system.mapper.*;
import com.klp.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 用户 业务层处理
*
* @author Lion Li
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class SysUserServiceImpl implements ISysUserService, UserService {
private final SysUserMapper baseMapper;
private final SysDeptMapper deptMapper;
private final SysRoleMapper roleMapper;
private final SysPostMapper postMapper;
private final SysUserRoleMapper userRoleMapper;
private final SysUserPostMapper userPostMapper;
@Override
public TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery) {
Page<SysUser> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user));
return TableDataInfo.build(page);
}
/**
* 根据条件分页查询用户列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
@Override
public List<SysUser> selectUserList(SysUser user) {
return baseMapper.selectUserList(this.buildQueryWrapper(user));
}
private Wrapper<SysUser> buildQueryWrapper(SysUser user) {
Map<String, Object> params = user.getParams();
QueryWrapper<SysUser> wrapper = Wrappers.query();
wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
.eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId())
.like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
.eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
.like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber())
.between(params.get("beginTime") != null && params.get("endTime") != null,
"u.create_time", params.get("beginTime"), params.get("endTime"))
.and(ObjectUtil.isNotNull(user.getDeptId()), w -> {
List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
.select(SysDept::getDeptId)
.apply(DataBaseHelper.findInSet(user.getDeptId(), "ancestors")));
List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
ids.add(user.getDeptId());
w.in("u.dept_id", ids);
});
return wrapper;
}
/**
* 根据条件分页查询已分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
@Override
public TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery) {
QueryWrapper<SysUser> wrapper = Wrappers.query();
wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
.eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId())
.like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
.eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
.like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
Page<SysUser> page = baseMapper.selectAllocatedList(pageQuery.build(), wrapper);
return TableDataInfo.build(page);
}
/**
* 根据条件分页查询未分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
@Override
public TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery) {
List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(user.getRoleId());
QueryWrapper<SysUser> wrapper = Wrappers.query();
wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
.and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id"))
.notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds)
.like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
.like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
Page<SysUser> page = baseMapper.selectUnallocatedList(pageQuery.build(), wrapper);
return TableDataInfo.build(page);
}
/**
* 通过用户名查询用户
*
* @param userName 用户名
* @return 用户对象信息
*/
@Override
public SysUser selectUserByUserName(String userName) {
return baseMapper.selectUserByUserName(userName);
}
/**
* 通过手机号查询用户
*
* @param phonenumber 手机号
* @return 用户对象信息
*/
@Override
public SysUser selectUserByPhonenumber(String phonenumber) {
return baseMapper.selectUserByPhonenumber(phonenumber);
}
/**
* 通过用户ID查询用户
*
* @param userId 用户ID
* @return 用户对象信息
*/
@Override
public SysUser selectUserById(Long userId) {
return baseMapper.selectUserById(userId);
}
/**
* 查询用户所属角色组
*
* @param userName 用户名
* @return 结果
*/
@Override
public String selectUserRoleGroup(String userName) {
List<SysRole> list = roleMapper.selectRolesByUserName(userName);
if (CollUtil.isEmpty(list)) {
return StringUtils.EMPTY;
}
return StreamUtils.join(list, SysRole::getRoleName);
}
/**
* 查询用户所属岗位组
*
* @param userName 用户名
* @return 结果
*/
@Override
public String selectUserPostGroup(String userName) {
List<SysPost> list = postMapper.selectPostsByUserName(userName);
if (CollUtil.isEmpty(list)) {
return StringUtils.EMPTY;
}
return StreamUtils.join(list, SysPost::getPostName);
}
/**
* 校验用户名称是否唯一
*
* @param user 用户信息
* @return 结果
*/
@Override
public boolean checkUserNameUnique(SysUser user) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getUserName, user.getUserName())
.ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
return !exist;
}
/**
* 校验手机号码是否唯一
*
* @param user 用户信息
*/
@Override
public boolean checkPhoneUnique(SysUser user) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getPhonenumber, user.getPhonenumber())
.ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
return !exist;
}
/**
* 校验email是否唯一
*
* @param user 用户信息
*/
@Override
public boolean checkEmailUnique(SysUser user) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getEmail, user.getEmail())
.ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
return !exist;
}
/**
* 校验用户是否允许操作
*
* @param user 用户信息
*/
@Override
public void checkUserAllowed(SysUser user) {
if (ObjectUtil.isNotNull(user.getUserId()) && user.isAdmin()) {
throw new ServiceException("不允许操作超级管理员用户");
}
}
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
@Override
public void checkUserDataScope(Long userId) {
if (!LoginHelper.isAdmin()) {
SysUser user = new SysUser();
user.setUserId(userId);
List<SysUser> users = this.selectUserList(user);
if (CollUtil.isEmpty(users)) {
throw new ServiceException("没有权限访问用户数据!");
}
}
}
/**
* 新增保存用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertUser(SysUser user) {
// 新增用户信息
int rows = baseMapper.insert(user);
// 新增用户岗位关联
insertUserPost(user);
// 新增用户与角色管理
insertUserRole(user);
return rows;
}
/**
* 注册用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
public boolean registerUser(SysUser user) {
user.setCreateBy(user.getUserName());
user.setUpdateBy(user.getUserName());
return baseMapper.insert(user) > 0;
}
/**
* 修改保存用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int updateUser(SysUser user) {
Long userId = user.getUserId();
// 删除用户与角色关联
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
// 新增用户与角色管理
insertUserRole(user);
// 删除用户与岗位关联
userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, userId));
// 新增用户与岗位管理
insertUserPost(user);
return baseMapper.updateById(user);
}
/**
* 用户授权角色
*
* @param userId 用户ID
* @param roleIds 角色组
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void insertUserAuth(Long userId, Long[] roleIds) {
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
.eq(SysUserRole::getUserId, userId));
insertUserRole(userId, roleIds);
}
/**
* 修改用户状态
*
* @param user 用户信息
* @return 结果
*/
@Override
public int updateUserStatus(SysUser user) {
return baseMapper.updateById(user);
}
/**
* 修改用户基本信息
*
* @param user 用户信息
* @return 结果
*/
@Override
public int updateUserProfile(SysUser user) {
return baseMapper.updateById(user);
}
/**
* 修改用户头像
*
* @param userName 用户名
* @param avatar 头像地址
* @return 结果
*/
@Override
public boolean updateUserAvatar(String userName, String avatar) {
return baseMapper.update(null,
new LambdaUpdateWrapper<SysUser>()
.set(SysUser::getAvatar, avatar)
.eq(SysUser::getUserName, userName)) > 0;
}
/**
* 重置用户密码
*
* @param user 用户信息
* @return 结果
*/
@Override
public int resetPwd(SysUser user) {
return baseMapper.updateById(user);
}
/**
* 重置用户密码
*
* @param userName 用户名
* @param password 密码
* @return 结果
*/
@Override
public int resetUserPwd(String userName, String password) {
return baseMapper.update(null,
new LambdaUpdateWrapper<SysUser>()
.set(SysUser::getPassword, password)
.eq(SysUser::getUserName, userName));
}
/**
* 新增用户角色信息
*
* @param user 用户对象
*/
public void insertUserRole(SysUser user) {
this.insertUserRole(user.getUserId(), user.getRoleIds());
}
/**
* 新增用户岗位信息
*
* @param user 用户对象
*/
public void insertUserPost(SysUser user) {
Long[] posts = user.getPostIds();
if (ArrayUtil.isNotEmpty(posts)) {
// 新增用户与岗位管理
List<SysUserPost> list = StreamUtils.toList(Arrays.asList(posts), postId -> {
SysUserPost up = new SysUserPost();
up.setUserId(user.getUserId());
up.setPostId(postId);
return up;
});
userPostMapper.insertBatch(list);
}
}
/**
* 新增用户角色信息
*
* @param userId 用户ID
* @param roleIds 角色组
*/
public void insertUserRole(Long userId, Long[] roleIds) {
if (ArrayUtil.isNotEmpty(roleIds)) {
// 新增用户与角色管理
List<SysUserRole> list = StreamUtils.toList(Arrays.asList(roleIds), roleId -> {
SysUserRole ur = new SysUserRole();
ur.setUserId(userId);
ur.setRoleId(roleId);
return ur;
});
userRoleMapper.insertBatch(list);
}
}
/**
* 通过用户ID删除用户
*
* @param userId 用户ID
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteUserById(Long userId) {
// 删除用户与角色关联
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
// 删除用户与岗位表
userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, userId));
return baseMapper.deleteById(userId);
}
/**
* 批量删除用户信息
*
* @param userIds 需要删除的用户ID
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteUserByIds(Long[] userIds) {
for (Long userId : userIds) {
checkUserAllowed(new SysUser(userId));
checkUserDataScope(userId);
}
List<Long> ids = Arrays.asList(userIds);
// 删除用户与角色关联
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, ids));
// 删除用户与岗位表
userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().in(SysUserPost::getUserId, ids));
return baseMapper.deleteBatchIds(ids);
}
@Cacheable(cacheNames = CacheNames.SYS_USER_NAME, key = "#userId")
@Override
public String selectUserNameById(Long userId) {
SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserName).eq(SysUser::getUserId, userId));
return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName();
}
@Cacheable(cacheNames = CacheNames.SYS_NICK_NAME, key = "#userId")
@Override
public String selectNickNameById(Long userId) {
SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getNickName).eq(SysUser::getUserId, userId));
return ObjectUtil.isNull(sysUser) ? null : sysUser.getNickName();
}
}

View File

@@ -0,0 +1,74 @@
package com.klp.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 流程抄送对象 wf_copy
*
* @author KonBAI
* @date 2022-05-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_copy")
public class WfCopy extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 抄送主键
*/
@TableId(value = "copy_id")
private Long copyId;
/**
* 抄送标题
*/
private String title;
/**
* 流程主键
*/
private String processId;
/**
* 流程名称
*/
private String processName;
/**
* 流程分类主键
*/
private String categoryId;
/**
* 部署主键
*/
private String deploymentId;
/**
* 流程实例主键
*/
private String instanceId;
/**
* 任务主键
*/
private String taskId;
/**
* 用户主键
*/
private Long userId;
/**
* 发起人Id
*/
private Long originatorId;
/**
* 发起人名称
*/
private String originatorName;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
}

View File

@@ -0,0 +1,46 @@
package com.klp.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 流程实例关联表单对象 sys_instance_form
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@Data
@TableName("wf_deploy_form")
public class WfDeployForm {
private static final long serialVersionUID = 1L;
/**
* 流程部署主键
*/
private String deployId;
/**
* 表单Key
*/
private String formKey;
/**
* 节点Key
*/
private String nodeKey;
/**
* 表单名称
*/
private String formName;
/**
* 节点名称
*/
private String nodeName;
/**
* 表单内容
*/
private String content;
}

View File

@@ -0,0 +1,57 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 待签流程对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfClaimTaskExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 任务编号
*/
@ExcelProperty(value = "任务编号")
private String taskId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String procDefName;
/**
* 任务节点
*/
@ExcelProperty(value = "任务节点")
private String taskName;
/**
* 流程版本
*/
@ExcelProperty(value = "流程版本")
private int procDefVersion;
/**
* 流程发起人名称
*/
@ExcelProperty(value = "流程发起人")
private String startUserName;
/**
* 接收时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "接收时间")
private Date createTime;
}

View File

@@ -0,0 +1,59 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 流程模型对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfModelExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 模型ID
*/
@ExcelProperty(value = "模型ID")
private String modelId;
/**
* 模型Key
*/
@ExcelProperty(value = "模型Key")
private String modelKey;
/**
* 模型名称
*/
@ExcelProperty(value = "模型名称")
private String modelName;
/**
* 分类编码
*/
@ExcelProperty(value = "分类编码")
private String category;
/**
* 流程分类
*/
@ExcelProperty(value = "流程分类")
private String categoryName;
/**
* 模型版本
*/
@ExcelProperty(value = "模型版本")
private Integer version;
/**
* 模型描述
*/
@ExcelProperty(value = "模型描述")
private String description;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,75 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 我拥有流程对象导出VO
*
* @author konbai
*/
@Data
@NoArgsConstructor
public class WfOwnTaskExportVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 流程实例ID
*/
@ExcelProperty(value = "流程编号")
private String procInsId;
/**
* 流程名称
*/
@ExcelProperty(value = "流程名称")
private String procDefName;
/**
* 流程类别
*/
@ExcelProperty(value = "流程类别")
private String category;
/**
* 流程版本
*/
@ExcelProperty(value = "流程版本")
private int procDefVersion;
/**
* 提交时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "提交时间")
private Date createTime;
/**
* 流程状态
*/
@ExcelProperty(value = "流程状态")
private String status;
/**
* 任务耗时
*/
@ExcelProperty(value = "任务耗时")
private String duration;
/**
* 当前节点
*/
@ExcelProperty(value = "当前节点")
private String taskName;
/**
* 任务完成时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date finishTime;
}

View File

@@ -0,0 +1,132 @@
package com.klp.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.workflow.domain.dto.WfCommentDto;
import lombok.Data;
import org.flowable.engine.task.Comment;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 工作流任务视图对象
*
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
@Data
@ExcelIgnoreUnannotated
public class WfTaskVo implements Serializable {
/**
* 任务编号
*/
private String taskId;
/**
* 任务名称
*/
private String taskName;
/**
* 任务Key
*/
private String taskDefKey;
/**
* 任务执行人Id
*/
private Long assigneeId;
/**
* 部门名称
*/
@Deprecated
private String deptName;
/**
* 流程发起人部门名称
*/
@Deprecated
private String startDeptName;
/**
* 任务执行人名称
*/
private String assigneeName;
/**
* 流程发起人Id
*/
private Long startUserId;
/**
* 流程发起人名称
*/
private String startUserName;
/**
* 流程类型
*/
private String category;
/**
* 流程变量信息
*/
private Object procVars;
/**
* 局部变量信息
*/
private Object taskLocalVars;
/**
* 流程部署编号
*/
private String deployId;
/**
* 流程ID
*/
private String procDefId;
/**
* 流程key
*/
private String procDefKey;
/**
* 流程定义名称
*/
private String procDefName;
/**
* 流程定义内置使用版本
*/
private int procDefVersion;
/**
* 流程实例ID
*/
private String procInsId;
/**
* 历史流程实例ID
*/
private String hisProcInsId;
/**
* 任务耗时
*/
private String duration;
/**
* 任务意见
*/
private WfCommentDto comment;
/**
* 任务意见
*/
private List<Comment> commentList;
/**
* 候选执行人
*/
private String candidate;
/**
* 任务创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 任务完成时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date finishTime;
/**
* 流程状态
*/
private String processStatus;
}

View File

@@ -0,0 +1,15 @@
package com.klp.workflow.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.workflow.domain.WfCopy;
import com.klp.workflow.domain.vo.WfCopyVo;
/**
* 流程抄送Mapper接口
*
* @author KonBAI
* @date 2022-05-19
*/
public interface WfCopyMapper extends BaseMapperPlus<WfCopyMapper, WfCopy, WfCopyVo> {
}

View File

@@ -0,0 +1,117 @@
package com.klp.workflow.service;
import com.klp.workflow.domain.bo.WfTaskBo;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.runtime.ProcessInstance;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* @author KonBAI
* @createTime 2022/3/10 00:12
*/
public interface IWfTaskService {
/**
* 审批任务
*
* @param task 请求实体参数
*/
void complete(WfTaskBo task);
/**
* 拒绝任务
*
* @param taskBo
*/
void taskReject(WfTaskBo taskBo);
/**
* 退回任务
*
* @param bo 请求实体参数
*/
void taskReturn(WfTaskBo bo);
/**
* 获取所有可回退的节点
*
* @param bo
* @return
*/
List<FlowElement> findReturnTaskList(WfTaskBo bo);
/**
* 删除任务
*
* @param bo 请求实体参数
*/
void deleteTask(WfTaskBo bo);
/**
* 认领/签收任务
*
* @param bo 请求实体参数
*/
void claim(WfTaskBo bo);
/**
* 取消认领/签收任务
*
* @param bo 请求实体参数
*/
void unClaim(WfTaskBo bo);
/**
* 委派任务
*
* @param bo 请求实体参数
*/
void delegateTask(WfTaskBo bo);
/**
* 转办任务
*
* @param bo 请求实体参数
*/
void transferTask(WfTaskBo bo);
/**
* 取消申请
* @param bo
* @return
*/
void stopProcess(WfTaskBo bo);
/**
* 撤回流程
* @param bo
* @return
*/
void revokeProcess(WfTaskBo bo);
/**
* 获取流程过程图
* @param processId
* @return
*/
InputStream diagram(String processId);
/**
* 获取流程变量
* @param taskId 任务ID
* @return 流程变量
*/
Map<String, Object> getProcessVariables(String taskId);
/**
* 启动第一个任务
* @param processInstance 流程实例
* @param variables 流程参数
*/
void startFirstTask(ProcessInstance processInstance, Map<String, Object> variables);
}

View File

@@ -0,0 +1,93 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.utils.StringUtils;
import com.klp.workflow.domain.WfCategory;
import com.klp.workflow.domain.vo.WfCategoryVo;
import com.klp.workflow.mapper.WfCategoryMapper;
import com.klp.workflow.service.IWfCategoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 流程分类Service业务层处理
*
* @author KonBAI
* @date 2022-01-15
*/
@RequiredArgsConstructor
@Service
public class WfCategoryServiceImpl implements IWfCategoryService {
private final WfCategoryMapper baseMapper;
@Override
public WfCategoryVo queryById(Long categoryId){
return baseMapper.selectVoById(categoryId);
}
@Override
public TableDataInfo<WfCategoryVo> queryPageList(WfCategory category, PageQuery pageQuery) {
LambdaQueryWrapper<WfCategory> lqw = buildQueryWrapper(category);
Page<WfCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<WfCategoryVo> queryList(WfCategory category) {
LambdaQueryWrapper<WfCategory> lqw = buildQueryWrapper(category);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WfCategory> buildQueryWrapper(WfCategory category) {
Map<String, Object> params = category.getParams();
LambdaQueryWrapper<WfCategory> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(category.getCategoryName()), WfCategory::getCategoryName, category.getCategoryName());
lqw.eq(StringUtils.isNotBlank(category.getCode()), WfCategory::getCode, category.getCode());
return lqw;
}
@Override
public int insertCategory(WfCategory categoryBo) {
WfCategory add = BeanUtil.toBean(categoryBo, WfCategory.class);
return baseMapper.insert(add);
}
@Override
public int updateCategory(WfCategory categoryBo) {
WfCategory update = BeanUtil.toBean(categoryBo, WfCategory.class);
return baseMapper.updateById(update);
}
@Override
public int deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids);
}
/**
* 校验分类编码是否唯一
*
* @param category 流程分类
* @return 结果
*/
@Override
public boolean checkCategoryCodeUnique(WfCategory category) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<WfCategory>()
.eq(WfCategory::getCode, category.getCode())
.ne(ObjectUtil.isNotNull(category.getCategoryId()), WfCategory::getCategoryId, category.getCategoryId()));
return !exist;
}
}

View File

@@ -0,0 +1,114 @@
package com.klp.workflow.service.impl;
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.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.StringUtils;
import com.klp.workflow.domain.WfCopy;
import com.klp.workflow.domain.bo.WfCopyBo;
import com.klp.workflow.domain.bo.WfTaskBo;
import com.klp.workflow.domain.vo.WfCopyVo;
import com.klp.workflow.mapper.WfCopyMapper;
import com.klp.workflow.service.IWfCopyService;
import lombok.RequiredArgsConstructor;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 流程抄送Service业务层处理
*
* @author KonBAI
* @date 2022-05-19
*/
@RequiredArgsConstructor
@Service
public class WfCopyServiceImpl implements IWfCopyService {
private final WfCopyMapper baseMapper;
private final HistoryService historyService;
/**
* 查询流程抄送
*
* @param copyId 流程抄送主键
* @return 流程抄送
*/
@Override
public WfCopyVo queryById(Long copyId){
return baseMapper.selectVoById(copyId);
}
/**
* 查询流程抄送列表
*
* @param bo 流程抄送
* @return 流程抄送
*/
@Override
public TableDataInfo<WfCopyVo> selectPageList(WfCopyBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WfCopy> lqw = buildQueryWrapper(bo);
lqw.orderByDesc(WfCopy::getCreateTime);
Page<WfCopyVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询流程抄送列表
*
* @param bo 流程抄送
* @return 流程抄送
*/
@Override
public List<WfCopyVo> selectList(WfCopyBo bo) {
LambdaQueryWrapper<WfCopy> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WfCopy> buildQueryWrapper(WfCopyBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WfCopy> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getUserId() != null, WfCopy::getUserId, bo.getUserId());
lqw.like(StringUtils.isNotBlank(bo.getProcessName()), WfCopy::getProcessName, bo.getProcessName());
lqw.like(StringUtils.isNotBlank(bo.getOriginatorName()), WfCopy::getOriginatorName, bo.getOriginatorName());
return lqw;
}
@Override
public Boolean makeCopy(WfTaskBo taskBo) {
if (StringUtils.isBlank(taskBo.getCopyUserIds())) {
// 若抄送用户为空,则不需要处理,返回成功
return true;
}
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(taskBo.getProcInsId()).singleResult();
String[] ids = taskBo.getCopyUserIds().split(",");
List<WfCopy> copyList = new ArrayList<>(ids.length);
Long originatorId = LoginHelper.getUserId();
String originatorName = LoginHelper.getNickName();
String title = historicProcessInstance.getProcessDefinitionName() + "-" + taskBo.getTaskName();
for (String id : ids) {
Long userId = Long.valueOf(id);
WfCopy copy = new WfCopy();
copy.setTitle(title);
copy.setProcessId(historicProcessInstance.getProcessDefinitionId());
copy.setProcessName(historicProcessInstance.getProcessDefinitionName());
copy.setDeploymentId(historicProcessInstance.getDeploymentId());
copy.setInstanceId(taskBo.getProcInsId());
copy.setTaskId(taskBo.getTaskId());
copy.setUserId(userId);
copy.setOriginatorId(originatorId);
copy.setOriginatorName(originatorName);
copyList.add(copy);
}
return baseMapper.insertBatch(copyList);
}
}

View File

@@ -0,0 +1,134 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import com.klp.flowable.utils.ModelUtils;
import com.klp.workflow.domain.WfDeployForm;
import com.klp.workflow.domain.WfForm;
import com.klp.workflow.domain.vo.WfFormVo;
import com.klp.workflow.mapper.WfDeployFormMapper;
import com.klp.workflow.mapper.WfFormMapper;
import com.klp.workflow.service.IWfDeployFormService;
import lombok.RequiredArgsConstructor;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 流程实例关联表单Service业务层处理
*
* @author KonBAI
* @createTime 2022/3/7 22:07
*/
@RequiredArgsConstructor
@Service
public class WfDeployFormServiceImpl implements IWfDeployFormService {
private final WfDeployFormMapper baseMapper;
private final WfFormMapper formMapper;
/**
* 新增流程实例关联表单
*
* @param deployForm 流程实例关联表单
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertWfDeployForm(WfDeployForm deployForm) {
// 删除部署流程和表单的关联关系
baseMapper.delete(new LambdaQueryWrapper<WfDeployForm>().eq(WfDeployForm::getDeployId, deployForm.getDeployId()));
// 新增部署流程和表单关系
return baseMapper.insert(deployForm);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean saveInternalDeployForm(String deployId, BpmnModel bpmnModel) {
List<WfDeployForm> deployFormList = new ArrayList<>();
// 获取开始节点
StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
if (ObjectUtil.isNull(startEvent)) {
throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
}
// 保存开始节点表单信息
WfDeployForm startDeployForm = buildDeployForm(deployId, startEvent);
if (ObjectUtil.isNotNull(startDeployForm)) {
deployFormList.add(startDeployForm);
}
// 保存用户节点表单信息
Collection<UserTask> userTasks = ModelUtils.getAllUserTaskEvent(bpmnModel);
if (CollUtil.isNotEmpty(userTasks)) {
for (UserTask userTask : userTasks) {
WfDeployForm userTaskDeployForm = buildDeployForm(deployId, userTask);
if (ObjectUtil.isNotNull(userTaskDeployForm)) {
deployFormList.add(userTaskDeployForm);
}
}
}
// 批量新增部署流程和表单关联信息
return baseMapper.insertBatch(deployFormList);
}
/**
* 查询流程挂着的表单
*
* @param deployId
* @return
*/
@Override
public WfFormVo selectDeployFormByDeployId(String deployId) {
QueryWrapper<WfForm> wrapper = Wrappers.query();
wrapper.eq("t2.deploy_id", deployId);
List<WfFormVo> list = formMapper.selectFormVoList(wrapper);
if (ObjectUtil.isNotEmpty(list)) {
if (list.size() != 1) {
throw new ServiceException("表单信息查询错误");
} else {
return list.get(0);
}
} else {
return null;
}
}
/**
* 构建部署表单关联信息对象
* @param deployId 部署ID
* @param node 节点信息
* @return 部署表单关联对象。若无表单信息formKey则返回null
*/
private WfDeployForm buildDeployForm(String deployId, FlowNode node) {
String formKey = ModelUtils.getFormKey(node);
if (StringUtils.isEmpty(formKey)) {
return null;
}
Long formId = Convert.toLong(StringUtils.substringAfter(formKey, "key_"));
WfForm wfForm = formMapper.selectById(formId);
if (ObjectUtil.isNull(wfForm)) {
throw new ServiceException("表单信息查询错误");
}
WfDeployForm deployForm = new WfDeployForm();
deployForm.setDeployId(deployId);
deployForm.setFormKey(formKey);
deployForm.setNodeKey(node.getId());
deployForm.setFormName(wfForm.getFormName());
deployForm.setNodeName(node.getName());
deployForm.setContent(wfForm.getContent());
return deployForm;
}
}

View File

@@ -0,0 +1,146 @@
package com.klp.workflow.service.impl;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.flowable.core.domain.ProcessQuery;
import com.klp.flowable.utils.ProcessUtils;
import com.klp.workflow.domain.WfDeployForm;
import com.klp.workflow.domain.vo.WfDeployVo;
import com.klp.workflow.mapper.WfDeployFormMapper;
import com.klp.workflow.service.IWfDeployService;
import lombok.RequiredArgsConstructor;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author KonBAI
* @createTime 2022/6/30 9:04
*/
@RequiredArgsConstructor
@Service
public class WfDeployServiceImpl implements IWfDeployService {
private final RepositoryService repositoryService;
private final WfDeployFormMapper deployFormMapper;
@Override
public TableDataInfo<WfDeployVo> queryPageList(ProcessQuery processQuery, PageQuery pageQuery) {
// 流程定义列表数据查询
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
.latestVersion()
.orderByProcessDefinitionKey()
.asc();
// 构建搜索条件
ProcessUtils.buildProcessSearch(processDefinitionQuery, processQuery);
long pageTotal = processDefinitionQuery.count();
if (pageTotal <= 0) {
return TableDataInfo.build();
}
int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
List<ProcessDefinition> definitionList = processDefinitionQuery.listPage(offset, pageQuery.getPageSize());
List<WfDeployVo> deployVoList = new ArrayList<>(definitionList.size());
for (ProcessDefinition processDefinition : definitionList) {
String deploymentId = processDefinition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
WfDeployVo vo = new WfDeployVo();
vo.setDefinitionId(processDefinition.getId());
vo.setProcessKey(processDefinition.getKey());
vo.setProcessName(processDefinition.getName());
vo.setVersion(processDefinition.getVersion());
vo.setCategory(processDefinition.getCategory());
vo.setDeploymentId(processDefinition.getDeploymentId());
vo.setSuspended(processDefinition.isSuspended());
// 流程部署信息
vo.setCategory(deployment.getCategory());
vo.setDeploymentTime(deployment.getDeploymentTime());
deployVoList.add(vo);
}
Page<WfDeployVo> page = new Page<>();
page.setRecords(deployVoList);
page.setTotal(pageTotal);
return TableDataInfo.build(page);
}
@Override
public TableDataInfo<WfDeployVo> queryPublishList(String processKey, PageQuery pageQuery) {
// 创建查询条件
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(processKey)
.orderByProcessDefinitionVersion()
.desc();
long pageTotal = processDefinitionQuery.count();
if (pageTotal <= 0) {
return TableDataInfo.build();
}
// 根据查询条件,查询所有版本
int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1);
List<ProcessDefinition> processDefinitionList = processDefinitionQuery
.listPage(offset, pageQuery.getPageSize());
List<WfDeployVo> deployVoList = processDefinitionList.stream().map(item -> {
WfDeployVo vo = new WfDeployVo();
vo.setDefinitionId(item.getId());
vo.setProcessKey(item.getKey());
vo.setProcessName(item.getName());
vo.setVersion(item.getVersion());
vo.setCategory(item.getCategory());
vo.setDeploymentId(item.getDeploymentId());
vo.setSuspended(item.isSuspended());
return vo;
}).collect(Collectors.toList());
Page<WfDeployVo> page = new Page<>();
page.setRecords(deployVoList);
page.setTotal(pageTotal);
return TableDataInfo.build(page);
}
/**
* 激活或挂起流程
*
* @param state 状态
* @param definitionId 流程定义ID
*/
@Override
public void updateState(String definitionId, String state) {
if (SuspensionState.ACTIVE.toString().equals(state)) {
// 激活
repositoryService.activateProcessDefinitionById(definitionId, true, null);
} else if (SuspensionState.SUSPENDED.toString().equals(state)) {
// 挂起
repositoryService.suspendProcessDefinitionById(definitionId, true, null);
}
}
@Override
public String queryBpmnXmlById(String definitionId) {
InputStream inputStream = repositoryService.getProcessModel(definitionId);
try {
return IoUtil.readUtf8(inputStream);
} catch (IORuntimeException exception) {
throw new RuntimeException("加载xml文件异常");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByIds(List<String> deployIds) {
for (String deployId : deployIds) {
repositoryService.deleteDeployment(deployId, true);
deployFormMapper.delete(new LambdaQueryWrapper<WfDeployForm>().eq(WfDeployForm::getDeployId, deployId));
}
}
}