Kaynağa Gözat

fix(recommend): 恢复被误删的 AiChatController

上一提交 b16c0fe 夹带了 index 中残留的 AiChatController 删除(疑似此前 subagent git add -A 误带),
AiChatController 是 AI 助手核心接口,从基线 1a7760f 完整恢复,编译通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jintao.geng 1 ay önce
ebeveyn
işleme
f44db5d5fe

+ 71 - 0
mango-application/src/main/java/com/mangoo/rating/recommend/app/controller/AiChatController.java

@@ -0,0 +1,71 @@
+package com.mangoo.rating.recommend.app.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.mangoo.rating.recommend.ai.service.AiChatService;
+import com.mangoo.rating.recommend.request.ai.AiChatRequest;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import javax.annotation.Resource;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+
+/** 小程序 AI 会话入口(SSE 流式打字机输出) */
+@Slf4j
+@RestController
+@RequestMapping("/api/ai")
+@RequiredArgsConstructor
+public class AiChatController {
+
+    private final AiChatService aiChatService;
+
+    @Resource(name = "aiChatExecutor")
+    private Executor aiChatExecutor;
+
+    /**
+     * 发起一轮 AI 会话,SSE 流式返回。
+     * 用户身份:主线程取 X-USER-BASE64 原始头,透传给下游工具 Feign 调 ratingApp(由其解析隔离)。
+     */
+    @PostMapping("/chat/stream")
+    public SseEmitter chatStream(@RequestBody AiChatRequest req,
+                                 @RequestHeader(value = "X-USER-BASE64", required = false) String userHeader) {
+        final String sessionId = (req.getSessionId() == null || req.getSessionId().isEmpty())
+            ? UUID.randomUUID().toString().replace("-", "") : req.getSessionId();
+        final String message = req.getMessage();
+        final String header = userHeader;
+
+        SseEmitter emitter = new SseEmitter(600000L); // 10 分钟超时
+        aiChatExecutor.execute(() -> {
+            try {
+                aiChatService.chat(header, sessionId, message, delta -> {
+                    try {
+                        JSONObject d = new JSONObject();
+                        d.put("text", delta);
+                        emitter.send(SseEmitter.event().name("delta").data(d.toJSONString()));
+                    } catch (Exception se) {
+                        throw new RuntimeException(se);
+                    }
+                });
+                JSONObject done = new JSONObject();
+                done.put("sessionId", sessionId);
+                done.put("finishReason", "end_turn");
+                emitter.send(SseEmitter.event().name("done").data(done.toJSONString()));
+                emitter.complete();
+            } catch (Exception e) {
+                log.warn("AI 会话处理失败 sessionId={}", sessionId, e);
+                try {
+                    JSONObject err = new JSONObject();
+                    err.put("code", -1);
+                    err.put("msg", "服务繁忙,请稍后再试");
+                    emitter.send(SseEmitter.event().name("error").data(err.toJSONString()));
+                    emitter.complete();
+                } catch (Exception ignore) {
+                    emitter.completeWithError(e);
+                }
+            }
+        });
+        return emitter;
+    }
+}