From 33a883b0d7edbf633dcf142d2e3c5bf2e334b121 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Mon, 25 Aug 2025 16:10:09 +0800
Subject: [PATCH] feat(ai): 添加 AI 灵通相关功能
---
src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkVo.java | 19 +++
src/main/java/cc/mrbird/febs/ai/entity/AiTalk.java | 5
src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkItemServiceImpl.java | 28 ++++
src/main/java/cc/mrbird/febs/ai/controller/talk/ApiAiTalkController.java | 68 +++++++++++
src/main/java/cc/mrbird/febs/ai/mapper/AiTalkMapper.java | 7 +
src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkPageDto.java | 26 ++++
src/main/resources/mapper/modules/AiTalkMapper.xml | 12 ++
src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkPageVo.java | 26 ++++
src/main/java/cc/mrbird/febs/ai/entity/AiTalkItem.java | 2
src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkServiceImpl.java | 83 +++++++++++++
src/main/java/cc/mrbird/febs/ai/service/AiTalkItemService.java | 11 +
src/main/java/cc/mrbird/febs/ai/service/AiTalkService.java | 21 +++
src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkDto.java | 27 ++++
src/main/java/cc/mrbird/febs/ai/enumerates/AiTypeEnum.java | 7 +
14 files changed, 341 insertions(+), 1 deletions(-)
diff --git a/src/main/java/cc/mrbird/febs/ai/controller/talk/ApiAiTalkController.java b/src/main/java/cc/mrbird/febs/ai/controller/talk/ApiAiTalkController.java
new file mode 100644
index 0000000..a8d47bd
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/controller/talk/ApiAiTalkController.java
@@ -0,0 +1,68 @@
+package cc.mrbird.febs.ai.controller.talk;
+
+import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkAnswerDto;
+import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkDto;
+import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
+import cc.mrbird.febs.ai.req.talk.ApiTalkDto;
+import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto;
+import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo;
+import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkStreamVo;
+import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkVo;
+import cc.mrbird.febs.ai.res.talk.ApiTalkPageVo;
+import cc.mrbird.febs.ai.res.talk.ApiTalkVo;
+import cc.mrbird.febs.ai.service.AiMemberTalkService;
+import cc.mrbird.febs.ai.service.AiTalkService;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+import reactor.core.publisher.Flux;
+
+import java.io.IOException;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/api/ai/talk")
+@Api(value = "ApiAiTalkController", tags = "AI-灵通")
+public class ApiAiTalkController {
+
+ private final AiTalkService aiTalkService;
+
+ @ApiOperation(value = "用户AI问答", notes = "用户AI问答")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "success", response = ApiTalkVo.class)
+ })
+ @PostMapping(value = "/talkOpen")
+ public FebsResponse talkOpen(@RequestBody @Validated ApiTalkDto dto) {
+
+ return aiTalkService.talkOpen(dto);
+ }
+
+ @ApiOperation(value = "用户AI问答记录分页查询", notes = "用户AI问答记录分页查询")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "success", response = ApiTalkPageVo.class)
+ })
+ @PostMapping(value = "/talkList")
+ public FebsResponse talkList(@RequestBody @Validated ApiTalkPageDto dto) {
+
+ return aiTalkService.talkList(dto);
+ }
+
+ @ApiOperation("提问AI(流式)")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "流式响应", response = ApiMemberTalkStreamVo.class),
+ })
+ @GetMapping("/answer-stream")
+ public Flux<FebsResponse> answerStream(@RequestParam String question) {
+
+ return aiTalkService.answerStream(question);
+ }
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/entity/AiTalk.java b/src/main/java/cc/mrbird/febs/ai/entity/AiTalk.java
index c804e18..b324bb2 100644
--- a/src/main/java/cc/mrbird/febs/ai/entity/AiTalk.java
+++ b/src/main/java/cc/mrbird/febs/ai/entity/AiTalk.java
@@ -19,6 +19,11 @@
private String companyId;
/**
+ * 主要问题
+ */
+ private String question;
+
+ /**
* 用户ID (UUID)
*/
private String memberId;
diff --git a/src/main/java/cc/mrbird/febs/ai/entity/AiTalkItem.java b/src/main/java/cc/mrbird/febs/ai/entity/AiTalkItem.java
index 15e95d3..8526911 100644
--- a/src/main/java/cc/mrbird/febs/ai/entity/AiTalkItem.java
+++ b/src/main/java/cc/mrbird/febs/ai/entity/AiTalkItem.java
@@ -25,7 +25,7 @@
/**
* 用户对话ID (UUID)
*/
- private String memberTalkId;
+ private String talkId;
/**
* 类型 1-用户提问 2-AI回答
diff --git a/src/main/java/cc/mrbird/febs/ai/enumerates/AiTypeEnum.java b/src/main/java/cc/mrbird/febs/ai/enumerates/AiTypeEnum.java
index d66f6b0..18ae5fd 100644
--- a/src/main/java/cc/mrbird/febs/ai/enumerates/AiTypeEnum.java
+++ b/src/main/java/cc/mrbird/febs/ai/enumerates/AiTypeEnum.java
@@ -10,6 +10,13 @@
public enum AiTypeEnum {
/**
+ * 1:用户提问
+ * 2:AI回答
+ */
+ MEMBER_QUESTION(1,"用户提问"),
+ AI_ANSWER(2,"AI回答"),
+
+ /**
* 1:AI提问
* 2:用户回答
* 3:生成答案解析
diff --git a/src/main/java/cc/mrbird/febs/ai/mapper/AiTalkMapper.java b/src/main/java/cc/mrbird/febs/ai/mapper/AiTalkMapper.java
index 9196dcf..c6d1872 100644
--- a/src/main/java/cc/mrbird/febs/ai/mapper/AiTalkMapper.java
+++ b/src/main/java/cc/mrbird/febs/ai/mapper/AiTalkMapper.java
@@ -1,7 +1,14 @@
package cc.mrbird.febs.ai.mapper;
import cc.mrbird.febs.ai.entity.AiTalk;
+import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto;
+import cc.mrbird.febs.ai.res.talk.ApiTalkPageVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
public interface AiTalkMapper extends BaseMapper<AiTalk> {
+
+ Page<ApiTalkPageVo> getPageTalkListByQuery(Page<ApiTalkPageVo> page, @Param("record")ApiTalkPageDto dto);
+
}
diff --git a/src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkDto.java b/src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkDto.java
new file mode 100644
index 0000000..f5f200e
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkDto.java
@@ -0,0 +1,27 @@
+package cc.mrbird.febs.ai.req.talk;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Administrator
+ */
+@Data
+@ApiModel(value = "ApiTalkDto", description = "参数")
+public class ApiTalkDto {
+
+ @NotBlank(message = "内容不能为空")
+ @ApiModelProperty(value = "内容", example = "10")
+ private String context;
+
+ @NotNull(message = "类型不能为空")
+ @ApiModelProperty(value = "类型 1-用户提问 2-AI回答", example = "10")
+ private Integer type;
+
+ @ApiModelProperty(value = "会话ID", example = "10")
+ private String talkId;
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkPageDto.java b/src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkPageDto.java
new file mode 100644
index 0000000..e47db90
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkPageDto.java
@@ -0,0 +1,26 @@
+package cc.mrbird.febs.ai.req.talk;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Administrator
+ */
+@Data
+@ApiModel(value = "ApiTalkPageDto", description = "参数")
+public class ApiTalkPageDto {
+
+ @NotNull(message = "页码不能为空")
+ @ApiModelProperty(value = "页码", example = "1")
+ private Integer pageNow;
+
+ @NotNull(message = "每页数量不能为空")
+ @ApiModelProperty(value = "每页数量", example = "10")
+ private Integer pageSize;
+
+ @ApiModelProperty(hidden = true)
+ private String memberUuid;
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkPageVo.java b/src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkPageVo.java
new file mode 100644
index 0000000..5526373
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkPageVo.java
@@ -0,0 +1,26 @@
+package cc.mrbird.febs.ai.res.talk;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author Administrator
+ */
+@Data
+@ApiModel(value = "ApiTalkPageVo", description = "参数")
+public class ApiTalkPageVo {
+
+ @ApiModelProperty(value = "会话ID")
+ private String talkId;
+
+ @ApiModelProperty(value = "题目")
+ private String question;
+
+ @ApiModelProperty(value = "时间")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date createdTime;
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkVo.java b/src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkVo.java
new file mode 100644
index 0000000..22d61aa
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkVo.java
@@ -0,0 +1,19 @@
+package cc.mrbird.febs.ai.res.talk;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author Administrator
+ */
+@Data
+@ApiModel(value = "ApiTalkVo", description = "参数")
+public class ApiTalkVo {
+
+ /**
+ * 视频号 id,以"sph"开头的id,可在视频号助手获取
+ */
+ @ApiModelProperty(value = "会话ID")
+ private String talkId;
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/service/AiTalkItemService.java b/src/main/java/cc/mrbird/febs/ai/service/AiTalkItemService.java
new file mode 100644
index 0000000..229f2b6
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/service/AiTalkItemService.java
@@ -0,0 +1,11 @@
+package cc.mrbird.febs.ai.service;
+
+import cc.mrbird.febs.ai.entity.AiTalkItem;
+import cn.hutool.core.date.DateTime;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+public interface AiTalkItemService extends IService<AiTalkItem> {
+
+ void add(String id, int code, String context, String memberUuid, DateTime date);
+
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/service/AiTalkService.java b/src/main/java/cc/mrbird/febs/ai/service/AiTalkService.java
new file mode 100644
index 0000000..d89047d
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/service/AiTalkService.java
@@ -0,0 +1,21 @@
+package cc.mrbird.febs.ai.service;
+
+import cc.mrbird.febs.ai.entity.AiTalk;
+import cc.mrbird.febs.ai.req.talk.ApiTalkDto;
+import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import com.baomidou.mybatisplus.extension.service.IService;
+import reactor.core.publisher.Flux;
+
+import java.util.Date;
+
+public interface AiTalkService extends IService<AiTalk> {
+
+ FebsResponse talkOpen(ApiTalkDto dto);
+
+ AiTalk add(String memberUuid, String question, Date date);
+
+ Flux<FebsResponse> answerStream(String question);
+
+ FebsResponse talkList(ApiTalkPageDto dto);
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkItemServiceImpl.java b/src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkItemServiceImpl.java
new file mode 100644
index 0000000..7a4a121
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkItemServiceImpl.java
@@ -0,0 +1,28 @@
+package cc.mrbird.febs.ai.service.impl;
+
+import cc.mrbird.febs.ai.entity.AiTalkItem;
+import cc.mrbird.febs.ai.mapper.AiTalkItemMapper;
+import cc.mrbird.febs.ai.service.AiTalkItemService;
+import cc.mrbird.febs.ai.utils.UUID;
+import cn.hutool.core.date.DateTime;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class AiTalkItemServiceImpl extends ServiceImpl<AiTalkItemMapper, AiTalkItem> implements AiTalkItemService {
+ @Override
+ public void add(String id, int code, String context, String memberUuid, DateTime date) {
+ AiTalkItem aiTalkItem = new AiTalkItem();
+ aiTalkItem.setId(UUID.getSimpleUUIDString());
+ aiTalkItem.setMemberId(memberUuid);
+ aiTalkItem.setType(code);
+ aiTalkItem.setTalkId(id);
+ aiTalkItem.setCreatedTime(date);
+ aiTalkItem.setContext(context);
+ this.baseMapper.insert(aiTalkItem);
+ }
+}
diff --git a/src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkServiceImpl.java b/src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkServiceImpl.java
new file mode 100644
index 0000000..9410135
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkServiceImpl.java
@@ -0,0 +1,83 @@
+package cc.mrbird.febs.ai.service.impl;
+
+import cc.mrbird.febs.ai.entity.AiTalk;
+import cc.mrbird.febs.ai.mapper.AiTalkMapper;
+import cc.mrbird.febs.ai.req.talk.ApiTalkDto;
+import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto;
+import cc.mrbird.febs.ai.res.memberAnswer.ApiMemberProductWorkVo;
+import cc.mrbird.febs.ai.res.talk.ApiTalkPageVo;
+import cc.mrbird.febs.ai.res.talk.ApiTalkVo;
+import cc.mrbird.febs.ai.service.AiService;
+import cc.mrbird.febs.ai.service.AiTalkItemService;
+import cc.mrbird.febs.ai.service.AiTalkService;
+import cc.mrbird.febs.ai.utils.UUID;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.common.utils.LoginUserUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Flux;
+
+import java.util.Date;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class AiTalkServiceImpl extends ServiceImpl<AiTalkMapper, AiTalk> implements AiTalkService {
+
+ private final AiTalkItemService aiTalkItemService;
+ private final AiService aiService;
+ @Override
+ public FebsResponse talkOpen(ApiTalkDto dto) {
+ String talkId = dto.getTalkId();
+ String context = dto.getContext();
+ Integer type = dto.getType();
+ String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
+
+ AiTalk aiTalk = this.getById(talkId);
+ DateTime date = DateUtil.date();
+ if (StrUtil.isEmpty(talkId)){
+ aiTalk = this.add(memberUuid,context, date);
+ }
+
+ aiTalkItemService.add(aiTalk.getId(), type, context, memberUuid, date);
+
+ ApiTalkVo apiTalkVo = new ApiTalkVo();
+ apiTalkVo.setTalkId(aiTalk.getId());
+ return new FebsResponse().success().data(apiTalkVo);
+ }
+
+ @Override
+ public AiTalk add(String memberUuid, String question, Date date) {
+ AiTalk aiTalk = new AiTalk();
+ aiTalk.setId(UUID.getSimpleUUIDString());
+ aiTalk.setQuestion(question);
+ aiTalk.setCreatedTime(date);
+ aiTalk.setMemberId(memberUuid);
+ this.baseMapper.insert(aiTalk);
+ return aiTalk;
+ }
+
+ @Override
+ public Flux<FebsResponse> answerStream(String question) {
+
+ return aiService.answerStream(question);
+ }
+
+ @Override
+ public FebsResponse talkList(ApiTalkPageDto dto) {
+ String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
+ dto.setMemberUuid(memberUuid);
+ // 创建分页对象,传入当前页和每页大小
+ Page<ApiTalkPageVo> page = new Page<>(dto.getPageNow(), dto.getPageSize());
+ Page<ApiTalkPageVo> pageListByQuery = this.getBaseMapper().getPageTalkListByQuery(page, dto);
+
+ return new FebsResponse().success().data(pageListByQuery);
+ }
+
+}
diff --git a/src/main/resources/mapper/modules/AiTalkMapper.xml b/src/main/resources/mapper/modules/AiTalkMapper.xml
index 22f7f0e..d2bdb52 100644
--- a/src/main/resources/mapper/modules/AiTalkMapper.xml
+++ b/src/main/resources/mapper/modules/AiTalkMapper.xml
@@ -1,4 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cc.mrbird.febs.ai.mapper.AiTalkMapper">
+
+
+ <select id="getPageTalkListByQuery" resultType="cc.mrbird.febs.ai.res.talk.ApiTalkPageVo">
+ select
+ a.id as talkId,
+ a.question as question,
+ a.CREATED_TIME as createdTime
+ from ai_talk a
+ where a.member_id = #{record.memberUuid}
+ order by a.CREATED_TIME desc
+ </select>
+
</mapper>
\ No newline at end of file
--
Gitblit v1.9.1