Browse Source

公众号推文消息持久化

wangqi49 1 month ago
parent
commit
5041fab9f9
23 changed files with 496 additions and 17 deletions
  1. 6 1
      resources/nacos-yaml/webchat-search-service-dev.yaml
  2. 5 1
      webchat-admin/src/main/java/com/webchat/admin/config/interceptor/ValidatePermissionInterceptor.java
  3. 22 0
      webchat-admin/src/main/java/com/webchat/admin/controller/OfficialArticleController.java
  4. 14 0
      webchat-admin/src/main/java/com/webchat/admin/service/OfficialArticleService.java
  5. 34 0
      webchat-client-chat/src/main/java/com/webchat/client/chat/controller/ArticleController.java
  6. 30 0
      webchat-client-chat/src/main/java/com/webchat/client/chat/service/ArticleService.java
  7. 32 0
      webchat-connect/src/main/java/com/webchat/connect/messagequeue/consumer/service/ArticlePushConsumeService.java
  8. 16 0
      webchat-pgc/src/main/java/com/webchat/pgc/controller/OfficialArticleController.java
  9. 16 1
      webchat-pgc/src/main/java/com/webchat/pgc/messagequeue/consumer/ArticlePushDelayQueueConsumer.java
  10. 4 2
      webchat-pgc/src/main/java/com/webchat/pgc/repository/dao/IArticleDAO.java
  11. 1 1
      webchat-pgc/src/main/java/com/webchat/pgc/service/OfficialArticleService.java
  12. 27 0
      webchat-remote/src/main/java/com/webchat/rmi/pgc/OfficialArticleClient.java
  13. 16 0
      webchat-remote/src/main/java/com/webchat/rmi/search/SearchEngineClient.java
  14. 1 8
      webchat-search/pom.xml
  15. 7 1
      webchat-search/src/main/java/com/webchat/search/WebchatSearchApplication.java
  16. 41 0
      webchat-search/src/main/java/com/webchat/search/controller/SearchClientController.java
  17. 32 0
      webchat-search/src/main/java/com/webchat/search/controller/SearchController.java
  18. 83 0
      webchat-search/src/main/java/com/webchat/search/service/AccountService.java
  19. 36 0
      webchat-search/src/main/java/com/webchat/search/service/ArticleService.java
  20. 15 0
      webchat-search/src/main/java/com/webchat/search/service/es/AbstractWebChatElasticSearchClient.java
  21. 30 0
      webchat-search/src/main/java/com/webchat/search/service/es/WebChatElasticSearchService.java
  22. 25 1
      webchat-ugc/src/main/java/com/webchat/ugc/messaegqueue/service/PersistentMessageService.java
  23. 3 1
      webchat-ugc/src/main/java/com/webchat/ugc/service/AccountService.java

+ 6 - 1
resources/nacos-yaml/webchat-search-service-dev.yaml

@@ -1,3 +1,8 @@
 spring:
   application:
-    name: webchat-search-service
+    name: webchat-search-service
+    # elastic search config
+  elasticsearch:
+    message-index: chat_mess_dev
+    rest:
+      uris: http://8.140.184.12:9200

+ 5 - 1
webchat-admin/src/main/java/com/webchat/admin/config/interceptor/ValidatePermissionInterceptor.java

@@ -21,7 +21,11 @@ public class ValidatePermissionInterceptor implements HandlerInterceptor {
     private AccountRoleService accountRoleService;
 
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
-
+        // 检查 handler 是否为 HandlerMethod 类型
+        if (!(handler instanceof HandlerMethod)) {
+            // 不是 HandlerMethod 类型,可能是静态资源请求,直接放行
+            return true;
+        }
         HandlerMethod handlerMethod = (HandlerMethod) handler;
         // 获取拦截到的方法
         Method method = handlerMethod.getMethod();

+ 22 - 0
webchat-admin/src/main/java/com/webchat/admin/controller/OfficialArticleController.java

@@ -2,16 +2,24 @@ package com.webchat.admin.controller;
 
 
 import com.webchat.admin.service.OfficialArticleService;
+import com.webchat.common.bean.APIPageResponseBean;
 import com.webchat.common.bean.APIResponseBean;
 import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.common.config.annotation.ValidatePermission;
+import com.webchat.common.enums.RoleCodeEnum;
 import com.webchat.common.helper.SessionHelper;
 import com.webchat.domain.vo.request.publicaccount.SaveArticleRequestVO;
+import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
 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 java.util.List;
+
 @RestController
 @RequestMapping("/admin-service/official/article")
 public class OfficialArticleController {
@@ -24,6 +32,7 @@ public class OfficialArticleController {
      *
      * @return
      */
+    @ValidatePermission(role = RoleCodeEnum.ADMIN)
     @PostMapping("/submit")
     public APIResponseBean<Long> submit(@RequestBody SaveArticleRequestVO saveArticleRequest) {
         // TODO 参数校验
@@ -32,4 +41,17 @@ public class OfficialArticleController {
         return APIResponseBeanUtil.success(officialArticleService.submit(saveArticleRequest));
     }
 
+    /**
+     * 文章列表查询接口
+     *
+     * @param pageNo
+     * @param pageSize
+     * @return
+     */
+    @ValidatePermission(role = RoleCodeEnum.ADMIN)
+    @GetMapping("/page")
+    public APIPageResponseBean<ArticleBaseResponseVO> page(@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
+                                                                 @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
+        return officialArticleService.page(pageNo, pageSize);
+    }
 }

+ 14 - 0
webchat-admin/src/main/java/com/webchat/admin/service/OfficialArticleService.java

@@ -1,14 +1,18 @@
 package com.webchat.admin.service;
 
 
+import com.webchat.common.bean.APIPageResponseBean;
 import com.webchat.common.bean.APIResponseBean;
 import com.webchat.common.bean.APIResponseBeanUtil;
 import com.webchat.common.exception.BusinessException;
 import com.webchat.domain.vo.request.publicaccount.SaveArticleRequestVO;
+import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
 import com.webchat.rmi.pgc.OfficialArticleClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 @Service
 public class OfficialArticleService {
 
@@ -25,4 +29,14 @@ public class OfficialArticleService {
         }
         throw new BusinessException("公众号文章提交失败!");
     }
+
+    public APIPageResponseBean<ArticleBaseResponseVO> page(Integer pageNo, Integer pageSize) {
+
+        APIResponseBean<APIPageResponseBean<ArticleBaseResponseVO>> responseBean =
+                officialArticleClient.page(pageNo, pageSize);
+        if (APIResponseBeanUtil.isOk(responseBean)) {
+            return responseBean.getData();
+        }
+        return null;
+    }
 }

+ 34 - 0
webchat-client-chat/src/main/java/com/webchat/client/chat/controller/ArticleController.java

@@ -0,0 +1,34 @@
+package com.webchat.client.chat.controller;
+
+
+import com.webchat.client.chat.service.ArticleService;
+import com.webchat.common.bean.APIResponseBean;
+import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.common.helper.SessionHelper;
+import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/client-service/chat/article")
+public class ArticleController {
+
+
+    @Autowired
+    private ArticleService articleService;
+
+    /**
+     * 文章详情查询
+     *
+     * @param id
+     * @return
+     */
+    @GetMapping("/detail/{id}")
+    public APIResponseBean<ArticleBaseResponseVO> detail(@PathVariable Long id) {
+        String userId = SessionHelper.getCurrentUserId();
+        return APIResponseBeanUtil.success(articleService.detail(id, userId));
+    }
+}

+ 30 - 0
webchat-client-chat/src/main/java/com/webchat/client/chat/service/ArticleService.java

@@ -0,0 +1,30 @@
+package com.webchat.client.chat.service;
+
+import com.webchat.common.bean.APIResponseBean;
+import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
+import com.webchat.rmi.pgc.OfficialArticleClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ArticleService {
+
+
+    @Autowired
+    private OfficialArticleClient officialArticleClient;
+
+    /**
+     * 获取文章详情
+     *
+     * @param id
+     * @return
+     */
+    public ArticleBaseResponseVO detail(Long id, String userId) {
+        APIResponseBean<ArticleBaseResponseVO> responseBean = officialArticleClient.detail(id, true);
+        if (APIResponseBeanUtil.isOk(responseBean)) {
+            return responseBean.getData();
+        }
+        return null;
+    }
+}

+ 32 - 0
webchat-connect/src/main/java/com/webchat/connect/messagequeue/consumer/service/ArticlePushConsumeService.java

@@ -5,10 +5,13 @@ import com.webchat.common.bean.APIResponseBean;
 import com.webchat.common.bean.APIResponseBeanUtil;
 import com.webchat.common.constants.ConnectConstants;
 import com.webchat.common.enums.ChatMessageTypeEnum;
+import com.webchat.common.enums.messagequeue.MessageQueueEnum;
+import com.webchat.common.service.messagequeue.producer.MessageQueueProducer;
 import com.webchat.common.util.JsonUtil;
 import com.webchat.connect.service.AccountService;
 import com.webchat.connect.websocket.handler.ChatWebSocketEndPointServletHandler;
 import com.webchat.domain.dto.queue.ArticleDelayMessageDTO;
+import com.webchat.domain.vo.request.mess.ChatMessageRequestVO;
 import com.webchat.domain.vo.response.mess.ChatMessageResponseVO;
 import com.webchat.domain.vo.response.mess.PublicAccountArticleMessageVO;
 import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
@@ -39,6 +42,9 @@ public class ArticlePushConsumeService {
     @Autowired
     private OfficialArticleClient officialArticleClient;
 
+    @Autowired
+    private MessageQueueProducer<ChatMessageRequestVO, Long> messageQueueProducer;
+
     public void consume(String message) {
 
         /**
@@ -85,7 +91,14 @@ public class ArticlePushConsumeService {
                 chatMessageResponseVO.setSenderId(publicAccount);
                 chatMessageResponseVO.setType(ChatMessageTypeEnum.PUBLIC_ACCOUNT_ARTICLE.getType());
                 try {
+                    /**
+                     * 公众号文章推送
+                     */
                     wsSession.sendMessage(new TextMessage(JsonUtil.toJsonString(chatMessageResponseVO)));
+                    /**
+                     *  推送数据持久化
+                     */
+                    this.persistentArticlePushMessage(publicAccount, userId, articleId);
                 } catch (IOException e) {
                     // 不能抛异常出去,不能阻塞其他用户的推送
                     log.error("公众号文章推送异常 =====> publicAccount:{}, userId:{}, articleId:{}",
@@ -96,6 +109,25 @@ public class ArticlePushConsumeService {
         }
     }
 
+
+    /**
+     * 公众号推送消息持久化
+     *
+     */
+    private void persistentArticlePushMessage(String officialAccount, String userId, Long articleId) {
+
+        ChatMessageRequestVO persistentMessage = new ChatMessageRequestVO();
+        persistentMessage.setType(ChatMessageTypeEnum.PUBLIC_ACCOUNT_ARTICLE.getType());
+        persistentMessage.setSenderId(officialAccount);
+        persistentMessage.setReceiverId(userId);
+        persistentMessage.setMessage(String.valueOf(articleId));
+        /**
+         * 走统一的消息持久化处理服务(服用了对话场景持久化服务)
+         *
+         */
+        messageQueueProducer.send(MessageQueueEnum.QUEUE_PERSISTENT_MESSAGE, persistentMessage);
+    }
+
     /**
      * 获取文章详情,这里不需要返回正文(降低相应网络传输包大小,节约流量成本,提高接口性能)
      *

+ 16 - 0
webchat-pgc/src/main/java/com/webchat/pgc/controller/OfficialArticleController.java

@@ -1,5 +1,6 @@
 package com.webchat.pgc.controller;
 
+import com.webchat.common.bean.APIPageResponseBean;
 import com.webchat.common.bean.APIResponseBean;
 import com.webchat.common.bean.APIResponseBeanUtil;
 import com.webchat.domain.vo.request.publicaccount.SaveArticleRequestVO;
@@ -11,6 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+import java.util.Map;
+
 @RestController
 public class OfficialArticleController implements OfficialArticleClient {
 
@@ -31,4 +35,16 @@ public class OfficialArticleController implements OfficialArticleClient {
                 officialArticleService.getArticleDetailFromCache(id, ObjectUtils.equals(isNeedContent, true));
         return APIResponseBeanUtil.success(articleVo);
     }
+
+    @Override
+    public APIResponseBean<APIPageResponseBean<ArticleBaseResponseVO>> page(Integer pageNo, Integer pageSize) {
+
+        return APIResponseBeanUtil.success(officialArticleService.page(pageNo, pageSize));
+    }
+
+    @Override
+    public APIResponseBean<Map<Long, ArticleBaseResponseVO>> batchGet(@RequestBody List<Long> articleIds) {
+
+        return APIResponseBeanUtil.success(officialArticleService.batchGetArticleDetailFromCache(articleIds));
+    }
 }

+ 16 - 1
webchat-pgc/src/main/java/com/webchat/pgc/messagequeue/consumer/ArticlePushDelayQueueConsumer.java

@@ -6,10 +6,12 @@ import com.webchat.common.service.messagequeue.consumer.AbstractRedisDelayQueueC
 import com.webchat.common.service.messagequeue.producer.MessageQueueProducer;
 import com.webchat.common.util.JsonUtil;
 import com.webchat.domain.dto.queue.ArticleDelayMessageDTO;
+import com.webchat.pgc.repository.dao.IArticleDAO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * 公众号推送MQ消费
@@ -20,6 +22,9 @@ public class ArticlePushDelayQueueConsumer extends AbstractRedisDelayQueueConsum
     @Autowired
     private MessageQueueProducer<Set<String>, Long> messageQueueProducer;
 
+    @Autowired
+    private IArticleDAO articleDAO;
+
     @Override
     protected ArticleDelayMessageDTO convert(String s) {
 
@@ -36,8 +41,18 @@ public class ArticlePushDelayQueueConsumer extends AbstractRedisDelayQueueConsum
     protected void doNextConsume(Set<String> messages) {
 
         /**
-         * 广播通知connect service完成推文、以及消息持久化,批量提交任务到普通队列
+         * 1. 广播通知connect service完成推文、以及消息持久化,批量提交任务到普通队列
          */
         messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_ARTICLE_PUSH_MESSAGE, messages);
+        /**
+         * 2. 更新文章已经推送状态
+         */
+        Set<ArticleDelayMessageDTO> articleDelayMessages = messages.stream().map(this::convert).collect(Collectors.toSet());
+        Set<Long> articleIds = articleDelayMessages.stream()
+                .map(ArticleDelayMessageDTO::getArticleId).collect(Collectors.toSet());
+        articleDAO.updatePushedStatus(articleIds);
+        /**
+         * 3. 持久化消息: 由connect服务来完成,在推送成功之后
+         */
     }
 }

+ 4 - 2
webchat-pgc/src/main/java/com/webchat/pgc/repository/dao/IArticleDAO.java

@@ -8,6 +8,8 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Collection;
+
 
 @Repository
 public interface IArticleDAO extends JpaSpecificationExecutor<ArticleEntity>,
@@ -16,7 +18,7 @@ public interface IArticleDAO extends JpaSpecificationExecutor<ArticleEntity>,
 
     @Transactional
     @Modifying
-    @Query(value = "update ArticleEntity a set a.status = 2 where a.id = :id")
-    int updatePushedStatus(Long id);
+    @Query(value = "update ArticleEntity a set a.status = 2 where a.id in :ids")
+    int updatePushedStatus(Collection<Long> ids);
 
 }

+ 1 - 1
webchat-pgc/src/main/java/com/webchat/pgc/service/OfficialArticleService.java

@@ -265,7 +265,7 @@ public class OfficialArticleService {
      * @param pageSize
      * @return
      */
-    public APIPageResponseBean<List<ArticleBaseResponseVO>> page(Integer pageNo, Integer pageSize) {
+    public APIPageResponseBean<ArticleBaseResponseVO> page(Integer pageNo, Integer pageSize) {
         Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "id"));
         Page<ArticleEntity> userEntities = articleDAO.findAll(pageable);
         List<ArticleBaseResponseVO> articles = new ArrayList<>();

+ 27 - 0
webchat-remote/src/main/java/com/webchat/rmi/pgc/OfficialArticleClient.java

@@ -1,5 +1,6 @@
 package com.webchat.rmi.pgc;
 
+import com.webchat.common.bean.APIPageResponseBean;
 import com.webchat.common.bean.APIResponseBean;
 import com.webchat.domain.vo.request.publicaccount.SaveArticleRequestVO;
 import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
@@ -10,6 +11,10 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.util.List;
+import java.util.Map;
+
+
 @FeignClient(name = "webchat-pgc-service")
 public interface OfficialArticleClient {
 
@@ -32,4 +37,26 @@ public interface OfficialArticleClient {
     APIResponseBean<ArticleBaseResponseVO> detail(@PathVariable Long id,
                                                   @RequestParam(name = "isNeedContent", required = false,
                                                           defaultValue = "false") Boolean isNeedContent);
+
+    /**
+     * 查询文章列表
+     *
+     * @param pageNo
+     * @param pageSize
+     * @return
+     */
+    @GetMapping("/pgc-service/official/article/page")
+    APIResponseBean<APIPageResponseBean<ArticleBaseResponseVO>> page(
+            @RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
+            @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize);
+
+    /**
+     * 批量查询redis,获取文章详情缓存
+     *
+     * 场景:公众号详情页,一次可能查询10篇文章
+     * @param articleIds
+     * @return
+     */
+    @GetMapping("/pgc-service/official/article/batchGet")
+    APIResponseBean<Map<Long, ArticleBaseResponseVO>> batchGet(@RequestBody List<Long> articleIds);
 }

+ 16 - 0
webchat-remote/src/main/java/com/webchat/rmi/search/SearchEngineClient.java

@@ -0,0 +1,16 @@
+package com.webchat.rmi.search;
+
+import com.webchat.common.bean.APIPageResponseBean;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(name = "webchat-search-service")
+public interface SearchEngineClient {
+
+    @GetMapping("/search-service/content/query")
+    APIPageResponseBean query(@RequestParam(value = "q", required = false) String query,
+                              @RequestParam(value = "type", required = false) Integer type,
+                              @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
+                              @RequestParam(value = "size", required = false, defaultValue = "10") Integer size);
+}

+ 1 - 8
webchat-search/pom.xml

@@ -29,16 +29,9 @@
             <version>1.0-SNAPSHOT</version>
         </dependency>
 
-        <!--引入mysql驱动-->
-        <dependency>
-            <groupId>mysql</groupId>
-            <artifactId>mysql-connector-java</artifactId>
-            <version>5.1.46</version>
-        </dependency>
-        <!--使用JPA作为ORM框架 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
         </dependency>
 
         <dependency>

+ 7 - 1
webchat-search/src/main/java/com/webchat/search/WebchatSearchApplication.java

@@ -3,8 +3,14 @@ package com.webchat.search;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.ComponentScan;
 
-@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
+@SpringBootApplication
+@EnableDiscoveryClient
+@ComponentScan("com.webchat")
+@EnableFeignClients("com.webchat.rmi")
 public class WebchatSearchApplication {
 
     public static void main(String[] args) {

+ 41 - 0
webchat-search/src/main/java/com/webchat/search/controller/SearchClientController.java

@@ -0,0 +1,41 @@
+package com.webchat.search.controller;
+
+
+import com.webchat.common.bean.APIPageResponseBean;
+import com.webchat.common.enums.ESMessageTypeEum;
+import com.webchat.common.helper.SessionHelper;
+import com.webchat.rmi.search.SearchEngineClient;
+import com.webchat.search.service.es.WebChatElasticSearchService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@RestController
+@RequestMapping("/api/search")
+public class SearchClientController implements SearchEngineClient {
+
+    @Autowired
+    private WebChatElasticSearchService webChatElasticSearchService;
+
+    /**
+     * 聊天消息搜索
+     *
+     * @param query 关键词
+     * @param type  搜索内容:空代表聚合搜索,搜全部;可以置顶具体的消息类型(聊天、公众号文章、用户)
+     * @see ESMessageTypeEum
+     *
+     * @param size
+     * @return
+     */
+    @GetMapping("/query")
+    public APIPageResponseBean query(@RequestParam(value = "q", required = false) String query,
+                                     @RequestParam(value = "type", required = false) Integer type,
+                                     @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
+                                     @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
+        String userId = SessionHelper.getCurrentUserId();
+        return webChatElasticSearchService.query(type, userId, query, page, size);
+    }
+}

+ 32 - 0
webchat-search/src/main/java/com/webchat/search/controller/SearchController.java

@@ -0,0 +1,32 @@
+package com.webchat.search.controller;
+
+
+import com.webchat.common.bean.APIResponseBean;
+import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.search.service.es.WebChatElasticSearchService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@RestController
+@RequestMapping("/api/search")
+public class SearchController {
+
+    @Autowired
+    private WebChatElasticSearchService webChatElasticSearchService;
+
+
+    @GetMapping("/createIndex")
+    public APIResponseBean<Boolean> createChatMessageIndex() {
+        boolean createIndexResult = webChatElasticSearchService.createIndex();
+        return APIResponseBeanUtil.success(createIndexResult);
+    }
+
+    @GetMapping("/deleteIndex")
+    public APIResponseBean<Boolean> deleteIndex() {
+        boolean createIndexResult = webChatElasticSearchService.deleteIndex();
+        return APIResponseBeanUtil.success(createIndexResult);
+    }
+}

+ 83 - 0
webchat-search/src/main/java/com/webchat/search/service/AccountService.java

@@ -0,0 +1,83 @@
+package com.webchat.search.service;
+
+import com.webchat.common.bean.APIResponseBean;
+import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.common.enums.AccountRelationTypeEnum;
+import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
+import com.webchat.rmi.user.UserServiceClient;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Service
+public class AccountService {
+
+    @Autowired
+    private UserServiceClient userServiceClient;
+
+    /**
+     * 查询当前账号信息
+     *
+     * @param account
+     * @return
+     */
+
+    public UserBaseResponseInfoVO accountInfo(String account) {
+
+        APIResponseBean<UserBaseResponseInfoVO> responseBean = userServiceClient.userInfo(account);
+        if (APIResponseBeanUtil.isOk(responseBean)) {
+            return responseBean.getData();
+        }
+        return null;
+    }
+
+    /**
+     *  批量查询账号详情数据
+     *
+     * @param accounts
+     * @return
+     */
+    public List<UserBaseResponseInfoVO> batchGet(List<String> accounts) {
+        if (CollectionUtils.isEmpty(accounts)) {
+            return Collections.emptyList();
+        }
+        APIResponseBean<List<UserBaseResponseInfoVO>> responseBean =
+                userServiceClient.batchGet(accounts);
+        if (APIResponseBeanUtil.isOk(responseBean)) {
+            return responseBean.getData();
+        }
+        throw new RuntimeException(responseBean.getMsg());
+    }
+
+    public Map<String, UserBaseResponseInfoVO> batchGet(Set<String> accounts) {
+        if (CollectionUtils.isEmpty(accounts)) {
+            return Collections.emptyMap();
+        }
+        APIResponseBean<Map<String, UserBaseResponseInfoVO>> responseBean =
+                userServiceClient.batchGet(accounts);
+        if (APIResponseBeanUtil.isOk(responseBean)) {
+            return responseBean.getData();
+        }
+        throw new RuntimeException(responseBean.getMsg());
+    }
+
+    /**
+     * 获取群组下的群成员用户id集合
+     *
+     * @param groupAccount
+     * @return
+     */
+    public Set<String> getGroupUserIds(String groupAccount) {
+        APIResponseBean<Set<String>> responseBean = userServiceClient.getAllSubscriberByAccount(
+                AccountRelationTypeEnum.USER_GROUP.getType(), groupAccount);
+        if (APIResponseBeanUtil.isOk(responseBean)) {
+            return responseBean.getData();
+        }
+        return null;
+    }
+}

+ 36 - 0
webchat-search/src/main/java/com/webchat/search/service/ArticleService.java

@@ -0,0 +1,36 @@
+package com.webchat.search.service;
+
+import com.webchat.common.bean.APIResponseBean;
+import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
+import com.webchat.rmi.pgc.OfficialArticleClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+
+@Service
+public class ArticleService {
+
+
+    @Autowired
+    private OfficialArticleClient officialArticleClient;
+
+    /**
+     * 批量查询redis,获取文章详情缓存
+     *
+     * 场景:公众号详情页,一次可能查询10篇文章
+     * @param articleIds
+     * @return
+     */
+    public Map<Long, ArticleBaseResponseVO> batchGet(List<Long> articleIds) {
+        APIResponseBean<Map<Long, ArticleBaseResponseVO>> responseBean = officialArticleClient.batchGet(articleIds);
+        if (APIResponseBeanUtil.isOk(responseBean)) {
+            return responseBean.getData();
+        }
+        return null;
+    }
+
+}

+ 15 - 0
webchat-search/src/main/java/com/webchat/search/service/es/AbstractWebChatElasticSearchClient.java

@@ -0,0 +1,15 @@
+package com.webchat.search.service.es;
+
+
+import com.webchat.domain.vo.dto.AbstractBaseEsDTO;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * webchat 抽象ES操作服务,不同搜索业务场景自己继承实现
+ */
+@Slf4j
+public abstract class AbstractWebChatElasticSearchClient<T extends AbstractBaseEsDTO> {
+
+
+
+}

+ 30 - 0
webchat-search/src/main/java/com/webchat/search/service/es/WebChatElasticSearchService.java

@@ -0,0 +1,30 @@
+package com.webchat.search.service.es;
+
+import com.webchat.domain.vo.dto.ChatMessageSearchResultDTO;
+import com.webchat.search.service.AccountService;
+import com.webchat.search.service.ArticleService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * 业务数据数据同步ES
+ *
+ * 一对一聊天消息、群聊消息、机器人对话消息、公众号文章推文消息、群组、人、公众号
+ */
+@Slf4j
+@Service
+public class WebChatElasticSearchService extends AbstractWebChatElasticSearchClient<ChatMessageSearchResultDTO> {
+
+    @Value("${spring.elasticsearch.message-index}")
+    private String chatMessageIndex;
+
+    @Autowired
+    private AccountService accountService;
+    @Autowired
+    private ArticleService articleService;
+
+
+}

+ 25 - 1
webchat-ugc/src/main/java/com/webchat/ugc/messaegqueue/service/PersistentMessageService.java

@@ -2,6 +2,8 @@ package com.webchat.ugc.messaegqueue.service;
 
 
 import com.webchat.common.bean.APIPageResponseBean;
+import com.webchat.common.bean.APIResponseBean;
+import com.webchat.common.bean.APIResponseBeanUtil;
 import com.webchat.common.enums.ChatMessageTypeEnum;
 import com.webchat.common.enums.RedisKeyEnum;
 import com.webchat.common.enums.RoleCodeEnum;
@@ -14,12 +16,16 @@ import com.webchat.common.util.JsonUtil;
 import com.webchat.domain.vo.request.mess.ChatMessageRequestVO;
 import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
 import com.webchat.domain.vo.response.mess.ChatMessageResponseVO;
+import com.webchat.domain.vo.response.mess.PublicAccountArticleMessageVO;
+import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
+import com.webchat.rmi.pgc.OfficialArticleClient;
 import com.webchat.ugc.repository.dao.IChatMessageDAO;
 import com.webchat.ugc.repository.entity.ChatMessageEntity;
 import com.webchat.ugc.service.AccountService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -55,6 +61,9 @@ public class PersistentMessageService {
     @Autowired
     private MessageQueueProducer<Object, Long> messageQueueProducer;
 
+    @Autowired
+    private OfficialArticleClient officialArticleClient;
+
     /**
      * 《离线场景》持久化消息队列,保存离线消息,同时会将数据同步到ES用于后续的RAG问答和消息搜索
      *
@@ -289,12 +298,27 @@ public class PersistentMessageService {
         if (ChatMessageTypeEnum.RED_PACKET.getType().equals(userMessEntity.getType())) {
 //            messageResponse.setRedPacketDetail(redPacketService.getRedPacketDetailCache(Long.valueOf(userMessEntity.getMessage())));
         } else if (ChatMessageTypeEnum.PUBLIC_ACCOUNT_ARTICLE.getType().equals(userMessEntity.getType())) {
-//            messageResponse.setPublicAccountArticle(articleService.getPublicAccountArticleMessage(Long.valueOf(userMessEntity.getMessage())));
+            messageResponse.setPublicAccountArticle(getArticleMessageVO(Long.valueOf(userMessEntity.getMessage())));
         }
         messageResponse.setGroupMessage(StringUtils.isNotBlank(userMessEntity.getProxySender()));
         return messageResponse;
     }
 
+    private PublicAccountArticleMessageVO getArticleMessageVO(Long articleId) {
+        APIResponseBean<ArticleBaseResponseVO> responseBean = officialArticleClient.detail(articleId, false);
+        if (!APIResponseBeanUtil.isOk(responseBean)) {
+            return null;
+        }
+        ArticleBaseResponseVO articleBaseResponseVO = responseBean.getData();
+        if (articleBaseResponseVO == null) {
+            return null;
+        }
+        PublicAccountArticleMessageVO articleMessageVO = new PublicAccountArticleMessageVO();
+        BeanUtils.copyProperties(articleBaseResponseVO, articleMessageVO);
+        articleMessageVO.setArticleId(articleBaseResponseVO.getId());
+        return articleMessageVO;
+    }
+
     public String getUserMessRedisKey(String sender, String receiver) {
         return RedisKeyEnum.USER_CHAT_MESS_CACHE_KEY.getKey(sender, receiver);
     }

+ 3 - 1
webchat-ugc/src/main/java/com/webchat/ugc/service/AccountService.java

@@ -2,6 +2,7 @@ package com.webchat.ugc.service;
 
 import com.webchat.common.bean.APIResponseBean;
 import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.common.enums.AccountRelationTypeEnum;
 import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
 import com.webchat.rmi.user.UserServiceClient;
 import org.apache.commons.collections.CollectionUtils;
@@ -72,7 +73,8 @@ public class AccountService {
      * @return
      */
     public Set<String> getGroupUserIds(String groupAccount) {
-        APIResponseBean<Set<String>> responseBean = userServiceClient.getGroupUserIds(groupAccount);
+        APIResponseBean<Set<String>> responseBean = userServiceClient.getAllSubscriberByAccount(
+                AccountRelationTypeEnum.USER_GROUP.getType(), groupAccount);
         if (APIResponseBeanUtil.isOk(responseBean)) {
             return responseBean.getData();
         }