Răsfoiți Sursa

消息模块解耦和重构

1811872455@163.com 2 săptămâni în urmă
părinte
comite
5883ec6691
29 a modificat fișierele cu 497 adăugiri și 94 ștergeri
  1. 33 0
      java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/EqualsFunction.java
  2. 33 0
      java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/IndexOfFunction.java
  3. 31 0
      java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/MapKeyExistsFunction.java
  4. 34 0
      java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/NoIndexOfFunction.java
  5. 109 0
      java/storlead-framework/storlead-mybatis/src/main/java/com/storlead/framework/mybatis/entity/SysBaseField.java
  6. 3 3
      java/storlead-message/storlead-message-api/pom.xml
  7. 2 26
      java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageApiController.java
  8. 25 29
      java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageTemplateApiController.java
  9. 4 4
      java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/UserMessageConfigApiController.java
  10. 58 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/contract/support/MessageEventPortImpl.java
  11. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/InsideMessageRecordService.java
  12. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/InsideMessageSendLogService.java
  13. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/MessageTemplateEventDetailService.java
  14. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/MessageTemplateEventGroupService.java
  15. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/UserMessageNoticeConfigService.java
  16. 3 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/WechatMessageService.java
  17. 1 2
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/InsideMessageRecordServiceImpl.java
  18. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageService.java
  19. 3 2
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageTemplateEventDetailServiceImpl.java
  20. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/UserMessageNoticeConfigServiceImpl.java
  21. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/WechatMessageServiceImpl.java
  22. 2 0
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/dto/MessageTemplateEventDTO.java
  23. 3 0
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/MessageTemplateEventDetailEntity.java
  24. 3 0
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/MessageTemplateEventGroupEntity.java
  25. 1 16
      java/storlead-message/storlead-message-spi/pom.xml
  26. 38 0
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/contract/MessageEventPort.java
  27. 68 0
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/contract/MessageVariables.java
  28. 34 0
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/contract/RowIdentity.java
  29. 1 4
      java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/entity/MenuEntity.java

+ 33 - 0
java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/EqualsFunction.java

@@ -0,0 +1,33 @@
+package com.storlead.framework.common.aviator;
+
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.function.FunctionUtils;
+import com.googlecode.aviator.runtime.type.AviatorBoolean;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+
+import java.util.Map;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-04-26 15:44
+ */
+public class EqualsFunction extends AbstractFunction {
+    @Override
+    public AviatorBoolean call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
+
+        String num1 = FunctionUtils.getStringValue(arg1, env);
+        String num2 = FunctionUtils.getStringValue(arg2, env);
+        return AviatorBoolean.valueOf(num1.equals(num2));
+    }
+
+    @Override
+    public String getName() {
+        return "myequals";
+    }
+
+    public static String getFunctionName() {
+        return "myequals";
+    }
+}

+ 33 - 0
java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/IndexOfFunction.java

@@ -0,0 +1,33 @@
+package com.storlead.framework.common.aviator;
+
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.function.FunctionUtils;
+import com.googlecode.aviator.runtime.type.AviatorBoolean;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+
+import java.util.Map;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-04-26 15:45
+ */
+public class IndexOfFunction extends AbstractFunction {
+    @Override
+    public AviatorBoolean call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
+
+        String num1 = FunctionUtils.getStringValue(arg1, env);
+        String num2 = FunctionUtils.getStringValue(arg2, env);
+        return AviatorBoolean.valueOf(num1.indexOf(num2) >= 0);
+    }
+
+    @Override
+    public String getName() {
+        return "myIndexOf";
+    }
+
+    public static String getFunctionName() {
+        return "myIndexOf";
+    }
+}

+ 31 - 0
java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/MapKeyExistsFunction.java

@@ -0,0 +1,31 @@
+package com.storlead.framework.common.aviator;
+
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.type.AviatorBoolean;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+
+import java.util.Map;
+
+/**
+ * @program: sp-sales-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2024-06-18 18:25
+ */
+public class MapKeyExistsFunction extends AbstractFunction {
+
+    @Override
+    public AviatorBoolean call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
+
+        Map<?, ?> map = (Map<?, ?>) arg1.getValue(env);
+        String key = arg2.stringValue(env);
+        return AviatorBoolean.valueOf(map.containsKey(key));
+    }
+
+    @Override
+    public String getName() {
+        return "containsKey";
+    }
+
+
+}

+ 34 - 0
java/storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/aviator/NoIndexOfFunction.java

@@ -0,0 +1,34 @@
+package com.storlead.framework.common.aviator;
+
+import com.googlecode.aviator.runtime.function.AbstractFunction;
+import com.googlecode.aviator.runtime.function.FunctionUtils;
+import com.googlecode.aviator.runtime.type.AviatorBoolean;
+import com.googlecode.aviator.runtime.type.AviatorObject;
+
+import java.util.Map;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-04-26 16:22
+ */
+public class NoIndexOfFunction extends AbstractFunction {
+    @Override
+    public AviatorBoolean call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
+
+        String num1 = FunctionUtils.getStringValue(arg1, env);
+        String num2 = FunctionUtils.getStringValue(arg2, env);
+        return AviatorBoolean.valueOf(num1.indexOf(num2) < 0);
+    }
+
+    @Override
+    public String getName() {
+        return "myNoIndexOf";
+    }
+
+    public static String getFunctionName() {
+        return "myNoIndexOf";
+    }
+}
+

+ 109 - 0
java/storlead-framework/storlead-mybatis/src/main/java/com/storlead/framework/mybatis/entity/SysBaseField.java

@@ -1,5 +1,10 @@
 package com.storlead.framework.mybatis.entity;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.storlead.framework.common.util.SpringContextUtils;
+import lombok.SneakyThrows;
+import ma.glasnost.orika.impl.DefaultMapperFactory;
 import org.springframework.format.annotation.DateTimeFormat;
 import com.alibaba.fastjson.annotation.JSONField;
 import com.baomidou.mybatisplus.annotation.FieldFill;
@@ -11,6 +16,10 @@ import lombok.extern.log4j.Log4j2;
 import lombok.EqualsAndHashCode;
 import java.io.Serializable;
 import lombok.Data;
+import org.springframework.util.CollectionUtils;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.util.*;
 
 /**
@@ -53,4 +62,104 @@ public class SysBaseField implements Serializable {
 
     @ApiModelProperty(value = "排序")
     private Integer sort;
+
+
+    public static  <T>  void dictFileds(List<T> tList) {
+        if (CollectionUtils.isEmpty(tList)) {
+            return;
+        }
+//        for (T t : tList) {
+        try {
+            long be = System.currentTimeMillis();
+            log.debug("dictUtils---convertDict");
+            Object myClassInstance = SpringContextUtils.getBean("dictUtils");
+            Class<?> clazz = myClassInstance.getClass();
+            Method method = clazz.getMethod("convertDictls",List.class);
+            // 调用未编写的方法
+            method.invoke(myClassInstance,tList);
+            log.debug("-------------------耗时 ==: "+(System.currentTimeMillis() - be));
+        } catch (Exception e1) {
+            log.error("方法不存在",e1);
+        }
+//        }
+    }
+
+    public void dictFiled() {
+        dictFileds(Arrays.asList(this));
+    }
+
+    public static void dictFiled(Object t) {
+        dictFileds(Arrays.asList(t));
+    }
+
+    public static  <T> void orgFileds(Object... vars) {
+        orgFileds(Arrays.asList(vars));
+    }
+    public static  <T>  void orgFileds(List<T> tList) {
+        if (CollectionUtils.isEmpty(tList)) {
+            return;
+        }
+        try {
+            log.debug("dictUtils---convertDict");
+            Object myClassInstance = SpringContextUtils.getBean("orgAnnotateConvertUtils");
+            Class<?> clazz = myClassInstance.getClass();
+            Method method = clazz.getMethod("convertOrg",List.class);
+            // 调用未编写的方法
+            method.invoke(myClassInstance,tList);
+        } catch (Exception e1) {
+            log.error("方法不存在",e1);
+        }
+    }
+    @SneakyThrows
+    public void orgFiled() {
+        orgFileds(Arrays.asList(this));
+    }
+
+    // Method to set empty strings to null
+    public void setEmptyStringsToNull() {
+        try {
+            Field[] fields = this.getClass().getDeclaredFields();
+            for (Field field : fields) {
+                field.setAccessible(true);  // Allow access to private fields
+                if (field.getType().equals(String.class)) {
+                    String value = (String) field.get(this);
+                    if (value != null && value.isEmpty()) {
+                        field.set(this, null);
+                    }
+                }
+            }
+        }catch (Exception e){
+            log.error("转换失败",e);
+        }
+    }
+    /**
+     * 对象集合转换
+     * @param tList
+     * @param t
+     * @return
+     * @param <T>
+     */
+    public static  <T>  List<T> list(List tList,Class<T> t) {
+        DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
+        List<T> vos = mapperFactory.getMapperFacade().mapAsList(tList,t);
+        return vos;
+    }
+    /**
+     * page 类转换
+     * @param page
+     * @param t
+     * @return
+     * @param <T>
+     */
+    public static  <T> IPage<T> page(IPage page, Class<T> t) {
+        DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
+        IPage<T> pageVo = new Page<>(page.getCurrent(),page.getSize());
+        if (CollectionUtils.isEmpty(page.getRecords())) {
+            return page;
+        }
+        List<T> vos = mapperFactory.getMapperFacade().mapAsList(page.getRecords(),t);
+        pageVo.setTotal(page.getTotal());
+        pageVo.setRecords(vos);
+        return pageVo;
+    }
 }

+ 3 - 3
java/storlead-message/storlead-message-api/pom.xml

@@ -23,15 +23,15 @@
         </dependency>
         <dependency>
             <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-message-spi</artifactId>
+            <artifactId>storlead-message-biz</artifactId>
         </dependency>
         <dependency>
             <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-message-biz</artifactId>
+            <artifactId>storlead-web</artifactId>
         </dependency>
         <dependency>
             <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-web</artifactId>
+            <artifactId>storlead-common</artifactId>
         </dependency>
     </dependencies>
 </project>

+ 2 - 26
java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageApiController.java

@@ -4,8 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.storlead.frame.auth.util.LoginUserUtil;
-import com.storlead.frame.core.assemble.Result;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.util.LoginUserUtil;
 import com.storlead.message.enums.MessageTypeEnum;
 import com.storlead.message.pojo.dto.MessageDTO;
 import com.storlead.message.pojo.dto.MessageTestDTO;
@@ -14,7 +14,6 @@ import com.storlead.message.pojo.vo.MessageDetailVO;
 import com.storlead.message.pojo.vo.MessageNoReadTotalVO;
 import com.storlead.message.pojo.vo.MessageTypeReadStateVO;
 import com.storlead.message.service.InsideMessageSendLogService;
-import com.storlead.sales.customer.service.MessageAssembleService;
 import io.swagger.annotations.*;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -41,29 +40,6 @@ public class MessageApiController {
     @Resource
     private InsideMessageSendLogService messageSendLogService;
 
-    @Resource
-    private MessageAssembleService assembleService;
-
-    @PostMapping(value = "/testMessage")
-    @ApiOperation(value = "测试客户消息" )
-    @ApiResponses({
-            @ApiResponse(code = 200, message = "", response = MessageDetailVO.class)
-    })
-    public Result<?> testMessage(MessageTestDTO dto) {
-        assembleService.sendCustomerEventMessages(dto.getDataId(),dto.getEventCode(),dto.getToUserIds());
-        return Result.ok();
-    }
-
-    @PostMapping(value = "/getMessageTypes")
-    @ApiOperation(value = "获取分类" )
-    @ApiResponses({
-            @ApiResponse(code = 200, message = "", response = MessageDetailVO.class)
-    })
-    public Result<?> getMessageTypes(MessageTestDTO dto) {
-        assembleService.sendCustomerEventMessages(dto.getDataId(),dto.getEventCode(),dto.getToUserIds());
-        return Result.ok();
-    }
-
 
     @PostMapping(value = "/pageList")
     @ApiOperation(value = "获取当前用户的站内消息" )

+ 25 - 29
java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageTemplateApiController.java

@@ -6,8 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.storlead.frame.core.assemble.Result;
-import com.storlead.frame.mybatis.entity.SysBaseField;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.entity.SysBaseField;
 import com.storlead.message.enums.MessageTypeEnum;
 import com.storlead.message.pojo.dto.MessageTemplateEventDTO;
 import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
@@ -16,8 +16,6 @@ import com.storlead.message.pojo.vo.MessageArgTemplateVO;
 import com.storlead.message.pojo.vo.MessageTemplateVO;
 import com.storlead.message.service.MessageTemplateEventDetailService;
 import com.storlead.message.service.MessageTemplateEventGroupService;
-import com.storlead.model.customer.vo.*;
-import com.storlead.report.business.pojo.vo.BroadcastTotalMessageVO;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiOperation;
@@ -55,8 +53,6 @@ public class MessageTemplateApiController {
     @ApiOperation("保存模板")
     @PostMapping("save")
     public Result save(@RequestBody MessageTemplateEventGroupEntity groupEntity) {
-
-//        groupEntity.dictFiled();
         templateEventGroupService.saveOrUpdate(groupEntity);
         return Result.ok();
     }
@@ -115,29 +111,29 @@ public class MessageTemplateApiController {
 
         List<MessageArgTemplateVO> argTemplatels = new ArrayList<>();
         Class clazz = null;
-        if (MessageTypeEnum.CUSTOMER.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = CustomerMessageVO.class;
-        } else if (MessageTypeEnum.CLUS.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = CustomerMessageVO.class;
-        } else if (MessageTypeEnum.ORDER_FORM.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = OrderMessageVO.class;
-        } else if (MessageTypeEnum.BUSINESS.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = BusinessMessageVO.class;
-        } else if (MessageTypeEnum.TASK_CANCELED.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = TaskMessageVO.class;
-        } else if (MessageTypeEnum.FOLLOW_UP.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = FollowMessageVO.class;
-        } else if (MessageTypeEnum.LIAISON.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = LiaisonMessageVO.class;
-        } else if (MessageTypeEnum.PERFORMANCE_GOAL.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = PerformanceGoalMessgeVO.class;
-        } else if (MessageTypeEnum.BULLETIN.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = BulletinMessageVO.class;
-        } else if (MessageTypeEnum.OTHER_EXTEND.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
-            clazz = OtherExtendMessageVO.class;
-        } else if (MessageTypeEnum.BROADCAST.getCode().equals(templateEventGroup.getTemplateServiceType().toString())){
-            clazz = BroadcastTotalMessageVO.class;
-        }
+//        if (MessageTypeEnum.CUSTOMER.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = CustomerMessageVO.class;
+//        } else if (MessageTypeEnum.CLUS.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = CustomerMessageVO.class;
+//        } else if (MessageTypeEnum.ORDER_FORM.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = OrderMessageVO.class;
+//        } else if (MessageTypeEnum.BUSINESS.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = BusinessMessageVO.class;
+//        } else if (MessageTypeEnum.TASK_CANCELED.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = TaskMessageVO.class;
+//        } else if (MessageTypeEnum.FOLLOW_UP.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = FollowMessageVO.class;
+//        } else if (MessageTypeEnum.LIAISON.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = LiaisonMessageVO.class;
+//        } else if (MessageTypeEnum.PERFORMANCE_GOAL.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = PerformanceGoalMessgeVO.class;
+//        } else if (MessageTypeEnum.BULLETIN.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = BulletinMessageVO.class;
+//        } else if (MessageTypeEnum.OTHER_EXTEND.getCode().equals(templateEventGroup.getTemplateServiceType().toString())) {
+//            clazz = OtherExtendMessageVO.class;
+//        } else if (MessageTypeEnum.BROADCAST.getCode().equals(templateEventGroup.getTemplateServiceType().toString())){
+//            clazz = BroadcastTotalMessageVO.class;
+//        }
 
         if (clazz != null) {
             for (Field field : clazz.getDeclaredFields()) {

+ 4 - 4
java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/UserMessageConfigApiController.java

@@ -5,11 +5,11 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.storlead.frame.auth.util.LoginUserUtil;
-import com.storlead.frame.core.assemble.Result;
-import com.storlead.message.entity.UserMessageNoticeConfigEntity;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.util.LoginUserUtil;
 import com.storlead.message.pojo.dto.MessageTemplateEventDTO;
 import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
+import com.storlead.message.pojo.entity.UserMessageNoticeConfigEntity;
 import com.storlead.message.pojo.vo.MessageTemplateVO;
 import com.storlead.message.service.MessageTemplateEventGroupService;
 import com.storlead.message.service.UserMessageNoticeConfigService;
@@ -48,7 +48,7 @@ public class UserMessageConfigApiController {
     public Result setMessageConfig(@RequestBody UserMessageNoticeConfigEntity entity) {
 
         LambdaQueryWrapper<UserMessageNoticeConfigEntity> queryWrapper = new LambdaQueryWrapper();
-        queryWrapper.eq(UserMessageNoticeConfigEntity::getOwnerBy,LoginUserUtil.getCurrentUserId());
+        queryWrapper.eq(UserMessageNoticeConfigEntity::getOwnerBy, LoginUserUtil.getCurrentUserId());
         queryWrapper.eq(UserMessageNoticeConfigEntity::getTemplateEventId,entity.getTemplateEventId());
         queryWrapper.eq(UserMessageNoticeConfigEntity::getTemplateDetailType,entity.getTemplateDetailType());
         queryWrapper.last(" limit 1");

+ 58 - 0
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/contract/support/MessageEventPortImpl.java

@@ -0,0 +1,58 @@
+package com.storlead.message.contract.support;
+
+import com.storlead.message.contract.MessageEventPort;
+import com.storlead.message.contract.MessageVariables;
+import com.storlead.message.contract.RowIdentity;
+import com.storlead.message.service.impl.MessageService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * {@link MessageEventPort} 的默认实现,委托给 {@link MessageService}。
+ */
+@Service
+public class MessageEventPortImpl implements MessageEventPort {
+
+    @Resource
+    private MessageService messageService;
+
+    @Override
+    public void fireDataChangeMessages(MessageVariables before, MessageVariables after, String templateServiceCode) {
+        messageService.autoMatchEventSendMessage(toEngineMap(before), toEngineMap(after), templateServiceCode);
+    }
+
+    @Override
+    public void fireDataChangeMessages(MessageVariables before, MessageVariables after, String templateServiceCode, String... channels) {
+        messageService.autoMatchEventSendMessage(toEngineMap(before), toEngineMap(after), templateServiceCode, channels);
+    }
+
+    @Override
+    public void fireByTemplateServiceTypeAndEvent(MessageVariables payload, String templateServiceType, String eventCode, Set<Long> toUserIds, String... args) {
+        messageService.autoMatchEventSendMessage(toEngineMap(payload), templateServiceType, eventCode, toUserIds, args);
+    }
+
+    @Override
+    public MessageVariables snapshotBeforeRow(RowIdentity row) {
+        Map<String, Object> rowKey = new HashMap<>(2);
+        rowKey.put("id", row.getId());
+        @SuppressWarnings("unchecked")
+        Map<String, Object> raw = messageService.getOldMapData(rowKey, row.getFieldColumn(), row.getTable());
+        if (raw == null || raw.isEmpty()) {
+            return MessageVariables.empty();
+        }
+        return MessageVariables.fromMap(raw);
+    }
+
+    private static Map<String, Object> toEngineMap(MessageVariables v) {
+        if (v == null || v.isEmpty()) {
+            return new HashMap<>();
+        }
+        Map<String, Object> m = new HashMap<>();
+        v.forEach(m::put);
+        return m;
+    }
+}

+ 1 - 1
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/InsideMessageRecordService.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/InsideMessageRecordService.java

@@ -10,7 +10,7 @@ import java.util.Collection;
 import java.util.Map;
 
 /**
- * 系统内部消息 服务类
+ * 系统内部消息 服务类(域内接口,与实现同置于 biz)。
  *
  * @author chenkq
  * @since 2024-04-19

+ 1 - 1
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/InsideMessageSendLogService.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/InsideMessageSendLogService.java

@@ -12,7 +12,7 @@ import com.storlead.message.pojo.vo.MessageTypeReadStateVO;
 import java.util.List;
 
 /**
- * 内部消息人员接收记录表 服务类
+ * 内部消息人员接收记录表 服务类(域内接口,与实现同置于 biz)。
  *
  * @author chenkq
  * @since 2024-04-19

+ 1 - 1
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/MessageTemplateEventDetailService.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/MessageTemplateEventDetailService.java

@@ -8,7 +8,7 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * 消息模板 服务类
+ * 消息模板 服务类(域内接口,与实现同置于 biz)。
  *
  * @author chenkq
  * @since 2024-04-19

+ 1 - 1
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/MessageTemplateEventGroupService.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/MessageTemplateEventGroupService.java

@@ -8,7 +8,7 @@ import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
 import com.storlead.message.pojo.vo.MessageTemplateVO;
 
 /**
- * 实践规则模板 服务类
+ * 实践规则模板 服务类(域内接口,与实现同置于 biz)。
  *
  * @author chenkq
  * @since 2024-04-19

+ 1 - 1
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/UserMessageNoticeConfigService.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/UserMessageNoticeConfigService.java

@@ -6,7 +6,7 @@ import com.storlead.message.pojo.entity.UserMessageNoticeConfigEntity;
 import java.util.Set;
 
 /**
- * 消息开关配置 服务类
+ * 消息开关配置 服务类(域内接口,与实现同置于 biz)。
  *
  * @author chenkq
  * @since 2025-04-25

+ 3 - 0
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/WechatMessageService.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/WechatMessageService.java

@@ -6,6 +6,9 @@ import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
 import java.util.Collection;
 import java.util.Map;
 
+/**
+ * 企业微信消息发送(域内接口,与实现同置于 biz)。
+ */
 public interface WechatMessageService {
 
     Result sendWechatMessage(MessageTemplateEventDetailEntity eventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam);

+ 1 - 2
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/InsideMessageRecordServiceImpl.java

@@ -1,10 +1,9 @@
 package com.storlead.message.service.impl;
 
 import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.storlead.common.util.HtmlUtils;
 import com.storlead.framework.common.result.Result;
 import com.storlead.framework.common.enums.ErrorMsgCode;
+import com.storlead.framework.common.util.HtmlUtils;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import com.storlead.message.pojo.entity.InsideMessageRecordEntity;
 import com.storlead.message.mapper.InsideMessageRecordMapper;

+ 1 - 1
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageService.java

@@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.googlecode.aviator.AviatorEvaluator;
 import com.googlecode.aviator.Expression;
-import com.storlead.common.aviator.MapKeyExistsFunction;
+import com.storlead.framework.common.aviator.MapKeyExistsFunction;
 import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
 import com.storlead.message.service.InsideMessageRecordService;
 import com.storlead.message.service.MessageTemplateEventDetailService;

+ 3 - 2
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageTemplateEventDetailServiceImpl.java

@@ -3,8 +3,8 @@ package com.storlead.message.service.impl;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.ttl.TtlRunnable;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.storlead.common.util.HtmlUtils;
-import com.storlead.common.util.encryptor.AccessKeyEncryptor;
+import com.storlead.framework.common.util.HtmlUtils;
+import com.storlead.framework.common.util.encryptor.AccessKeyEncryptor;
 import com.storlead.framework.util.LoginUserUtil;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import com.storlead.framework.common.thread.ThreadPoolUtil;
@@ -25,6 +25,7 @@ import com.storlead.user.service.IDepartService;
 import com.storlead.user.service.IUserService;
 import javax.annotation.Resource;
 import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;

+ 1 - 1
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/UserMessageNoticeConfigServiceImpl.java

@@ -1,7 +1,7 @@
 package com.storlead.message.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.storlead.common.constant.CommonConstant;
+import com.storlead.framework.common.constant.CommonConstant;
 import com.storlead.message.pojo.entity.UserMessageNoticeConfigEntity;
 import com.storlead.message.mapper.UserMessageNoticeConfigMapper;
 import com.storlead.message.service.UserMessageNoticeConfigService;

+ 1 - 1
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/WechatMessageServiceImpl.java

@@ -1,9 +1,9 @@
 package com.storlead.message.service.impl;
 
 import cn.hutool.core.util.StrUtil;
-import com.storlead.common.util.HtmlUtils;
 import com.storlead.framework.common.result.Result;
 import com.storlead.framework.common.enums.ErrorMsgCode;
+import com.storlead.framework.common.util.HtmlUtils;
 import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
 import com.storlead.message.service.WechatMessageService;
 import com.storlead.user.pojo.entity.UserEntity;

+ 2 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/dto/MessageTemplateEventDTO.java

@@ -1,5 +1,7 @@
 package com.storlead.message.pojo.dto;
 
+import com.storlead.framework.common.dto.page.PageDTO;
+import com.storlead.framework.common.dto.query.QueryBaseDTO;
 import lombok.Data;
 
 /**

+ 3 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/MessageTemplateEventDetailEntity.java

@@ -37,6 +37,9 @@ public class MessageTemplateEventDetailEntity extends SysBaseField {
     @ApiModelProperty(value = "模板id")
     private Long templateEventId;
 
+    @ApiModelProperty(value = "应用ID")
+    private String appId;
+
     @ApiModelProperty(value = "模板图标")
     private String templateIcon;
 

+ 3 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/MessageTemplateEventGroupEntity.java

@@ -36,6 +36,9 @@ public class MessageTemplateEventGroupEntity extends SysBaseField {
     @ApiModelProperty(value = "模块名称")
     private String templateServiceName;
 
+    @ApiModelProperty(value = "应用ID")
+    private String appId;
+
     @ApiModelProperty(value = "业务模块,对应消息类型")
     @Dict(dictCode = "work_data_group",valueField = "templateServiceName")
     private Integer templateServiceType;

+ 1 - 16
java/storlead-message/storlead-message-spi/pom.xml

@@ -14,20 +14,5 @@
     <artifactId>storlead-message-spi</artifactId>
     <packaging>jar</packaging>
     <name>storlead-message-spi</name>
-    <description>消息域对外契约(SPI):服务接口,无实现、无 Web。</description>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-message-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-mybatis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-common</artifactId>
-        </dependency>
-    </dependencies>
+    <description>消息域对外 SPI:仅暴露跨域调用的 Port 接口(无第三方依赖)。</description>
 </project>

+ 38 - 0
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/contract/MessageEventPort.java

@@ -0,0 +1,38 @@
+package com.storlead.message.contract;
+
+import java.util.Set;
+
+/**
+ * 消息域对<strong>外部业务域</strong>的对外契约(Port),本模块仅此一类 API。
+ * <p>
+ * 入参使用 {@link MessageVariables}、{@link RowIdentity} 等对象,不依赖消息实体、MyBatis;
+ * 业务模块编译期只需依赖 {@code storlead-message-spi}。
+ * </p>
+ * <p>
+ * 运行时请引入 {@code storlead-message-biz},由
+ * {@code com.storlead.message.contract.support.MessageEventPortImpl} 注册为 Spring Bean。
+ * </p>
+ */
+public interface MessageEventPort {
+
+    /**
+     * 按模板服务编码匹配规则并异步发送(默认渠道:site、wecom、sms、mail)。
+     */
+    void fireDataChangeMessages(MessageVariables before, MessageVariables after, String templateServiceCode);
+
+    /**
+     * 按模板服务编码匹配规则并异步发送,可指定渠道参数(与站内实现约定一致)。
+     */
+    void fireDataChangeMessages(MessageVariables before, MessageVariables after, String templateServiceCode, String... channels);
+
+    /**
+     * 按服务类型 + 事件编码定位唯一模板并异步发送。
+     */
+    void fireByTemplateServiceTypeAndEvent(MessageVariables payload, String templateServiceType, String eventCode, Set<Long> toUserIds, String... args);
+
+    /**
+     * 根据表主键拉取变更前行数据,并转换为带 {@code before*} 前缀的扁平变量(供规则脚本使用)。
+     * <p>无数据时返回 {@link MessageVariables#empty()}(非 {@code null})。</p>
+     */
+    MessageVariables snapshotBeforeRow(RowIdentity row);
+}

+ 68 - 0
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/contract/MessageVariables.java

@@ -0,0 +1,68 @@
+package com.storlead.message.contract;
+
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiConsumer;
+
+/**
+ * 模板规则 / 消息发送使用的<strong>变量集合</strong>(键值对),不暴露为 {@code Map} 形态给调用方,
+ * 由 {@link MessageEventPort} 入参使用;消息域内部会转为 Map 供规则引擎与模板替换使用。
+ */
+public final class MessageVariables implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final LinkedHashMap<String, Object> entries = new LinkedHashMap<>();
+
+    public static MessageVariables empty() {
+        return new MessageVariables();
+    }
+
+    /**
+     * 从已有 Map 拷贝一份(防御性拷贝),便于与遗留 Map 数据对接。
+     */
+    public static MessageVariables fromMap(Map<String, ?> source) {
+        MessageVariables v = new MessageVariables();
+        if (source != null) {
+            source.forEach((k, val) -> {
+                if (k != null) {
+                    v.entries.put(k, val);
+                }
+            });
+        }
+        return v;
+    }
+
+    public MessageVariables put(String name, Object value) {
+        if (name != null) {
+            entries.put(name, value);
+        }
+        return this;
+    }
+
+    public Object get(String name) {
+        return entries.get(name);
+    }
+
+    public boolean contains(String name) {
+        return entries.containsKey(name);
+    }
+
+    public boolean isEmpty() {
+        return entries.isEmpty();
+    }
+
+    public int size() {
+        return entries.size();
+    }
+
+    /**
+     * 遍历所有变量(供消息域实现转换为引擎入参)。
+     */
+    public void forEach(BiConsumer<String, Object> consumer) {
+        Objects.requireNonNull(consumer, "consumer");
+        entries.forEach(consumer);
+    }
+}

+ 34 - 0
java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/contract/RowIdentity.java

@@ -0,0 +1,34 @@
+package com.storlead.message.contract;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 快照查询主键:表名、主键列名、主键值(与站内 {@code getOldMapData} 约定一致)。
+ */
+public final class RowIdentity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Long id;
+    private final String fieldColumn;
+    private final String table;
+
+    public RowIdentity(Long id, String fieldColumn, String table) {
+        this.id = Objects.requireNonNull(id, "id");
+        this.fieldColumn = Objects.requireNonNull(fieldColumn, "fieldColumn");
+        this.table = Objects.requireNonNull(table, "table");
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getFieldColumn() {
+        return fieldColumn;
+    }
+
+    public String getTable() {
+        return table;
+    }
+}

+ 1 - 4
java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/entity/MenuEntity.java

@@ -29,7 +29,7 @@ public class MenuEntity extends SysBaseField {
     @ApiModelProperty(value = "父级ID(仅type=1时为0 或>1时 为其对应上级菜单ID)")
     private Long pid;
 
-    @ApiModelProperty(value = "应用id,只有单pid = 0 时候,appid 必传")
+    @ApiModelProperty(value = "所属服务: 0:主应用,10:智能贸易,20:销售,30:otr,40:工资,50:项目,60:领存平台")
     private Long appId;
 
     @ApiModelProperty(value = "菜单的请求路径")
@@ -49,9 +49,6 @@ public class MenuEntity extends SysBaseField {
 
     @ApiModelProperty(value = "所属服务类型: 0 ,后端,1:移动端")
     private Integer serviceModeType;
-//
-//    @ApiModelProperty(value = "显示位置: 0:哪里都不显示,1:tabbar 显示,2: 首页显示,3:工作台显示:tab显示")
-//    private Integer menuShowPosition;
 
     @ApiModelProperty(value = "权限标识")
     private String perms;