Administrator
2025-10-10 3861ca73a58797316065f49c22f48734b4160c6a
feat(ai): 新增陪练记录相关接口和分页查询功能

- 添加了获取陪练记录列表的分页查询接口
- 实现了陪练记录答题详情的分页查询接口
- 增加了查看陪练报告内容的接口
- 创建了对应的DTO和VO类用于数据传输
- 在Mapper和Service层添加了分页查询的实现
- 补充了MyBatis XML映射文件中的查询语句
- 控制器层增加了三个新的API端点用于前端调用
11 files modified
6 files added
295 ■■■■■ changed files
src/main/java/cc/mrbird/febs/ai/controller/memberTalk/ApiMemberTalkStreamController.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/mapper/AiMemberTalkItemMapper.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/mapper/AiMemberTalkMapper.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/req/memberTalk/ApiMemberTalkListDto.java 30 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/req/memberTalk/ApiTalkMemberListDto.java 31 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/req/memberTalk/ApiTalkReportListDto.java 16 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/res/memberTalk/ApiMemberTalkListVo.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/res/memberTalk/ApiTalkMemberListVo.java 38 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/res/memberTalk/ApiTalkReportListVo.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkItemService.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkService.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkStreamService.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkItemServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkServiceImpl.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java 27 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/AiMemberTalkItemMapper.xml 15 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/AiMemberTalkMapper.xml 15 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/memberTalk/ApiMemberTalkStreamController.java
@@ -1,10 +1,11 @@
package cc.mrbird.febs.ai.controller.memberTalk;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkMemberListDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkReportListDto;
import cc.mrbird.febs.ai.req.memberTalkStream.*;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkMemberAnswerSavaVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkStreamVoOld;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkListDto;
import cc.mrbird.febs.ai.res.memberTalk.*;
import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkReloadStreamVo;
import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkStreamVo;
import cc.mrbird.febs.ai.service.AiMemberTalkStreamService;
@@ -39,6 +40,36 @@
        return aiMemberTalkStreamService.start(dto);
    }
    @ApiOperation(value = "陪练记录", notes = "陪练记录")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiMemberTalkListVo.class)
    })
    @PostMapping(value = "/talkList")
    public FebsResponse talkList(@RequestBody @Validated ApiMemberTalkListDto dto) {
        return aiMemberTalkStreamService.talkList(dto);
    }
    @ApiOperation(value = "陪练记录-答题记录", notes = "陪练记录-答题记录")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiTalkMemberListVo.class)
    })
    @PostMapping(value = "/talkMemberList")
    public FebsResponse talkMemberList(@RequestBody @Validated ApiTalkMemberListDto dto) {
        return aiMemberTalkStreamService.talkMemberList(dto);
    }
    @ApiOperation(value = "陪练记录-查看报告", notes = "陪练记录-查看报告")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiTalkReportListVo.class)
    })
    @PostMapping(value = "/talkReportList")
    public FebsResponse talkReportList(@RequestBody @Validated ApiTalkReportListDto dto) {
        return aiMemberTalkStreamService.talkReportList(dto);
    }
    @ApiOperation(value = "再练一次(重新回答)", notes = "再练一次(重新回答)")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiMemberTalkReloadStreamVo.class)
src/main/java/cc/mrbird/febs/ai/mapper/AiMemberTalkItemMapper.java
@@ -2,9 +2,12 @@
import cc.mrbird.febs.ai.entity.AiMemberTalkItem;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkMemberListDto;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiTalkMemberListVo;
import cc.mrbird.febs.ai.res.product.ApiProductVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
@@ -17,4 +20,6 @@
public interface AiMemberTalkItemMapper extends BaseMapper<AiMemberTalkItem> {
    Page<ApiMemberTalkItemVo> getPageListByQuery(Page<ApiMemberTalkItemVo> page, @Param("record") ApiMemberTalkItemPageDto dto);
    IPage<ApiTalkMemberListVo> getPageByDto(Page<ApiTalkMemberListVo> page,  @Param("record") ApiTalkMemberListDto dto);
}
src/main/java/cc/mrbird/febs/ai/mapper/AiMemberTalkMapper.java
@@ -1,7 +1,12 @@
package cc.mrbird.febs.ai.mapper;
import cc.mrbird.febs.ai.entity.AiMemberTalk;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkListDto;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkListVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
/**
 * AI用户对话训练记录 Mapper接口
@@ -11,4 +16,5 @@
 */
public interface AiMemberTalkMapper extends BaseMapper<AiMemberTalk> {
    IPage<ApiMemberTalkListVo> getPageByDto(Page<ApiMemberTalkListVo> page, @Param("record")ApiMemberTalkListDto dto);
}
src/main/java/cc/mrbird/febs/ai/req/memberTalk/ApiMemberTalkListDto.java
New file
@@ -0,0 +1,30 @@
package cc.mrbird.febs.ai.req.memberTalk;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiMemberTalkListDto", description = "参数")
public class ApiMemberTalkListDto {
    @NotNull(message = "页码不能为空")
    @ApiModelProperty(value = "页码", example = "1")
    private Integer pageNow;
    @NotNull(message = "每页数量不能为空")
    @ApiModelProperty(value = "每页数量", example = "10")
    private Integer pageSize;
    @NotBlank(message = "产品ID不能为空")
    @ApiModelProperty(value = "产品ID", example = "10")
    private String productId;
    @NotBlank(message = "会员ID不能为空")
    @ApiModelProperty(value = "会员ID", example = "10")
    private String memberUuid;
}
src/main/java/cc/mrbird/febs/ai/req/memberTalk/ApiTalkMemberListDto.java
New file
@@ -0,0 +1,31 @@
package cc.mrbird.febs.ai.req.memberTalk;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiTalkMemberListDto", description = "参数")
public class ApiTalkMemberListDto {
    @NotNull(message = "页码不能为空")
    @ApiModelProperty(value = "页码", example = "1")
    private Integer pageNow;
    @NotNull(message = "每页数量不能为空")
    @ApiModelProperty(value = "每页数量", example = "10")
    private Integer pageSize;
    @NotNull(message = "会话ID不能为空")
    @ApiModelProperty(value = "会话ID", example = "1")
    private String memberTalkId;
    @NotBlank(message = "会员ID不能为空")
    @ApiModelProperty(value = "会员ID", example = "10")
    private String memberUuid;
}
src/main/java/cc/mrbird/febs/ai/req/memberTalk/ApiTalkReportListDto.java
New file
@@ -0,0 +1,16 @@
package cc.mrbird.febs.ai.req.memberTalk;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiTalkReportListDto", description = "参数")
public class ApiTalkReportListDto {
    @NotNull(message = "会话ID不能为空")
    @ApiModelProperty(value = "会话ID", example = "1")
    private String memberTalkId;
}
src/main/java/cc/mrbird/febs/ai/res/memberTalk/ApiMemberTalkListVo.java
New file
@@ -0,0 +1,23 @@
package cc.mrbird.febs.ai.res.memberTalk;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "ApiMemberTalkListVo", description = "参数")
public class ApiMemberTalkListVo {
    @ApiModelProperty(value = "会话ID")
    private String talkId;
    @ApiModelProperty(value = "标题")
    private String productName;
    @ApiModelProperty(value = "时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createdTime;
}
src/main/java/cc/mrbird/febs/ai/res/memberTalk/ApiTalkMemberListVo.java
New file
@@ -0,0 +1,38 @@
package cc.mrbird.febs.ai.res.memberTalk;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "ApiTalkMemberListVo", description = "参数")
public class ApiTalkMemberListVo {
    /**
     * 用户对话ID (UUID)
     */
    @ApiModelProperty(value = "会话ID")
    private String memberTalkId;
    /**
     * 用户消息ID (UUID)
     */
    @ApiModelProperty(value = "消息ID")
    private String memberTalkItemId;
    /**
     * 类型 1-AI提问 2-用户回答 3-AI分析结果
     */
    @ApiModelProperty(value = "类型 1-AI提问 2-用户回答 3-AI分析结果")
    private Integer type;
    /**
     * 内容
     */
    @ApiModelProperty(value = "内容(文本格式)")
    private String context;
}
src/main/java/cc/mrbird/febs/ai/res/memberTalk/ApiTalkReportListVo.java
New file
@@ -0,0 +1,13 @@
package cc.mrbird.febs.ai.res.memberTalk;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "ApiTalkReportListVo", description = "参数")
public class ApiTalkReportListVo {
    @ApiModelProperty(value = "报告")
    private String analysis;
}
src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkItemService.java
@@ -3,7 +3,9 @@
import cc.mrbird.febs.ai.entity.AiMemberTalkItem;
import cc.mrbird.febs.ai.req.ai.AiMessage;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkMemberListDto;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiTalkMemberListVo;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.vo.MallGoodsListVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -32,4 +34,5 @@
    List<AiMessage> getQuestionUpDownContext(String memberTalkId, int code);
    IPage<ApiTalkMemberListVo>  getPageByDto(ApiTalkMemberListDto dto);
}
src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkService.java
@@ -2,9 +2,13 @@
import cc.mrbird.febs.ai.entity.AiMemberTalk;
import cc.mrbird.febs.ai.req.memberTalk.*;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkListDto;
import cc.mrbird.febs.ai.res.ai.AiResponse;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkListVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiTalkMemberListVo;
import cc.mrbird.febs.common.entity.FebsResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import reactor.core.publisher.Flux;
@@ -44,4 +48,6 @@
    List<AiMemberTalk> getListByCompanyId(String companyId);
    List<AiMemberTalk> getListByCompanyIdAndMemberUuid(String companyId, String memberUuid);
    IPage<ApiMemberTalkListVo> getPageByDto(ApiMemberTalkListDto dto);
}
src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkStreamService.java
@@ -2,7 +2,10 @@
import cc.mrbird.febs.ai.entity.AiMemberTalk;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkMemberListDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkReportListDto;
import cc.mrbird.febs.ai.req.memberTalkStream.*;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkListDto;
import cc.mrbird.febs.common.entity.FebsResponse;
import com.baomidou.mybatisplus.extension.service.IService;
import reactor.core.publisher.Flux;
@@ -17,6 +20,12 @@
     */
    FebsResponse start(ApiMemberTalkStreamDto dto);
    FebsResponse talkList(ApiMemberTalkListDto dto);
    FebsResponse talkMemberList(ApiTalkMemberListDto dto);
    FebsResponse talkReportList(ApiTalkReportListDto dto);
    FebsResponse reload(ApiMemberTalkReloadStreamDto dto);
    FebsResponse historyPage(ApiMemberTalkItemPageDto dto);
src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkItemServiceImpl.java
@@ -5,7 +5,9 @@
import cc.mrbird.febs.ai.mapper.AiMemberTalkItemMapper;
import cc.mrbird.febs.ai.req.ai.AiMessage;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkMemberListDto;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiTalkMemberListVo;
import cc.mrbird.febs.ai.service.AiMemberTalkItemService;
import cc.mrbird.febs.ai.utils.UUID;
import cc.mrbird.febs.common.entity.FebsResponse;
@@ -103,4 +105,11 @@
        return aiMessages;
    }
    @Override
    public IPage<ApiTalkMemberListVo> getPageByDto(ApiTalkMemberListDto dto) {
        // 创建分页对象,传入当前页和每页大小
        Page<ApiTalkMemberListVo> page = new Page<>(dto.getPageNow(), dto.getPageSize());
        return aiMemberTalkItemMapper.getPageByDto(page, dto);
    }
}
src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkServiceImpl.java
@@ -8,9 +8,12 @@
import cc.mrbird.febs.ai.req.ai.AiMessage;
import cc.mrbird.febs.ai.req.ai.AiRequest;
import cc.mrbird.febs.ai.req.memberTalk.*;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkListDto;
import cc.mrbird.febs.ai.res.ai.AiResponse;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkListVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkReloadVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiTalkMemberListVo;
import cc.mrbird.febs.ai.service.AiMemberTalkItemService;
import cc.mrbird.febs.ai.service.AiMemberTalkService;
import cc.mrbird.febs.ai.service.AiProductRoleLinkService;
@@ -23,7 +26,9 @@
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -315,4 +320,11 @@
        );
    }
    @Override
    public IPage<ApiMemberTalkListVo> getPageByDto(ApiMemberTalkListDto dto) {
        // 创建分页对象,传入当前页和每页大小
        Page<ApiMemberTalkListVo> page = new Page<>(dto.getPageNow(), dto.getPageSize());
        return aiMemberTalkMapper.getPageByDto(page, dto);
    }
}
src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java
@@ -5,10 +5,15 @@
import cc.mrbird.febs.ai.enumerates.AiTypeEnum;
import cc.mrbird.febs.ai.mapper.AiMemberTalkMapper;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkMemberListDto;
import cc.mrbird.febs.ai.req.memberTalk.ApiTalkReportListDto;
import cc.mrbird.febs.ai.req.memberTalkStream.*;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkListDto;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkMemberAnswerSavaVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiTalkReportListVo;
import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkReloadStreamVo;
import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkStreamVo;
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkListVo;
import cc.mrbird.febs.ai.service.*;
import cc.mrbird.febs.ai.strategy.LlmStrategyFactory;
import cc.mrbird.febs.ai.strategy.enumerates.LlmApplicationAppIdEnum;
@@ -104,6 +109,28 @@
    }
    @Override
    public FebsResponse talkList(ApiMemberTalkListDto dto) {
        return new FebsResponse().success().data(aiMemberTalkService.getPageByDto(dto));
    }
    @Override
    public FebsResponse talkMemberList(ApiTalkMemberListDto dto) {
        return new FebsResponse().success().data(aiMemberTalkItemService.getPageByDto(dto));
    }
    @Override
    public FebsResponse talkReportList(ApiTalkReportListDto dto) {
        ApiTalkReportListVo apiTalkReportListDto = new ApiTalkReportListVo();
        String memberTalkId = dto.getMemberTalkId();
        AiMemberTalk byId = aiMemberTalkService.getById(memberTalkId);
        apiTalkReportListDto.setAnalysis(byId.getAnalysis());
        return new FebsResponse().success().data(apiTalkReportListDto);
    }
    @Override
    public FebsResponse reload(ApiMemberTalkReloadStreamDto dto) {
        String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
src/main/resources/mapper/modules/AiMemberTalkItemMapper.xml
@@ -18,4 +18,19 @@
        </where>
        order by a.CREATED_TIME desc
    </select>
    <select id="getPageByDto" resultType="cc.mrbird.febs.ai.res.memberTalk.ApiTalkMemberListVo">
        select
        a.ID as memberTalkItemId,
        a.member_talk_id as memberTalkId,
        a.type as type,
        a.context as context
        from ai_member_talk_item a
        <where>
            and a.member_id = #{record.memberUuid}
            and a.member_talk_id = #{record.memberTalkId}
        </where>
        order by a.CREATED_TIME asc
    </select>
</mapper>
src/main/resources/mapper/modules/AiMemberTalkMapper.xml
@@ -1,4 +1,19 @@
<?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.AiMemberTalkMapper">
    <select id="getPageByDto" resultType="cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkListVo">
        select
        a.ID as talkId,
        b.name as productName,
        a.CREATED_TIME as createdTime
        from ai_member_talk a
        left join ai_product b on a.product_id = b.id
        <where>
            and a.member_id = #{record.memberUuid}
            and a.product_id = #{record.productId}
        </where>
        order by a.CREATED_TIME desc
    </select>
</mapper>