Răsfoiți Sursa

消息模块改造

1811872455@163.com 2 săptămâni în urmă
părinte
comite
8f6f998337
53 a modificat fișierele cu 1213 adăugiri și 117 ștergeri
  1. 40 5
      java/storlead-api/src/main/java/com/storlead/system/controller/MenuApiController.java
  2. 141 0
      java/storlead-api/src/main/java/com/storlead/system/controller/SysAppApiController.java
  3. 1 0
      java/storlead-message/pom.xml
  4. 9 1
      java/storlead-message/storlead-message-api/pom.xml
  5. 170 0
      java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageApiController.java
  6. 185 0
      java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageTemplateApiController.java
  7. 110 0
      java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/UserMessageConfigApiController.java
  8. 28 13
      java/storlead-message/storlead-message-biz/pom.xml
  9. 0 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/InsideMessageRecordMapper.java
  10. 0 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/InsideMessageSendLogMapper.java
  11. 0 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/MessageTemplateEventDetailMapper.java
  12. 0 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/MessageTemplateEventGroupMapper.java
  13. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/UserMessageNoticeConfigMapper.java
  14. 4 2
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/InsideMessageRecordServiceImpl.java
  15. 0 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/InsideMessageSendLogServiceImpl.java
  16. 0 7
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageService.java
  17. 5 8
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageTemplateEventDetailServiceImpl.java
  18. 0 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageTemplateEventGroupServiceImpl.java
  19. 1 1
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/UserMessageNoticeConfigServiceImpl.java
  20. 2 4
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/WechatMessageServiceImpl.java
  21. 12 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/entity/SmtpPopSettingsEntity.java
  22. 15 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/pojo/SendMailDTO.java
  23. 12 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/EmailsService.java
  24. 16 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/SmtpPopSettingsService.java
  25. 18 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/impl/NoopEmailsServiceImpl.java
  26. 26 0
      java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/impl/NoopSmtpPopSettingsServiceImpl.java
  27. 0 0
      java/storlead-message/storlead-message-biz/src/main/resources/mapper/InsideMessageRecordMapper.xml
  28. 0 0
      java/storlead-message/storlead-message-biz/src/main/resources/mapper/InsideMessageSendLogMapper.xml
  29. 0 0
      java/storlead-message/storlead-message-biz/src/main/resources/mapper/MessageTemplateEventDetailMapper.xml
  30. 0 0
      java/storlead-message/storlead-message-biz/src/main/resources/mapper/MessageTemplateEventGroupMapper.xml
  31. 1 1
      java/storlead-message/storlead-message-biz/src/main/resources/mapper/UserMessageNoticeConfigMapper.xml
  32. 3 3
      java/storlead-message/storlead-message-core/pom.xml
  33. 95 0
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/enums/MessageTypeEnum.java
  34. 77 0
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/enums/OperationEventEnum.java
  35. 1 4
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/MessageTemplateEventGroupEntity.java
  36. 5 9
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/UserMessageNoticeConfigEntity.java
  37. 1 1
      java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/vo/MessageTemplateVO.java
  38. 0 13
      java/storlead-message/storlead-message-core/src/test/java/com/storlead/tems/message/MessageApplicationTests.java
  39. 33 0
      java/storlead-message/storlead-message-spi/pom.xml
  40. 7 23
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/InsideMessageRecordService.java
  41. 0 4
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/InsideMessageSendLogService.java
  42. 0 3
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/MessageTemplateEventDetailService.java
  43. 0 2
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/MessageTemplateEventGroupService.java
  44. 2 4
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/UserMessageNoticeConfigService.java
  45. 1 8
      java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/WechatMessageService.java
  46. 10 0
      java/storlead-system/storlead-system-biz/src/main/java/com/storlead/system/mapper/SysAppMapper.java
  47. 48 0
      java/storlead-system/storlead-system-biz/src/main/java/com/storlead/system/service/impl/SysAppServiceImpl.java
  48. 3 0
      java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/dto/MenuParamDTO.java
  49. 29 0
      java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/dto/SysAppPageDTO.java
  50. 70 0
      java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/entity/SysAppEntity.java
  51. 22 0
      java/storlead-system/storlead-system-spi/src/main/java/com/storlead/system/service/SysAppService.java
  52. 3 0
      java/storlead-user/storlead-user-core/src/main/java/com/storlead/user/pojo/dto/MenuParam.java
  53. 6 0
      pom.xml

+ 40 - 5
java/storlead-api/src/main/java/com/storlead/system/controller/MenuApiController.java

@@ -28,7 +28,6 @@ import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
 import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
 import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
 import org.apache.commons.lang3.StringUtils;
-import javax.annotation.Resource;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -75,6 +74,7 @@ public class MenuApiController {
                 queryWrapper.eq(MenuEntity::getServiceModeType,0);
             } else {
                 queryWrapper.eq(MenuEntity::getServiceModeType,dto.getServiceModeType());
+                applyAppIdFilter(queryWrapper, dto.getAppId());
             }
             queryWrapper.orderByAsc(MenuEntity::getSort);
             List<MenuEntity> menus = menuService.list(queryWrapper);
@@ -102,6 +102,7 @@ public class MenuApiController {
                 queryWrapper.eq(MenuEntity::getServiceModeType,0);
             } else {
                 queryWrapper.eq(MenuEntity::getServiceModeType,dto.getServiceModeType());
+                applyAppIdFilter(queryWrapper, dto.getAppId());
             }
             List<MenuEntity> menus = menuService.list(queryWrapper);
             List<RouterVo> routerVos = menuToRouter(menus);
@@ -147,13 +148,18 @@ public class MenuApiController {
 
     @ApiOperation("查询菜单Tree")
     @PostMapping("listResTree")
-    public Result listResTree() {
+    public Result listResTree(@RequestBody(required = false) MenuParamDTO dto) {
         try {
             LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper();
             queryWrapper.eq(MenuEntity::getIsDelete,0);
             queryWrapper.eq(MenuEntity::getEnabled,1);
             queryWrapper.orderByAsc(MenuEntity::getSort);
-            queryWrapper.eq(MenuEntity::getServiceModeType,0);
+            if (Objects.isNull(dto)) {
+                queryWrapper.eq(MenuEntity::getServiceModeType,0);
+            } else {
+                queryWrapper.eq(MenuEntity::getServiceModeType, dto.getServiceModeType());
+                applyAppIdFilter(queryWrapper, dto.getAppId());
+            }
 
             List<MenuEntity> menus = menuService.list(queryWrapper);
             if(CollectionUtils.isEmpty(menus)) {
@@ -198,6 +204,7 @@ public class MenuApiController {
                 queryWrapper.eq(MenuEntity::getServiceModeType,0);
             } else {
                 queryWrapper.eq(MenuEntity::getServiceModeType,dto.getServiceModeType());
+                applyAppIdFilter(queryWrapper, dto.getAppId());
             }
             List<MenuEntity> menus = menuService.list(queryWrapper);
             if(CollectionUtils.isEmpty(menus)) {
@@ -237,8 +244,10 @@ public class MenuApiController {
         try {
             IPage<MenuEntity> page = new Page<>(dto.getPageIndex(),dto.getPageSize());
             LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper();
-            if (Objects.nonNull(dto)) {
+            if
+            (Objects.nonNull(dto)) {
                 queryWrapper.eq(MenuEntity::getServiceModeType,dto.getServiceModeType());
+                applyAppIdFilter(queryWrapper, dto.getAppId());
             }
             IPage<MenuEntity> menus = menuService.page(page,queryWrapper);
             return Result.ok(menus);
@@ -254,6 +263,9 @@ public class MenuApiController {
         if (Objects.isNull(menu.getPid())) {
             menu.setPid(0L);
         }
+        if (Long.valueOf(0L).equals(menu.getPid()) && menu.getAppId() == null) {
+            return Result.error("顶级菜单(pid=0)必须指定 appId");
+        }
         convertMenuCode(menu);
         return Result.ok(menuService.saveOrUpdate(menu));
     }
@@ -473,7 +485,7 @@ public class MenuApiController {
 
     @ApiOperation("查询菜单所有菜单")
     @PostMapping("allMenulist")
-    public Result allMenulist(String menuName, Integer[] types) {
+    public Result allMenulist(String menuName, Integer[] types, String appId) {
         if(types == null) {
             types = new Integer[]{1, 2};
         }
@@ -482,6 +494,7 @@ public class MenuApiController {
             queryWrapper.eq(MenuEntity::getIsDelete,0);
             queryWrapper.eq(MenuEntity::getEnabled,1);
             queryWrapper.in(MenuEntity::getMenuType, Arrays.asList(types));
+            applyAppIdFilter(queryWrapper, appId);
             queryWrapper.likeLeft(StringUtils.isNotEmpty(menuName), MenuEntity::getMenuName, menuName);
             queryWrapper.likeRight(StringUtils.isNotEmpty(menuName), MenuEntity::getMenuName, menuName);
             queryWrapper.orderByAsc(MenuEntity::getSort);
@@ -502,4 +515,26 @@ public class MenuApiController {
         }
     }
 
+    /**
+     * 从 DTO 字符串解析应用维度;非空且合法时在查询上追加 app_id 条件(要求库表 menu.app_id 与数据一致)。
+     */
+    private void applyAppIdFilter(LambdaQueryWrapper<MenuEntity> queryWrapper, String appIdRaw) {
+        Long appId = parseAppId(appIdRaw);
+        if (appId != null) {
+            queryWrapper.eq(MenuEntity::getAppId, appId);
+        }
+    }
+
+    private Long parseAppId(String appIdRaw) {
+        if (StrUtil.isBlank(appIdRaw)) {
+            return null;
+        }
+        try {
+            return Long.parseLong(appIdRaw.trim());
+        } catch (NumberFormatException e) {
+            log.warn("非法 appId,已忽略: {}", appIdRaw);
+            return null;
+        }
+    }
+
 }

+ 141 - 0
java/storlead-api/src/main/java/com/storlead/system/controller/SysAppApiController.java

@@ -0,0 +1,141 @@
+package com.storlead.system.controller;
+
+import cn.hutool.core.util.StrUtil;
+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.framework.common.result.Result;
+import com.storlead.system.pojo.dto.SysAppPageDTO;
+import com.storlead.system.pojo.entity.SysAppEntity;
+import com.storlead.system.service.SysAppService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * 系统应用管理
+ */
+@Api(tags = "系统: 应用管理")
+@RestController
+@RequestMapping("/sys/app")
+public class SysAppApiController {
+
+    @Resource
+    private SysAppService sysAppService;
+
+    @ApiOperation("应用分页")
+    @PostMapping("/pagelist")
+    public Result<IPage<SysAppEntity>> pagelist(@RequestBody SysAppPageDTO dto) {
+        IPage<SysAppEntity> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
+        LambdaQueryWrapper<SysAppEntity> w = new LambdaQueryWrapper<>();
+        w.eq(SysAppEntity::getIsDelete, 0);
+        if (StrUtil.isNotBlank(dto.getAppCode())) {
+            w.like(SysAppEntity::getAppCode, dto.getAppCode().trim());
+        }
+        if (StrUtil.isNotBlank(dto.getAppName())) {
+            w.like(SysAppEntity::getAppName, dto.getAppName().trim());
+        }
+        if (dto.getEnabled() != null) {
+            w.eq(SysAppEntity::getEnabled, dto.getEnabled());
+        }
+        w.orderByAsc(SysAppEntity::getSort).orderByAsc(SysAppEntity::getId);
+        return Result.ok(sysAppService.page(page, w));
+    }
+
+    @ApiOperation("已启用应用列表(下拉等)")
+    @PostMapping("/listEnabled")
+    public Result<?> listEnabled() {
+        return Result.ok(sysAppService.listEnabled());
+    }
+
+    @ApiOperation("详情")
+    @PostMapping("/detail")
+    public Result<?> detail(@RequestParam Long id) {
+        SysAppEntity one = sysAppService.getOne(new LambdaQueryWrapper<SysAppEntity>()
+                .eq(SysAppEntity::getId, id)
+                .eq(SysAppEntity::getIsDelete, 0));
+        if (one == null) {
+            return Result.error("应用不存在或已删除");
+        }
+        return Result.ok(one);
+    }
+
+    @ApiOperation("保存或更新")
+    @PostMapping("/save")
+    public Result<?> save(@RequestBody SysAppEntity body) {
+        if (body == null || StrUtil.isBlank(body.getAppCode()) || StrUtil.isBlank(body.getAppName())) {
+            return Result.error("appCode、appName 不能为空");
+        }
+        body.setAppCode(body.getAppCode().trim());
+        body.setAppName(body.getAppName().trim());
+
+        Date now = new Date();
+        if (body.getId() == null) {
+            if (body.getEnabled() == null) {
+                body.setEnabled(1);
+            }
+            if (body.getIsDelete() == null) {
+                body.setIsDelete(0);
+            }
+            if (body.getSort() == null) {
+                body.setSort(0);
+            }
+            if (body.getOwnerBy() == null) {
+                body.setOwnerBy(0L);
+            }
+            body.setCreateTime(now);
+        }
+
+        LambdaQueryWrapper<SysAppEntity> dup = new LambdaQueryWrapper<SysAppEntity>()
+                .eq(SysAppEntity::getAppCode, body.getAppCode())
+                .eq(SysAppEntity::getIsDelete, 0);
+        if (body.getId() != null) {
+            dup.ne(SysAppEntity::getId, body.getId());
+        }
+        if (sysAppService.count(dup) > 0) {
+            return Result.error("应用编码已存在: " + body.getAppCode());
+        }
+
+        body.setUpdateTime(now);
+
+        sysAppService.saveOrUpdate(body);
+        return Result.ok();
+    }
+
+    @ApiOperation("启用/禁用")
+    @PostMapping("/enable")
+    public Result<?> enable(@RequestParam Long id, @RequestParam Boolean enabled) {
+        if (id == null || enabled == null) {
+            return Result.error("参数错误");
+        }
+        LambdaUpdateWrapper<SysAppEntity> uw = new LambdaUpdateWrapper<>();
+        uw.set(SysAppEntity::getEnabled, Boolean.TRUE.equals(enabled) ? 1 : 0);
+        uw.set(SysAppEntity::getUpdateTime, new Date());
+        uw.eq(SysAppEntity::getId, id).eq(SysAppEntity::getIsDelete, 0);
+        if (!sysAppService.update(uw)) {
+            return Result.error("更新失败,应用不存在或已删除");
+        }
+        return Result.ok();
+    }
+
+    @ApiOperation("逻辑删除(无关联菜单时)")
+    @PostMapping("/delete")
+    public Result<?> delete(@RequestParam Long id) {
+        if (Objects.isNull(id)) {
+            return Result.error("id 不能为空");
+        }
+        if (!sysAppService.trySoftDelete(id)) {
+            return Result.error("删除失败:仍存在关联菜单,或记录不存在");
+        }
+        return Result.ok();
+    }
+}

+ 1 - 0
java/storlead-message/pom.xml

@@ -18,6 +18,7 @@
 
     <modules>
         <module>storlead-message-core</module>
+        <module>storlead-message-spi</module>
         <module>storlead-message-biz</module>
         <module>storlead-message-api</module>
     </modules>

+ 9 - 1
java/storlead-message/storlead-message-api/pom.xml

@@ -14,16 +14,24 @@
     <artifactId>storlead-message-api</artifactId>
     <packaging>jar</packaging>
     <name>storlead-message-api</name>
+    <description>消息域 Web:Controller 等。</description>
 
     <dependencies>
         <dependency>
             <groupId>com.storlead.boot</groupId>
             <artifactId>storlead-message-core</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-message-spi</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.storlead.boot</groupId>
             <artifactId>storlead-message-biz</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-web</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 170 - 0
java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageApiController.java

@@ -0,0 +1,170 @@
+package com.storlead.message.controller;
+
+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.message.enums.MessageTypeEnum;
+import com.storlead.message.pojo.dto.MessageDTO;
+import com.storlead.message.pojo.dto.MessageTestDTO;
+import com.storlead.message.pojo.entity.InsideMessageSendLogEntity;
+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;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @program: sp-sales-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2024-04-19 16:36
+ */
+@RestController
+@RequestMapping("/sys/inside/message")
+@Api(tags = "消息系统: 站内消息相关接口")
+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 = "获取当前用户的站内消息" )
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "", response = MessageDetailVO.class)
+    })
+    public Result<?> getMessage(MessageDTO dto) {
+        Page<InsideMessageSendLogEntity> page = new Page<>(dto.getPageIndex(),dto.getPageSize());
+        QueryWrapper<InsideMessageSendLogEntity> queryWrapper = new QueryWrapper();
+        queryWrapper.eq("mlog.receiver_user_id", LoginUserUtil.getCurrentUserId());
+        if (Objects.nonNull(dto.getMessageType())) {
+            queryWrapper.eq("mr.message_type",dto.getMessageType());
+        }
+        if (Objects.nonNull(dto.getIsRead())) {
+            queryWrapper.eq("mlog.is_read",dto.getIsRead());
+            queryWrapper.eq("mlog.is_read",dto.getIsRead());
+        }
+        queryWrapper.eq("mlog.is_delete",Integer.valueOf(0));
+        queryWrapper.orderByAsc("mlog.is_read");
+        queryWrapper.orderByDesc("mlog.id");
+        IPage<MessageDetailVO> pageList =  messageSendLogService.queryListMessageLog(page,queryWrapper);
+        return Result.ok(pageList);
+    }
+
+    @PostMapping(value = "/read")
+    @ApiOperation(value = "更新为已读" )
+    public Result<?> updateStatus(Long [] messageLogIds) {
+        if (Objects.isNull(messageLogIds) || messageLogIds.length == 0) {
+            return Result.error("参数错误");
+        }
+        LambdaUpdateWrapper<InsideMessageSendLogEntity> updateWrapper = new LambdaUpdateWrapper();
+        updateWrapper.in(InsideMessageSendLogEntity::getId,messageLogIds);
+        updateWrapper.eq(InsideMessageSendLogEntity::getIsDelete,Integer.valueOf(0));
+        updateWrapper.set(InsideMessageSendLogEntity::getIsRead,1);
+        return Result.ok(messageSendLogService.update(updateWrapper));
+    }
+
+    @PostMapping(value = "/readAll")
+    @ApiOperation(value = "更新为已读" )
+    public Result<?> readAll(@ApiParam(value = "") Integer messageType) {
+        LambdaUpdateWrapper<InsideMessageSendLogEntity> updateWrapper = new LambdaUpdateWrapper();
+        updateWrapper.in(InsideMessageSendLogEntity::getReceiverUserId,LoginUserUtil.getCurrentUserId());
+        updateWrapper.in(InsideMessageSendLogEntity::getIsDelete,Integer.valueOf(0));
+        updateWrapper.in(InsideMessageSendLogEntity::getIsRead,Integer.valueOf(0));
+        if (Objects.nonNull(messageType)) {
+            updateWrapper.in(InsideMessageSendLogEntity::getMessageType,messageType);
+        }
+        updateWrapper.set(InsideMessageSendLogEntity::getIsRead,1);
+        return Result.ok(messageSendLogService.update(updateWrapper));
+    }
+
+    @PostMapping(value = "/cleanAll")
+    @ApiOperation(value = "清除消息" )
+    public Result<?> cleanAll(MessageDTO dto) {
+        LambdaUpdateWrapper<InsideMessageSendLogEntity> updateWrapper = new LambdaUpdateWrapper();
+        updateWrapper.in(InsideMessageSendLogEntity::getReceiverUserId,LoginUserUtil.getCurrentUserId());
+        if (Objects.nonNull(dto.getMessageType())) {
+            updateWrapper.in(InsideMessageSendLogEntity::getMessageType,dto.getMessageType());
+        }
+        if (Objects.nonNull(dto.getIsRead())) {
+            updateWrapper.in(InsideMessageSendLogEntity::getIsRead,dto.getIsRead());
+        }
+        updateWrapper.eq(InsideMessageSendLogEntity::getIsDelete,Integer.valueOf(0));
+        updateWrapper.set(InsideMessageSendLogEntity::getIsDelete,1);
+        return Result.ok(messageSendLogService.update(updateWrapper));
+    }
+
+    @PostMapping(value = "/getMessageCount")
+    @ApiOperation(value = "获取未读消息数" )
+    public Result<?> getMessageCount(MessageDTO dto) {
+        QueryWrapper<InsideMessageSendLogEntity> queryWrapper = new QueryWrapper();
+        queryWrapper.eq("mlog.receiver_user_id", LoginUserUtil.getCurrentUserId());
+        queryWrapper.eq("mlog.is_read",0);
+        if (Objects.nonNull(dto.getMessageType())) {
+            queryWrapper.eq("mr.message_type",dto.getMessageType());
+        }
+        queryWrapper.eq("mlog.is_delete",Integer.valueOf(0));
+        MessageNoReadTotalVO countMap = messageSendLogService.countNoReadtotal(queryWrapper);
+        return Result.ok(countMap);
+    }
+
+    @PostMapping(value = "/getNoReadCount")
+    @ApiOperation(value = "获取未读消息数" )
+    public Result<?> getNoReadCount(MessageDTO dto) {
+        QueryWrapper<InsideMessageSendLogEntity> queryWrapper = new QueryWrapper();
+        queryWrapper.eq("mlog.receiver_user_id", LoginUserUtil.getCurrentUserId());
+        queryWrapper.eq("mlog.is_read",0);
+        List<String> types = new ArrayList<>();
+        if (Objects.nonNull(dto.getMessageType())) {
+            queryWrapper.eq("mlog.message_type",dto.getMessageType());
+            types.add(dto.getMessageType());
+        }
+        queryWrapper.eq("mlog.is_delete",Integer.valueOf(0));
+        List<MessageTypeReadStateVO> statuVOS = messageSendLogService.getCountNoReadCount(queryWrapper);
+
+        List<MessageTypeReadStateVO> readStatels = MessageTypeEnum.getMessageTypeReadStatels(types);
+        Map<Integer, Integer> statuMap = statuVOS.stream()
+                .collect(Collectors.toMap(MessageTypeReadStateVO::getMessageType, MessageTypeReadStateVO::getStateNumber));
+        for (MessageTypeReadStateVO readState : readStatels) {
+            readState.setStateNumber(statuMap.getOrDefault(readState.getMessageType(),0));
+        }
+        return Result.ok(readStatels);
+    }
+}

+ 185 - 0
java/storlead-message/storlead-message-api/src/main/java/com/storlead/message/controller/MessageTemplateApiController.java

@@ -0,0 +1,185 @@
+package com.storlead.message.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+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.message.enums.MessageTypeEnum;
+import com.storlead.message.pojo.dto.MessageTemplateEventDTO;
+import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
+import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
+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;
+import org.springframework.beans.BeanUtils;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @program: sp-sales-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2024-04-26 15:15
+ */
+@RestController
+@RequestMapping("/sys/message/template")
+@Api(tags = "消息: 消息模板机制配置")
+public class MessageTemplateApiController {
+
+    @Resource
+    private MessageTemplateEventGroupService templateEventGroupService;
+
+    @Resource
+    private MessageTemplateEventDetailService templateEventDetailService;
+
+    @ApiOperation("保存模板")
+    @PostMapping("save")
+    public Result save(@RequestBody MessageTemplateEventGroupEntity groupEntity) {
+
+//        groupEntity.dictFiled();
+        templateEventGroupService.saveOrUpdate(groupEntity);
+        return Result.ok();
+    }
+
+    @ApiOperation("分页查询")
+    @PostMapping("listPage")
+    public Result listPage(@RequestBody MessageTemplateEventDTO dto) {
+
+        Page<MessageTemplateEventGroupEntity> page = new Page<>(dto.getPageIndex(),dto.getPageSize());
+        LambdaQueryWrapper<MessageTemplateEventGroupEntity> queryWrapper = new LambdaQueryWrapper();
+        if (Objects.nonNull(dto.getTemplateServiceType())) {
+            queryWrapper.eq(MessageTemplateEventGroupEntity::getTemplateServiceType,dto.getTemplateServiceType());
+        }
+        if (StrUtil.isNotBlank(dto.getBlurry())) {
+            queryWrapper.like(MessageTemplateEventGroupEntity::getEventName,dto.getBlurry());
+        }
+        IPage<MessageTemplateVO>  pageList = templateEventGroupService.listPage(page, queryWrapper);
+        if (CollectionUtil.isNotEmpty(pageList.getRecords())) {
+            List<Long> dt = pageList.getRecords().stream().map(MessageTemplateVO::getId).collect(Collectors.toList());
+            LambdaQueryWrapper<MessageTemplateEventDetailEntity> wrapper = new LambdaQueryWrapper<>();
+            wrapper.in(MessageTemplateEventDetailEntity::getTemplateEventId,dt);
+            List<MessageTemplateEventDetailEntity>  detailEntities = templateEventDetailService.list(wrapper);
+            Map<Long, List<MessageTemplateEventDetailEntity>> groupMap = detailEntities.stream().collect(Collectors.groupingBy(MessageTemplateEventDetailEntity::getTemplateEventId));
+            pageList.getRecords().forEach(arg -> {
+                arg.setDetailEntities(groupMap.get(arg.getId()));
+            });
+            SysBaseField.dictFileds(pageList.getRecords());
+        }
+        return Result.ok(pageList);
+    }
+
+    @ApiOperation("保存模板详情")
+    @PostMapping("saveTempleteContent")
+    public Result saveTempleteContent(@RequestBody MessageTemplateEventDetailEntity entity) {
+        templateEventDetailService.saveOrUpdate(entity);
+        return Result.ok();
+    }
+
+    @ApiOperation("获取消息模板详情")
+    @PostMapping("getGroupDetail")
+    public Result getGroupDetail(Long id,String templateDetailType) {
+        MessageTemplateEventGroupEntity templateEventGroup =  templateEventGroupService.getById(id);
+        if (Objects.isNull(templateEventGroup)) {
+            return Result.ok();
+        }
+        MessageTemplateVO templateVO = new MessageTemplateVO();
+        BeanUtils.copyProperties(templateEventGroup,templateVO);
+        LambdaQueryWrapper<MessageTemplateEventDetailEntity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(MessageTemplateEventDetailEntity::getTemplateEventId,templateEventGroup.getId());
+        if (Objects.nonNull(templateDetailType)) {
+            wrapper.eq(MessageTemplateEventDetailEntity::getTemplateDetailType,templateDetailType);
+        }
+        List<MessageTemplateEventDetailEntity>  detailEntities = templateEventDetailService.list(wrapper);
+        templateVO.setDetailEntities(detailEntities);
+        templateVO.dictFiled();
+
+        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 (clazz != null) {
+            for (Field field : clazz.getDeclaredFields()) {
+                MessageArgTemplateVO vo = new MessageArgTemplateVO();
+                vo.setPropertyKey("${" + field.getName() + "}$");
+                // 检查字段是否有 @Column 注解
+                if (field.isAnnotationPresent(ApiModelProperty.class)) {
+                    // 获取注解实例
+                    ApiModelProperty property = field.getAnnotation(ApiModelProperty.class);
+                    vo.setPropertyName(property.value());
+                    // 输出字段名和注解的值
+                }
+                argTemplatels.add(vo);
+            }
+        }
+        templateVO.setArgls(argTemplatels);
+        return Result.result(templateVO);
+    }
+    @ApiOperation("获取消息模板详情")
+    @PostMapping("getDetail")
+    public Result getDetail(Long id) {
+        MessageTemplateEventDetailEntity detailEntity =  templateEventDetailService.getById(id);
+        return Result.result(detailEntity);
+    }
+
+    @ApiOperation("禁用或启用模型")
+    @PostMapping("enabledDetail")
+    public Result enabledTemplateDetail(Long id,Boolean enable) {
+        LambdaUpdateWrapper<MessageTemplateEventDetailEntity> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.set(MessageTemplateEventDetailEntity::getEnabled,enable);
+        updateWrapper.eq(MessageTemplateEventDetailEntity::getId,id);
+        templateEventDetailService.update(updateWrapper);
+        return Result.ok();
+    }
+
+    @ApiOperation("删除模板")
+    @PostMapping("delete")
+    public Result delete(Long id) {
+        if(Objects.isNull(id)) {
+            return Result.error("参数错误");
+        }
+        templateEventGroupService.lgDelete(id);
+        return Result.ok();
+    }
+}

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

@@ -0,0 +1,110 @@
+package com.storlead.message.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+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.message.pojo.dto.MessageTemplateEventDTO;
+import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
+import com.storlead.message.pojo.vo.MessageTemplateVO;
+import com.storlead.message.service.MessageTemplateEventGroupService;
+import com.storlead.message.service.UserMessageNoticeConfigService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @program: sp-sales-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2025-04-25 11:26
+ */
+@RestController
+@RequestMapping("/sys/message/config")
+@Api(tags = "消息: 用户消息设置")
+public class UserMessageConfigApiController {
+
+
+    @Resource
+    private UserMessageNoticeConfigService userMessageNoticeConfigService;
+
+    @Resource
+    private MessageTemplateEventGroupService templateEventGroupService;
+
+    @ApiOperation("保存用户配置详情")
+    @PostMapping("setMessageConfig")
+    public Result setMessageConfig(@RequestBody UserMessageNoticeConfigEntity entity) {
+
+        LambdaQueryWrapper<UserMessageNoticeConfigEntity> queryWrapper = new LambdaQueryWrapper();
+        queryWrapper.eq(UserMessageNoticeConfigEntity::getOwnerBy,LoginUserUtil.getCurrentUserId());
+        queryWrapper.eq(UserMessageNoticeConfigEntity::getTemplateEventId,entity.getTemplateEventId());
+        queryWrapper.eq(UserMessageNoticeConfigEntity::getTemplateDetailType,entity.getTemplateDetailType());
+        queryWrapper.last(" limit 1");
+        UserMessageNoticeConfigEntity o1 = userMessageNoticeConfigService.getOne(queryWrapper);
+        if (Objects.nonNull(o1)) {
+            entity.setId(o1.getId());
+        }
+        userMessageNoticeConfigService.saveOrUpdate(entity);
+        return Result.ok();
+    }
+
+    @ApiOperation("分页查询")
+    @PostMapping("listPage")
+    public Result listPage(@RequestBody MessageTemplateEventDTO dto) {
+        Page<MessageTemplateEventGroupEntity> page = new Page<>(dto.getPageIndex(),dto.getPageSize());
+        LambdaQueryWrapper<MessageTemplateEventGroupEntity> queryWrapper = new LambdaQueryWrapper();
+        if (Objects.nonNull(dto.getTemplateServiceType())) {
+            queryWrapper.eq(MessageTemplateEventGroupEntity::getTemplateServiceType,dto.getTemplateServiceType());
+        }
+        if (StrUtil.isNotBlank(dto.getBlurry())) {
+            queryWrapper.like(MessageTemplateEventGroupEntity::getEventName,dto.getBlurry());
+        }
+        IPage<MessageTemplateVO> pageList = templateEventGroupService.listPage(page, queryWrapper);
+        if (CollectionUtil.isNotEmpty(pageList.getRecords())) {
+            List<Long> dt = pageList.getRecords().stream().map(MessageTemplateVO::getId).collect(Collectors.toList());
+            LambdaQueryWrapper<UserMessageNoticeConfigEntity> wrapper = new LambdaQueryWrapper<>();
+            wrapper.in(UserMessageNoticeConfigEntity::getTemplateEventId,dt);
+            wrapper.eq(UserMessageNoticeConfigEntity::getOwnerBy, LoginUserUtil.getCurrentUserId());
+            List<UserMessageNoticeConfigEntity>  detailEntities = userMessageNoticeConfigService.list(wrapper);
+            Map<Long, List<UserMessageNoticeConfigEntity>> groupMap = detailEntities.stream().collect(Collectors.groupingBy(UserMessageNoticeConfigEntity::getTemplateEventId));
+            pageList.getRecords().forEach(arg -> {
+                List<UserMessageNoticeConfigEntity> rs =  groupMap.get(arg.getId());
+                arg.setUserDetails(Objects.isNull(rs) ? Collections.emptyList() : rs);
+            });
+        }
+        return Result.ok(pageList);
+    }
+
+    @ApiOperation("消息开启关闭")
+    @PostMapping("on_off_message_config")
+    public Result onOffMessageConfig(@RequestBody UserMessageNoticeConfigEntity entity) {
+
+        //    @ApiModelProperty(value = "site:站内,sms:短信,wecom:企业微信,mail:邮件")
+        List<String> templateDetailTypels = CollectionUtils.isEmpty(entity.getTemplateDetailTypels()) ? Arrays.asList("site","wecom","mail") : entity.getTemplateDetailTypels();
+        for (String templateDetailType : templateDetailTypels) {
+            LambdaQueryWrapper<UserMessageNoticeConfigEntity> queryWrapper = new LambdaQueryWrapper();
+            queryWrapper.eq(UserMessageNoticeConfigEntity::getOwnerBy,LoginUserUtil.getCurrentUserId());
+            queryWrapper.eq(UserMessageNoticeConfigEntity::getTemplateEventId,entity.getTemplateEventId());
+            queryWrapper.eq(UserMessageNoticeConfigEntity::getTemplateDetailType,templateDetailType);
+            queryWrapper.last(" limit 1");
+            UserMessageNoticeConfigEntity o1 = userMessageNoticeConfigService.getOne(queryWrapper);
+            if (Objects.nonNull(o1)) {
+                entity.setId(o1.getId());
+            }
+            userMessageNoticeConfigService.saveOrUpdate(entity);
+        }
+        return Result.ok();
+    }
+}

+ 28 - 13
java/storlead-message/storlead-message-biz/pom.xml

@@ -14,41 +14,56 @@
     <artifactId>storlead-message-biz</artifactId>
     <packaging>jar</packaging>
     <name>storlead-message-biz</name>
+    <description>消息域实现:Mapper、Service 实现。</description>
 
     <dependencies>
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-message-spi</artifactId>
+        </dependency>
         <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>
-
         <dependency>
             <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-mybatis</artifactId>
+            <artifactId>storlead-auth</artifactId>
         </dependency>
-
         <dependency>
             <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-web</artifactId>
+            <artifactId>storlead-user-spi</artifactId>
         </dependency>
-
         <dependency>
             <groupId>com.storlead.boot</groupId>
             <artifactId>storlead-user-biz</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-thirdparty-wecom</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.googlecode.aviator</groupId>
+            <artifactId>aviator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>transmittable-thread-local</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
-        <sourceDirectory>${project.basedir}/../src/main/java</sourceDirectory>
-        <testSourceDirectory>${project.basedir}/../src/test/java</testSourceDirectory>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/../src/main/resources</directory>
-            </resource>
-        </resources>
+        <finalName>storlead-message-biz</finalName>
     </build>
 </project>

+ 0 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/mapper/InsideMessageRecordMapper.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/InsideMessageRecordMapper.java


+ 0 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/mapper/InsideMessageSendLogMapper.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/InsideMessageSendLogMapper.java


+ 0 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/mapper/MessageTemplateEventDetailMapper.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/MessageTemplateEventDetailMapper.java


+ 0 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/mapper/MessageTemplateEventGroupMapper.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/MessageTemplateEventGroupMapper.java


+ 1 - 1
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/mapper/UserMessageNoticeConfigMapper.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/mapper/UserMessageNoticeConfigMapper.java

@@ -1,6 +1,6 @@
 package com.storlead.message.mapper;
 
-import com.storlead.message.entity.UserMessageNoticeConfigEntity;
+import com.storlead.message.pojo.entity.UserMessageNoticeConfigEntity;
 import com.storlead.framework.mybatis.mapper.MyBaseMapper;
 
 /**

+ 4 - 2
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/impl/InsideMessageRecordServiceImpl.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/InsideMessageRecordServiceImpl.java

@@ -3,8 +3,8 @@ 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.frame.core.assemble.Result;
-import com.storlead.frame.enums.ErrorMsgCode;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.common.enums.ErrorMsgCode;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import com.storlead.message.pojo.entity.InsideMessageRecordEntity;
 import com.storlead.message.mapper.InsideMessageRecordMapper;
@@ -14,6 +14,7 @@ import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
 import com.storlead.message.service.InsideMessageRecordService;
 import com.storlead.message.service.InsideMessageSendLogService;
 import com.storlead.message.service.MessageTemplateEventGroupService;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -31,6 +32,7 @@ import java.util.regex.Pattern;
  * @author chenkq
  * @since 2024-04-19
  */
+@Log4j2
 @Service
 public class InsideMessageRecordServiceImpl extends MyBaseServiceImpl<InsideMessageRecordMapper, InsideMessageRecordEntity> implements InsideMessageRecordService {
 

+ 0 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/impl/InsideMessageSendLogServiceImpl.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/InsideMessageSendLogServiceImpl.java


+ 0 - 7
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/impl/MessageService.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageService.java

@@ -4,11 +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.googlecode.aviator.runtime.function.AbstractFunction;
-import com.googlecode.aviator.runtime.type.AviatorBoolean;
-import com.googlecode.aviator.runtime.type.AviatorObject;
 import com.storlead.common.aviator.MapKeyExistsFunction;
-import com.storlead.frame.auth.util.LoginUserUtil;
 import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
 import com.storlead.message.service.InsideMessageRecordService;
 import com.storlead.message.service.MessageTemplateEventDetailService;
@@ -16,11 +12,8 @@ import com.storlead.message.service.MessageTemplateEventGroupService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
-import com.googlecode.aviator.utils.Reflector;
 import javax.annotation.Resource;
 import java.util.*;
-
-import com.storlead.common.aviator.EqualsFunction;
 /**
  * @program: sp-sales-platform
  * @description:

+ 5 - 8
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/impl/MessageTemplateEventDetailServiceImpl.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageTemplateEventDetailServiceImpl.java

@@ -5,11 +5,9 @@ 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.frame.auth.util.LoginUserUtil;
-import com.storlead.frame.core.assemble.Result;
-import com.storlead.frame.enums.ErrorMsgCode;
+import com.storlead.framework.util.LoginUserUtil;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
-import com.storlead.frame.thread.ThreadPoolUtil;
+import com.storlead.framework.common.thread.ThreadPoolUtil;
 import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
 import com.storlead.message.mapper.MessageTemplateEventDetailMapper;
 import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
@@ -25,14 +23,12 @@ import com.storlead.user.pojo.entity.DeptEntity;
 import com.storlead.user.pojo.entity.UserEntity;
 import com.storlead.user.service.IDepartService;
 import com.storlead.user.service.IUserService;
-import org.apache.catalina.User;
-import org.springframework.beans.BeanUtils;
+import javax.annotation.Resource;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import javax.annotation.Resource;
-import java.lang.reflect.Array;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -44,6 +40,7 @@ import java.util.stream.Collectors;
  * @author chenkq
  * @since 2024-04-19
  */
+@Log4j2
 @Service
 public class MessageTemplateEventDetailServiceImpl extends MyBaseServiceImpl<MessageTemplateEventDetailMapper, MessageTemplateEventDetailEntity> implements MessageTemplateEventDetailService {
 

+ 0 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/impl/MessageTemplateEventGroupServiceImpl.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/MessageTemplateEventGroupServiceImpl.java


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

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

+ 2 - 4
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/impl/WechatMessageServiceImpl.java → java/storlead-message/storlead-message-biz/src/main/java/com/storlead/message/service/impl/WechatMessageServiceImpl.java

@@ -2,15 +2,13 @@ package com.storlead.message.service.impl;
 
 import cn.hutool.core.util.StrUtil;
 import com.storlead.common.util.HtmlUtils;
-import com.storlead.frame.core.assemble.Result;
-import com.storlead.frame.enums.ErrorMsgCode;
 import com.storlead.framework.common.result.Result;
-import com.storlead.framework.web.enums.ErrorMsgCode;
+import com.storlead.framework.common.enums.ErrorMsgCode;
 import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
 import com.storlead.message.service.WechatMessageService;
 import com.storlead.user.pojo.entity.UserEntity;
 import com.storlead.user.service.IUserService;
-import com.storlead.wx.service.CorpWeChatService;
+import com.storlead.wecom.service.CorpWeChatService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;

+ 12 - 0
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/entity/SmtpPopSettingsEntity.java

@@ -0,0 +1,12 @@
+package com.storlead.sales.mail.entity;
+
+import lombok.Data;
+
+/**
+ * 占位实体:真实邮件模块接入后可删除本包下占位代码。
+ */
+@Data
+public class SmtpPopSettingsEntity {
+    private String emailPassword;
+    private String emailAddress;
+}

+ 15 - 0
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/pojo/SendMailDTO.java

@@ -0,0 +1,15 @@
+package com.storlead.sales.mail.pojo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 占位 DTO:真实邮件模块接入后可删除本包下占位代码。
+ */
+@Data
+public class SendMailDTO {
+    private String subject;
+    private String content;
+    private List<String> recipientls;
+}

+ 12 - 0
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/EmailsService.java

@@ -0,0 +1,12 @@
+package com.storlead.sales.mail.service;
+
+import com.storlead.sales.mail.entity.SmtpPopSettingsEntity;
+import com.storlead.sales.mail.pojo.SendMailDTO;
+
+/**
+ * 占位接口:由 {@link com.storlead.sales.mail.service.impl.NoopEmailsServiceImpl} 提供空实现直至接入真实邮件模块。
+ */
+public interface EmailsService {
+
+    void sendEmail(SendMailDTO dto, SmtpPopSettingsEntity sendSmtpPops);
+}

+ 16 - 0
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/SmtpPopSettingsService.java

@@ -0,0 +1,16 @@
+package com.storlead.sales.mail.service;
+
+import com.storlead.sales.mail.entity.SmtpPopSettingsEntity;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 占位接口:由 {@link com.storlead.sales.mail.service.impl.NoopSmtpPopSettingsServiceImpl} 提供空实现直至接入真实邮件模块。
+ */
+public interface SmtpPopSettingsService {
+
+    SmtpPopSettingsEntity getSystemSmtpPop(Long companyId);
+
+    List<SmtpPopSettingsEntity> getDefaultSmtpPopls(Collection<Long> userIds);
+}

+ 18 - 0
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/impl/NoopEmailsServiceImpl.java

@@ -0,0 +1,18 @@
+package com.storlead.sales.mail.service.impl;
+
+import com.storlead.sales.mail.entity.SmtpPopSettingsEntity;
+import com.storlead.sales.mail.pojo.SendMailDTO;
+import com.storlead.sales.mail.service.EmailsService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 无操作实现,保证消息模块可单独编译;接入真实邮件服务后请删除本类并改为正式实现。
+ */
+@Service
+public class NoopEmailsServiceImpl implements EmailsService {
+
+    @Override
+    public void sendEmail(SendMailDTO dto, SmtpPopSettingsEntity sendSmtpPops) {
+        // no-op stub
+    }
+}

+ 26 - 0
java/storlead-message/storlead-message-biz/src/main/java/com/storlead/sales/mail/service/impl/NoopSmtpPopSettingsServiceImpl.java

@@ -0,0 +1,26 @@
+package com.storlead.sales.mail.service.impl;
+
+import com.storlead.sales.mail.entity.SmtpPopSettingsEntity;
+import com.storlead.sales.mail.service.SmtpPopSettingsService;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 无操作实现,保证消息模块可单独编译;接入真实邮件服务后请删除本类并改为正式实现。
+ */
+@Service
+public class NoopSmtpPopSettingsServiceImpl implements SmtpPopSettingsService {
+
+    @Override
+    public SmtpPopSettingsEntity getSystemSmtpPop(Long companyId) {
+        return null;
+    }
+
+    @Override
+    public List<SmtpPopSettingsEntity> getDefaultSmtpPopls(Collection<Long> userIds) {
+        return Collections.emptyList();
+    }
+}

+ 0 - 0
java/storlead-message/storlead-message-core/src/main/resources/mapper/InsideMessageRecordMapper.xml → java/storlead-message/storlead-message-biz/src/main/resources/mapper/InsideMessageRecordMapper.xml


+ 0 - 0
java/storlead-message/storlead-message-core/src/main/resources/mapper/InsideMessageSendLogMapper.xml → java/storlead-message/storlead-message-biz/src/main/resources/mapper/InsideMessageSendLogMapper.xml


+ 0 - 0
java/storlead-message/storlead-message-core/src/main/resources/mapper/MessageTemplateEventDetailMapper.xml → java/storlead-message/storlead-message-biz/src/main/resources/mapper/MessageTemplateEventDetailMapper.xml


+ 0 - 0
java/storlead-message/storlead-message-core/src/main/resources/mapper/MessageTemplateEventGroupMapper.xml → java/storlead-message/storlead-message-biz/src/main/resources/mapper/MessageTemplateEventGroupMapper.xml


+ 1 - 1
java/storlead-message/storlead-message-core/src/main/resources/mapper/UserMessageNoticeConfigMapper.xml → java/storlead-message/storlead-message-biz/src/main/resources/mapper/UserMessageNoticeConfigMapper.xml

@@ -3,7 +3,7 @@
 <mapper namespace="com.storlead.message.mapper.UserMessageNoticeConfigMapper">
 
         <!-- 通用查询映射结果 -->
-        <resultMap id="BaseResultMap" type="com.storlead.message.entity.UserMessageNoticeConfigEntity">
+        <resultMap id="BaseResultMap" type="com.storlead.message.pojo.entity.UserMessageNoticeConfigEntity">
                     <id column="id" property="id" />
                 <result column="create_by" property="createBy" />
                 <result column="owner_by" property="ownerBy" />

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

@@ -11,19 +11,19 @@
         <relativePath>../pom.xml</relativePath>
     </parent>
 
-
     <artifactId>storlead-message-core</artifactId>
     <packaging>jar</packaging>
     <name>storlead-message-core</name>
+    <description>消息域模型:entity、dto、vo、枚举。</description>
 
     <dependencies>
         <dependency>
             <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-common</artifactId>
+            <artifactId>storlead-mybatis</artifactId>
         </dependency>
         <dependency>
             <groupId>com.storlead.boot</groupId>
-            <artifactId>storlead-user-spi</artifactId>
+            <artifactId>storlead-common</artifactId>
         </dependency>
     </dependencies>
 </project>

+ 95 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/enums/MessageTypeEnum.java

@@ -0,0 +1,95 @@
+package com.storlead.message.enums;
+
+import com.storlead.message.pojo.vo.MessageTypeReadStateVO;
+import lombok.Getter;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @program: sp-sales-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2024-09-06 09:26
+ */
+@Getter
+public enum MessageTypeEnum {
+    /**
+     * 为了查询分类而产生
+     * 消息类型细分 0:普通消息,1:@我相关,2:审批消息,微信小程序用( 3:目标完成贡献值分配提醒,4:简报待审消息,5:赞扬,6:提升,7:报告,99:其他)
+     */
+    CUSTOMER("10", "客户"),
+    CLUS("11", "线索"),
+    LIAISON("20", "联系人"),
+    BUSINESS("30", "商机"),
+    ORDER_FORM("40", "订单"),
+    //    TASK_CANCELED("50", "回款"),
+//    TASK_CANCELED("60", "退款"),
+//    TASK_CANCELED("70", "费用"),
+    TASK_CANCELED("80", "任务"),
+    FOLLOW_UP("90", "跟进"),
+    WORK_ORDER("100", "工单"),
+    BULLETIN("120", "公告"),
+    PERFORMANCE_GOAL("130", "目标"),
+    BROADCAST("200", "统计"),
+    OTHER_EXTEND("999", "其他"),
+    /**
+     *  首页的消息需要查
+     *  首页包含:目标和简报
+     */
+    ;
+    public static MessageTypeEnum [] messageSubTypes = MessageTypeEnum.values();
+
+    public static Map getMessageTypeMap(List<String> types) {
+        Map<String,Integer> map = new HashMap<>();
+        for(MessageTypeEnum subTypeEnum: messageSubTypes) {
+            if (CollectionUtils.isEmpty(types)) {
+                map.put(subTypeEnum.getCode(),Integer.valueOf(0));
+            } else {
+                if (types.contains(subTypeEnum.getCode())) {
+                    map.put(subTypeEnum.getCode(),Integer.valueOf(0));
+                }
+            }
+        }
+        return map;
+    }
+
+    public static List<MessageTypeReadStateVO> getMessageTypeReadStatels(List<String> types) {
+        List<MessageTypeReadStateVO> arr = new ArrayList<>();
+        for(MessageTypeEnum subTypeEnum: messageSubTypes) {
+            MessageTypeReadStateVO vo = new MessageTypeReadStateVO();
+            vo.setMessageType(Integer.valueOf(subTypeEnum.getCode()));
+            vo.setMessageTypeName(subTypeEnum.getDesc());
+            if (CollectionUtils.isEmpty(types)) {
+                vo.setStateNumber(Integer.valueOf(0));
+                arr.add(vo);
+            } else {
+                if (types.contains(subTypeEnum.getCode())) {
+                    vo.setStateNumber(Integer.valueOf(0));
+                    arr.add(vo);
+                }
+            }
+        }
+        return arr;
+    }
+
+    private String code;
+    private String desc;
+
+    MessageTypeEnum(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public static MessageTypeEnum getByCode(Integer code) {
+        for (MessageTypeEnum tag : MessageTypeEnum.values()) {
+            if (tag.code.equals(code)) {
+                return tag;
+            }
+        }
+        return null; // 如果找不到对应的枚举值,可以返回null或者抛出异常
+    }
+}

+ 77 - 0
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/enums/OperationEventEnum.java

@@ -0,0 +1,77 @@
+package com.storlead.message.enums;
+
+/**
+ * @program: sp-sales-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2024-08-19 14:44
+ */
+public enum OperationEventEnum {
+    MEMBER_ADD_CLUE("MEMBER_ADD_CLUE", "成员新增线索"),
+    MEMBER_RECEIVE_CLUE("MEMBER_RECEIVE_CLUE", "成员领取线索"),
+    DISTRIBUTE_CLUE("DISTRIBUTE_CLUE", "分配线索"),
+    TRANSFER_CLUE("TRANSFER_CLUE", "转移线索"),
+    CONVERT_TO_CUSTOMER("CONVERT_TO_CUSTOMER", "转为客户"),
+    PUBLIC_WARNING("PUBLIC_WARNING", "置公预警"),
+    CLEAR_WARNING("CLEAR_WARNING", "清除预警"),
+    DATA_CHANGE("DATA_CHANGE", "数据变更"),
+    COMMENT_FOLLOW_UP("COMMENT_FOLLOW_UP", "评论跟进"),
+    NEW_EMAIL("NEW_EMAIL", "新邮件"),
+    NEW_TASK("NEW_TASK", "新建任务"),
+    FOLLOW_UP_REMINDER("FOLLOW_UP_REMINDER", "跟进提醒"),
+    FOLLOW_UP_OVERDUE("FOLLOW_UP_OVERDUE", "跟进逾期"),
+    DUPLICATE_WARNING("DUPLICATE_WARNING", "查重预警"),
+    ADD_CUSTOMER("ADD_CUSTOMER", "新增客户"),
+    TRANSFER_CUSTOMER("TRANSFER_CUSTOMER", "转移客户"),
+    MOVE_TO_PUBLIC("MOVE_TO_PUBLIC", "移入公海"),
+    DUPLICATE_WARNING_AGAIN("DUPLICATE_WARNING", "查重预警"),
+    DELETE_CUSTOMER("DELETE_CUSTOMER", "删除客户"),
+    PUBLIC_WARNING_AGAIN("PUBLIC_WARNING", "置公预警"),
+    GARBAGE_CUSTOMER_WARNING("GARBAGE_CUSTOMER_WARNING", "置垃圾客户预警"),
+    CLEAR_WARNING_AGAIN("CLEAR_WARNING", "清除预警"),
+    DATA_CHANGE_AGAIN("DATA_CHANGE", "数据变更"),
+    ADD_SAMPLE("ADD_SAMPLE", "新增寄样"),
+    CUSTOMER_COLLABORATION("CUSTOMER_COLLABORATION", "客户协作"),
+    CUSTOMER_MERGE("CUSTOMER_MERGE", "客户合并"),
+    COMMENT_FOLLOW_UP_AGAIN("COMMENT_FOLLOW_UP", "评论跟进"),
+    NEW_EMAIL_AGAIN("NEW_EMAIL", "新邮件"),
+    NEW_TASK_AGAIN("NEW_TASK", "新建任务"),
+    FOLLOW_UP_REMINDER_AGAIN("FOLLOW_UP_REMINDER", "跟进提醒"),
+    FOLLOW_UP_OVERDUE_AGAIN("FOLLOW_UP_OVERDUE", "跟进逾期"),
+    ADD_OPPORTUNITY("ADD_OPPORTUNITY", "新增商机"),
+    TRANSFER_OPPORTUNITY("TRANSFER_OPPORTUNITY", "转移商机"),
+    OPPORTUNITY_COLLABORATION("OPPORTUNITY_COLLABORATION", "商机协作"),
+    ADD_QUOTE("ADD_QUOTE", "新增报价"),
+    NEW_TASK_THIRD("NEW_TASK", "新建任务"),
+    FOLLOW_UP_REMINDER_THIRD("FOLLOW_UP_REMINDER", "跟进提醒"),
+    FOLLOW_UP_OVERDUE_THIRD("FOLLOW_UP_OVERDUE", "跟进逾期"),
+    DATA_CHANGE_THIRD("DATA_CHANGE", "数据变更"),
+    COMMENT_FOLLOW_UP_THIRD("COMMENT_FOLLOW_UP", "评论跟进"),
+    CONVERT_TO_ORDER("CONVERT_TO_ORDER", "转为订单"),
+    DELETE_OPPORTUNITY("DELETE_OPPORTUNITY", "删除商机"),
+    ADD_ORDER("ADD_ORDER", "新增订单"),
+    TRANSFER_ORDER("TRANSFER_ORDER", "转移订单"),
+    ADD_COLLABORATION("ADD_COLLABORATION", "添加协作"),
+    NEW_TASK_FOURTH("NEW_TASK", "新建任务"),
+    FOLLOW_UP_REMINDER_FOURTH("FOLLOW_UP_REMINDER", "跟进提醒"),
+    FOLLOW_UP_OVERDUE_FOURTH("FOLLOW_UP_OVERDUE", "跟进逾期"),
+    DATA_CHANGE_FOURTH("DATA_CHANGE", "数据变更"),
+    ADD_BULLETIN("ADD_BULLETIN", "发布公告"),
+    DELETE_ORDER("DELETE_ORDER", "删除订单");
+
+    private final String code;
+    private final String desc;
+
+    OperationEventEnum(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

+ 1 - 4
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/MessageTemplateEventGroupEntity.java

@@ -2,13 +2,10 @@ package com.storlead.message.pojo.entity;
 
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
 
-import com.storlead.frame.annotate.Dict;
+import com.storlead.framework.annotate.Dict;
 import com.storlead.framework.mybatis.entity.SysBaseField;
-import io.opentracing.tag.IntTag;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;

+ 5 - 9
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/entity/UserMessageNoticeConfigEntity.java → java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/entity/UserMessageNoticeConfigEntity.java

@@ -1,10 +1,10 @@
-package com.storlead.message.entity;
+package com.storlead.message.pojo.entity;
 
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.storlead.framework.mybatis.entity.SysBaseField;
-import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.storlead.framework.mybatis.entity.SysBaseField;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -14,9 +14,7 @@ import lombok.experimental.Accessors;
 import java.util.List;
 
 /**
- * <p>
  * 消息开关配置
- * </p>
  *
  * @author chenkq
  * @since 2025-04-25
@@ -25,7 +23,7 @@ import java.util.List;
 @EqualsAndHashCode(callSuper = true)
 @Accessors(chain = true)
 @TableName("user_message_notice_config")
-@ApiModel(value="UserMessageNoticeConfigEntity对象", description="消息开关配置")
+@ApiModel(value = "UserMessageNoticeConfigEntity对象", description = "消息开关配置")
 public class UserMessageNoticeConfigEntity extends SysBaseField {
 
     private static final long serialVersionUID = 1L;
@@ -53,6 +51,4 @@ public class UserMessageNoticeConfigEntity extends SysBaseField {
     @ApiModelProperty(value = "备注")
     @TableField("remark")
     private Long remark;
-
-
 }

+ 1 - 1
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/pojo/vo/MessageTemplateVO.java

@@ -1,6 +1,6 @@
 package com.storlead.message.pojo.vo;
 
-import com.storlead.message.entity.UserMessageNoticeConfigEntity;
+import com.storlead.message.pojo.entity.UserMessageNoticeConfigEntity;
 import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
 import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
 import io.swagger.annotations.ApiModelProperty;

+ 0 - 13
java/storlead-message/storlead-message-core/src/test/java/com/storlead/tems/message/MessageApplicationTests.java

@@ -1,13 +0,0 @@
-package com.storlead.tems.message;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class MessageApplicationTests {
-
-    @Test
-    void contextLoads() {
-    }
-
-}

+ 33 - 0
java/storlead-message/storlead-message-spi/pom.xml

@@ -0,0 +1,33 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.storlead.boot</groupId>
+        <artifactId>storlead-message</artifactId>
+        <version>1.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <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>
+</project>

+ 7 - 23
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/InsideMessageRecordService.java → java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/InsideMessageRecordService.java

@@ -1,7 +1,7 @@
 package com.storlead.message.service;
 
-import com.storlead.framework.mybatis.service.MyBaseService;
 import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.service.MyBaseService;
 import com.storlead.message.pojo.entity.InsideMessageRecordEntity;
 import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
 import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
@@ -10,36 +10,20 @@ import java.util.Collection;
 import java.util.Map;
 
 /**
- * <p>
  * 系统内部消息 服务类
- * </p>
  *
  * @author chenkq
  * @since 2024-04-19
  */
 public interface InsideMessageRecordService extends MyBaseService<InsideMessageRecordEntity> {
 
-    Map getOldMapDataById(String table,String fieldColumn,String id);
-
+    Map getOldMapDataById(String table, String fieldColumn, String id);
 
-    /**
-     * @param templateEventId  站内消息模板
-     * @param map 参数
-     * @param receiverUserId 接收人
-     * @param callbackParam 回调参数
-     * @return
-     */
     Result sendInsideMessage(MessageTemplateEventGroupEntity eventGroup, MessageTemplateEventDetailEntity templateEventDetail, Map map, Long receiverUserId, String callbackParam, Long sendUserId);
-    /**
-     * @param templateEventId  消息事件模板
-     * @param map 参数
-     * @param receiverUserIds 接收人
-     * @param callbackParam 回调参数
-     * @return
-     */
-    Result sendInsideMessage(MessageTemplateEventGroupEntity eventGroup,MessageTemplateEventDetailEntity templateEventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam, Long sendUserId);
-
-    void asynSendInsideMessage(MessageTemplateEventGroupEntity eventGroup,MessageTemplateEventDetailEntity templateEventDetail, Map map, Long receiverUserId, String callbackParam,Long sendUserId);
-    void asynSendInsideMessage(MessageTemplateEventGroupEntity eventGroup,MessageTemplateEventDetailEntity templateEventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam,Long sendUserId);
 
+    Result sendInsideMessage(MessageTemplateEventGroupEntity eventGroup, MessageTemplateEventDetailEntity templateEventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam, Long sendUserId);
+
+    void asynSendInsideMessage(MessageTemplateEventGroupEntity eventGroup, MessageTemplateEventDetailEntity templateEventDetail, Map map, Long receiverUserId, String callbackParam, Long sendUserId);
+
+    void asynSendInsideMessage(MessageTemplateEventGroupEntity eventGroup, MessageTemplateEventDetailEntity templateEventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam, Long sendUserId);
 }

+ 0 - 4
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/InsideMessageSendLogService.java → java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/InsideMessageSendLogService.java

@@ -12,9 +12,7 @@ import com.storlead.message.pojo.vo.MessageTypeReadStateVO;
 import java.util.List;
 
 /**
- * <p>
  * 内部消息人员接收记录表 服务类
- * </p>
  *
  * @author chenkq
  * @since 2024-04-19
@@ -26,6 +24,4 @@ public interface InsideMessageSendLogService extends MyBaseService<InsideMessage
     MessageNoReadTotalVO countNoReadtotal(Wrapper<InsideMessageSendLogEntity> wrapper);
 
     List<MessageTypeReadStateVO> getCountNoReadCount(Wrapper<InsideMessageSendLogEntity> wrapper);
-
-
 }

+ 0 - 3
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/MessageTemplateEventDetailService.java → java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/MessageTemplateEventDetailService.java

@@ -4,14 +4,11 @@ import com.storlead.framework.mybatis.service.MyBaseService;
 import com.storlead.message.pojo.entity.MessageTemplateEventDetailEntity;
 import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
 
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
 /**
- * <p>
  * 消息模板 服务类
- * </p>
  *
  * @author chenkq
  * @since 2024-04-19

+ 0 - 2
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/MessageTemplateEventGroupService.java → java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/MessageTemplateEventGroupService.java

@@ -8,9 +8,7 @@ import com.storlead.message.pojo.entity.MessageTemplateEventGroupEntity;
 import com.storlead.message.pojo.vo.MessageTemplateVO;
 
 /**
- * <p>
  * 实践规则模板 服务类
- * </p>
  *
  * @author chenkq
  * @since 2024-04-19

+ 2 - 4
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/UserMessageNoticeConfigService.java → java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/UserMessageNoticeConfigService.java

@@ -1,19 +1,17 @@
 package com.storlead.message.service;
 
-import com.storlead.message.entity.UserMessageNoticeConfigEntity;
 import com.storlead.framework.mybatis.service.MyBaseService;
+import com.storlead.message.pojo.entity.UserMessageNoticeConfigEntity;
 
 import java.util.Set;
 
 /**
- * <p>
  * 消息开关配置 服务类
- * </p>
  *
  * @author chenkq
  * @since 2025-04-25
  */
 public interface UserMessageNoticeConfigService extends MyBaseService<UserMessageNoticeConfigEntity> {
 
-    Set<Long> checkUserNoticeConfig(Set<Long> ids,Long templateId,String messageType);
+    Set<Long> checkUserNoticeConfig(Set<Long> ids, Long templateId, String messageType);
 }

+ 1 - 8
java/storlead-message/storlead-message-core/src/main/java/com/storlead/message/service/WechatMessageService.java → java/storlead-message/storlead-message-spi/src/main/java/com/storlead/message/service/WechatMessageService.java

@@ -8,14 +8,7 @@ import java.util.Map;
 
 public interface WechatMessageService {
 
-    /**
-     * @param eventDetail  短信模板
-     * @param map 参数
-     * @param receiverUserIds 接收人
-     * @param callbackParam 回调参数
-     * @return
-     */
     Result sendWechatMessage(MessageTemplateEventDetailEntity eventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam);
 
-    Result sendWechatMessage(MessageTemplateEventDetailEntity eventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam,String appCode);
+    Result sendWechatMessage(MessageTemplateEventDetailEntity eventDetail, Map map, Collection<Long> receiverUserIds, String callbackParam, String appCode);
 }

+ 10 - 0
java/storlead-system/storlead-system-biz/src/main/java/com/storlead/system/mapper/SysAppMapper.java

@@ -0,0 +1,10 @@
+package com.storlead.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.system.pojo.entity.SysAppEntity;
+
+/**
+ * 系统应用 Mapper
+ */
+public interface SysAppMapper extends BaseMapper<SysAppEntity> {
+}

+ 48 - 0
java/storlead-system/storlead-system-biz/src/main/java/com/storlead/system/service/impl/SysAppServiceImpl.java

@@ -0,0 +1,48 @@
+package com.storlead.system.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.storlead.system.mapper.MenuMapper;
+import com.storlead.system.mapper.SysAppMapper;
+import com.storlead.system.pojo.entity.MenuEntity;
+import com.storlead.system.pojo.entity.SysAppEntity;
+import com.storlead.system.service.SysAppService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 系统应用服务实现
+ */
+@Service
+public class SysAppServiceImpl extends ServiceImpl<SysAppMapper, SysAppEntity> implements SysAppService {
+
+    @Resource
+    private MenuMapper menuMapper;
+
+    @Override
+    public List<SysAppEntity> listEnabled() {
+        return list(new LambdaQueryWrapper<SysAppEntity>()
+                .eq(SysAppEntity::getIsDelete, 0)
+                .eq(SysAppEntity::getEnabled, 1)
+                .orderByAsc(SysAppEntity::getSort)
+                .orderByAsc(SysAppEntity::getId));
+    }
+
+    @Override
+    public boolean trySoftDelete(Long id) {
+        if (id == null) {
+            return false;
+        }
+        long menuCnt = menuMapper.selectCount(
+                new LambdaQueryWrapper<MenuEntity>().eq(MenuEntity::getAppId, id));
+        if (menuCnt > 0) {
+            return false;
+        }
+        LambdaUpdateWrapper<SysAppEntity> uw = new LambdaUpdateWrapper<>();
+        uw.set(SysAppEntity::getIsDelete, 1).eq(SysAppEntity::getId, id).eq(SysAppEntity::getIsDelete, 0);
+        return update(uw);
+    }
+}

+ 3 - 0
java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/dto/MenuParamDTO.java

@@ -13,4 +13,7 @@ import lombok.Data;
 public class MenuParamDTO {
     @ApiModelProperty(value = "所属服务类型: 0:PC,1:移动")
     private String serviceModeType;
+
+    @ApiModelProperty(value = "所属服务: 0:主应用,10:智能贸易,20:销售,30:otr,40:工资,50:项目,60:领存平台")
+    private String appId;
 }

+ 29 - 0
java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/dto/SysAppPageDTO.java

@@ -0,0 +1,29 @@
+package com.storlead.system.pojo.dto;
+
+import com.storlead.framework.mybatis.page.Page;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * 系统应用分页查询参数
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "SysAppPageDTO", description = "系统应用分页查询")
+public class SysAppPageDTO extends Page {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "应用编码(模糊)")
+    private String appCode;
+
+    @ApiModelProperty(value = "应用名称(模糊)")
+    private String appName;
+
+    @ApiModelProperty(value = "是否启用:1 启用,0 禁用,不传不过滤")
+    private Integer enabled;
+}

+ 70 - 0
java/storlead-system/storlead-system-core/src/main/java/com/storlead/system/pojo/entity/SysAppEntity.java

@@ -0,0 +1,70 @@
+package com.storlead.system.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 系统应用(sys_app),与 menu.app_id 对应。
+ */
+@Data
+@Accessors(chain = true)
+@TableName("sys_app")
+@ApiModel(value = "SysAppEntity", description = "系统应用")
+public class SysAppEntity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    @ApiModelProperty(value = "主键,对应 menu.app_id")
+    private Long id;
+
+    @ApiModelProperty(value = "应用编码,全局唯一")
+    private String appCode;
+
+    @ApiModelProperty(value = "应用名称")
+    private String appName;
+
+    @ApiModelProperty(value = "图标")
+    private String icon;
+
+    @ApiModelProperty(value = "默认首页路由/入口")
+    private String homePath;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "拥有者")
+    private Long ownerBy;
+
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(value = "更新者")
+    private Long updateBy;
+
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "更新时间")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "是否启用:1 启用,0 禁用")
+    private Integer enabled;
+
+    @ApiModelProperty(value = "是否删除:1 已删除,0 未删除")
+    private Integer isDelete;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+}

+ 22 - 0
java/storlead-system/storlead-system-spi/src/main/java/com/storlead/system/service/SysAppService.java

@@ -0,0 +1,22 @@
+package com.storlead.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.storlead.system.pojo.entity.SysAppEntity;
+
+import java.util.List;
+
+/**
+ * 系统应用服务
+ */
+public interface SysAppService extends IService<SysAppEntity> {
+
+    /**
+     * 未删除且已启用的应用列表,按 sort 升序。
+     */
+    List<SysAppEntity> listEnabled();
+
+    /**
+     * 逻辑删除;若仍存在 menu.app_id 指向该应用,则返回 false。
+     */
+    boolean trySoftDelete(Long id);
+}

+ 3 - 0
java/storlead-user/storlead-user-core/src/main/java/com/storlead/user/pojo/dto/MenuParam.java

@@ -17,4 +17,7 @@ public class MenuParam  extends Page {
     private String serviceModeType;
 
     private Long resourceId;
+
+    @ApiModelProperty(value = "所属服务: 0:主应用,10:智能贸易,20:销售,30:otr,40:工资,50:项目,60:领存平台")
+    private String appId;
 }

+ 6 - 0
pom.xml

@@ -190,6 +190,12 @@
             <version>${revision}</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-message-spi</artifactId>
+            <version>${revision}</version>
+        </dependency>
+
         <dependency>
             <groupId>com.storlead.boot</groupId>
             <artifactId>storlead-message-biz</artifactId>