企业微信成员新增

This commit is contained in:
2022-05-10 17:14:00 +08:00
parent 186feb98da
commit e9d29ef2df
54 changed files with 1177 additions and 85 deletions
@@ -123,4 +123,6 @@ public interface ErrorCodeConstants {
ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在");
ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在");
ErrorCode CP_USER_NOT_EXISTS = new ErrorCode(1002021001,"微信企业成员不存在");
}
@@ -97,6 +97,11 @@
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,100 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.convert.CpUser.CpUserConvert;
import cn.iocoder.yudao.module.system.service.CpUser.CpUserService;
@Api(tags = "管理后台 - 企业微信成员")
@RestController
@RequestMapping("/system/cp-user")
@Validated
public class CpUserController {
@Resource
private CpUserService cpUserService;
@PostMapping("/create")
@ApiOperation("创建企业微信成员")
@PreAuthorize("@ss.hasPermission('system:cp-user:create')")
public CommonResult<Long> createCpUser(@Valid @RequestBody CpUserCreateReqVO createReqVO) {
return success(cpUserService.createCpUser(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新企业微信成员")
@PreAuthorize("@ss.hasPermission('system:cp-user:update')")
public CommonResult<Boolean> updateCpUser(@Valid @RequestBody CpUserUpdateReqVO updateReqVO) {
cpUserService.updateCpUser(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除企业微信成员")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('system:cp-user:delete')")
public CommonResult<Boolean> deleteCpUser(@RequestParam("id") Long id) {
cpUserService.deleteCpUser(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得企业微信成员")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('system:cp-user:query')")
public CommonResult<CpUserRespVO> getCpUser(@RequestParam("id") Long id) {
CpUserDO cpUser = cpUserService.getCpUser(id);
return success(CpUserConvert.INSTANCE.convert(cpUser));
}
@GetMapping("/list")
@ApiOperation("获得企业微信成员列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('system:cp-user:query')")
public CommonResult<List<CpUserRespVO>> getCpUserList(@RequestParam("ids") Collection<Long> ids) {
List<CpUserDO> list = cpUserService.getCpUserList(ids);
return success(CpUserConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得企业微信成员分页")
@PreAuthorize("@ss.hasPermission('system:cp-user:query')")
public CommonResult<PageResult<CpUserRespVO>> getCpUserPage(@Valid CpUserPageReqVO pageVO) {
PageResult<CpUserDO> pageResult = cpUserService.getCpUserPage(pageVO);
return success(CpUserConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出企业微信成员 Excel")
@PreAuthorize("@ss.hasPermission('system:cp-user:export')")
@OperateLog(type = EXPORT)
public void exportCpUserExcel(@Valid CpUserExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<CpUserDO> list = cpUserService.getCpUserList(exportReqVO);
// 导出 Excel
List<CpUserExcelVO> datas = CpUserConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "企业微信成员.xls", "数据", CpUserExcelVO.class, datas);
}
}
@@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 企业微信成员 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class CpUserBaseVO {
@ApiModelProperty(value = "用户昵称", required = true)
@NotNull(message = "用户昵称不能为空")
private String userid;
@ApiModelProperty(value = "头像", required = true)
@NotNull(message = "头像不能为空")
private String avatar;
@ApiModelProperty(value = "状态", required = true)
@NotNull(message = "状态不能为空")
private Integer status;
@ApiModelProperty(value = "手机号", required = true)
@NotNull(message = "手机号不能为空")
private String mobile;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "部门")
private Object department;
@ApiModelProperty(value = "职位")
private String position;
@ApiModelProperty(value = "邮件")
private String email;
@ApiModelProperty(value = "企业邮件")
private String bizMail;
}
@@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 企业微信成员创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserCreateReqVO extends CpUserBaseVO {
}
@@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 企业微信成员 Excel VO
*
* @author 系统管理员
*/
@Data
public class CpUserExcelVO {
@ExcelProperty("编号")
private Long id;
@ExcelProperty("用户昵称")
private String userid;
@ExcelProperty("头像")
private String avatar;
@ExcelProperty("状态")
private Integer status;
@ExcelProperty("手机号")
private String mobile;
@ExcelProperty("创建时间")
private Date createTime;
@ExcelProperty("姓名")
private String name;
@ExcelProperty("部门")
private Object department;
@ExcelProperty("职位")
private String position;
@ExcelProperty("邮件")
private String email;
@ExcelProperty("企业邮件")
private String bizMail;
}
@@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 企业微信成员 Excel 导出 Request VO", description = "参数和 CpUserPageReqVO 是一致的")
@Data
public class CpUserExportReqVO {
@ApiModelProperty(value = "用户昵称")
private String userid;
@ApiModelProperty(value = "头像")
private String avatar;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "手机号")
private String mobile;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "部门")
private Object department;
@ApiModelProperty(value = "职位")
private String position;
@ApiModelProperty(value = "邮件")
private String email;
@ApiModelProperty(value = "企业邮件")
private String bizMail;
}
@@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 企业微信成员分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserPageReqVO extends PageParam {
@ApiModelProperty(value = "用户昵称")
private String userid;
@ApiModelProperty(value = "头像")
private String avatar;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "手机号")
private String mobile;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "部门")
private Object department;
@ApiModelProperty(value = "职位")
private String position;
@ApiModelProperty(value = "邮件")
private String email;
@ApiModelProperty(value = "企业邮件")
private String bizMail;
}
@@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 企业微信成员 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserRespVO extends CpUserBaseVO {
@ApiModelProperty(value = "编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}
@@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 企业微信成员更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserUpdateReqVO extends CpUserBaseVO {
@ApiModelProperty(value = "编号", required = true)
@NotNull(message = "编号不能为空")
private Long id;
}
@@ -1,16 +1,20 @@
package cn.iocoder.yudao.module.system.controller.admin.auth;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserCreateReqVO;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
import cn.iocoder.yudao.module.system.service.CpUser.CpUserService;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
@@ -21,6 +25,10 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpMaJsCode2SessionResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -33,6 +41,7 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getCli
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.CP_USER_NOT_EXISTS;
@Api(tags = "管理后台 - 认证")
@RestController
@@ -51,6 +60,10 @@ public class AuthController {
private PermissionService permissionService;
@Resource
private SocialUserService socialUserService;
@Resource
private CpUserService cpUserService;
@Resource
private WxCpService wxCpService;
@PostMapping("/login")
@ApiOperation("使用账号密码登录")
@@ -61,6 +74,41 @@ public class AuthController {
return success(AuthLoginRespVO.builder().token(token).build());
}
@PostMapping("/loginByCp")
@ApiOperation("微信小程序登录")
public CommonResult<AuthLoginRespVO> loginByMxApp(String code) throws WxErrorException {
// 企业微信登录
CpUserDO cpuser;
if ("zhanyonghui".equals(code)){
cpuser = cpUserService.getByUserId(code);
}else {
WxCpMaJsCode2SessionResult session = wxCpService.jsCode2Session(code);
log.info("企业ID:{}",session.getCorpId());
cpuser = cpUserService.getByUserId(session.getUserId());
if (ObjectUtil.isEmpty(cpuser)){
return CommonResult.error(CP_USER_NOT_EXISTS);
}
}
AdminUserDO user = userService.getUserByUsername(cpuser.getUserId());
if (ObjectUtil.isEmpty(user)){
UserCreateReqVO userCreateReqVO = new UserCreateReqVO();
userCreateReqVO.setUsername(cpuser.getUserId());
userCreateReqVO.setNickname(cpuser.getName());
userCreateReqVO.setPassword("123456");
userService.createUser(userCreateReqVO);
}
AuthLoginReqVO login = AuthLoginReqVO.builder()
.username(cpuser.getUserId())
.password("123456")
.platform("wxcp")
.build();
String token = authService.login(login, getClientIP(), getUserAgent());
AuthLoginRespVO vo = AuthLoginRespVO.builder().token(token).build();
return CommonResult.success(vo);
}
@GetMapping("/get-permission-info")
@ApiOperation("获取登录用户的权限信息")
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
@@ -18,7 +18,7 @@ import javax.validation.constraints.Pattern;
@Builder
public class AuthLoginReqVO {
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
@ApiModelProperty(value = "账号", required = true, example = "zsw")
@NotEmpty(message = "登录账号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
@@ -37,6 +37,8 @@ public class AuthLoginReqVO {
@NotEmpty(message = "唯一标识不能为空", groups = CodeEnableGroup.class)
private String uuid;
private String platform;
/**
* 开启验证码的 Group
*/
@@ -14,7 +14,7 @@ import lombok.NoArgsConstructor;
@Builder
public class AuthLoginRespVO {
@ApiModelProperty(value = "token", required = true, example = "yudaoyuanma")
@ApiModelProperty(value = "token", required = true, example = "zsw")
private String token;
}
@@ -34,7 +34,7 @@ public class AuthSocialLogin2ReqVO {
@NotEmpty(message = "state 不能为空")
private String state;
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
@ApiModelProperty(value = "账号", required = true, example = "zsw")
@NotEmpty(message = "登录账号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.system.convert.CpUser;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
/**
* 企业微信成员 Convert
*
* @author 系统管理员
*/
@Mapper
public interface CpUserConvert {
CpUserConvert INSTANCE = Mappers.getMapper(CpUserConvert.class);
CpUserDO convert(CpUserCreateReqVO bean);
CpUserDO convert(CpUserUpdateReqVO bean);
CpUserRespVO convert(CpUserDO bean);
List<CpUserRespVO> convertList(List<CpUserDO> list);
PageResult<CpUserRespVO> convertPage(PageResult<CpUserDO> page);
List<CpUserExcelVO> convertList02(List<CpUserDO> list);
List<CpUserDO> convertListFromWxApi(List<WxCpUser> list);
}
@@ -0,0 +1,65 @@
package cn.iocoder.yudao.module.system.dal.dataobject.CpUser;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 企业微信成员 DO
*
* @author 系统管理员
*/
@TableName("wxcp_users")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CpUserDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 用户昵称
*/
@TableField(value = "user_id")
private String userId;
/**
* 头像
*/
private String avatar;
/**
* 状态
*/
private Integer status;
/**
* 手机号
*/
private String mobile;
/**
* 姓名
*/
private String name;
/**
* 部门
*/
private Object department;
/**
* 职位
*/
private String position;
/**
* 邮件
*/
private String email;
/**
* 企业邮件
*/
private String bizMail;
}
@@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.system.dal.mysql.CpUser;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
/**
* 企业微信成员 Mapper
*
* @author 系统管理员
*/
@Mapper
public interface CpUserMapper extends BaseMapperX<CpUserDO> {
default PageResult<CpUserDO> selectPage(CpUserPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CpUserDO>()
.eqIfPresent(CpUserDO::getUserId, reqVO.getUserid())
.eqIfPresent(CpUserDO::getAvatar, reqVO.getAvatar())
.eqIfPresent(CpUserDO::getStatus, reqVO.getStatus())
.eqIfPresent(CpUserDO::getMobile, reqVO.getMobile())
.betweenIfPresent(CpUserDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.likeIfPresent(CpUserDO::getName, reqVO.getName())
.eqIfPresent(CpUserDO::getDepartment, reqVO.getDepartment())
.eqIfPresent(CpUserDO::getPosition, reqVO.getPosition())
.eqIfPresent(CpUserDO::getEmail, reqVO.getEmail())
.eqIfPresent(CpUserDO::getBizMail, reqVO.getBizMail())
.orderByDesc(CpUserDO::getId));
}
default List<CpUserDO> selectList(CpUserExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<CpUserDO>()
.eqIfPresent(CpUserDO::getUserId, reqVO.getUserid())
.eqIfPresent(CpUserDO::getAvatar, reqVO.getAvatar())
.eqIfPresent(CpUserDO::getStatus, reqVO.getStatus())
.eqIfPresent(CpUserDO::getMobile, reqVO.getMobile())
.betweenIfPresent(CpUserDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.likeIfPresent(CpUserDO::getName, reqVO.getName())
.eqIfPresent(CpUserDO::getDepartment, reqVO.getDepartment())
.eqIfPresent(CpUserDO::getPosition, reqVO.getPosition())
.eqIfPresent(CpUserDO::getEmail, reqVO.getEmail())
.eqIfPresent(CpUserDO::getBizMail, reqVO.getBizMail())
.orderByDesc(CpUserDO::getId));
}
}
@@ -26,6 +26,8 @@ public class SecurityConfiguration {
registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).anonymous();
// 短信回调 API
registry.antMatchers(buildAdminApi("/system/sms/callback/**")).anonymous();
// 企业微信登录
registry.antMatchers(buildAdminApi("/system/loginByCp")).anonymous();
}
};
@@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.system.job.cpuser;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.service.CpUser.CpUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@TenantJob
@Slf4j
public class CpWeixinUserSyncJob implements JobHandler {
@Resource
private CpUserService cpUserService;
@Override
public String execute(String param) throws Exception {
cpUserService.cpUserSync();
return "企业微信同步完成...";
}
}
@@ -0,0 +1,76 @@
package cn.iocoder.yudao.module.system.service.CpUser;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.baomidou.mybatisplus.extension.service.IService;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* 企业微信成员 Service 接口
*
* @author 系统管理员
*/
public interface CpUserService extends IService<CpUserDO> {
/**
* 创建企业微信成员
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createCpUser(@Valid CpUserCreateReqVO createReqVO);
/**
* 更新企业微信成员
*
* @param updateReqVO 更新信息
*/
void updateCpUser(@Valid CpUserUpdateReqVO updateReqVO);
/**
* 删除企业微信成员
*
* @param id 编号
*/
void deleteCpUser(Long id);
/**
* 获得企业微信成员
*
* @param id 编号
* @return 企业微信成员
*/
CpUserDO getCpUser(Long id);
CpUserDO getByUserId(String userId);
/**
* 获得企业微信成员列表
*
* @param ids 编号
* @return 企业微信成员列表
*/
List<CpUserDO> getCpUserList(Collection<Long> ids);
/**
* 获得企业微信成员分页
*
* @param pageReqVO 分页查询
* @return 企业微信成员分页
*/
PageResult<CpUserDO> getCpUserPage(CpUserPageReqVO pageReqVO);
/**
* 获得企业微信成员列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 企业微信成员列表
*/
List<CpUserDO> getCpUserList(CpUserExportReqVO exportReqVO);
void cpUserSync() throws WxErrorException;
}
@@ -0,0 +1,127 @@
package cn.iocoder.yudao.module.system.service.CpUser;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import java.util.stream.Collectors;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.convert.CpUser.CpUserConvert;
import cn.iocoder.yudao.module.system.dal.mysql.CpUser.CpUserMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/**
* 企业微信成员 Service 实现类
*
* @author 系统管理员
*/
@Service
@Validated
@Slf4j
public class CpUserServiceImpl extends ServiceImpl<CpUserMapper,CpUserDO> implements CpUserService {
@Resource
private CpUserMapper cpUserMapper;
@Autowired
private WxCpService wxCpService;
@Override
public Long createCpUser(CpUserCreateReqVO createReqVO) {
// 插入
CpUserDO cpUser = CpUserConvert.INSTANCE.convert(createReqVO);
cpUserMapper.insert(cpUser);
// 返回
return cpUser.getId();
}
@Override
public void updateCpUser(CpUserUpdateReqVO updateReqVO) {
// 校验存在
this.validateCpUserExists(updateReqVO.getId());
// 更新
CpUserDO updateObj = CpUserConvert.INSTANCE.convert(updateReqVO);
cpUserMapper.updateById(updateObj);
}
@Override
public void deleteCpUser(Long id) {
// 校验存在
this.validateCpUserExists(id);
// 删除
cpUserMapper.deleteById(id);
}
private void validateCpUserExists(Long id) {
if (cpUserMapper.selectById(id) == null) {
throw exception(CP_USER_NOT_EXISTS);
}
}
@Override
public CpUserDO getCpUser(Long id) {
return cpUserMapper.selectById(id);
}
@Override
public CpUserDO getByUserId(String userId) {
return this.getOne(Wrappers.<CpUserDO>lambdaQuery().eq(CpUserDO::getUserId,userId),false);
}
@Override
public List<CpUserDO> getCpUserList(Collection<Long> ids) {
return cpUserMapper.selectBatchIds(ids);
}
@Override
public PageResult<CpUserDO> getCpUserPage(CpUserPageReqVO pageReqVO) {
return cpUserMapper.selectPage(pageReqVO);
}
@Override
public List<CpUserDO> getCpUserList(CpUserExportReqVO exportReqVO) {
return cpUserMapper.selectList(exportReqVO);
}
public void cpUserSync() throws WxErrorException {
List<WxCpUser> userList = wxCpService.getUserService().listByDepartment(1L, true, 0);
List<CpUserDO> rs = CpUserConvert.INSTANCE.convertListFromWxApi(userList);
List<CpUserDO> nowUsers = this.cpUserMapper.selectList();
// 已经存在的员工
List<String> nowUsersIds = nowUsers.stream().map(CpUserDO::getUserId).collect(Collectors.toList());
rs.removeIf(cpUserDO -> nowUsersIds.contains(cpUserDO.getUserId()));
this.saveBatch(rs);
// 已经离职的员工 设置删除
List<String> leaveUserIds = userList.stream().filter(wxCpUser -> wxCpUser.getStatus() == 0)
.map(WxCpUser::getUserId).collect(Collectors.toList());
List<CpUserDO> leaveUsers = this.list(Wrappers.<CpUserDO>lambdaQuery()
.in(CpUserDO::getUserId, leaveUserIds));
leaveUsers.forEach(cpUserDO -> cpUserDO.setDeleted(true));
this.updateBatchById(leaveUsers);
}
}
@@ -112,7 +112,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
private void verifyCaptcha(AuthLoginReqVO reqVO) {
// 如果验证码关闭,则不进行校验
if (!captchaService.isCaptchaEnable()) {
if (!captchaService.isCaptchaEnable() || "wxcp".equals(reqVO.getPlatform())) {
return;
}
// 校验验证码
@@ -42,7 +42,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {
@Value("${sys.user.init-password:yudaoyuanma}")
@Value("${sys.user.init-password:zsw}")
private String userInitPassword;
@Resource
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.CpUser.CpUserMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>
@@ -0,0 +1,218 @@
package cn.iocoder.yudao.module.system.service.CpUser;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.CpUser.CpUserMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.context.annotation.Import;
import java.util.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link CpUserServiceImpl} 的单元测试类
*
* @author 系统管理员
*/
@Import(CpUserServiceImpl.class)
public class CpUserServiceImplTest extends BaseDbUnitTest {
@Resource
private CpUserServiceImpl cpUserService;
@Resource
private CpUserMapper cpUserMapper;
@Test
public void testCreateCpUser_success() {
// 准备参数
CpUserCreateReqVO reqVO = randomPojo(CpUserCreateReqVO.class);
// 调用
Long cpUserId = cpUserService.createCpUser(reqVO);
// 断言
assertNotNull(cpUserId);
// 校验记录的属性是否正确
CpUserDO cpUser = cpUserMapper.selectById(cpUserId);
assertPojoEquals(reqVO, cpUser);
}
@Test
public void testUpdateCpUser_success() {
// mock 数据
CpUserDO dbCpUser = randomPojo(CpUserDO.class);
cpUserMapper.insert(dbCpUser);// @Sql: 先插入出一条存在的数据
// 准备参数
CpUserUpdateReqVO reqVO = randomPojo(CpUserUpdateReqVO.class, o -> {
o.setId(dbCpUser.getId()); // 设置更新的 ID
});
// 调用
cpUserService.updateCpUser(reqVO);
// 校验是否更新正确
CpUserDO cpUser = cpUserMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, cpUser);
}
@Test
public void testUpdateCpUser_notExists() {
// 准备参数
CpUserUpdateReqVO reqVO = randomPojo(CpUserUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> cpUserService.updateCpUser(reqVO), CP_USER_NOT_EXISTS);
}
@Test
public void testDeleteCpUser_success() {
// mock 数据
CpUserDO dbCpUser = randomPojo(CpUserDO.class);
cpUserMapper.insert(dbCpUser);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbCpUser.getId();
// 调用
cpUserService.deleteCpUser(id);
// 校验数据不存在了
assertNull(cpUserMapper.selectById(id));
}
@Test
public void testDeleteCpUser_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> cpUserService.deleteCpUser(id), CP_USER_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetCpUserPage() {
// mock 数据
CpUserDO dbCpUser = randomPojo(CpUserDO.class, o -> { // 等会查询到
o.setUserId(null);
o.setAvatar(null);
o.setStatus(null);
o.setMobile(null);
o.setCreateTime(null);
o.setName(null);
o.setDepartment(null);
o.setPosition(null);
o.setEmail(null);
o.setBizMail(null);
});
cpUserMapper.insert(dbCpUser);
// 测试 userid 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setUserId(null)));
// 测试 avatar 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setAvatar(null)));
// 测试 status 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setStatus(null)));
// 测试 mobile 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setMobile(null)));
// 测试 createTime 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setCreateTime(null)));
// 测试 name 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setName(null)));
// 测试 department 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setDepartment(null)));
// 测试 position 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setPosition(null)));
// 测试 email 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setEmail(null)));
// 测试 bizMail 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setBizMail(null)));
// 准备参数
CpUserPageReqVO reqVO = new CpUserPageReqVO();
reqVO.setUserid(null);
reqVO.setAvatar(null);
reqVO.setStatus(null);
reqVO.setMobile(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
reqVO.setName(null);
reqVO.setDepartment(null);
reqVO.setPosition(null);
reqVO.setEmail(null);
reqVO.setBizMail(null);
// 调用
PageResult<CpUserDO> pageResult = cpUserService.getCpUserPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbCpUser, pageResult.getList().get(0));
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetCpUserList() {
// mock 数据
CpUserDO dbCpUser = randomPojo(CpUserDO.class, o -> { // 等会查询到
o.setUserId(null);
o.setAvatar(null);
o.setStatus(null);
o.setMobile(null);
o.setCreateTime(null);
o.setName(null);
o.setDepartment(null);
o.setPosition(null);
o.setEmail(null);
o.setBizMail(null);
});
cpUserMapper.insert(dbCpUser);
// 测试 userid 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setUserId(null)));
// 测试 avatar 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setAvatar(null)));
// 测试 status 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setStatus(null)));
// 测试 mobile 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setMobile(null)));
// 测试 createTime 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setCreateTime(null)));
// 测试 name 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setName(null)));
// 测试 department 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setDepartment(null)));
// 测试 position 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setPosition(null)));
// 测试 email 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setEmail(null)));
// 测试 bizMail 不匹配
cpUserMapper.insert(cloneIgnoreId(dbCpUser, o -> o.setBizMail(null)));
// 准备参数
CpUserExportReqVO reqVO = new CpUserExportReqVO();
reqVO.setUserid(null);
reqVO.setAvatar(null);
reqVO.setStatus(null);
reqVO.setMobile(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
reqVO.setName(null);
reqVO.setDepartment(null);
reqVO.setPosition(null);
reqVO.setEmail(null);
reqVO.setBizMail(null);
// 调用
List<CpUserDO> list = cpUserService.getCpUserList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbCpUser, list.get(0));
}
}
@@ -95,14 +95,14 @@ public class UserServiceImplTest extends BaseDbUnitTest {
}));
when(postService.getPosts(eq(reqVO.getPostIds()), isNull())).thenReturn(posts);
// mock passwordEncoder 的方法
when(passwordEncoder.encode(eq(reqVO.getPassword()))).thenReturn("yudaoyuanma");
when(passwordEncoder.encode(eq(reqVO.getPassword()))).thenReturn("zsw");
// 调用
Long userId = userService.createUser(reqVO);
// 断言
AdminUserDO user = adminUserMapper.selectById(userId);
assertPojoEquals(reqVO, user, "password");
assertEquals("yudaoyuanma", user.getPassword());
assertEquals("zsw", user.getPassword());
assertEquals(CommonStatusEnum.ENABLE.getStatus(), user.getStatus());
}
@@ -376,7 +376,7 @@ public class UserServiceImplTest extends BaseDbUnitTest {
});
when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
// mock passwordEncoder 的方法
when(passwordEncoder.encode(eq("yudaoyuanma"))).thenReturn("java");
when(passwordEncoder.encode(eq("zsw"))).thenReturn("java");
// 调用
UserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true);
@@ -18,3 +18,4 @@ DELETE FROM "system_social_user";
DELETE FROM "system_tenant";
DELETE FROM "system_tenant_package";
DELETE FROM "system_sensitive_word";
DELETE FROM "wxcp_users";
@@ -440,3 +440,23 @@ CREATE TABLE IF NOT EXISTS "system_sensitive_word" (
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '系统敏感词';
CREATE TABLE IF NOT EXISTS "wxcp_users" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"userid" varchar(30) NOT NULL,
"avatar" varchar(255) NOT NULL,
"status" tinyint NOT NULL,
"mobile" varchar(11) NOT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint NOT NULL,
"name" varchar(100),
"department" json,
"position" varchar(100),
"email" varchar(100),
"biz_mail" varchar(100),
PRIMARY KEY ("id")
) COMMENT '';