From 8e1b53966934087a702bd8d5053efdd4dc650525 Mon Sep 17 00:00:00 2001 From: DB <2502523450@qq.com> Date: Mon, 16 Oct 2023 17:19:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4Oam=E9=80=9A=E8=AE=AF?= =?UTF-8?q?=E5=BD=95,=E8=B0=83=E6=95=B4=E8=A7=92=E8=89=B2=E7=BB=91?= =?UTF-8?q?=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cpop-Core/sql/System.sql | 2 +- .../com/cpop/core/utils/SecurityUtils.java | 3 + .../src/main/resources/application-dev.yml | 8 +- .../src/main/resources/application-prod.yml | 2 +- .../src/main/resources/application-test.yml | 10 +- .../java/com/cpop/oam/web/CpopApiTests.java | 18 +- .../java/com/cpop/oam/web/CpopWxCpTests.java | 377 ++++++++++++++++++ .../java/com/cpop/oam/business/bo/DeptBo.java | 6 +- .../com/cpop/oam/business/bo/StaffBo.java | 2 + .../business/controller/LoginController.java | 4 +- .../business/controller/RoleController.java | 3 +- .../controller/WxCpPortalController.java | 78 ++++ .../com/cpop/oam/business/entity/Dept.java | 10 + .../com/cpop/oam/business/entity/Staff.java | 10 +- .../oam/business/entity/StaffMidDept.java | 37 ++ .../business/mapper/StaffMidDeptMapper.java | 14 + .../oam/business/service/MenuService.java | 8 - .../business/service/StaffMidDeptService.java | 14 + .../oam/business/service/StaffService.java | 11 + .../service/impl/MenuServiceImpl.java | 7 - .../service/impl/StaffMidDeptServiceImpl.java | 18 + .../service/impl/StaffServiceImpl.java | 72 +++- .../com/cpop/oam/business/vo/StaffPageVo.java | 2 + .../config/wxCp/WxCpConfiguration.java | 42 +- .../framework/constant/WxCpNoticeType.java | 38 ++ .../handler/wxCp/ContactChangeHandler.java | 52 +++ .../resources/mapper/StaffMidDeptMapper.xml | 7 + .../handler/wxCp/ContactChangeHandler.java | 30 -- .../src/main/resources/application-sdk.yml | 15 +- 29 files changed, 782 insertions(+), 118 deletions(-) create mode 100644 Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopWxCpTests.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/business/controller/WxCpPortalController.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/business/entity/StaffMidDept.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/business/mapper/StaffMidDeptMapper.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffMidDeptService.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffMidDeptServiceImpl.java rename {Cpop-Sdk/src/main/java/com/cpop/sdk => Cpop-Oam/src/main/java/com/cpop/oam}/framework/config/wxCp/WxCpConfiguration.java (83%) create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/framework/constant/WxCpNoticeType.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/framework/handler/wxCp/ContactChangeHandler.java create mode 100644 Cpop-Oam/src/main/resources/mapper/StaffMidDeptMapper.xml delete mode 100644 Cpop-Sdk/src/main/java/com/cpop/sdk/framework/handler/wxCp/ContactChangeHandler.java diff --git a/Cpop-Core/sql/System.sql b/Cpop-Core/sql/System.sql index 3021367..0979e42 100644 --- a/Cpop-Core/sql/System.sql +++ b/Cpop-Core/sql/System.sql @@ -77,7 +77,7 @@ CREATE TABLE `cp_sys_user` ( `nick_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称', `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱', `phone_number` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号', - `sex` tinyint(1) NULL DEFAULT NULL COMMENT '性别(0:男;1:女)', + `sex` tinyint(1) NULL DEFAULT '0' COMMENT '性别(0:男;1:女)', `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像', `salt` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '盐', `status` tinyint(1) NULL DEFAULT NULL COMMENT '状态(0:停用;1:启用)', diff --git a/Cpop-Core/src/main/java/com/cpop/core/utils/SecurityUtils.java b/Cpop-Core/src/main/java/com/cpop/core/utils/SecurityUtils.java index f764c6e..23fa51b 100644 --- a/Cpop-Core/src/main/java/com/cpop/core/utils/SecurityUtils.java +++ b/Cpop-Core/src/main/java/com/cpop/core/utils/SecurityUtils.java @@ -34,6 +34,9 @@ public class SecurityUtils { **/ public LoginUser getLoginUser() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null) { + return null; + } if (null != authentication.getPrincipal()) { return (LoginUser) authentication.getPrincipal(); } else { diff --git a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml index 925c510..4203f8f 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml +++ b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml @@ -77,10 +77,4 @@ knife4j: group-name: Oam api-rule: package api-rule-resources: - - com.cpop.oam - #jambox - jambox: - group-name: Jambox - api-rule: package - api-rule-resources: - - com.cpop.jambox \ No newline at end of file + - com.cpop.oam \ No newline at end of file diff --git a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-prod.yml b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-prod.yml index 9562ad2..316b6dc 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-prod.yml +++ b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-prod.yml @@ -4,7 +4,7 @@ cpop: profile: /root/jambox-union/jambox-oam/uploadPath/upload jwt: #白名单 - whiteList: /login,/getCaptcha,/profile/**,/wxOpen/receiveTicket,/wxOpen/*/callback,/wxOpen/bindOpenAccount/* + whiteList: /login,/getCaptcha,/profile/**,/wxOpen/receiveTicket,/wxOpen/*/callback,/wxOpen/bindOpenAccount/*,/wxCp/portal/* #拦截 gateway: rsa-keypair: diff --git a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-test.yml b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-test.yml index c17d295..e890337 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-test.yml +++ b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-test.yml @@ -4,7 +4,7 @@ cpop: profile: /root/jambox-union/jambox-oam/uploadPath/upload jwt: #白名单 - whiteList: /login,/getCaptcha,/profile/**,/doc.html,/webjars/**,/favicon.ico,/v2/api-docs/**,/swagger-resources,/wxOpen/receiveTicket,/wxOpen/*/callback,/wxOpen/bindOpenAccount/* + whiteList: /login,/getCaptcha,/profile/**,/doc.html,/webjars/**,/favicon.ico,/v2/api-docs/**,/swagger-resources,/wxOpen/receiveTicket,/wxOpen/*/callback,/wxOpen/bindOpenAccount/*,/wxCp/portal/* #拦截 gateway: rsa-keypair: @@ -78,10 +78,4 @@ knife4j: group-name: Oam api-rule: package api-rule-resources: - - com.cpop.oam - #jambox - jambox: - group-name: Jambox - api-rule: package - api-rule-resources: - - com.cpop.jambox \ No newline at end of file + - com.cpop.oam \ No newline at end of file diff --git a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java index 463ea96..b3afd62 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java +++ b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java @@ -1,7 +1,14 @@ package com.cpop.oam.web; +import com.cpop.api.tencent.wxWork.handler.WebHookSendHandler; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + /** * @author DB * @createTime 2023/09/15 17:44 @@ -10,14 +17,15 @@ import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class CpopApiTests { - /*@Autowired + @Autowired private WebHookSendHandler webHookSendHandler; - *//** + /** * @descriptions 机器人发送测试 * @author DB - * @date 2023/09/15 17:46 - *//* + * @date 2023/10/12 15:19 + * @return: void + */ @Test public void webHookSendTest(){ List list = new ArrayList<>(); @@ -27,5 +35,5 @@ public class CpopApiTests { } catch (IOException e) { throw new RuntimeException(e); } - }*/ + } } diff --git a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopWxCpTests.java b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopWxCpTests.java new file mode 100644 index 0000000..7d8f480 --- /dev/null +++ b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopWxCpTests.java @@ -0,0 +1,377 @@ +package com.cpop.oam.web; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import com.cpop.common.utils.bean.BeanUtils; +import com.cpop.core.base.entity.LoginUser; +import com.cpop.core.base.enums.UserType; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.base.table.SysUser; +import com.cpop.core.mapper.CoreMapper; +import com.cpop.core.utils.SecurityUtils; +import com.cpop.core.utils.SpringUtils; +import com.cpop.core.utils.uuid.IdUtils; +import com.cpop.oam.business.entity.Dept; +import com.cpop.oam.business.entity.Staff; +import com.cpop.oam.business.entity.StaffMidDept; +import com.cpop.oam.business.service.DeptService; +import com.cpop.oam.business.service.StaffMidDeptService; +import com.cpop.oam.business.service.StaffService; +import com.cpop.oam.framework.config.wxCp.WxCpConfiguration; +import com.mybatisflex.core.row.Db; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpDepart; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.export.WxCpExportRequest; +import me.chanjar.weixin.cp.bean.export.WxCpExportResult; +import me.chanjar.weixin.cp.bean.user.WxCpDeptUserResult; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +/** + * @author DB + * @createTime 2023/10/12 15:19 + * @description 企业微信Api测试 + */ +@SpringBootTest +@Slf4j +public class CpopWxCpTests { + + /** + * @descriptions 获取成员ID列表 + * @author DB + * @date 2023/10/12 15:33 + * @return: void + */ + @Test + public void userListId() { + try { + WxCpDeptUserResult userListId = WxCpConfiguration.getCpService(1000024).getUserService().getUserListId("", 100); + System.out.println(userListId); + } catch (WxErrorException e) { + throw new ServiceException(e.getMessage()); + } + } + + /** + * 根据手机号获取用户id + */ + @Test + public void getUserId() { + try { + String userId = WxCpConfiguration.getCpService(1000024).getUserService().getUserId("17728500831"); + System.out.println(userId); + } catch (WxErrorException e) { + throw new RuntimeException(e); + } + } + + /** + * 根据用户id获取用户 + */ + @Test + public void getUser() { + try { + WxCpUser user = WxCpConfiguration.getCpService(1000024).getUserService().getById("XiaoKanTianSeMuKanYun"); + System.out.println(user); + } catch (WxErrorException e) { + throw new RuntimeException(e); + } + } + + /** + * 获取部门列表 + */ + @Test + public void getDepartmentList() { + try { + List wxCpDeparts = WxCpConfiguration.getCpService(1000000).getDepartmentService().simpleList(1L); + System.out.println(wxCpDeparts); + } catch (WxErrorException e) { + throw new RuntimeException(e); + } + } + + @Test + public void getDeptById() { + try { + WxCpDepart wxCpDepart = WxCpConfiguration.getCpService(1000024).getDepartmentService().get(1L); + System.out.println(wxCpDepart); + } catch (WxErrorException e) { + throw new RuntimeException(e); + } + } + + /** + * 导出部门 + */ + @Test + public void exportDept() { + try { + WxCpExportRequest request = new WxCpExportRequest(); + request.setEncodingAesKey("DLSzfHVUZN3O9WhtL07RBXUoooqC2bjEJYwep8k8ojt"); + String jabId = WxCpConfiguration.getCpService(1000024).getExportService().department(request); + System.out.println(jabId); + } catch (WxErrorException e) { + throw new RuntimeException(e); + } + } + + /** + * @descriptions 获取导出结果 + * @author DB + * @date 2023/10/13 16:18 + * @return: void + */ + @Test + public void getExportResult() throws WxErrorException { + //jobid_dFssU8d6nirNJjOHwoxoPV23OzWH6edwrb__ilftwyA + WxCpExportResult result = WxCpConfiguration.getCpService(1000024).getExportService().getResult("jobid__qH9HAsRGgeErUVEaJA1UnOFpjuL7CQddh11dYtDE6s"); + System.out.println(result); + } + + /** + * @descriptions 解密导出数据 + * @author DB + * @date 2023/10/13 16:49 + * @return: void + */ + @Test + public void decryptExportData(){ + String result = getDecryptExportData("DLSzfHVUZN3O9WhtL07RBXUoooqC2bjEJYwep8k8ojt", "https://szfront.wxwork.qq.com:443/downloadobject?fileid=080112043133303122093131343535363239362a0131322463396566396533662d626332392d346666622d623033652d623034626633343633656539388004421453e8114eb1942bcda5dfca7c8457534c237ab95448015802600768b8177207333030303030308a010b6170706c69636174696f6e90018ffba3a9069a0100a001d5b703&weixinnum=2519320458&authkey=7008001005186022606b8b2cec47b7d5c6a502d671c77f8b35bfb4908f7cc912258e5c54554a0485f9b61c484bb3f5c56fc823c2b3aefed8b319fd113a0220b6297a7879c4a3d50313c6bc91b004c50efd6d2849165eb511f52b8027d3f34de5e970d95291af935be7&filename=data_0.json"); + if (result != null) { + System.out.println(result.substring(0, result.lastIndexOf("}") + 1)); + } + } + + public final String getDecryptExportData(String aesKey, String url) { + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity responseEntity = restTemplate.getForEntity(url, byte[].class); + if (responseEntity.getBody() == null) { + return null; + } + byte[] key = Base64.decodeBase64(aesKey + "="); + byte[] original = null; + try { + // 设置解密模式为AES的CBC模式 + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(key, 0, 16)); + cipher.init(Cipher.DECRYPT_MODE, keySpec, iv); + original = cipher.doFinal(responseEntity.getBody()); + } catch (Exception e) { + log.error("", e); + } + assert original != null; + return new String(original); + } + + /** + * @descriptions 导入部门 + * @author DB + * @date 2023/10/13 16:54 + * @return: void + */ + @Test + public void importDept() { + //将导出数据转换 + String result = getDecryptExportData("DLSzfHVUZN3O9WhtL07RBXUoooqC2bjEJYwep8k8ojt", "https://szfront.wxwork.qq.com:443/downloadobject?fileid=080112043133303122093131343535363239362a0131322463396566396533662d626332392d346666622d623033652d623034626633343633656539388004421453e8114eb1942bcda5dfca7c8457534c237ab95448015802600768b8177207333030303030308a010b6170706c69636174696f6e90018ffba3a9069a0100a001d5b703&weixinnum=2519320458&authkey=7008001005186022606b8b2cec47b7d5c6a502d671c77f8b35bfb4908f7cc912258e5c54554a0485f9b61c484bb3f5c56fc823c2b3aefed8b319fd113a0220b6297a7879c4a3d50313c6bc91b004c50efd6d2849165eb511f52b8027d3f34de5e970d95291af935be7&filename=data_0.json"); + //导出集合 + List exportDeptList = JSONObject.parseObject(result).getJSONArray("department").toJavaList(ExportDept.class); + //转换部门 + List list = new ArrayList<>(); + exportDeptList.forEach(item -> { + Dept dept = new Dept(); + dept.setWxCpId(item.getId()) + .setWxCpParentId(item.getParentId()) + .setOrderNo(item.getOrder()) + .setName(item.getName()); + list.add(dept); + }); + //批量导入数据 + DeptService deptService = SpringUtils.getBean(DeptService.class); + deptService.saveBatch(list); + //同步父id + Map deptMap = list.stream().collect(Collectors.toMap(Dept::getWxCpId, item -> item)); + list.forEach(item->{ + if (null != deptMap.get(item.getWxCpParentId())){ + item.setParentId(deptMap.get(item.getWxCpParentId()).getId()); + } + }); + //批量更新 + deptService.updateBatch(list); + } + + /** + * 导出部门数据 + */ + @Data + public class ExportDept { + + /** + * 部门id + */ + private Long id; + + /** + * 部门名 + */ + private String name; + + /** + * 父部门id + */ + @JSONField(name = "parentid") + private Long parentId; + + /** + * 排序 + */ + private Integer order; + } + + @Test + public void getUserList() throws WxErrorException { + WxCpExportRequest request = new WxCpExportRequest(); + request.setEncodingAesKey("DLSzfHVUZN3O9WhtL07RBXUoooqC2bjEJYwep8k8ojt"); + String jobId = WxCpConfiguration.getCpService(1000024).getExportService().user(request); + System.out.println(jobId); + } + + /** + * @descriptions 导出员工 + * @author DB + * @date 2023/10/16 9:20 + * @return: void + */ + @Test + public void importStaffList() throws WxErrorException { + //https://szfront.wxwork.qq.com:443/downloadobject?fileid=080112043133303122093131343535363239362a0131322464333430383931612d386139312d346262652d616231302d62353464653065383035316138a03b42149c55bf3c6169f900ae391370dd348245dd7308a548015802600768b8177207333030303030308a010b6170706c69636174696f6e900197a4b2a9069a0100a0019cdf03&weixinnum=2909765272&authkey=700800100918602260b996bf284cb359495885b1480d4065832650ca9911785379ca2fe340691640e9e97f18aa5e0df436f97b866f7364f9ea4b81497eca584fedd26dca5fb1afdbcf42508abe97ef4529ec213ade2dac789a350500807294c0c941157438264a30c7&filename=data_0.json + String result = getDecryptExportData("DLSzfHVUZN3O9WhtL07RBXUoooqC2bjEJYwep8k8ojt", "https://szfront.wxwork.qq.com:443/downloadobject?fileid=080112043133303122093131343535363239362a0131322464333430383931612d386139312d346262652d616231302d62353464653065383035316138a03b42149c55bf3c6169f900ae391370dd348245dd7308a548015802600768b8177207333030303030308a010b6170706c69636174696f6e900197a4b2a9069a0100a0019cdf03&weixinnum=2909765272&authkey=700800100918602260b996bf284cb359495885b1480d4065832650ca9911785379ca2fe340691640e9e97f18aa5e0df436f97b866f7364f9ea4b81497eca584fedd26dca5fb1afdbcf42508abe97ef4529ec213ade2dac789a350500807294c0c941157438264a30c7&filename=data_0.json"); + JSONArray department = JSONObject.parseObject(result).getJSONArray("userlist"); + //转换员工,用户 + List staffList = new ArrayList<>(); + List sysUserList = new ArrayList<>(); + List exportUsers = department.toJavaList(ExportUser.class); + //获取当前创建人员信息 + LoginUser loginUser = SecurityUtils.getInstance().getLoginUser(); + Map userMapStaff = new HashMap<>(); + AtomicReference flag = new AtomicReference<>(0); + exportUsers.forEach(item -> { + //创建用户 + SysUser sysUser = new SysUser(); + //TODO:获取初始化密码 + sysUser.setId(IdUtils.fastSimpleUUID()); + sysUser.setPassword("$2a$10$6CA0M3iyO8u8zSVtmufYGO3KfLvjaE5fxdHCqTQ2NpxYH/Dxi/fBu") + .setNickName(item.getAlias()) + .setStatus(item.getStatus()) + .setUserType(UserType.OAM_USER); + sysUser.setCreateUserId(loginUser == null ? "1" : loginUser.getUserId()); + sysUser.setUpdateUserId(loginUser == null ? "1" : loginUser.getUserId()); + sysUserList.add(sysUser); + //转换员工 + Staff staff = BeanUtils.mapToClass(item, Staff.class); + staff.setName(item.getName()) + //默认售后人员,由管理人员修改 + .setStaffType(1) + //设置角色信息 + //.setRoleId() + .setWxCpUserId(item.getWxCpUserId()); + //放入一个map集合中 + userMapStaff.put(flag.get(), staff); + flag.getAndSet(flag.get() + 1); + }); + Db.executeBatch(sysUserList, CoreMapper.class, CoreMapper::insertSysUser); + for (int i = 0; i < sysUserList.size(); i++) { + SysUser sysUser = sysUserList.get(i); + Staff staff = userMapStaff.get(i); + staff.setUserId(sysUser.getId()); + staffList.add(staff); + } + SpringUtils.getBean(StaffService.class).saveBatch(staffList); + //导入用户信息分组 + Map exportUserMap = exportUsers.stream().collect(Collectors.toMap(ExportUser::getWxCpUserId, item -> item)); + //获取所有部门信息 + Map deptMap = SpringUtils.getBean(DeptService.class).list().stream().collect(Collectors.toMap(Dept::getWxCpId, item -> item)); + List staffMidDeptList = new ArrayList<>(); + //设置中间部门表信息 + staffList.forEach(item->{ + ExportUser exportUser = exportUserMap.get(item.getWxCpUserId()); + exportUser.getDepartment().forEach(innerItem->{ + StaffMidDept staffMidDept = new StaffMidDept(); + staffMidDept.setDeptId(deptMap.get(innerItem).getId()); + staffMidDept.setStaffId(item.getId()); + staffMidDeptList.add(staffMidDept); + }); + }); + SpringUtils.getBean(StaffMidDeptService.class).getMapper().insertBatch(staffMidDeptList); + } + + /** + * 导入用户 + */ + @Data + public class ExportUser { + + /** + * 成员名称 + */ + private String name; + + /** + * 别名 + */ + private String alias; + + /** + * 座机 + */ + private String telephone; + + /** + * 职位名称 + */ + private String position; + + /** + * 成员所属部门id列表 + */ + private List department; + + /** + * 表示在所在的部门内是否为部门负责人 + */ + @JSONField(name = "is_leader_in_dept") + private List isLeaderInDept; + + /** + * 企业微信用户id + */ + @JSONField(name = "userid") + private String wxCpUserId; + + /** + * 是否启用 + */ + private Boolean status; + + /** + * 部门排序 + */ + private List order; + } + +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/DeptBo.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/DeptBo.java index 8043c5d..ca05a97 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/DeptBo.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/DeptBo.java @@ -35,13 +35,13 @@ public class DeptBo implements Serializable { /** * 部门名称 */ - @ApiModelProperty("部门名称") + @ApiModelProperty(value = "部门名称",required = true) private String name; /** * 排序 */ - @ApiModelProperty("排序") + @ApiModelProperty(value = "排序",required = true) private Integer orderNo; /** @@ -65,7 +65,7 @@ public class DeptBo implements Serializable { /** * 部门状态:1正常,0停用 */ - @ApiModelProperty("部门状态:1正常,0停用") + @ApiModelProperty(value = "部门状态:1正常,0停用",required = true) private Boolean status; /** diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/StaffBo.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/StaffBo.java index 061483d..ef7c631 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/StaffBo.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/StaffBo.java @@ -1,5 +1,6 @@ package com.cpop.oam.business.bo; +import com.cpop.core.annontation.StringArrayConvert; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -38,6 +39,7 @@ public class StaffBo implements Serializable { /** * 部门id */ + @StringArrayConvert @NotBlank(message = "部门不能为空") @ApiModelProperty(value = "部门id",required = true) private String deptId; diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/LoginController.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/LoginController.java index 2c9e423..def7933 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/LoginController.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/LoginController.java @@ -28,7 +28,7 @@ public class LoginController { * @author LOST.yuan * @Description 获取登录用户详情 * @date 14:52 2022/9/7 - * @return {@link R< LoginUserInfoVo >} + * @return {@link R} **/ @GetMapping("/getUserInfo") @ApiOperation("获取登录用户详情") @@ -53,7 +53,7 @@ public class LoginController { * @author LOST.yuan * @Description 获取菜单列表 * @date 14:52 2022/9/7 - * @return {@link R>} + * @return {@link R>} **/ @ApiOperation("获取菜单列表") @GetMapping("/getMenuList") diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/RoleController.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/RoleController.java index e29be2e..c713457 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/RoleController.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/RoleController.java @@ -3,6 +3,7 @@ package com.cpop.oam.business.controller; import com.cpop.core.annontation.OperationLog; import com.cpop.core.base.R; import com.cpop.core.base.enums.OperationLogEnum; +import com.cpop.oam.business.bo.MenuListBo; import com.cpop.oam.business.bo.RoleBo; import com.cpop.oam.business.bo.RolePageBo; import com.cpop.oam.business.bo.RoleStatusBo; @@ -77,7 +78,7 @@ public class RoleController { @ApiOperation("获取菜单树列表") @GetMapping("/getFilterAuthMenuTreeList") public R> getFilterAuthMenuTreeList() { - List list = menuService.getFilterAuthMenuTreeList(); + List list = menuService.getOamMenuTreeList(new MenuListBo()); //过滤掉没有权限的数据 return R.ok(list); } diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/WxCpPortalController.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/WxCpPortalController.java new file mode 100644 index 0000000..89297fe --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/WxCpPortalController.java @@ -0,0 +1,78 @@ +package com.cpop.oam.business.controller; + +import com.cpop.common.utils.StringUtils; +import com.cpop.oam.framework.config.wxCp.WxCpConfiguration; +import com.cpop.sdk.framework.utils.JsonUtils; +import io.swagger.annotations.Api; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + +/** + * @author DB + * @createTime 2023/10/12 15:17 + * @description 企业微信认证回调接口 + */ +@Api(tags = "企业微信消息接收controller") +@RestController +@RequestMapping("/wxCp/portal/{agentId}") +public class WxCpPortalController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @GetMapping(produces = "text/plain;charset=utf-8") + public String authGet(@PathVariable Integer agentId, + @RequestParam(name = "msg_signature", required = false) String signature, + @RequestParam(name = "timestamp", required = false) String timestamp, + @RequestParam(name = "nonce", required = false) String nonce, + @RequestParam(name = "echostr", required = false) String echostr) { + this.logger.info("\n接收到来自微信服务器的认证消息:signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", + signature, timestamp, nonce, echostr); + if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { + throw new IllegalArgumentException("请求参数非法,请核实!"); + } + final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId); + if (wxCpService == null) { + throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置,请核实!", agentId)); + } + if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) { + return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr); + } + return "非法请求"; + } + + @PostMapping(produces = "application/xml; charset=UTF-8") + public String post(@PathVariable Integer agentId, + @RequestBody String requestBody, + @RequestParam("msg_signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce) { + this.logger.info("\n接收微信请求:[signature=[{}], timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + signature, timestamp, nonce, requestBody); + + final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId); + WxCpXmlMessage inMessage = WxCpXmlMessage.fromEncryptedXml(requestBody, wxCpService.getWxCpConfigStorage(), + timestamp, nonce, signature); + this.logger.debug("\n消息解密后内容为:\n{} ", JsonUtils.toJson(inMessage)); + WxCpXmlOutMessage outMessage = this.route(agentId, inMessage); + if (outMessage == null) { + return ""; + } + String out = outMessage.toEncryptedXml(wxCpService.getWxCpConfigStorage()); + this.logger.debug("\n组装回复信息:{}", out); + return out; + } + + private WxCpXmlOutMessage route(Integer agentId, WxCpXmlMessage message) { + try { + return WxCpConfiguration.getRouters().get(agentId).route(message); + } catch (Exception e) { + this.logger.error(e.getMessage(), e); + } + return null; + } +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Dept.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Dept.java index 0570f99..b60995f 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Dept.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Dept.java @@ -37,6 +37,16 @@ public class Dept extends BaseEntity implements Serializable { */ private String parentId; + /** + * 企微id + */ + private Long wxCpId; + + /** + * 企微父id + */ + private Long wxCpParentId; + /** * 部门名称 */ diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Staff.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Staff.java index eccba09..cc434f8 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Staff.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/Staff.java @@ -37,11 +37,6 @@ public class Staff extends BaseEntity implements Serializable { */ private String name; - /** - * 部门id - */ - private String deptId; - /** * 用户id */ @@ -57,6 +52,11 @@ public class Staff extends BaseEntity implements Serializable { */ private String roleId; + /** + * 企微用户id + */ + private String wxCpUserId; + /** * 逻辑删除(0否1是) */ diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/StaffMidDept.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/StaffMidDept.java new file mode 100644 index 0000000..defd4b5 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/entity/StaffMidDept.java @@ -0,0 +1,37 @@ +package com.cpop.oam.business.entity; + +import com.cpop.core.base.entity.BaseEntity; +import com.cpop.core.base.entity.BaseInsertListener; +import com.cpop.core.base.entity.BaseUpdateListener; +import com.mybatisflex.annotation.Table; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * Oam-员工-用户中间表 实体类。 + * + * @author DB + * @since 2023-10-13 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@Table(value = "cp_oam_staff_mid_dept", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false) +public class StaffMidDept extends BaseEntity implements Serializable { + + /** + * 员工id + */ + private String staffId; + + /** + * 部门id + */ + private String deptId; + +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/mapper/StaffMidDeptMapper.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/mapper/StaffMidDeptMapper.java new file mode 100644 index 0000000..23916d6 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/mapper/StaffMidDeptMapper.java @@ -0,0 +1,14 @@ +package com.cpop.oam.business.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cpop.oam.business.entity.StaffMidDept; + +/** + * Oam-员工-用户中间表 映射层。 + * + * @author DB + * @since 2023-10-13 + */ +public interface StaffMidDeptMapper extends BaseMapper { + +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/MenuService.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/MenuService.java index 1521222..c6cc5b7 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/MenuService.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/MenuService.java @@ -67,12 +67,4 @@ public interface MenuService extends IService { */ List getOamMenuList(); - /** - * @Description: 获取菜单树列表 - * @param - * @return List - * @Author DB - * @Date: 2023/10/11 19:47 - */ - List getFilterAuthMenuTreeList(); } diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffMidDeptService.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffMidDeptService.java new file mode 100644 index 0000000..2a59479 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffMidDeptService.java @@ -0,0 +1,14 @@ +package com.cpop.oam.business.service; + +import com.mybatisflex.core.service.IService; +import com.cpop.oam.business.entity.StaffMidDept; + +/** + * Oam-员工-用户中间表 服务层。 + * + * @author DB + * @since 2023-10-13 + */ +public interface StaffMidDeptService extends IService { + +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffService.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffService.java index c6dfce5..1f44f86 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffService.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/StaffService.java @@ -11,6 +11,8 @@ import com.cpop.oam.business.vo.StaffInfoVo; import com.cpop.oam.business.vo.StaffPageVo; import com.cpop.oam.business.vo.StaffVo; import com.cpop.oam.business.vo.SysOperationLogVo; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; import java.util.List; @@ -108,4 +110,13 @@ public interface StaffService extends IService { * @Date: 2023/5/11 17:50 **/ List getTechnologyStaffList(); + + /** + * @descriptions 创建企业微信用户 + * @author DB + * @date 2023/10/13 14:31 + * @param wxMessage 企业微信用户信息 + * @return: void + */ + void createWxCpUser(WxCpXmlMessage wxMessage, WxCpService cpService); } diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/MenuServiceImpl.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/MenuServiceImpl.java index 9197651..129c642 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/MenuServiceImpl.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/MenuServiceImpl.java @@ -232,13 +232,6 @@ public class MenuServiceImpl extends ServiceImpl implements Me } } - @Override - public List getFilterAuthMenuTreeList() { - return buildMenuTree(this.listAs(QueryWrapper.create() - .and(MENU.TYPE.eq(0).or(MENU.TYPE.ne(0).and(MENU.PERMISSION.isNotNull().or(MENU.PERMISSION.eq(""))))) - .orderBy(MENU.ORDER_NO.asc()), MenuVo.class)); - } - /** * @Description: 构建菜单路由树 * @param menus 菜单集合 diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffMidDeptServiceImpl.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffMidDeptServiceImpl.java new file mode 100644 index 0000000..948cafc --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffMidDeptServiceImpl.java @@ -0,0 +1,18 @@ +package com.cpop.oam.business.service.impl; + +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.cpop.oam.business.entity.StaffMidDept; +import com.cpop.oam.business.mapper.StaffMidDeptMapper; +import com.cpop.oam.business.service.StaffMidDeptService; +import org.springframework.stereotype.Service; + +/** + * Oam-员工-用户中间表 服务层实现。 + * + * @author DB + * @since 2023-10-13 + */ +@Service("staffMidDeptService") +public class StaffMidDeptServiceImpl extends ServiceImpl implements StaffMidDeptService { + +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffServiceImpl.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffServiceImpl.java index 34ad457..1f33c96 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffServiceImpl.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/StaffServiceImpl.java @@ -1,11 +1,6 @@ package com.cpop.oam.business.service.impl; -import com.mybatisflex.core.paginate.Page; -import com.mybatisflex.core.query.QueryWrapper; -import com.mybatisflex.core.row.Db; -import com.mybatisflex.core.row.DbChain; -import com.mybatisflex.core.row.Row; -import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.alibaba.fastjson.JSONObject; import com.cpop.common.constant.Constants; import com.cpop.common.utils.StringUtils; import com.cpop.common.utils.bean.BeanUtils; @@ -31,6 +26,15 @@ import com.cpop.oam.business.vo.StaffInfoVo; import com.cpop.oam.business.vo.StaffPageVo; import com.cpop.oam.business.vo.StaffVo; import com.cpop.oam.business.vo.SysOperationLogVo; +import com.cpop.oam.framework.utils.OamUtils; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.row.Db; +import com.mybatisflex.core.row.DbChain; +import com.mybatisflex.core.row.Row; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; import org.springframework.security.crypto.bcrypt.BCrypt; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,7 +46,10 @@ import java.util.List; import static com.cpop.core.base.table.table.SysOperationLogTableDef.SYS_OPERATION_LOG; import static com.cpop.core.base.table.table.SysUserTableDef.SYS_USER; import static com.cpop.oam.business.entity.table.RoleTableDef.ROLE; +import static com.cpop.oam.business.entity.table.StaffMidDeptTableDef.STAFF_MID_DEPT; import static com.cpop.oam.business.entity.table.StaffTableDef.STAFF; +import static com.mybatisflex.core.query.QueryMethods.distinct; +import static com.mybatisflex.core.query.QueryMethods.groupConcat; /** * 员工表 服务层实现。 @@ -65,18 +72,25 @@ public class StaffServiceImpl extends ServiceImpl implements PageDomain pageDomain = SqlUtils.getInstance().getPageDomain(); return this.mapper.paginateAs(pageDomain.getPageNum(), pageDomain.getPageSize() , QueryWrapper.create() - .select(STAFF.ALL_COLUMNS) - .select(SYS_USER.ALL_COLUMNS,SYS_USER.ID.as("user_id")) - .select(ROLE.ROLE_NAME,ROLE.ID.as("roleId")) + //去重 + .select(distinct(STAFF.ALL_COLUMNS)) + .select(SYS_USER.USER_NAME,SYS_USER.NICK_NAME, SYS_USER.EMAIL, SYS_USER.PHONE_NUMBER, SYS_USER.SEX, SYS_USER.AVATAR, SYS_USER.STATUS, SYS_USER.PASSWORD) + .select(ROLE.ROLE_NAME) + //将部门id分组 + .select(groupConcat(STAFF_MID_DEPT.DEPT_ID).as(StaffPageVo::getDeptId)) + .from(STAFF) .leftJoin(SYS_USER).on(SYS_USER.ID.eq(STAFF.USER_ID)) .leftJoin(ROLE).on(ROLE.ID.eq(STAFF.ROLE_ID)) + //左联中间表 + .leftJoin(STAFF_MID_DEPT).on(STAFF_MID_DEPT.STAFF_ID.eq(STAFF.ID)) //姓名 .and(STAFF.NAME.like(bo.getName())) //员工类型 .and(STAFF.STAFF_TYPE.eq(bo.getStaffType())) //部门id - .and(STAFF.DEPT_ID.eq(bo.getDeptId())) - .and(SYS_USER.USER_NAME.ne(Constants.SUPER_ADMIN)) + .and(STAFF_MID_DEPT.DEPT_ID.eq(bo.getDeptId())) + .and(SYS_USER.USER_NAME.ne(Constants.SUPER_ADMIN).or(SYS_USER.USER_NAME.isNull())) + .groupBy(STAFF.ID) , StaffPageVo.class); } @@ -174,8 +188,9 @@ public class StaffServiceImpl extends ServiceImpl implements this.updateById(sysStaff); //获取缓存信息 RedisService redisService = SpringUtils.getBean(RedisService.class); - LoginUser loginUser = redisService.getCacheObject(UserType.OAM_USER.getKey() + bo.getUserName()); - if (null != loginUser) { + JSONObject jsonObject = redisService.getCacheObject(UserType.OAM_USER.getKey() + bo.getUserName()); + if (jsonObject != null) { + LoginUser loginUser = jsonObject.getObject("user", LoginUser.class); OamStaffLoginInfo staffLoginInfo = BeanUtils.mapToClass(bo, OamStaffLoginInfo.class); loginUser.setUser(staffLoginInfo); redisService.setCacheObject(UserType.OAM_USER.getKey() + loginUser.getUsername(), loginUser); @@ -264,7 +279,7 @@ public class StaffServiceImpl extends ServiceImpl implements .and(SYS_OPERATION_LOG.CREATE_TIME.le(LocalDateTime.parse(split[1], df))); } PageDomain pageDomain = SqlUtils.getInstance().getPageDomain(); - Page page = Db.paginate("pp_sys_operation_log", pageDomain.getPageNum(), pageDomain.getPageSize(), queryWrapper); + Page page = Db.paginate("cp_sys_operation_log", pageDomain.getPageNum(), pageDomain.getPageSize(), queryWrapper); return page.map(row -> row.toEntity(SysOperationLogVo.class)); } @@ -277,13 +292,19 @@ public class StaffServiceImpl extends ServiceImpl implements **/ @Override public void modifyUserPassword(ModifyUserPasswordBo bo) { - //先用rsa解密 - RsaUtils rsaUtils = SpringUtils.getBean(RsaUtils.class); - String oldPassword = rsaUtils.decrypt(bo.getOldPassword()); + //只允许超级管理员或自己修改面膜 + OamStaffLoginInfo loginStaffInfo = SpringUtils.getBean(OamUtils.class).getLoginStaffInfo(); + String userName = loginStaffInfo.getUserName(); //同数据库密码进行比较 SysUser user = DbChain.table(SYS_USER) .where(SYS_USER.ID.eq(bo.getUserId())) .oneAs(SysUser.class); + if (!StringUtils.equals(userName, Constants.SUPER_ADMIN) || !StringUtils.equals(userName, user.getUserName())) { + throw new ServiceException("非超级管理员不允许修改他人密码"); + } + //先用rsa解密 + RsaUtils rsaUtils = SpringUtils.getBean(RsaUtils.class); + String oldPassword = rsaUtils.decrypt(bo.getOldPassword()); if (BCrypt.checkpw(oldPassword, user.getPassword())) { //存入系统 DbChain.table(SYS_USER) @@ -304,7 +325,7 @@ public class StaffServiceImpl extends ServiceImpl implements @Override public List getServiceStaffList() { return SpringUtils.getBean(StaffService.class).listAs(QueryWrapper.create() - .select(STAFF.ID, STAFF.NAME, STAFF.DEPT_ID, STAFF.USER_ID, STAFF.STAFF_TYPE) + .select(STAFF.ID, STAFF.NAME, STAFF.USER_ID, STAFF.STAFF_TYPE) .from(STAFF) .leftJoin(SYS_USER).on(SYS_USER.ID.eq(STAFF.USER_ID)) .where(STAFF.STAFF_TYPE.eq(1)) @@ -322,7 +343,7 @@ public class StaffServiceImpl extends ServiceImpl implements @Override public List getTechnologyStaffList() { return this.listAs(QueryWrapper.create() - .select(STAFF.ID, STAFF.NAME, STAFF.DEPT_ID, STAFF.USER_ID, STAFF.STAFF_TYPE) + .select(STAFF.ID, STAFF.NAME, STAFF.USER_ID, STAFF.STAFF_TYPE) .from(STAFF) .leftJoin(SYS_USER).on(SYS_USER.ID.eq(STAFF.USER_ID)) .where(STAFF.STAFF_TYPE.eq(0)) @@ -330,4 +351,17 @@ public class StaffServiceImpl extends ServiceImpl implements .and(SYS_USER.STATUS.eq(true)), StaffVo.class); } + + /** + * @descriptions 创建企业微信用户 + * @author DB + * @date 2023/10/13 14:31 + * @param wxMessage 企业微信用户信息 + * @return: void + */ + @Override + public void createWxCpUser(WxCpXmlMessage wxMessage, WxCpService cpService) { + //TODO:先改造部门 + //insertStaff(wxCpUserToStaff(wxMessage, cpService)); + } } diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/vo/StaffPageVo.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/vo/StaffPageVo.java index a361cdd..fdc502c 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/vo/StaffPageVo.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/vo/StaffPageVo.java @@ -1,5 +1,6 @@ package com.cpop.oam.business.vo; +import com.cpop.core.annontation.StringArrayConvert; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -43,6 +44,7 @@ public class StaffPageVo implements Serializable { /** * 部门id */ + @StringArrayConvert @ApiModelProperty("部门id") private String deptId; diff --git a/Cpop-Sdk/src/main/java/com/cpop/sdk/framework/config/wxCp/WxCpConfiguration.java b/Cpop-Oam/src/main/java/com/cpop/oam/framework/config/wxCp/WxCpConfiguration.java similarity index 83% rename from Cpop-Sdk/src/main/java/com/cpop/sdk/framework/config/wxCp/WxCpConfiguration.java rename to Cpop-Oam/src/main/java/com/cpop/oam/framework/config/wxCp/WxCpConfiguration.java index cc7b82d..9688b2d 100644 --- a/Cpop-Sdk/src/main/java/com/cpop/sdk/framework/config/wxCp/WxCpConfiguration.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/framework/config/wxCp/WxCpConfiguration.java @@ -1,6 +1,8 @@ -package com.cpop.sdk.framework.config.wxCp; +package com.cpop.oam.framework.config.wxCp; +import com.cpop.sdk.framework.config.wxCp.WxCpProperties; import com.cpop.sdk.framework.handler.wxCp.*; +import com.cpop.oam.framework.handler.wxCp.ContactChangeHandler; import com.google.common.collect.Maps; import lombok.val; import me.chanjar.weixin.common.api.WxConsts; @@ -26,16 +28,16 @@ import java.util.stream.Collectors; @EnableConfigurationProperties(WxCpProperties.class) public class WxCpConfiguration { - private LogHandler logHandler; - private NullHandler nullHandler; - private LocationHandler locationHandler; - private MenuHandler menuHandler; - private MsgHandler msgHandler; - private UnsubscribeHandler unsubscribeHandler; - private SubscribeHandler subscribeHandler; - private WxCpProperties properties; + private final LogHandler logHandler; + private final NullHandler nullHandler; + private final LocationHandler locationHandler; + private final MenuHandler menuHandler; + private final MsgHandler msgHandler; + private final UnsubscribeHandler unsubscribeHandler; + private final SubscribeHandler subscribeHandler; + private final WxCpProperties properties; - private static Map routers = Maps.newHashMap(); + private static final Map routers = Maps.newHashMap(); private static Map cpServices = Maps.newHashMap(); @Autowired @@ -61,6 +63,12 @@ public class WxCpConfiguration { return cpServices.get(agentId); } + /** + * @descriptions 初始化服务 + * @author DB + * @date 2023/10/13 14:08 + * @return: void + */ @PostConstruct public void initServices() { cpServices = this.properties.getAppConfigs().stream().map(a -> { @@ -80,10 +88,14 @@ public class WxCpConfiguration { private WxCpMessageRouter newRouter(WxCpService wxCpService) { val newRouter = new WxCpMessageRouter(wxCpService); - // 记录所有事件的日志 (异步执行) + // 记录所有事件的日志(异步执行) newRouter.rule().handler(this.logHandler).next(); - // 自定义菜单事件 + //通讯录变更 + newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) + .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(new ContactChangeHandler()).end(); + + /*// 自定义菜单事件 newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) .event(WxConsts.MenuButtonType.CLICK).handler(this.menuHandler).end(); @@ -114,11 +126,9 @@ public class WxCpConfiguration { newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) .event(WxConsts.EventType.SCAN).handler(this.nullHandler).end(); + //进入应用 newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(new ContactChangeHandler()).end(); - - newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT) - .event(WxCpConsts.EventType.ENTER_AGENT).handler(new EnterAgentHandler()).end(); + .event(WxCpConsts.EventType.ENTER_AGENT).handler(new EnterAgentHandler()).end();*/ // 默认 newRouter.rule().async(false).handler(this.msgHandler).end(); diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/framework/constant/WxCpNoticeType.java b/Cpop-Oam/src/main/java/com/cpop/oam/framework/constant/WxCpNoticeType.java new file mode 100644 index 0000000..465309c --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/framework/constant/WxCpNoticeType.java @@ -0,0 +1,38 @@ +package com.cpop.oam.framework.constant; + +/** + * 企业微信通知类型实体类 + * @author DB + */ +public interface WxCpNoticeType { + + /** + * 创建用户 + */ + String CREATE_USER = "create_user"; + + /** + * 更新用户 + */ + String UPDATE_USER = "update_user"; + + /** + * 删除用户 + */ + String DELETE_USER = "delete_user"; + + /** + * 创建部门 + */ + String CREATE_DEPT = "create_party"; + + /** + * 更新部门 + */ + String UPDATE_DEPT = "update_party"; + + /** + * 删除部门 + */ + String DELETE_DEPT = "delete_party"; +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/framework/handler/wxCp/ContactChangeHandler.java b/Cpop-Oam/src/main/java/com/cpop/oam/framework/handler/wxCp/ContactChangeHandler.java new file mode 100644 index 0000000..9933378 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/framework/handler/wxCp/ContactChangeHandler.java @@ -0,0 +1,52 @@ +package com.cpop.oam.framework.handler.wxCp; + +import com.cpop.oam.business.service.StaffService; +import com.cpop.oam.framework.constant.WxCpNoticeType; +import com.cpop.sdk.framework.builder.wxCp.TextBuilder; +import com.cpop.sdk.framework.handler.wxCp.AbstractHandler; +import com.cpop.sdk.framework.utils.JsonUtils; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 通讯录变更事件处理器. + * + * @author Binary Wang + */ +@Component +public class ContactChangeHandler extends AbstractHandler { + + @Autowired + private StaffService staffService; + + @Override + public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, WxSessionManager sessionManager) { + String content = "收到通讯录变更事件,内容:" + JsonUtils.toJson(wxMessage); + this.logger.info(content); + //通知处理 + switch (wxMessage.getChangeType()){ + case WxCpNoticeType.CREATE_USER: + staffService.createWxCpUser(wxMessage, cpService); + break; + case WxCpNoticeType.UPDATE_USER: + break; + case WxCpNoticeType.DELETE_USER: + break; + case WxCpNoticeType.CREATE_DEPT: + break; + case WxCpNoticeType.UPDATE_DEPT: + break; + case WxCpNoticeType.DELETE_DEPT: + break; + default: + } + return new TextBuilder().build(content, wxMessage, cpService); + } + +} diff --git a/Cpop-Oam/src/main/resources/mapper/StaffMidDeptMapper.xml b/Cpop-Oam/src/main/resources/mapper/StaffMidDeptMapper.xml new file mode 100644 index 0000000..7539bd5 --- /dev/null +++ b/Cpop-Oam/src/main/resources/mapper/StaffMidDeptMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/Cpop-Sdk/src/main/java/com/cpop/sdk/framework/handler/wxCp/ContactChangeHandler.java b/Cpop-Sdk/src/main/java/com/cpop/sdk/framework/handler/wxCp/ContactChangeHandler.java deleted file mode 100644 index 5a84b36..0000000 --- a/Cpop-Sdk/src/main/java/com/cpop/sdk/framework/handler/wxCp/ContactChangeHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.cpop.sdk.framework.handler.wxCp; - -import com.cpop.sdk.framework.builder.wxCp.TextBuilder; -import com.cpop.sdk.framework.utils.JsonUtils; -import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.cp.api.WxCpService; -import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; -import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * 通讯录变更事件处理器. - * - * @author Binary Wang - */ -@Component -public class ContactChangeHandler extends AbstractHandler { - - @Override - public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map context, WxCpService cpService, - WxSessionManager sessionManager) { - String content = "收到通讯录变更事件,内容:" + JsonUtils.toJson(wxMessage); - this.logger.info(content); - - return new TextBuilder().build(content, wxMessage, cpService); - } - -} diff --git a/Cpop-Sdk/src/main/resources/application-sdk.yml b/Cpop-Sdk/src/main/resources/application-sdk.yml index 91a8018..23b0f2d 100644 --- a/Cpop-Sdk/src/main/resources/application-sdk.yml +++ b/Cpop-Sdk/src/main/resources/application-sdk.yml @@ -32,8 +32,13 @@ wx: cp: corpId: ww9b83a363662f219f appConfigs: - #通讯录 - - agentId: 1000001 - secret: - token: - aesKey: \ No newline at end of file + #通讯录同步 + - agentId: 1000000 + secret: YAvZS9i2Ccc3_arbH-qi3zTEDJfmEt_2L-k2LG_TTEw + token: xKOLVqjOUklbQ + aesKey: A71T8zPqzb5B2uPesyfRyuTEFpDjhinIRdHg65NuUFj + #Oam-企业微信互通应用 + - agentId: 1000024 + secret: VJFNBvZgK6oNEKpfrb5B9KQcm7yB0CacpWS2BfTln5Q + token: 1i2dz2yxD0Np2xvMYTD + aesKey: DLSzfHVUZN3O9WhtL07RBXUoooqC2bjEJYwep8k8ojt \ No newline at end of file