ソースを参照

Merge branch '84-integrate' into 'develop'

20220714版本

1. 实现统一发送及记录功能
2. 调整包层级

See merge request !7

linwenhua 3 年 前
コミット
dc2cffb14c
66 ファイル変更2226 行追加172 行削除
  1. 34 0
      smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/InformTestController.java
  2. 29 0
      smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/TenantExceptionInformStrategyController.java
  3. 4 9
      smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/authcode/AuthCodeController.java
  4. 3 3
      smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/keyclaok/KeycloakController.java
  5. 16 16
      smsb-customer-manager-app/pom.xml
  6. 23 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/config/MybatisPlusConfiguration.java
  7. 24 16
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/authcode/AuthCodeServiceImpl.java
  8. 289 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/CommonInformServiceImpl.java
  9. 37 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/InformMessageContentRecordServiceImpl.java
  10. 114 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/InformMessageRecordServiceImpl.java
  11. 21 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/AbstractMessageHandler.java
  12. 45 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/EmailMessageHandler.java
  13. 25 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/NoteMessageHandler.java
  14. 45 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/WeChatAppletMessageHandler.java
  15. 49 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/WeChatMessageHandler.java
  16. 64 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/object/InformResult.java
  17. 3 3
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/keycloak/KeycloakServiceImpl.java
  18. 109 0
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/tenant/TenantExceptionInformStrategyServiceImpl.java
  19. 2 2
      smsb-customer-manager-app/src/main/java/com/inspur/customer/service/wechat/WeChatServiceImpl.java
  20. 7 0
      smsb-customer-manager-app/src/main/resources/email/AiAuditCreditInsufficientWarn.html
  21. 7 0
      smsb-customer-manager-app/src/main/resources/email/AiAuditMediaWarn.html
  22. 8 0
      smsb-customer-manager-app/src/main/resources/email/DevicePicAuditCreditWarn.html
  23. 30 0
      smsb-customer-manager-app/src/main/resources/weChat/AiAuditCreditInsufficientWarn.json
  24. 32 0
      smsb-customer-manager-app/src/main/resources/weChat/AiAuditMediaWarn.json
  25. 32 0
      smsb-customer-manager-app/src/main/resources/weChat/DevicePicAuditCreditWarn.json
  26. 16 4
      smsb-customer-manager-client/pom.xml
  27. 5 5
      smsb-customer-manager-client/src/main/java/com/inspur/customer/client/authcode/AuthCodeService.java
  28. 43 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/client/inform/CommonInformService.java
  29. 20 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/client/inform/InformMessageContentRecordService.java
  30. 33 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/client/inform/InformMessageRecordService.java
  31. 3 3
      smsb-customer-manager-client/src/main/java/com/inspur/customer/client/keycloak/KeycloakService.java
  32. 34 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/client/tenant/TenantExceptionInformStrategyService.java
  33. 1 1
      smsb-customer-manager-client/src/main/java/com/inspur/customer/client/wechat/IWeChatService.java
  34. 1 1
      smsb-customer-manager-client/src/main/java/com/inspur/customer/context/HttpUrlConstant.java
  35. 63 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/context/inform/InformLevelEnum.java
  36. 55 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/context/inform/InformTypeEnum.java
  37. 53 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/context/inform/MessageTemplateEnum.java
  38. 60 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/CommonInformCO.java
  39. 21 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/CommonMessageCO.java
  40. 40 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/CustomerBaseException.java
  41. 71 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformAddressees.java
  42. 44 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformMessageContentRecordDto.java
  43. 56 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformMessageRecordDto.java
  44. 59 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformStrategy.java
  45. 22 1
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/keycloak/KeycloakUserCO.java
  46. 110 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/tenant/ExceptionInformStrategyCmd.java
  47. 60 0
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/tenant/TenantExceptionInformStrategyCO.java
  48. 1 1
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/user/authcode/AuthCodeCheckDTO.java
  49. 1 1
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/user/authcode/AuthCodeCheckResponse.java
  50. 1 2
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/user/authcode/AuthCodeDTO.java
  51. 1 1
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/wechat/Pair.java
  52. 1 1
      smsb-customer-manager-client/src/main/java/com/inspur/customer/object/wechat/SubscribeDto.java
  53. 14 0
      smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/mapper/inform/InformMessageContentRecordMapper.java
  54. 13 0
      smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/mapper/inform/InformMessageRecordMapper.java
  55. 13 0
      smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/mapper/tenant/TenantExceptionInformStrategyMapper.java
  56. 48 0
      smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/object/inform/InformMessageContentRecordDO.java
  57. 81 0
      smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/object/inform/InformMessageRecordDO.java
  58. 32 0
      smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/object/tenant/TenantExceptionInformStrategyDO.java
  59. 5 0
      smsb-customer-manager-infrastructure/src/main/resources/mapper/inform/InformMessageContentRecordMapper.xml
  60. 5 0
      smsb-customer-manager-infrastructure/src/main/resources/mapper/inform/InformMessageRecordMapper.xml
  61. 5 0
      smsb-customer-manager-infrastructure/src/main/resources/mapper/tenant/TenantExceptionInformStrategyMapper.xml
  62. 2 0
      smsb-customer-manager-start-web/src/main/java/com/inspur/customer/SmsbCustomerWebApplication.java
  63. 2 6
      smsb-customer-manager-start-web/src/test/java/com/inspur/customer/KeycloakTest.java
  64. 79 0
      smsb-customer-manager-start-web/src/test/java/com/inspur/customer/MessageHandlerTest.java
  65. 0 72
      smsb-customer-manager-start/pom.xml
  66. 0 24
      smsb-customer-manager-start/src/test/java/com/inspur/customer/KeycloakTest.java

+ 34 - 0
smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/InformTestController.java

@@ -0,0 +1,34 @@
+package com.inspur.customer.web.controller;
+
+import com.inspur.customer.client.inform.CommonInformService;
+import com.inspur.customer.context.inform.InformTypeEnum;
+import com.inspur.customer.object.inform.CommonInformCO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author linwenhua
+ * @date 2022-07-04 14:37
+ **/
+@Slf4j
+@RestController
+public class InformTestController {
+
+    @DubboReference
+    private CommonInformService commonInformService;
+
+    @PostMapping("inform/test")
+    public void testInform(@RequestBody CommonInformCO commonInformCO) {
+        commonInformCO.setTypeEnum(InformTypeEnum.AI_MEDIA_WARN);
+        commonInformService.commonInform(commonInformCO);
+    }
+
+    @PostMapping("inform/tenant")
+    public void testTenant(@RequestBody CommonInformCO commonInformCO) {
+        commonInformCO.setTypeEnum(InformTypeEnum.AI_AUDIT_CREDIT_INSUFFICIENT_WARN);
+        commonInformService.tenantLevelInform(commonInformCO);
+    }
+}

+ 29 - 0
smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/TenantExceptionInformStrategyController.java

@@ -0,0 +1,29 @@
+package com.inspur.customer.web.controller;
+
+import com.alibaba.cola.dto.SingleResponse;
+import com.inspur.customer.client.tenant.TenantExceptionInformStrategyService;
+import com.inspur.customer.object.tenant.TenantExceptionInformStrategyCO;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-08 14:38
+ **/
+@RestController
+public class TenantExceptionInformStrategyController {
+
+    @DubboReference
+    private TenantExceptionInformStrategyService tenantExceptionInformStrategyService;
+
+    @PostMapping("/device/informStrategy")
+    public SingleResponse<TenantExceptionInformStrategyCO> setTenantInformStrategy(@RequestBody TenantExceptionInformStrategyCO informStrategyCo) {
+        return tenantExceptionInformStrategyService.setInformStrategy(informStrategyCo);
+    }
+
+    @GetMapping("/device/informStrategy")
+    public SingleResponse<TenantExceptionInformStrategyCO> setTenantInformStrategy(@RequestParam String tenant) {
+        return tenantExceptionInformStrategyService.getTenantInformStrategy(tenant);
+    }
+
+}

+ 4 - 9
smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/authcode/AuthCodeController.java

@@ -2,12 +2,10 @@ package com.inspur.customer.web.controller.authcode;
 
 import com.alibaba.cola.dto.Response;
 import com.alibaba.cola.dto.SingleResponse;
-import com.inspur.customer.service.client.authcode.AuthCodeService;
-import com.inspur.customer.service.dto.AuthCodeCheckDTO;
-import com.inspur.customer.service.dto.AuthCodeDTO;
-import com.inspur.customer.service.dto.AuthCodeCheckResponse;
-import com.inspur.inform.client.email.SmsbEmailService;
-import com.inspur.inform.object.message.EmailMessage;
+import com.inspur.customer.client.authcode.AuthCodeService;
+import com.inspur.customer.object.user.authcode.AuthCodeCheckDTO;
+import com.inspur.customer.object.user.authcode.AuthCodeCheckResponse;
+import com.inspur.customer.object.user.authcode.AuthCodeDTO;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.dubbo.config.annotation.DubboReference;
@@ -17,9 +15,6 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.ArrayList;
-import java.util.List;
-
 
 /**@Description: 验证码相关接口
  * @version v1.0

+ 3 - 3
smsb-customer-manager-adapter/src/main/java/com/inspur/customer/web/controller/keyclaok/KeycloakController.java

@@ -3,9 +3,9 @@ package com.inspur.customer.web.controller.keyclaok;
 import com.alibaba.cola.dto.Response;
 import com.alibaba.cola.dto.SingleResponse;
 import com.alibaba.fastjson.JSONObject;
-import com.inspur.customer.service.client.keycloak.KeycloakService;
-import com.inspur.customer.service.client.wechat.IWeChatService;
-import com.inspur.customer.service.dto.SubscribeDto;
+import com.inspur.customer.client.keycloak.KeycloakService;
+import com.inspur.customer.client.wechat.IWeChatService;
+import com.inspur.customer.object.wechat.SubscribeDto;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.dubbo.config.annotation.DubboReference;

+ 16 - 16
smsb-customer-manager-app/pom.xml

@@ -15,12 +15,20 @@
         <dependency>
             <groupId>com.inspur</groupId>
             <artifactId>smsb-customer-manager-infrastructure</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
+            <groupId>com.inspur</groupId>
+            <artifactId>smsb-customer-manager-client</artifactId>
+            <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.inspur</groupId>
+            <artifactId>smsb-event-logging-client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- dubbo -->
         <dependency>
             <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-spring-boot-starter</artifactId>
@@ -29,37 +37,29 @@
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>
         </dependency>
-        <dependency>
-            <groupId>com.inspur</groupId>
-            <artifactId>smsb-customer-manager-client</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-            <scope>compile</scope>
-        </dependency>
+
         <!--keycloak-->
         <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-admin-client</artifactId>
             <version>16.1.0</version>
         </dependency>
+
         <!--HttpClient -->
         <dependency>
             <groupId>commons-httpclient</groupId>
             <artifactId>commons-httpclient</artifactId>
             <version>3.1</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-web</artifactId>
         </dependency>
         <dependency>
-            <groupId>com.inspur</groupId>
-            <artifactId>smsb-event-logging-client</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>

+ 23 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/config/MybatisPlusConfiguration.java

@@ -0,0 +1,23 @@
+package com.inspur.customer.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * @author linwenhua
+ */
+@EnableTransactionManagement
+@Configuration
+public class MybatisPlusConfiguration {
+
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        return interceptor;
+    }
+}

+ 24 - 16
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/authcode/AuthCodeServiceImpl.java

@@ -3,16 +3,15 @@ package com.inspur.customer.service.authcode;
 import com.alibaba.cola.dto.Response;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.inspur.customer.service.client.authcode.AuthCodeService;
-import com.inspur.customer.service.dto.AuthCodeCheckDTO;
-import com.inspur.customer.service.dto.AuthCodeCheckResponse;
-import com.inspur.customer.service.dto.AuthCodeDTO;
+import com.inspur.customer.client.authcode.AuthCodeService;
+import com.inspur.customer.object.user.authcode.AuthCodeCheckDTO;
+import com.inspur.customer.object.user.authcode.AuthCodeCheckResponse;
+import com.inspur.customer.object.user.authcode.AuthCodeDTO;
 import com.inspur.inform.client.email.SmsbEmailService;
 import com.inspur.inform.client.sms.SmsbSmsService;
 import com.inspur.inform.object.message.EmailMessage;
 import com.inspur.inform.object.message.SmsMessage;
-import com.inspur.inform.object.message.sms.SmsbSmsMessageResponse;
-import com.inspur.inform.object.message.sms.SmsbSmsTemplateType;
+import com.inspur.inform.constants.SmsbSmsTemplateType;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.dubbo.config.annotation.DubboReference;
@@ -24,7 +23,8 @@ import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 
-/**@Description: 验证码相关功能实现类
+/**
+ * 验证码相关功能实现类
  * @version v1.0
  * @author joe wan
  * @date 2022/6/29 17:22
@@ -49,6 +49,7 @@ public class AuthCodeServiceImpl implements AuthCodeService {
      * @author joe wan
      * @date 2022/6/29 17:20
      */
+    @Override
     public Response sendAuthCode(AuthCodeDTO authCodeDTO){
         try{
 
@@ -61,7 +62,9 @@ public class AuthCodeServiceImpl implements AuthCodeService {
                 emailMessage.setEmailContent("【浪潮安播云】您的验证码"+ authcode +",该验证码5分钟内有效,请勿泄漏于他人!");
                 emailMessage.setAddressees(Lists.newArrayList(authCodeDTO.getEmail()));
                 Boolean aBoolean = smsbEmailService.sendEmail(emailMessage);
-                if(aBoolean)redisTemplate.opsForValue().set("smsb:authcode:email:" + authCodeDTO.getEmail(), authcode + "", 5, TimeUnit.MINUTES);
+                if(aBoolean) {
+                    redisTemplate.opsForValue().set("smsb:authcode:email:" + authCodeDTO.getEmail(), authcode + "", 5, TimeUnit.MINUTES);
+                }
             }
             //发送手机短信
             if(StringUtils.isNotBlank(authCodeDTO.getPhoneNum())){
@@ -72,12 +75,12 @@ public class AuthCodeServiceImpl implements AuthCodeService {
                 smsMessage.setPhones(Lists.newArrayList(authCodeDTO.getPhoneNum()));
                 smsMessage.setSignName("浪潮安播云");
                 smsMessage.setTemplateType(SmsbSmsTemplateType.AUTH_CODE);
-                SmsbSmsMessageResponse smsbSmsMessageResponse = smsbSmsService.sendWarningMessage(smsMessage);
-                if (smsbSmsMessageResponse.getSuccess()) {
+                Response sendResponse = smsbSmsService.sendWarningMessage(smsMessage);
+                if (sendResponse.isSuccess()) {
                     redisTemplate.opsForValue().set("smsb:authcode:phoneNum:" + authCodeDTO.getPhoneNum(), authcode + "", 5, TimeUnit.MINUTES);
                 }
             }
-        }catch (Exception e){
+        } catch (Exception e){
             log.error("发送验证码报错 --》 {}", authCodeDTO, e);
             return Response.buildFailure("999","发送失败!");
         }
@@ -86,21 +89,26 @@ public class AuthCodeServiceImpl implements AuthCodeService {
 
     /**@Description: 电话、邮件验证码check
      * @param[com.inspur.customer.service.dto.AuthCodeCheckDTO]
-     * @return com.inspur.customer.service.dto.AuthCodeCheckResponse
+     * @return com.inspur.customer.object.user.authcode.AuthCodeCheckResponse
      * @version v1.0
      * @author joe wan
      * @date 2022/6/30 17:56
      */
+    @Override
     public AuthCodeCheckResponse checkAuthCode(AuthCodeCheckDTO authCodeCheckDTO){
 
         AuthCodeCheckResponse result = new AuthCodeCheckResponse();
-        if(StringUtils.isNotBlank(authCodeCheckDTO.getPhoneNumAuthCode())){
+        if (StringUtils.isNotBlank(authCodeCheckDTO.getPhoneNumAuthCode())) {
             String authcodePhone = redisTemplate.opsForValue().get("smsb:authcode:phoneNum:" + authCodeCheckDTO.getPhoneNum());
-            if(authCodeCheckDTO.getPhoneNumAuthCode().equals(authcodePhone))result.setCheckPhoneNum(true);
+            if (authCodeCheckDTO.getPhoneNumAuthCode().equals(authcodePhone)) {
+                result.setCheckPhoneNum(true);
+            }
         }
-        if(StringUtils.isNotBlank(authCodeCheckDTO.getEmailAuthCode())){
+        if (StringUtils.isNotBlank(authCodeCheckDTO.getEmailAuthCode())) {
             String authcodeEmail = redisTemplate.opsForValue().get("smsb:authcode:email:" + authCodeCheckDTO.getEmail());
-            if(authCodeCheckDTO.getEmailAuthCode().equals(authcodeEmail))result.setCheckEmail(true);
+            if (authCodeCheckDTO.getEmailAuthCode().equals(authcodeEmail)) {
+                result.setCheckEmail(true);
+            }
         }
        return result;
     }

+ 289 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/CommonInformServiceImpl.java

@@ -0,0 +1,289 @@
+package com.inspur.customer.service.inform;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.inspur.customer.client.inform.CommonInformService;
+import com.inspur.customer.client.inform.InformMessageRecordService;
+import com.inspur.customer.client.keycloak.KeycloakService;
+import com.inspur.customer.client.tenant.TenantExceptionInformStrategyService;
+import com.inspur.customer.context.inform.MessageTemplateEnum;
+import com.inspur.customer.object.inform.*;
+import com.inspur.customer.object.keycloak.KeycloakUserCO;
+import com.inspur.customer.object.tenant.ExceptionInformStrategyCmd;
+import com.inspur.customer.object.tenant.TenantExceptionInformStrategyCO;
+import com.inspur.customer.service.inform.handler.EmailMessageHandler;
+import com.inspur.customer.service.inform.handler.NoteMessageHandler;
+import com.inspur.customer.service.inform.handler.WeChatAppletMessageHandler;
+import com.inspur.customer.service.inform.handler.WeChatMessageHandler;
+import com.inspur.customer.service.inform.object.InformResult;
+import com.inspur.inform.client.email.SmsbEmailService;
+import com.inspur.inform.client.sms.SmsbSmsService;
+import com.inspur.inform.client.wechat.IWeChatService;
+import com.inspur.inform.client.wechat.applet.IWxAppletUserMessageService;
+import com.inspur.inform.object.applet.message.WxAppletUserMessageDto;
+import com.inspur.inform.object.message.EmailMessage;
+import com.inspur.inform.object.message.SmsMessage;
+import com.inspur.inform.object.message.WechatMessage;
+import com.inspur.logging.object.EventBaseException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.annotation.DubboService;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * common inform service impl
+ *
+ * @author linwenhua
+ * @date 2022-06-29 15:30
+ **/
+@Slf4j
+@DubboService(interfaceClass = CommonInformService.class)
+public class CommonInformServiceImpl implements CommonInformService {
+
+    @Resource
+    private ObjectMapper objectMapper;
+
+    @Resource
+    private EmailMessageHandler emailMessageHandler;
+    @Resource
+    private NoteMessageHandler noteMessageHandler;
+    @Resource
+    private WeChatMessageHandler weChatMessageHandler;
+    @Resource
+    private WeChatAppletMessageHandler weChatAppletMessageHandler;
+
+    @DubboReference
+    private KeycloakService keycloakService;
+    @DubboReference
+    private TenantExceptionInformStrategyService tenantExceptionInformStrategyService;
+    @DubboReference
+    private InformMessageRecordService informMessageRecordService;
+
+    @DubboReference(async = true)
+    private SmsbEmailService smsbEmailService;
+    @DubboReference(async = true)
+    private SmsbSmsService smsbSmsService;
+    @DubboReference(async = true)
+    private IWeChatService weChatService;
+    @DubboReference(async = true)
+    private IWxAppletUserMessageService wxAppletUserMessageService;
+
+    @Override
+    public void commonInform(CommonInformCO informCo) {
+        // get base user
+        List<KeycloakUserCO> users = keycloakService.getUsersByIds(Collections.singletonList(informCo.getUserId()));
+        // get strategy
+        TenantExceptionInformStrategyCO informStrategyCo = tenantExceptionInformStrategyService.getTenantInformStrategyCache(informCo.getTenant());
+        ExceptionInformStrategyCmd informStrategyCmd = informStrategyCo.getStrategy().get(String.valueOf(informCo.getTypeEnum().getLevel().getId()));
+        switch (informCo.getTypeEnum().getLevel()) {
+            case HINT: {
+                log.info("hint");
+                break;
+            }
+            case INTERMEDIATE: {
+                log.info("intermediate");
+                //todo replace get user method
+                users.addAll(keycloakService.getUsersInRole("ROLE_SUPER_ADMIN"));
+                break;
+            }
+            case URGENT: {
+                log.info("urgent");
+                //todo replace get user method
+                users.addAll(keycloakService.getUsersInRole("ROLE_SUPER_ADMIN"));
+                break;
+            }
+            default: {
+                log.info("not support");
+                throw new EventBaseException("类型错误", 500);
+            }
+        }
+        // execute inform
+        executeInformUserCmd(informCo, informStrategyCmd, users);
+    }
+
+    @Override
+    public void tenantLevelInform(CommonInformCO informCo) {
+        log.info("tenant level: {}", informCo.getTenant());
+        // get user
+        List<KeycloakUserCO> users = keycloakService.getGroupSupervisor(informCo.getTenant());
+        // get strategy
+        TenantExceptionInformStrategyCO informStrategyCo = tenantExceptionInformStrategyService.getTenantInformStrategyCache(informCo.getTenant());
+        log.info("strategy: {}", informStrategyCo);
+        ExceptionInformStrategyCmd informStrategyCmd = informStrategyCo.getStrategy().get(String.valueOf(informCo.getTypeEnum().getLevel().getId()));
+        // execute inform
+        executeInformUserCmd(informCo, informStrategyCmd, users);
+    }
+
+    @Override
+    public void departmentLevelInform(CommonInformCO informCo) {
+        log.info("department level: {}", informCo.getOrg());
+        // get user
+        List<KeycloakUserCO> users = keycloakService.getGroupAdmin(informCo.getOrg());
+        // get strategy
+        TenantExceptionInformStrategyCO informStrategyCo = tenantExceptionInformStrategyService.getTenantInformStrategyCache(informCo.getTenant());
+        ExceptionInformStrategyCmd informStrategyCmd = informStrategyCo.getStrategy().get(String.valueOf(informCo.getTypeEnum().getLevel().getId()));
+        // execute inform
+        executeInformUserCmd(informCo, informStrategyCmd, users);
+    }
+
+    @Override
+    public void singleInformMethod(CommonInformCO informCo) {
+        log.info("single inform level: {}", informCo.getUserId());
+        List<KeycloakUserCO> users = keycloakService.getUsersByIds(Collections.singletonList(informCo.getUserId()));
+        // get strategy
+        TenantExceptionInformStrategyCO informStrategyCo = tenantExceptionInformStrategyService.getTenantInformStrategyCache(informCo.getTenant());
+        ExceptionInformStrategyCmd informStrategyCmd = informStrategyCo.getStrategy().get(String.valueOf(informCo.getTypeEnum().getLevel().getId()));
+        // execute inform
+        executeInformUserCmd(informCo, informStrategyCmd, users);
+    }
+
+    /**
+     * execute inform action
+     * @param informCo inform object
+     * @param informStrategyCmd strategy
+     * @param users users
+     */
+    private void executeInformUserCmd(CommonInformCO informCo, ExceptionInformStrategyCmd informStrategyCmd, List<KeycloakUserCO> users) {
+        // set addressees
+        InformAddressees addressees = new InformAddressees(users.size());
+        users.forEach(user -> {
+            log.info("user: {}", user);
+            addressees.addPhone(user.getPhone());
+            addressees.addEmailAddressee(user.getEmail());
+            addressees.addOpenId(user.getWechat());
+            addressees.addUserId(user.getId());
+        });
+        try {
+            // save record
+            Long contentId = this.saveSendRecord(informCo, informStrategyCmd, users);
+            // send message
+            InformResult informResult = sendMessage(informCo, informStrategyCmd, addressees);
+            // update record
+            updateSendRecord(informResult, contentId, informStrategyCmd);
+        } catch (IOException e) {
+            if (e instanceof JsonProcessingException) {
+                log.error("序列化出错: {}", e.getMessage(), e);
+                throw new CustomerBaseException("参数序列化出错", 500);
+            }
+            log.error("模板转换出错: {}", e.getMessage(), e);
+            throw new CustomerBaseException("模板转换出错", 500);
+        }
+    }
+
+    /**
+     * send message
+     * @param informCo inform co
+     * @param informStrategyCmd strategy
+     * @param addressees address
+     * @return inform result(CompletableFuture)
+     */
+    private InformResult sendMessage(CommonInformCO informCo, ExceptionInformStrategyCmd informStrategyCmd, InformAddressees addressees) throws IOException {
+        MessageTemplateEnum templateEnum = informCo.getTypeEnum().getTemplateEnum();
+        // inform result
+        InformResult informResult = new InformResult();
+        if (Boolean.TRUE.equals(informStrategyCmd.getEmail())) {
+            EmailMessage emailMessage = emailMessageHandler.makeEmailMessage(informCo.getEmailMessage(), templateEnum.getEmail(), addressees.getEmailAddressees());
+            log.info("email");
+            informResult.setEmailResult(smsbEmailService.asyncSendEmail(emailMessage));
+        }
+        if (Boolean.TRUE.equals(informStrategyCmd.getNote())) {
+            SmsMessage smsMessage = noteMessageHandler.makeSmsMessage(informCo.getNoteMessage(), addressees.getPhones(), templateEnum.getNote());
+            log.info("note");
+            informResult.setNoteResult(smsbSmsService.asyncSend(smsMessage));
+        }
+        if (Boolean.TRUE.equals(informStrategyCmd.getWechat())) {
+            WechatMessage wechatMessage = weChatMessageHandler.makeWeChatMessage(informCo.getWeChatMessage(), addressees.getOpenIds(), templateEnum.getWechat());
+            log.info("wechat");
+            informResult.setWeChatResult(weChatService.asyncSend(wechatMessage));
+        }
+        if (Boolean.TRUE.equals(informStrategyCmd.getWechatApplet())) {
+            WxAppletUserMessageDto wxAppletUserMessageDto = weChatAppletMessageHandler.makeWeChatAppletMessage(informCo.getWeChatAppletMessage(), templateEnum.getApplet());
+            log.info("applet");
+            informResult.setWeChatAppletResult(wxAppletUserMessageService.asyncInsertBatch(wxAppletUserMessageDto, addressees.getUserIds()));
+        }
+        return informResult;
+    }
+
+    /**
+     * save record
+     * @param informCo inform co
+     * @param informStrategyCmd strategy
+     * @param users users
+     * @return content id
+     * @throws JsonProcessingException json
+     */
+    private Long saveSendRecord(CommonInformCO informCo, ExceptionInformStrategyCmd informStrategyCmd, List<KeycloakUserCO> users) throws JsonProcessingException {
+        InformMessageRecordDto messageRecordDto = new InformMessageRecordDto();
+        messageRecordDto.setTenant(informCo.getTenant());
+        messageRecordDto.setOrg(informCo.getOrg());
+        Map<String, String> messageMap = new HashMap<>(4);
+        log.info("strategy: {}", informStrategyCmd);
+        if (Boolean.TRUE.equals(informStrategyCmd.getEmail())) {
+            messageMap.put(InformMessageRecordDto.EMAIL_KEY, objectMapper.writeValueAsString(informCo.getEmailMessage()));
+        }
+        if (Boolean.TRUE.equals(informStrategyCmd.getNote())) {
+            messageMap.put(InformMessageRecordDto.NOTE_KEY, objectMapper.writeValueAsString(informCo.getNoteMessage()));
+        }
+        if (Boolean.TRUE.equals(informStrategyCmd.getWechat())) {
+            messageMap.put(InformMessageRecordDto.WECHAT_KEY, objectMapper.writeValueAsString(informCo.getWeChatMessage()));
+        }
+        if (Boolean.TRUE.equals(informStrategyCmd.getWechatApplet())) {
+            messageMap.put(InformMessageRecordDto.WECHAT_APPLET_KEY, objectMapper.writeValueAsString(informCo.getWeChatAppletMessage()));
+        }
+        messageRecordDto.setMessageMap(messageMap);
+        return informMessageRecordService.saveRecord(users, informStrategyCmd, messageRecordDto);
+    }
+
+    /**
+     * update record after future done
+     * @param informResult result
+     * @param contentId contentId
+     * @param informStrategyCmd strategy
+     */
+    private void updateSendRecord(InformResult informResult, Long contentId, ExceptionInformStrategyCmd informStrategyCmd) {
+        CompletableFuture<Void> totalFuture = setFutureCombine(informResult, informStrategyCmd.getCount());
+        totalFuture.whenComplete((result, error) -> {
+            log.error("future error: {}", error.getMessage(), error);
+            log.info("update result flag");
+        });
+        totalFuture.join();
+        informResult.updateResultFlag();
+        // update record
+        informMessageRecordService.updateRecord(contentId, informResult.getResultFlag());
+    }
+
+    /**
+     * set future combine
+     * @param informResult result
+     * @param size future count
+     * @return combined future
+     */
+    public CompletableFuture<Void> setFutureCombine(InformResult informResult, Integer size) {
+        int index = 0;
+        CompletableFuture[] completableFutures = new CompletableFuture[size];
+        if (informResult.getNoteResult() != null) {
+            completableFutures[index] = informResult.getNoteResult();
+            index++;
+        }
+        if (informResult.getEmailResult() != null) {
+            completableFutures[index] = informResult.getEmailResult();
+            index++;
+        }
+        if (informResult.getWeChatResult() != null) {
+            completableFutures[index] = informResult.getWeChatResult();
+            index++;
+        }
+        if (informResult.getWeChatAppletResult() != null) {
+            completableFutures[index] = informResult.getWeChatAppletResult();
+        }
+        log.info("combine future");
+        return CompletableFuture.allOf(completableFutures);
+    }
+}

+ 37 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/InformMessageContentRecordServiceImpl.java

@@ -0,0 +1,37 @@
+package com.inspur.customer.service.inform;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.inspur.customer.client.inform.InformMessageContentRecordService;
+import com.inspur.customer.infrastructure.mapper.inform.InformMessageContentRecordMapper;
+import com.inspur.customer.infrastructure.object.inform.InformMessageContentRecordDO;
+import com.inspur.customer.object.inform.InformMessageContentRecordDto;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.beans.BeanUtils;
+
+import javax.annotation.Resource;
+
+/**
+ * message content record service
+ * @author linwenhua
+ * @date 2022-07-01 10:08
+ **/
+@Slf4j
+@DubboService(interfaceClass = InformMessageContentRecordService.class)
+public class InformMessageContentRecordServiceImpl extends ServiceImpl<InformMessageContentRecordMapper, InformMessageContentRecordDO> implements InformMessageContentRecordService {
+
+    @Resource
+    private ObjectMapper objectMapper;
+
+    @Override
+    public Long saveContentRecord(InformMessageContentRecordDto informMessageContentRecordDto) throws JsonProcessingException {
+        InformMessageContentRecordDO informMessageContentRecordDo = new InformMessageContentRecordDO();
+        BeanUtils.copyProperties(informMessageContentRecordDto, informMessageContentRecordDo);
+        // transform to json
+        informMessageContentRecordDo.setMessageMapJson(objectMapper.writeValueAsString(informMessageContentRecordDto.getMessageMap()));
+        this.save(informMessageContentRecordDo);
+        return informMessageContentRecordDo.getId();
+    }
+}

+ 114 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/InformMessageRecordServiceImpl.java

@@ -0,0 +1,114 @@
+package com.inspur.customer.service.inform;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.inspur.customer.client.inform.InformMessageContentRecordService;
+import com.inspur.customer.client.inform.InformMessageRecordService;
+import com.inspur.customer.infrastructure.mapper.inform.InformMessageRecordMapper;
+import com.inspur.customer.infrastructure.object.inform.InformMessageRecordDO;
+import com.inspur.customer.object.inform.InformMessageContentRecordDto;
+import com.inspur.customer.object.inform.InformMessageRecordDto;
+import com.inspur.customer.object.keycloak.KeycloakUserCO;
+import com.inspur.customer.object.tenant.ExceptionInformStrategyCmd;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.beans.BeanUtils;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+/**
+ * message send record service
+ * @author linwenhua
+ * @date 2022-06-30 17:40
+ **/
+@Slf4j
+@DubboService(interfaceClass = InformMessageRecordService.class)
+public class InformMessageRecordServiceImpl extends ServiceImpl<InformMessageRecordMapper, InformMessageRecordDO> implements InformMessageRecordService {
+
+    @DubboReference
+    private InformMessageContentRecordService informMessageContentRecordService;
+
+    @Override
+    public Long saveRecord(List<KeycloakUserCO> users, ExceptionInformStrategyCmd informStrategyCmd, InformMessageRecordDto informMessageRecordDto) throws JsonProcessingException {
+        List<InformMessageRecordDO> informMessageRecordDos = new ArrayList<>(users.size());
+        // save content
+        Long contentId = this.saveMessageContent(informMessageRecordDto, informStrategyCmd, users.size());
+        users.forEach(user -> {
+            InformMessageRecordDO informMessageRecordDo = new InformMessageRecordDO();
+            BeanUtils.copyProperties(informMessageRecordDto, informMessageRecordDo);
+            // set inform flag
+            informMessageRecordDo.setInformFlag(getInformFlag(user, informStrategyCmd));
+            // status default 0
+            informMessageRecordDo.setInformStatus(0);
+            informMessageRecordDo.setContentId(contentId);
+            informMessageRecordDo.setUserId(user.getId());
+            informMessageRecordDos.add(informMessageRecordDo);
+        });
+        this.saveBatch(informMessageRecordDos, informMessageRecordDos.size());
+        return contentId;
+    }
+
+    @Override
+    public void updateRecord(Long contentId, Integer informStatus) {
+        log.info("update send record: {}", contentId);
+        BitSet informBitMap = BitSet.valueOf(new byte[]{informStatus.byteValue()});
+        List<InformMessageRecordDO> messageRecordDos = this.list(Wrappers
+            .<InformMessageRecordDO>lambdaQuery()
+            .eq(InformMessageRecordDO::getContentId, contentId));
+        messageRecordDos.forEach(messageRecordDo -> {
+            BitSet userBitMap = messageRecordDo.getBitMap();
+            userBitMap.and(informBitMap);
+            if (userBitMap.isEmpty()) {
+                messageRecordDo.setInformStatus(0);
+            } else {
+                messageRecordDo.setInformStatus((int) userBitMap.toByteArray()[0]);
+            }
+        });
+        this.updateBatchById(messageRecordDos);
+    }
+
+    /**
+     * save message content
+     * @param informMessageRecordDto record
+     * @param informStrategyCmd strategy
+     * @param size record count
+     * @return contentId
+     * @throws JsonProcessingException json parse exception
+     */
+    private Long saveMessageContent(InformMessageRecordDto informMessageRecordDto, ExceptionInformStrategyCmd informStrategyCmd, Integer size) throws JsonProcessingException {
+        InformMessageContentRecordDto informMessageContentRecordDto = new InformMessageContentRecordDto();
+        informMessageContentRecordDto.setTenant(informMessageRecordDto.getTenant());
+        informMessageContentRecordDto.setUsers(size);
+        informMessageContentRecordDto.setMessageMap(informMessageRecordDto.getMessageMap());
+        informMessageContentRecordDto.setInformFlag(informStrategyCmd.getStrategyFlag());
+        return informMessageContentRecordService.saveContentRecord(informMessageContentRecordDto);
+    }
+
+    /**
+     * get inform flag by bitMap
+     * 从低位开始
+     * 0 位: note 1
+     * 1 位: email 2
+     * 2 位: weChat 4
+     * 3 位: weChatApplet 8
+     * @param keycloakUserCo user
+     * @param informStrategyCmd strategy
+     * @return flag
+     */
+    private Integer getInformFlag(KeycloakUserCO keycloakUserCo, ExceptionInformStrategyCmd informStrategyCmd) {
+        log.info("user: {}", keycloakUserCo);
+        BitSet userBitSet = keycloakUserCo.getInformFlag();
+        BitSet strategyBitSet = informStrategyCmd.getStrategySet();
+        userBitSet.and(strategyBitSet);
+        log.info("userBitSet: {}", userBitSet);
+        log.info("strategy: {}", strategyBitSet);
+        if (userBitSet.isEmpty()) {
+            return 0;
+        }
+        return (int) userBitSet.toByteArray()[0];
+    }
+}

+ 21 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/AbstractMessageHandler.java

@@ -0,0 +1,21 @@
+package com.inspur.customer.service.inform.handler;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author linwenhua
+ * @date 2022-07-01 15:44
+ **/
+public class AbstractMessageHandler {
+
+    protected String getTemplate(String filePath) throws IOException {
+        ClassPathResource classPathResource = new ClassPathResource(filePath);
+        InputStream inputStream = classPathResource.getInputStream();
+        return IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+    }
+}

+ 45 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/EmailMessageHandler.java

@@ -0,0 +1,45 @@
+package com.inspur.customer.service.inform.handler;
+
+import com.inspur.customer.object.inform.CommonMessageCO;
+import com.inspur.inform.object.message.EmailMessage;
+import org.apache.commons.io.IOUtils;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * email message content handler
+ * @author linwenhua
+ * @date 2022-07-01 10:58
+ **/
+@Component
+public class EmailMessageHandler extends AbstractMessageHandler {
+
+    private static final String FILE_PATH_PRE = "email/";
+
+    private static final String FILE_PATH_SUF = ".html";
+
+    public EmailMessage makeEmailMessage(CommonMessageCO commonMessageCo, String fileName, List<String> addressees) throws IOException {
+        // get content
+        String filePath = FILE_PATH_PRE + fileName + FILE_PATH_SUF;
+        String content = getTemplate(filePath);
+        Iterator<String> integer = commonMessageCo.getMessageMap().keySet().iterator();
+        String key;
+        while (integer.hasNext()) {
+            key = integer.next();
+            content = content.replaceFirst(key, commonMessageCo.getMessageMap().get(key));
+        }
+        // set email message
+        // todo attach file and subject
+        EmailMessage emailMessage = new EmailMessage();
+        emailMessage.setAddressees(addressees);
+        emailMessage.setEmailContent(content);
+        emailMessage.setSubject(commonMessageCo.getSubject());
+        return emailMessage;
+    }
+}

+ 25 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/NoteMessageHandler.java

@@ -0,0 +1,25 @@
+package com.inspur.customer.service.inform.handler;
+
+import com.inspur.customer.object.inform.CommonMessageCO;
+import com.inspur.inform.object.message.SmsMessage;
+import com.inspur.inform.constants.SmsbSmsTemplateType;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * note message content handler
+ * @author linwenhua
+ * @date 2022-07-01 10:57
+ **/
+@Component
+public class NoteMessageHandler extends AbstractMessageHandler {
+
+    public SmsMessage makeSmsMessage(CommonMessageCO commonMessageCo, List<String> phones, Integer smsType) {
+        SmsMessage message = new SmsMessage();
+        message.setPhones(phones);
+        message.setTemplateParam(commonMessageCo.getMessageMap());
+        message.setTemplateType(SmsbSmsTemplateType.getTypeById(smsType));
+        return message;
+    }
+}

+ 45 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/WeChatAppletMessageHandler.java

@@ -0,0 +1,45 @@
+package com.inspur.customer.service.inform.handler;
+
+import com.inspur.customer.object.inform.CommonMessageCO;
+import com.inspur.inform.client.wechat.applet.IWxAppletUserMessageService;
+import com.inspur.inform.constants.UserMsgType;
+import com.inspur.inform.constants.applet.WxAppletMessageTemplate;
+import com.inspur.inform.object.applet.message.WxAppletUserMessageDto;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.stereotype.Component;
+
+import java.util.Iterator;
+
+/**
+ * weChat applet message content handler
+ * @author linwenhua
+ * @date 2022-07-01 10:58
+ **/
+@Slf4j
+@Component
+public class WeChatAppletMessageHandler extends AbstractMessageHandler {
+
+    @DubboReference(timeout = 10000, retries = 0)
+    private IWxAppletUserMessageService wxAppletUserMessageService;
+
+    public WxAppletUserMessageDto makeWeChatAppletMessage(CommonMessageCO commonMessageCo, String fileName) {
+        // get content
+        WxAppletMessageTemplate messageTemplateEnum = WxAppletMessageTemplate.getTemplateByFilePath(fileName);
+        log.info("template: {}", messageTemplateEnum);
+        String content = wxAppletUserMessageService.getTemplate(messageTemplateEnum);
+        Iterator<String> integer = commonMessageCo.getMessageMap().keySet().iterator();
+        String key;
+        while (integer.hasNext()) {
+            key = integer.next();
+            content = content.replaceFirst(key, commonMessageCo.getMessageMap().get(key));
+        }
+        WxAppletUserMessageDto wxAppletUserMessageDto = new WxAppletUserMessageDto();
+        wxAppletUserMessageDto.setSubject(commonMessageCo.getSubject());
+        //todo type level pic
+        wxAppletUserMessageDto.setType(UserMsgType.SYSTEM.getType());
+        wxAppletUserMessageDto.setPic(0);
+        wxAppletUserMessageDto.setMessage(content);
+        return wxAppletUserMessageDto;
+    }
+}

+ 49 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/handler/WeChatMessageHandler.java

@@ -0,0 +1,49 @@
+package com.inspur.customer.service.inform.handler;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.inspur.customer.object.inform.CommonMessageCO;
+import com.inspur.inform.object.message.WechatKeyword;
+import com.inspur.inform.object.message.WechatMessage;
+import com.inspur.inform.object.message.WechatRealMessage;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.List;
+
+/**
+ * weChat message content handler
+ * @author linwenhua
+ * @date 2022-07-01 10:57
+ **/
+@Component
+public class WeChatMessageHandler extends AbstractMessageHandler {
+
+    @Resource
+    private ObjectMapper objectMapper;
+
+    private static final String FILE_PATH_PRE = "weChat/";
+
+    private static final String FILE_PATH_SUF = ".json";
+
+    public WechatMessage makeWeChatMessage(CommonMessageCO commonMessageCo, List<String> openIds, String fileName) throws IOException {
+        WechatRealMessage wechatRealMessage = getRealMessage(fileName);
+        commonMessageCo.getMessageMap().forEach((key, word) -> {
+            WechatKeyword wechatKeyword = wechatRealMessage.getData().get(key);
+            String keywordValue = wechatKeyword.getValue();
+            String[] words = word.split("/");
+            wechatKeyword.setValue(MessageFormat.format(keywordValue, words));
+        });
+        WechatMessage wechatMessage = new WechatMessage(wechatRealMessage);
+        wechatMessage.setInformAddresses(openIds);
+        return wechatMessage;
+    }
+
+    private WechatRealMessage getRealMessage(String fileName) throws IOException {
+        // get content
+        String filePath = FILE_PATH_PRE + fileName + FILE_PATH_SUF;
+        String content = getTemplate(filePath);
+        return objectMapper.readValue(content, WechatRealMessage.class);
+    }
+}

+ 64 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/inform/object/InformResult.java

@@ -0,0 +1,64 @@
+package com.inspur.customer.service.inform.object;
+
+import com.inspur.inform.object.message.MessageSendResponse;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.BitSet;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author linwenhua
+ * @date 2022-07-01 19:01
+ **/
+@Data
+@Slf4j
+public class InformResult {
+
+    private BitSet resultFlag = new BitSet(4);
+
+    private CompletableFuture<MessageSendResponse> emailResult;
+    private CompletableFuture<MessageSendResponse> noteResult;
+    private CompletableFuture<MessageSendResponse> weChatResult;
+    private CompletableFuture<MessageSendResponse> weChatAppletResult;
+
+    public void updateResultFlag(Integer index) {
+        resultFlag.set(index);
+    }
+
+    public void updateResultFlag() {
+        if (noteResult != null) {
+            log.info("update note flag");
+            getFlagFromFuture(noteResult, 0);
+        }
+        if (emailResult != null) {
+            log.info("update email flag");
+            getFlagFromFuture(emailResult, 1);
+        }
+        if (weChatResult != null) {
+            log.info("update weChat flag");
+            getFlagFromFuture(weChatResult, 2);
+        }
+        if (weChatAppletResult != null) {
+            log.info("update applet flag");
+            getFlagFromFuture(weChatAppletResult, 3);
+        }
+    }
+
+    public Integer getResultFlag() {
+        if (resultFlag.isEmpty()) {
+            return 0;
+        }
+        return (int) resultFlag.toByteArray()[0];
+    }
+
+    private void getFlagFromFuture(CompletableFuture<MessageSendResponse> future, Integer index) {
+        future.whenComplete((result, error) -> {
+            if (error == null) {
+                resultFlag.set(index);
+            }
+        });
+    }
+
+
+}

+ 3 - 3
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/keycloak/KeycloakServiceImpl.java

@@ -1,8 +1,8 @@
 package com.inspur.customer.service.keycloak;
 
-import com.inspur.customer.service.client.keycloak.KeycloakService;
-import com.inspur.customer.service.dto.KeycloakUserCO;
-import com.inspur.customer.service.dto.Pair;
+import com.inspur.customer.client.keycloak.KeycloakService;
+import com.inspur.customer.object.keycloak.KeycloakUserCO;
+import com.inspur.customer.object.wechat.Pair;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.keycloak.admin.client.Keycloak;

+ 109 - 0
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/tenant/TenantExceptionInformStrategyServiceImpl.java

@@ -0,0 +1,109 @@
+package com.inspur.customer.service.tenant;
+
+import com.alibaba.cola.dto.SingleResponse;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.inspur.customer.client.tenant.TenantExceptionInformStrategyService;
+import com.inspur.customer.infrastructure.mapper.tenant.TenantExceptionInformStrategyMapper;
+import com.inspur.customer.infrastructure.object.tenant.TenantExceptionInformStrategyDO;
+import com.inspur.customer.object.tenant.ExceptionInformStrategyCmd;
+import com.inspur.customer.object.tenant.TenantExceptionInformStrategyCO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * tenant exception inform strategy service implement
+ * @author linwenhua
+ * @date 2022-06-08 11:49
+ **/
+@Slf4j
+@DubboService(interfaceClass = TenantExceptionInformStrategyService.class)
+public class TenantExceptionInformStrategyServiceImpl extends ServiceImpl<TenantExceptionInformStrategyMapper, TenantExceptionInformStrategyDO> implements TenantExceptionInformStrategyService {
+
+    @Override
+    @CacheEvict(value = "msr:tenant:informStrategy", key = "#informStrategyCo.getTenant()")
+    public SingleResponse<TenantExceptionInformStrategyCO> setInformStrategy(TenantExceptionInformStrategyCO informStrategyCo) {
+        TenantExceptionInformStrategyDO informStrategyDO = changeToInformStrategyDo(informStrategyCo);
+        this.saveOrUpdate(informStrategyDO);
+        return SingleResponse.of(informStrategyCo);
+    }
+
+    @Override
+    public SingleResponse<TenantExceptionInformStrategyCO> getTenantInformStrategy(String tenant) {
+        TenantExceptionInformStrategyDO informStrategyDO = this.getById(tenant);
+        if (informStrategyDO == null) {
+            return SingleResponse.of(getDefaultStrategy(tenant));
+        }
+        return SingleResponse.of(changeToInformStrategyCo(informStrategyDO));
+    }
+
+    @Override
+    @Cacheable(value = "msr:tenant:informStrategy", key = "#tenant")
+    public TenantExceptionInformStrategyCO getTenantInformStrategyCache(String tenant) {
+        log.info("get inform strategy: {}", tenant);
+        TenantExceptionInformStrategyDO informStrategyDo = this.getById(tenant);
+        // if user didn't not set strategy, return default
+        if (informStrategyDo == null) {
+            return getDefaultStrategy(tenant);
+        }
+        return changeToInformStrategyCo(informStrategyDo);
+    }
+
+    /**
+     * change to do
+     * @param informStrategyCo co
+     * @return do
+     */
+    private TenantExceptionInformStrategyDO changeToInformStrategyDo(TenantExceptionInformStrategyCO informStrategyCo) {
+        TenantExceptionInformStrategyDO informStrategyDO = new TenantExceptionInformStrategyDO();
+        informStrategyDO.setTenant(informStrategyCo.getTenant());
+        informStrategyDO.setHintLevelFlag(informStrategyCo.getInformFlagByLevel(TenantExceptionInformStrategyCO.HINT_LEVEL_KEY));
+        informStrategyDO.setMiddleLevelFlag(informStrategyCo.getInformFlagByLevel(TenantExceptionInformStrategyCO.MIDDLE_LEVEL_KEY));
+        informStrategyDO.setUrgencyLevelFlag(informStrategyCo.getInformFlagByLevel(TenantExceptionInformStrategyCO.URGENT_LEVEL_KEY));
+        return informStrategyDO;
+    }
+
+    /**
+     * change to co
+     * @param informStrategyDo do
+     * @return co
+     */
+    private TenantExceptionInformStrategyCO changeToInformStrategyCo(TenantExceptionInformStrategyDO informStrategyDo) {
+        TenantExceptionInformStrategyCO informStrategyCo = new TenantExceptionInformStrategyCO(informStrategyDo.getTenant(), 10);
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.HINT_LEVEL_KEY, new ExceptionInformStrategyCmd(informStrategyDo.getHintLevelFlag()));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.MIDDLE_LEVEL_KEY, new ExceptionInformStrategyCmd(informStrategyDo.getMiddleLevelFlag()));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.URGENT_LEVEL_KEY, new ExceptionInformStrategyCmd(informStrategyDo.getUrgencyLevelFlag()));
+        // special strategy
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.TENANT_LEVEL_KEY, new ExceptionInformStrategyCmd(15));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.DEPARTMENT_LEVEL, new ExceptionInformStrategyCmd(15));
+        // single method
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.SINGLE_NOTE, new ExceptionInformStrategyCmd(1));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.SINGLE_EMAIL, new ExceptionInformStrategyCmd(2));
+        return informStrategyCo;
+    }
+
+    /**
+     * if user didn't set strategy, return default one
+     * @param tenant tenant identifier
+     * @return strategy
+     */
+    private TenantExceptionInformStrategyCO getDefaultStrategy(String tenant) {
+        log.info("get default strategy");
+        TenantExceptionInformStrategyCO informStrategyCo = new TenantExceptionInformStrategyCO(tenant, 10);
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.HINT_LEVEL_KEY, new ExceptionInformStrategyCmd(14));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.MIDDLE_LEVEL_KEY, new ExceptionInformStrategyCmd(15));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.URGENT_LEVEL_KEY, new ExceptionInformStrategyCmd(15));
+        // special strategy
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.TENANT_LEVEL_KEY, new ExceptionInformStrategyCmd(15));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.DEPARTMENT_LEVEL, new ExceptionInformStrategyCmd(15));
+        // single method
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.SINGLE_NOTE, new ExceptionInformStrategyCmd(1));
+        informStrategyCo.updateStrategy(TenantExceptionInformStrategyCO.SINGLE_EMAIL, new ExceptionInformStrategyCmd(2));
+        return informStrategyCo;
+    }
+
+}

+ 2 - 2
smsb-customer-manager-app/src/main/java/com/inspur/customer/service/wechat/WeChatServiceImpl.java

@@ -1,7 +1,7 @@
 package com.inspur.customer.service.wechat;
 
-import com.inspur.customer.service.client.wechat.IWeChatService;
-import com.inspur.customer.service.constans.HttpUrlConstant;
+import com.inspur.customer.client.wechat.IWeChatService;
+import com.inspur.customer.context.HttpUrlConstant;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.springframework.http.HttpEntity;

+ 7 - 0
smsb-customer-manager-app/src/main/resources/email/AiAuditCreditInsufficientWarn.html

@@ -0,0 +1,7 @@
+尊敬的用户,您好!<br>
+<br>
+&nbsp;&nbsp;您的AI机审有一条{MSR_LEVEL}预警,相关信息如下:<br>
+&nbsp;&nbsp;&nbsp;库存类型:{MSR_TYPE}<br>
+&nbsp;&nbsp;&nbsp;库存余数:{MSR_REMAINING}<br>
+&nbsp;&nbsp;&nbsp;预警阈值:{MSR_THRESHOLD}<br>
+&nbsp;&nbsp;&nbsp;统计日期: {MSR_WARN_DATE}<br>

+ 7 - 0
smsb-customer-manager-app/src/main/resources/email/AiAuditMediaWarn.html

@@ -0,0 +1,7 @@
+尊敬的用户,您好!<br>
+<br>
+&nbsp;&nbsp;您的AI机审有一条{MSR_LEVEL}预警,相关信息如下:<br>
+&nbsp;&nbsp;&nbsp;操作人员:{MSR_OPERATOR_NAME}<br>
+&nbsp;&nbsp;&nbsp;上传文件名:{MSR_FILE_ORIGINAL_NAME}<br>
+&nbsp;&nbsp;&nbsp;上传时间: {MSR_CREATE_TIME}<br>
+&nbsp;&nbsp;&nbsp;AI审核结果: {MSR_AI_AUDIT_RESULT}<br>

+ 8 - 0
smsb-customer-manager-app/src/main/resources/email/DevicePicAuditCreditWarn.html

@@ -0,0 +1,8 @@
+尊敬的用户,您好!<br>
+<br>
+&nbsp;&nbsp;您的AI机审有一条{MSR_LEVEL}预警,相关信息如下:<br>
+&nbsp;&nbsp;&nbsp;库存类型:{MSR_TYPE}<br>
+&nbsp;&nbsp;&nbsp;库存余数:{MSR_REMAINING}<br>
+&nbsp;&nbsp;&nbsp;预警阈值:{MSR_THRESHOLD}<br>
+&nbsp;&nbsp;&nbsp;统计日期: {MSR_WARN_DATE}<br>
+&nbsp;&nbsp;&nbsp;预警详情: 当天库存余数已到达设备回采审核库存阈值,请及时充值.<br>

+ 30 - 0
smsb-customer-manager-app/src/main/resources/weChat/AiAuditCreditInsufficientWarn.json

@@ -0,0 +1,30 @@
+{
+    "data":
+    {
+        "first":
+        {
+            "value": "【浪潮安播云】您的AI机审有一条 {0} 预警,请及时关注,谢谢。",
+            "color": "#173177"
+        },
+        "keyword1":
+        {
+            "value": "{0}",
+            "color": "#173177"
+        },
+        "keyword2":
+        {
+            "value": "无",
+            "color": "#173177"
+        },
+        "keyword3":
+        {
+            "value": "当前库存: {0}, 预警阈值: {1}",
+            "color": "#173177"
+        },
+        "keyword4":
+        {
+            "value": "{0}",
+            "color": "#173177"
+        }
+    }
+}

+ 32 - 0
smsb-customer-manager-app/src/main/resources/weChat/AiAuditMediaWarn.json

@@ -0,0 +1,32 @@
+{
+    "data":
+
+    {
+        "first":
+        {
+            "value": "【浪潮安播云】您的 AI 机审有一条 {0} 预警,请及时关注,谢谢。",
+            "color": "#173177"
+        },
+        "keyword1":
+        {
+            "value": "AI 审核",
+            "color": "#173177"
+        },
+        "keyword2":
+        {
+            "value": "无",
+            "color": "#173177"
+        },
+        "keyword3":
+        {
+            "value": "审核结果: 不合规, 操作人员:{0}, 上传文件名:{1}",
+            "color": "#173177"
+        },
+        "keyword4":
+        {
+            "value": "{0}",
+            "color": "#173177"
+        }
+
+    }
+}

+ 32 - 0
smsb-customer-manager-app/src/main/resources/weChat/DevicePicAuditCreditWarn.json

@@ -0,0 +1,32 @@
+{
+    "data":
+
+    {
+        "first":
+        {
+            "value": "【浪潮安播云】您的 AI 机审有一条 {0} 预警,请及时关注,谢谢。",
+            "color": "#173177"
+        },
+        "keyword1":
+        {
+            "value": "图片库存",
+            "color": "#173177"
+        },
+        "keyword2":
+        {
+            "value": "无",
+            "color": "#173177"
+        },
+        "keyword3":
+        {
+            "value": "设备回采审核库存不足,当前库存: {0}, 预警阈值: {1}",
+            "color": "#173177"
+        },
+        "keyword4":
+        {
+            "value": "{0}",
+            "color": "#173177"
+        }
+
+    }
+}

+ 16 - 4
smsb-customer-manager-client/pom.xml

@@ -20,20 +20,28 @@
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <scope>compile</scope>
-            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
         </dependency>
         <!-- cola -->
         <dependency>
             <groupId>com.alibaba.cola</groupId>
             <artifactId>cola-component-dto</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-annotations</artifactId>
+            <artifactId>jackson-core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
         </dependency>
         <!--validation-->
         <dependency>
@@ -45,6 +53,10 @@
             <artifactId>hibernate-validator</artifactId>
             <version>6.1.5.Final</version>
         </dependency>
+        <dependency>
+            <groupId>jakarta.validation</groupId>
+            <artifactId>jakarta.validation-api</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

+ 5 - 5
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/client/authcode/AuthCodeService.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/client/authcode/AuthCodeService.java

@@ -1,9 +1,9 @@
-package com.inspur.customer.service.client.authcode;
+package com.inspur.customer.client.authcode;
 
 import com.alibaba.cola.dto.Response;
-import com.inspur.customer.service.dto.AuthCodeCheckDTO;
-import com.inspur.customer.service.dto.AuthCodeDTO;
-import com.inspur.customer.service.dto.AuthCodeCheckResponse;
+import com.inspur.customer.object.user.authcode.AuthCodeCheckDTO;
+import com.inspur.customer.object.user.authcode.AuthCodeDTO;
+import com.inspur.customer.object.user.authcode.AuthCodeCheckResponse;
 
 /**@Description: 验证码相关
  * @version v1.0
@@ -23,7 +23,7 @@ public interface AuthCodeService {
 
     /**@Description: 电话、邮件验证码check
      * @param[com.inspur.customer.service.dto.AuthCodeCheckDTO]
-     * @return com.inspur.customer.service.dto.AuthCodeCheckResponse
+     * @return com.inspur.customer.object.user.authcode.AuthCodeCheckResponse
      * @version v1.0
      * @author joe wan
      * @date 2022/6/30 17:56

+ 43 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/client/inform/CommonInformService.java

@@ -0,0 +1,43 @@
+package com.inspur.customer.client.inform;
+
+import com.inspur.customer.object.inform.CommonInformCO;
+
+/**
+ * common inform service
+ * @author linwenhua
+ * @date 2022-06-29 14:59
+ **/
+public interface CommonInformService {
+
+    /**
+     * common inform for some level like that:
+     * @see com.inspur.customer.context.inform.InformLevelEnum#HINT
+     * @see com.inspur.customer.context.inform.InformLevelEnum#INTERMEDIATE
+     * @see com.inspur.customer.context.inform.InformLevelEnum#URGENT
+     * @param informCo informCo
+     */
+    void commonInform(CommonInformCO informCo);
+
+    /**
+     * tenant level inform for tenant manager
+     * @see com.inspur.customer.context.inform.InformLevelEnum#TENANT
+     * @param informCo informCO
+     */
+    void tenantLevelInform(CommonInformCO informCo);
+
+    /**
+     * department level inform for department leader
+     * @see com.inspur.customer.context.inform.InformLevelEnum#HINT
+     * @param informCo informCO
+     */
+    void departmentLevelInform(CommonInformCO informCo);
+
+    /**
+     * single inform method for some level like that:
+     * @see com.inspur.customer.context.inform.InformLevelEnum#SINGLE_EMAIL
+     * @see com.inspur.customer.context.inform.InformLevelEnum#SINGLE_NOTE
+     * @param informCo informCo
+     */
+    void singleInformMethod(CommonInformCO informCo);
+
+}

+ 20 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/client/inform/InformMessageContentRecordService.java

@@ -0,0 +1,20 @@
+package com.inspur.customer.client.inform;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.inspur.customer.object.inform.InformMessageContentRecordDto;
+
+/**
+ * message content record service
+ * @author linwenhua
+ * @date 2022-06-29 16:31
+ **/
+public interface InformMessageContentRecordService {
+
+    /**
+     * save content
+     * @param informMessageContentRecordDto content record
+     * @throws JsonProcessingException json parse exception
+     * @return content id
+     */
+    Long saveContentRecord(InformMessageContentRecordDto informMessageContentRecordDto) throws JsonProcessingException;
+}

+ 33 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/client/inform/InformMessageRecordService.java

@@ -0,0 +1,33 @@
+package com.inspur.customer.client.inform;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.inspur.customer.object.inform.InformMessageRecordDto;
+import com.inspur.customer.object.keycloak.KeycloakUserCO;
+import com.inspur.customer.object.tenant.ExceptionInformStrategyCmd;
+
+import java.util.List;
+
+/**
+ * message send record service
+ * @author linwenhua
+ * @date 2022-06-29 16:31
+ **/
+public interface InformMessageRecordService {
+
+    /**
+     * save send record
+     * @param users users
+     * @param informStrategyCmd inform strategy
+     * @param informMessageRecordDto message record
+     * @throws JsonProcessingException json parse exception
+     * @return content id
+     */
+    Long saveRecord(List<KeycloakUserCO> users, ExceptionInformStrategyCmd informStrategyCmd, InformMessageRecordDto informMessageRecordDto) throws JsonProcessingException;
+
+    /**
+     * update record
+     * @param contentId contentId
+     * @param informStatus status
+     */
+    void updateRecord(Long contentId, Integer informStatus);
+}

+ 3 - 3
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/client/keycloak/KeycloakService.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/client/keycloak/KeycloakService.java

@@ -1,6 +1,6 @@
-package com.inspur.customer.service.client.keycloak;
-import com.inspur.customer.service.dto.KeycloakUserCO;
-import com.inspur.customer.service.dto.Pair;
+package com.inspur.customer.client.keycloak;
+import com.inspur.customer.object.keycloak.KeycloakUserCO;
+import com.inspur.customer.object.wechat.Pair;
 
 import java.util.List;
 import java.util.Map;

+ 34 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/client/tenant/TenantExceptionInformStrategyService.java

@@ -0,0 +1,34 @@
+package com.inspur.customer.client.tenant;
+
+
+import com.alibaba.cola.dto.SingleResponse;
+import com.inspur.customer.object.tenant.TenantExceptionInformStrategyCO;
+
+/**
+ * tenant exception inform strategy service
+ * @author linwenhua
+ * @date 2022-06-08 11:48
+ **/
+public interface TenantExceptionInformStrategyService {
+
+    /**
+     * set tenant inform strategy
+     * @param informStrategyCo strategy
+     * @return result
+     */
+    SingleResponse<TenantExceptionInformStrategyCO> setInformStrategy(TenantExceptionInformStrategyCO informStrategyCo);
+
+    /**
+     * get tenant inform strategy
+     * @param tenant tenant identifier
+     * @return result
+     */
+    SingleResponse<TenantExceptionInformStrategyCO> getTenantInformStrategy(String tenant);
+
+    /**
+     * get and cache strategy
+     * @param tenant tenant identifier
+     * @return result
+     */
+    TenantExceptionInformStrategyCO getTenantInformStrategyCache(String tenant);
+}

+ 1 - 1
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/client/wechat/IWeChatService.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/client/wechat/IWeChatService.java

@@ -1,4 +1,4 @@
-package com.inspur.customer.service.client.wechat;
+package com.inspur.customer.client.wechat;
 
 /**
  * 微信接口处理

+ 1 - 1
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/constans/HttpUrlConstant.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/context/HttpUrlConstant.java

@@ -1,4 +1,4 @@
-package com.inspur.customer.service.constans;
+package com.inspur.customer.context;
 
 /**
  * url统一管理

+ 63 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/context/inform/InformLevelEnum.java

@@ -0,0 +1,63 @@
+package com.inspur.customer.context.inform;
+
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * inform level enum
+ * @author linwenhua
+ */
+public enum InformLevelEnum {
+
+    /**
+     * test level
+     */
+    TEST(-1, "测试"),
+    /**
+     * hint level
+     */
+    HINT(0, "提示"),
+    /**
+     * intermediate level
+     */
+    INTERMEDIATE(1, "中级"),
+    /**
+     * urgent
+     */
+    URGENT(2, "紧急"),
+    /**
+     * tenant level
+     */
+    TENANT(3, "租户管理级别"),
+    /**
+     * 部门级别
+     */
+    DEPARTMENT(4, "部门领导级别"),
+    /**
+     * only email
+     */
+    SINGLE_EMAIL(10, "仅邮件通知"),
+    /**
+     * only note
+     */
+    SINGLE_NOTE(11, "仅短信通知");
+
+    @Getter
+    private final int id;
+
+    /**
+     * 预警级别
+     */
+    @Getter
+    private final String name;
+
+    public static String getLevelName(int id) {
+        return Arrays.stream(InformLevelEnum.values()).filter(informLevel -> id == informLevel.getId()).findFirst().map(InformLevelEnum::getName).orElse(null);
+    }
+
+    InformLevelEnum(int id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+}

+ 55 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/context/inform/InformTypeEnum.java

@@ -0,0 +1,55 @@
+package com.inspur.customer.context.inform;
+
+import lombok.Getter;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-29 16:57
+ **/
+public enum InformTypeEnum {
+
+    /**
+     * phone verify
+     */
+    PHONE_VERIFY_MESSAGE("屏媒安播云平台手机绑定验证", InformLevelEnum.SINGLE_NOTE, MessageTemplateEnum.PHONE_VERIFY_TEMPLATE),
+    /**
+     * email verify
+     */
+    EMAIL_VERIFY_MESSAGE("屏媒安播云平台邮箱绑定验证", InformLevelEnum.SINGLE_EMAIL, MessageTemplateEnum.EMAIL_VERIFY_TEMPLATE),
+    /**
+     * ai 审核库存预警
+     */
+    AI_AUDIT_CREDIT_INSUFFICIENT_WARN("ai 审核库存预警", InformLevelEnum.TENANT, MessageTemplateEnum.AI_AUDIT_CREDIT_INSUFFICIENT_WARN),
+    /**
+     * ai 审核不通过预警
+     */
+    AI_MEDIA_WARN("ai 审核不通过预警", InformLevelEnum.HINT, MessageTemplateEnum.AI_AUDIT_NON_COMPLIANCE),
+    /**
+     * 设备视频回采次数库存预警
+     */
+    DEVICE_PIC_AUDIT_CREDIT_WARN("设备视频回采次数库存预警", InformLevelEnum.HINT, MessageTemplateEnum.AI_AUDIT_NON_COMPLIANCE)
+    ;
+
+    /**
+     * type name
+     */
+    @Getter
+    private final String name;
+
+    /**
+     * inform level
+     */
+    @Getter
+    private final InformLevelEnum level;
+
+    @Getter
+    private final MessageTemplateEnum templateEnum;
+
+    InformTypeEnum(String name, InformLevelEnum level, MessageTemplateEnum templateEnum) {
+        this.name = name;
+        this.level = level;
+        this.templateEnum = templateEnum;
+    }
+
+
+}

+ 53 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/context/inform/MessageTemplateEnum.java

@@ -0,0 +1,53 @@
+package com.inspur.customer.context.inform;
+
+import lombok.Getter;
+
+/**
+ * message template enum
+ * @author linwenhua
+ */
+
+public enum MessageTemplateEnum {
+
+    /**
+     * phone verify template
+     */
+    PHONE_VERIFY_TEMPLATE("todo", 7, "wechat",  ""),
+    /**
+     * email verify template
+     */
+    EMAIL_VERIFY_TEMPLATE("todo", -1, "wechat",  ""),
+    /**
+     * AI 审核库存
+     */
+    AI_AUDIT_CREDIT_INSUFFICIENT_WARN("AiAuditCreditInsufficientWarn", 5, "AiAuditCreditInsufficientWarn",  "appletMessage/AiAuditCreditInsufficientWarn.RTF"),
+    /**
+     * 媒资 AI 不通过异常
+     */
+    AI_AUDIT_NON_COMPLIANCE("AiAuditMediaWarn", 4, "AiAuditMediaWarn",  "appletMessage/AiAuditMediaWarn.RTF"),
+    /**
+     * 设备视频回传次数不足
+     */
+    DEVICE_PIC_AUDIT_CREDIT_WARN("DevicePicAuditCreditWarn", 6, "DevicePicAuditCreditWarn", "appletMessage/DevicePicAuditCreditWarn.RTF")
+    ;
+
+    @Getter
+    private final String email;
+
+    @Getter
+    private final Integer note;
+
+    @Getter
+    private final String wechat;
+
+    @Getter
+    private final String applet;
+
+
+    MessageTemplateEnum(String email, Integer note, String wechat, String applet) {
+        this.email = email;
+        this.note = note;
+        this.wechat = wechat;
+        this.applet = applet;
+    }
+}

+ 60 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/CommonInformCO.java

@@ -0,0 +1,60 @@
+package com.inspur.customer.object.inform;
+
+import com.inspur.customer.context.inform.InformTypeEnum;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-29 16:40
+ **/
+@Data
+public class CommonInformCO implements Serializable {
+
+    private static final long serialVersionUID = 4485440990149055018L;
+
+    private InformTypeEnum typeEnum;
+
+    /*---------------- batch inform ----------------*/
+
+    /**
+     * tenant identifier
+     */
+    private String tenant;
+
+    /**
+     * department
+     */
+    private String org;
+
+    /*---------------- single inform ----------------*/
+
+    /**
+     * user id
+     */
+    private String userId;
+
+    /*-------------------------------- message consider to make a list  --------------------------------*/
+
+    /**
+     * email message
+     */
+    private CommonMessageCO emailMessage;
+
+    /**
+     * note message
+     */
+    private CommonMessageCO noteMessage;
+
+    /**
+     * weChat message
+     */
+    private CommonMessageCO weChatMessage;
+
+    /**
+     * weChat applet
+     */
+    private CommonMessageCO weChatAppletMessage;
+
+}

+ 21 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/CommonMessageCO.java

@@ -0,0 +1,21 @@
+package com.inspur.customer.object.inform;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-29 16:43
+ **/
+@Data
+public class CommonMessageCO implements Serializable {
+
+    private String subject;
+
+    private static final long serialVersionUID = -4561191896624275223L;
+
+    private Map<String, String> messageMap;
+
+}

+ 40 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/CustomerBaseException.java

@@ -0,0 +1,40 @@
+package com.inspur.customer.object.inform;
+
+import lombok.Getter;
+
+/**
+ * @author linwenhua
+ * @date 2022-07-01 16:31
+ **/
+public class CustomerBaseException extends RuntimeException{
+
+    private static final long serialVersionUID = 6432409098208302604L;
+
+    @Getter
+    private String msg;
+
+    @Getter
+    private int code = 500;
+
+    public CustomerBaseException(String msg) {
+        super(msg);
+        this.msg = msg;
+    }
+
+    public CustomerBaseException(String msg, Throwable e) {
+        super(msg, e);
+        this.msg = msg;
+    }
+
+    public CustomerBaseException(String msg, int code) {
+        super(msg);
+        this.msg = msg;
+        this.code = code;
+    }
+
+    public CustomerBaseException(String msg, int code, Throwable e) {
+        super(msg, e);
+        this.msg = msg;
+        this.code = code;
+    }
+}

+ 71 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformAddressees.java

@@ -0,0 +1,71 @@
+package com.inspur.customer.object.inform;
+
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.lang.Nullable;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-14 09:45
+ **/
+public class InformAddressees implements Serializable {
+
+    private static final long serialVersionUID = 5978949873926901132L;
+
+    @Getter
+    private final List<String> phones;
+
+    @Getter
+    private final List<String> emailAddressees;
+
+    @Getter
+    private final List<String> openIds;
+    /**
+     * user id for applet
+     */
+    @Getter
+    List<String> userIds;
+    
+    public InformAddressees(List<String> openIds) {
+        this.phones = Collections.emptyList();
+        this.emailAddressees = Collections.emptyList();
+        this.openIds = Collections.emptyList();
+        this.userIds = Collections.emptyList();
+    }
+    
+    public InformAddressees(Integer size) {
+        phones = new ArrayList<>(size);
+        emailAddressees = new ArrayList<>(size);
+        openIds = new ArrayList<>(size);
+        userIds = new ArrayList<>(size);
+    }
+
+    public void addPhone(@Nullable String phone) {
+        if (StringUtils.isNotBlank(phone)) {
+            phones.add(phone);
+        }
+    }
+
+    public void addEmailAddressee(@Nullable String emailAddressee) {
+        if (StringUtils.isNotBlank(emailAddressee)) {
+            emailAddressees.add(emailAddressee);
+        }
+    }
+
+    public void addOpenId(@Nullable String openId) {
+        if (StringUtils.isNotBlank(openId)) {
+            openIds.add(openId);
+        }
+    }
+
+    public void addUserId(@Nullable String userId) {
+        if (StringUtils.isNotBlank(userId)) {
+            userIds.add(userId);
+        }
+    }
+}

+ 44 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformMessageContentRecordDto.java

@@ -0,0 +1,44 @@
+package com.inspur.customer.object.inform;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-29 16:36
+ **/
+@Data
+public class InformMessageContentRecordDto implements Serializable {
+
+    private static final long serialVersionUID = -1708529192978236713L;
+
+    private Long id;
+
+    /**
+     * tenant identifier
+     */
+    private String tenant;
+
+    /**
+     * the number of user
+     */
+    private Integer users;
+
+    /**
+     * inform flag
+     * bit 0: note
+     * bit 1: email
+     * bit 2: weChat
+     * bit 3: weChat applet
+     */
+    private Integer informFlag;
+
+    /**
+     * message map
+     */
+    private Map<String, String> messageMap;
+
+    private String contentMapJson;
+}

+ 56 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformMessageRecordDto.java

@@ -0,0 +1,56 @@
+package com.inspur.customer.object.inform;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * message send record
+ * @author linwenhua
+ * @date 2022-06-29 16:35
+ **/
+@Data
+public class InformMessageRecordDto implements Serializable {
+
+    private static final long serialVersionUID = -1729327083071852247L;
+
+    public static final String EMAIL_KEY = "email";
+
+    public static final String NOTE_KEY = "note";
+
+    public static final String WECHAT_KEY = "weChat";
+
+    public static final String WECHAT_APPLET_KEY = "weChatApplet";
+
+    private Long id;
+
+    /**
+     * content record id
+     * @see InformMessageContentRecordDto#getId()
+     */
+    private Long contentId;
+
+    private Integer type;
+
+    /**
+     * tenant identifier
+     */
+    private String tenant;
+
+    /**
+     * department
+     */
+    private String org;
+
+    /**
+     * user id
+     */
+    private String userId;
+
+    /**
+     * message map
+     */
+    private Map<String, String> messageMap;
+
+}

+ 59 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/inform/InformStrategy.java

@@ -0,0 +1,59 @@
+package com.inspur.customer.object.inform;
+
+import com.inspur.customer.context.inform.InformLevelEnum;
+import lombok.Getter;
+
+import java.io.Serializable;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-30 09:50
+ **/
+public class InformStrategy implements Serializable {
+
+    private static final long serialVersionUID = -7952204074632539933L;
+
+    @Getter
+    private Boolean email;
+
+    @Getter
+    private Boolean note;
+
+    @Getter
+    private Boolean weChat;
+
+    @Getter
+    private Boolean weChatApplet;
+
+    public InformStrategy(InformLevelEnum informLevelEnum) {
+        switch (informLevelEnum) {
+            case SINGLE_EMAIL: {
+                this.email = true;
+                break;
+            }
+            case SINGLE_NOTE : {
+                this.note = true;
+                break;
+            }
+            case TEST:
+            case  HINT : {
+                this.email = true;
+                this.note = false;
+                this.weChat = true;
+                this.weChatApplet = true;
+                break;
+            }
+            case INTERMEDIATE :
+            case URGENT : {
+                this.email = true;
+                this.note = true;
+                this.weChat = true;
+                this.weChatApplet = true;
+                break;
+            }
+            default : {
+                break;
+            }
+        }
+    }
+}

+ 22 - 1
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/dto/KeycloakUserCO.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/object/keycloak/KeycloakUserCO.java

@@ -1,9 +1,12 @@
-package com.inspur.customer.service.dto;
+package com.inspur.customer.object.keycloak;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.lang.Nullable;
 
 import java.io.Serializable;
+import java.util.BitSet;
 import java.util.List;
 
 /**
@@ -51,4 +54,22 @@ public class KeycloakUserCO implements Serializable {
             }
         }
     }
+
+    @JsonIgnore
+    public BitSet getInformFlag() {
+        BitSet bitSet = new BitSet(4);
+        if (StringUtils.isNotBlank(phone)) {
+            bitSet.set(0);
+        }
+        if (StringUtils.isNotBlank(email)) {
+            bitSet.set(1);
+        }
+        if (StringUtils.isNotBlank(wechat)) {
+            bitSet.set(2);
+        }
+        if (StringUtils.isNotBlank(wechatAppletOpenId)) {
+            bitSet.set(3);
+        }
+        return bitSet;
+    }
 }

+ 110 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/tenant/ExceptionInformStrategyCmd.java

@@ -0,0 +1,110 @@
+package com.inspur.customer.object.tenant;
+
+import com.alibaba.cola.dto.Command;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.BitSet;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-07 18:39
+ **/
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ExceptionInformStrategyCmd extends Command {
+
+    private static final long serialVersionUID = 6924729697795216039L;
+
+    /**
+     * inform user by note
+     */
+    private Boolean note;
+
+    /**
+     * inform user by email
+     */
+    private Boolean email;
+
+    /**
+     * inform user by wechat
+     */
+    private Boolean wechat;
+
+    /**
+     * inform user by wechatApplet
+     */
+    private Boolean wechatApplet;
+
+    public ExceptionInformStrategyCmd() {
+
+    }
+
+    public ExceptionInformStrategyCmd(Integer integerFlag) {
+        byte[] byteFlag = new byte[]{integerFlag.byteValue()};
+        setFlag(byteFlag);
+    }
+
+    /**
+     * get inform strategy flag with bit identifier
+     * 从低位开始
+     * 0 位: note 1
+     * 1 位: email 2
+     * 2 位: weChat 4
+     * 3 位: weChatApplet 8
+     * @return strategy flag
+     */
+    @JsonIgnore
+    public Integer getStrategyFlag() {
+        BitSet bitSet = getStrategySet();
+        byte[] byteFlag = bitSet.toByteArray();
+        return (int) byteFlag[0];
+    }
+
+    @JsonIgnore
+    public BitSet getStrategySet() {
+        BitSet bitSet = new BitSet(4);
+        if (Boolean.TRUE.equals(note)) {
+            bitSet.set(0);
+        }
+        if (Boolean.TRUE.equals(email)) {
+            bitSet.set(1);
+        }
+        if (Boolean.TRUE.equals(wechat)) {
+            bitSet.set(2);
+        }
+        if (Boolean.TRUE.equals(wechatApplet)) {
+            bitSet.set(3);
+        }
+        return bitSet;
+    }
+
+    @JsonIgnore
+    public Integer getCount() {
+        int count = 0;
+        if (Boolean.TRUE.equals(note)) {
+            count += 1;
+        }
+        if (Boolean.TRUE.equals(email)) {
+            count += 1;
+        }
+        if (Boolean.TRUE.equals(wechat)) {
+            count += 1;
+        }
+        if (Boolean.TRUE.equals(wechatApplet)) {
+            count += 1;
+        }
+        return count;
+    }
+
+
+    private void setFlag(byte[] byteFlag) {
+        BitSet bitSet = BitSet.valueOf(byteFlag);
+        this.note = bitSet.get(0);
+        this.email = bitSet.get(1);
+        this.wechat = bitSet.get(2);
+        this.wechatApplet = bitSet.get(3);
+    }
+
+}

+ 60 - 0
smsb-customer-manager-client/src/main/java/com/inspur/customer/object/tenant/TenantExceptionInformStrategyCO.java

@@ -0,0 +1,60 @@
+package com.inspur.customer.object.tenant;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * tenant exception inform strategy
+ * @author linwenhua
+ * @date 2022-06-07 18:37
+ **/
+@Data
+public class TenantExceptionInformStrategyCO implements Serializable {
+
+    private static final long serialVersionUID = -2981913767151035603L;
+
+    public static final String HINT_LEVEL_KEY = "0";
+
+    public static final String MIDDLE_LEVEL_KEY = "1";
+
+    public static final String URGENT_LEVEL_KEY = "2";
+
+    public static final String TENANT_LEVEL_KEY = "3";
+
+    public static final String DEPARTMENT_LEVEL = "4";
+
+    public static final String SINGLE_NOTE = "10";
+
+    public static final String SINGLE_EMAIL = "11";
+
+
+    /**
+     * tenant identifier
+     */
+    private String tenant;
+
+    /**
+     * exception inform strategy
+     */
+    private Map<String, ExceptionInformStrategyCmd> strategy;
+
+    public TenantExceptionInformStrategyCO() {
+        this.strategy = new HashMap<>(10);
+    }
+
+    public TenantExceptionInformStrategyCO(String tenant, Integer size) {
+        this.tenant = tenant;
+        this.strategy = new HashMap<>(size);
+    }
+
+    public Integer getInformFlagByLevel(String level) {
+        return strategy.get(level).getStrategyFlag();
+    }
+
+    public void updateStrategy(String strategyKey, ExceptionInformStrategyCmd informStrategyCmd) {
+        this.strategy.put(strategyKey, informStrategyCmd);
+    }
+}

+ 1 - 1
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/dto/AuthCodeCheckDTO.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/object/user/authcode/AuthCodeCheckDTO.java

@@ -1,4 +1,4 @@
-package com.inspur.customer.service.dto;
+package com.inspur.customer.object.user.authcode;
 
 import lombok.Data;
 

+ 1 - 1
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/dto/AuthCodeCheckResponse.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/object/user/authcode/AuthCodeCheckResponse.java

@@ -1,4 +1,4 @@
-package com.inspur.customer.service.dto;
+package com.inspur.customer.object.user.authcode;
 
 import lombok.Data;
 

+ 1 - 2
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/dto/AuthCodeDTO.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/object/user/authcode/AuthCodeDTO.java

@@ -1,10 +1,9 @@
-package com.inspur.customer.service.dto;
+package com.inspur.customer.object.user.authcode;
 
 import lombok.Data;
 
 import javax.validation.constraints.Email;
 import javax.validation.constraints.Pattern;
-import javax.validation.constraints.Size;
 import java.io.Serializable;
 
 @Data

+ 1 - 1
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/dto/Pair.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/object/wechat/Pair.java

@@ -1,4 +1,4 @@
-package com.inspur.customer.service.dto;
+package com.inspur.customer.object.wechat;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;

+ 1 - 1
smsb-customer-manager-client/src/main/java/com/inspur/customer/service/dto/SubscribeDto.java → smsb-customer-manager-client/src/main/java/com/inspur/customer/object/wechat/SubscribeDto.java

@@ -1,4 +1,4 @@
-package com.inspur.customer.service.dto;
+package com.inspur.customer.object.wechat;
 
 import lombok.Data;
 

+ 14 - 0
smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/mapper/inform/InformMessageContentRecordMapper.java

@@ -0,0 +1,14 @@
+package com.inspur.customer.infrastructure.mapper.inform;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.inspur.customer.infrastructure.object.inform.InformMessageContentRecordDO;
+import com.inspur.customer.infrastructure.object.inform.InformMessageRecordDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-29 16:08
+ **/
+@Mapper
+public interface InformMessageContentRecordMapper extends BaseMapper<InformMessageContentRecordDO> {
+}

+ 13 - 0
smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/mapper/inform/InformMessageRecordMapper.java

@@ -0,0 +1,13 @@
+package com.inspur.customer.infrastructure.mapper.inform;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.inspur.customer.infrastructure.object.inform.InformMessageRecordDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-29 16:08
+ **/
+@Mapper
+public interface InformMessageRecordMapper extends BaseMapper<InformMessageRecordDO> {
+}

+ 13 - 0
smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/mapper/tenant/TenantExceptionInformStrategyMapper.java

@@ -0,0 +1,13 @@
+package com.inspur.customer.infrastructure.mapper.tenant;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.inspur.customer.infrastructure.object.tenant.TenantExceptionInformStrategyDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author linwenhua
+ * @date 2022-04-12 18:42
+ **/
+@Mapper
+public interface TenantExceptionInformStrategyMapper extends BaseMapper<TenantExceptionInformStrategyDO> {
+}

+ 48 - 0
smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/object/inform/InformMessageContentRecordDO.java

@@ -0,0 +1,48 @@
+package com.inspur.customer.infrastructure.object.inform;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * message content record
+ * @author linwenhua
+ * @date 2022-06-29 15:46
+ **/
+@Data
+@TableName("inform_message_content_record")
+public class InformMessageContentRecordDO implements Serializable {
+
+    private static final long serialVersionUID = 4564437666438735274L;
+
+    /**
+     * record id
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * tenant identifier
+     */
+    @TableField("tenant")
+    private String tenant;
+
+    /**
+     * inform flag
+     * bit 0: note
+     * bit 1: email
+     * bit 2: weChat
+     * bit 3: weChat applet
+     */
+    @TableField("inform_flag")
+    private Integer informFlag;
+
+    /**
+     * message map json
+     */
+    @TableField("message_map_json")
+    private String messageMapJson;
+}

+ 81 - 0
smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/object/inform/InformMessageRecordDO.java

@@ -0,0 +1,81 @@
+package com.inspur.customer.infrastructure.object.inform;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.BitSet;
+
+/**
+ * record of message sending
+ * @author linwenhua
+ * @date 2022-06-29 15:46
+ **/
+@Data
+@TableName("inform_message_record")
+public class InformMessageRecordDO implements Serializable {
+
+    private static final long serialVersionUID = 493815370400441472L;
+
+    @TableId
+    private Long id;
+
+    /**
+     * content record id
+     * @see InformMessageContentRecordDO#getId()
+     */
+    @TableField("content_id")
+    private Long contentId;
+
+    /**
+     * tenant identifier
+     */
+    @TableField("tenant")
+    private String tenant;
+
+    /**
+     * department
+     */
+    @TableField("org")
+    private String org;
+
+    /**
+     * user id
+     */
+    @TableField("user_id")
+    private String userId;
+
+    /**
+     * message type
+     */
+    @TableField("type")
+    private Integer type;
+
+    /**
+     * inform flag
+     * bit 0: note
+     * bit 1: email
+     * bit 2: weChat
+     * bit 3: weChat applet
+     */
+    @TableField("inform_flag")
+    private Integer informFlag;
+
+    /**
+     * inform flag
+     * bit 0: note
+     * bit 1: email
+     * bit 2: weChat
+     * bit 3: weChat applet
+     */
+    @TableField("inform_status")
+    private Integer informStatus;
+
+    public BitSet getBitMap() {
+        byte[] byteFlag = new byte[]{informFlag.byteValue()};
+        return BitSet.valueOf(byteFlag);
+    }
+
+}

+ 32 - 0
smsb-customer-manager-infrastructure/src/main/java/com/inspur/customer/infrastructure/object/tenant/TenantExceptionInformStrategyDO.java

@@ -0,0 +1,32 @@
+package com.inspur.customer.infrastructure.object.tenant;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author linwenhua
+ * @date 2022-06-08 11:41
+ **/
+@Data
+@TableName("tenant_exception_inform_strategy")
+public class TenantExceptionInformStrategyDO implements Serializable {
+
+    private static final long serialVersionUID = 4637196747617452014L;
+
+    @TableId(value = "tenant", type = IdType.INPUT)
+    private String tenant;
+
+    @TableField("hint_level_flag")
+    private Integer hintLevelFlag;
+
+    @TableField("middle_level_flag")
+    private Integer middleLevelFlag;
+
+    @TableField("urgency_level_flag")
+    private Integer urgencyLevelFlag;
+}

+ 5 - 0
smsb-customer-manager-infrastructure/src/main/resources/mapper/inform/InformMessageContentRecordMapper.xml

@@ -0,0 +1,5 @@
+<?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="com.inspur.customer.infrastructure.mapper.inform.InformMessageContentRecordMapper">
+
+</mapper>

+ 5 - 0
smsb-customer-manager-infrastructure/src/main/resources/mapper/inform/InformMessageRecordMapper.xml

@@ -0,0 +1,5 @@
+<?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="com.inspur.customer.infrastructure.mapper.inform.InformMessageRecordMapper">
+
+</mapper>

+ 5 - 0
smsb-customer-manager-infrastructure/src/main/resources/mapper/tenant/TenantExceptionInformStrategyMapper.xml

@@ -0,0 +1,5 @@
+<?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="com.inspur.customer.infrastructure.mapper.tenant.TenantExceptionInformStrategyMapper">
+
+</mapper>

+ 2 - 0
smsb-customer-manager-start-web/src/main/java/com/inspur/customer/SmsbCustomerWebApplication.java

@@ -3,6 +3,7 @@ package com.inspur.customer;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
 
 /**
  * 用户管理模块启动类
@@ -10,6 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
  * @author wangbo
  */
 @EnableDubbo
+@EnableAsync
 @SpringBootApplication
 public class SmsbCustomerWebApplication {
 

+ 2 - 6
smsb-customer-manager-start-web/src/test/java/com/inspur/customer/KeycloakTest.java

@@ -1,17 +1,12 @@
 package com.inspur.customer;
 
-import com.inspur.customer.service.client.keycloak.KeycloakService;
+import com.inspur.customer.client.keycloak.KeycloakService;
 import lombok.extern.slf4j.Slf4j;
-import org.junit.jupiter.api.Test;
 import org.keycloak.admin.client.Keycloak;
-import org.keycloak.representations.idm.*;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.test.context.SpringBootTest;
 
 import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
 
 /**
  * @author zengweijie
@@ -21,6 +16,7 @@ import java.util.Optional;
 @Slf4j
 @SpringBootTest
 class KeycloakTest {
+
     @Resource
     Keycloak keycloak;
     @Value("${keycloak.realm}")

+ 79 - 0
smsb-customer-manager-start-web/src/test/java/com/inspur/customer/MessageHandlerTest.java

@@ -0,0 +1,79 @@
+package com.inspur.customer;
+
+import com.inspur.customer.object.inform.CommonMessageCO;
+import com.inspur.customer.service.inform.handler.EmailMessageHandler;
+import com.inspur.customer.service.inform.handler.WeChatAppletMessageHandler;
+import com.inspur.customer.service.inform.handler.WeChatMessageHandler;
+import com.inspur.inform.object.applet.WeChatAppletUserDataDto;
+import com.inspur.inform.object.applet.message.WxAppletUserMessageDto;
+import com.inspur.inform.object.message.EmailMessage;
+import com.inspur.inform.object.message.WechatMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author linwenhua
+ * @date 2022-07-01 13:56
+ **/
+@Slf4j
+class MessageHandlerTest {
+
+    private final EmailMessageHandler emailMessageHandler = new EmailMessageHandler();
+
+    private final WeChatAppletMessageHandler weChatAppletMessageHandler = new WeChatAppletMessageHandler();
+
+    private final WeChatMessageHandler weChatMessageHandler = new WeChatMessageHandler();
+
+    @Test
+    void testEmail() throws IOException {
+        CommonMessageCO commonMessageCo = new CommonMessageCO();
+        commonMessageCo.setSubject("测试");
+        Map<String, String> attributes = new HashMap<>(10);
+        attributes.put("MSRlevel", "紧急");
+        attributes.put("MSRdevice", "紧急");
+        attributes.put("MSRarea", "紧急");
+        attributes.put("MSRtime", "紧急");
+        commonMessageCo.setMessageMap(attributes);
+        EmailMessage emailMessage = emailMessageHandler.makeEmailMessage(commonMessageCo, "BatchDeviceEmptyOrchestration", Collections.emptyList());
+        log.info("message: {}", emailMessage);
+    }
+
+    @Test
+    void testApplet() throws IOException {
+        CommonMessageCO commonMessageCo = new CommonMessageCO();
+        commonMessageCo.setSubject("测试");
+        Map<String, String> attributes = new HashMap<>(10);
+        attributes.put("MSRlevel", "紧急");
+        attributes.put("MSRdevice", "紧急");
+        attributes.put("MSRarea", "紧急");
+        attributes.put("MSRtime", "紧急");
+        commonMessageCo.setMessageMap(attributes);
+        WxAppletUserMessageDto wxAppletUserMessageDto = weChatAppletMessageHandler.makeWeChatAppletMessage(commonMessageCo, "MultiWarn");
+        log.info("message: {}", wxAppletUserMessageDto);
+    }
+
+    @Test
+    void testWeChat() throws IOException {
+        CommonMessageCO commonMessageCo = new CommonMessageCO();
+        commonMessageCo.setSubject("测试");
+        Map<String, String> attributes = new HashMap<>(10);
+        attributes.put("keyword1", "紧急");
+        attributes.put("keyword3", "紧急");
+        commonMessageCo.setMessageMap(attributes);
+        WechatMessage wechatMessage = weChatMessageHandler.makeWeChatMessage(commonMessageCo, Collections.emptyList(), "device");
+        log.info("message: {}", wechatMessage);
+    }
+
+    @Test
+    void testBitset() {
+        BitSet bitSet = new BitSet(4);
+        bitSet.set(2);
+        log.info("size: {}", bitSet.length());
+    }
+}

+ 0 - 72
smsb-customer-manager-start/pom.xml

@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>smsb-customer-manager</artifactId>
-        <groupId>com.inspur</groupId>
-        <version>0.0.1-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>smsb-customer-manager-start</artifactId>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.inspur</groupId>
-            <artifactId>smsb-customer-manager-app</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <!-- dubbo -->
-        <dependency>
-            <groupId>com.alibaba.cloud</groupId>
-            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.alibaba.cloud</groupId>
-            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-bootstrap</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <configuration>
-                    <layers>
-                        <enabled>true</enabled>
-                    </layers>
-                    <executable>true</executable>
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

+ 0 - 24
smsb-customer-manager-start/src/test/java/com/inspur/customer/KeycloakTest.java

@@ -1,24 +0,0 @@
-package com.inspur.customer;
-
-import com.inspur.customer.service.client.keycloak.KeycloakService;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.dubbo.config.annotation.DubboReference;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-/**
- * @author linwenhua
- * @date 2022-06-14 17:20
- **/
-@Slf4j
-@SpringBootTest
-class KeycloakTest {
-
-    @DubboReference
-    private KeycloakService keycloakService;
-
-    @Test
-    void getUsersInRole() {
-        log.info("user: {}", keycloakService.getUsersInRole("ROLE_SUPER_ADMIN"));
-    }
-}