xiangpei
2025-04-18 0aa739db8268b442ab74634289ffed00124a976a
会话管理、聊天接口(待测试)
9个文件已修改
24个文件已添加
1496 ■■■■■ 已修改文件
ai-chat/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/config/AIConfig.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/controller/ChatController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/controller/SessionController.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/controller/SessionMsgController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/entity/Session.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/entity/SessionMsg.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/form/ChatForm.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/form/SessionForm.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/form/SessionMsgForm.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/query/SessionMsgQuery.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/query/SessionQuery.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/vo/SessionCountVO.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/vo/SessionMsgVO.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/domain/vo/SessionVO.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/mapper/SessionMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/mapper/SessionMsgMapper.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/service/ChatService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/service/SessionMsgService.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/service/SessionService.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/service/impl/ChatServiceImpl.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/service/impl/SessionMsgServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/java/com/monkeylessey/service/impl/SessionServiceImpl.java 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/resources/mapper/SessionMapper.xml 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/src/main/resources/mapper/SessionMsgMapper.xml 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dev-admin/src/main/resources/application-dev.yml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dev-admin/src/main/resources/application-prod.yml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dev-sys/src/main/java/com/monkeylessey/framework/config/TokenSecurityConfig.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dev-sys/src/main/java/com/monkeylessey/gen/handler/QueryHandler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
dev-sys/src/main/java/com/monkeylessey/gen/handler/VoHandler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
dev-sys/src/main/java/com/monkeylessey/gen/utils/GenerateCodeUtil.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dev-sys/src/main/resources/templates/serviceImpl.java.vm 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ai-chat/pom.xml
@@ -17,6 +17,12 @@
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>com.monkeylessey</groupId>
            <artifactId>dev-sys</artifactId>
ai-chat/src/main/java/com/monkeylessey/config/AIConfig.java
New file
@@ -0,0 +1,50 @@
package com.monkeylessey.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
 * @author:xp
 * @date:2025/4/18 14:28
 */
@Configuration
@ConfigurationProperties(prefix = "ai")
public class AIConfig {
    /**
     * 域名
     */
    private String domain;
    /**
     * 端口
     */
    private String port;
    public String getDomain() {
        return domain;
    }
    public void setDomain(String domain) {
        this.domain = domain;
    }
    public String getPort() {
        return port;
    }
    public void setPort(String port) {
        this.port = port;
    }
    /**
     * 获取完整的域
     *
     * @return
     */
    public String getFullDomain() {
        return this.domain + ":" + this.port;
    }
}
ai-chat/src/main/java/com/monkeylessey/controller/ChatController.java
New file
@@ -0,0 +1,38 @@
package com.monkeylessey.controller;
import com.monkeylessey.domain.form.ChatForm;
import com.monkeylessey.domain.form.SessionForm;
import com.monkeylessey.group.Add;
import com.monkeylessey.response.Result;
import com.monkeylessey.service.ChatService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.servlet.http.HttpServletResponse;
/**
 * @author:xp
 * @date:2025/4/18 13:59
 */
@Validated
@RequiredArgsConstructor
@Api(value = "chat对话", tags = "chat对话管理")
@RestController
@RequestMapping("/chat")
public class ChatController {
    private final ChatService chatService;
    @PostMapping(value = "/send/msg", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @ApiOperation(value = "问问题/对话", notes = "问问题/对话")
    public SseEmitter sendMsg(@RequestBody @Validated ChatForm form) {
        return chatService.sendMsg(form);
    }
}
ai-chat/src/main/java/com/monkeylessey/controller/SessionController.java
New file
@@ -0,0 +1,88 @@
package com.monkeylessey.controller;
import com.monkeylessey.domain.form.SessionForm;
import com.monkeylessey.domain.query.SessionQuery;
import com.monkeylessey.group.Update;
import com.monkeylessey.group.Add;
import com.monkeylessey.service.SessionService;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import lombok.RequiredArgsConstructor;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.monkeylessey.response.Result;
import org.springframework.web.bind.annotation.*;
/**
 * chat对话 前端控制器
 *
 * @author 向培
 * @since 2025-04-18
 */
@Validated
@RequiredArgsConstructor
@Api(value = "会话管理", tags = "会话管理")
@RestController
@RequestMapping("/session")
public class SessionController {
    private final SessionService sessionService;
    @PostMapping
    @ApiOperation(value = "添加", notes = "添加")
//    @PreAuthorize("hasAuthority('session:add')")
    public Result add(@RequestBody @Validated(Add.class) SessionForm form) {
        return sessionService.add(form);
    }
    @PutMapping
    @ApiOperation(value = "修改", notes = "修改")
    @PreAuthorize("hasAuthority('session:edit')")
    public Result update(@RequestBody @Validated(Update.class) SessionForm form) {
        return sessionService.update(form);
    }
    @DeleteMapping("/{id}")
    @ApiOperation(value = "ID删除", notes = "ID删除")
    @PreAuthorize("hasAuthority('session:del')")
    public Result removeById(@PathVariable("id") String id) {
        return sessionService.removeById(id);
    }
    @DeleteMapping("/batch")
    @ApiOperation(value = "批量删除", notes = "批量删除")
    @PreAuthorize("hasAuthority('session:del:batch')")
    public Result remove(@RequestBody @NotEmpty(message = "请选择数据") List<String> ids) {
        return sessionService.remove(ids);
    }
    @GetMapping("/page")
    @ApiOperation(value = "分页", notes = "分页")
    @PreAuthorize("hasAuthority('session:page')")
    public Result page(SessionQuery query) {
        return sessionService.page(query);
    }
    @GetMapping("/{id}")
    @ApiOperation(value = "详情", notes = "详情")
//    @PreAuthorize("hasAuthority('session:detail')")
    public Result detail(@PathVariable("id") Integer id) {
        return sessionService.detail(id);
    }
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('session:list')")
    @ApiOperation(value = "列表", notes = "列表")
    public Result list() {
        return sessionService.all();
    }
    @GetMapping("/client/list")
//    @PreAuthorize("hasAuthority('session:client:list')")
    @ApiOperation(value = "客户端会话列表", notes = "客户端会话列表")
    public Result clientList() {
        return sessionService.clientList();
    }
}
ai-chat/src/main/java/com/monkeylessey/controller/SessionMsgController.java
New file
@@ -0,0 +1,83 @@
package com.monkeylessey.controller;
import com.monkeylessey.group.Update;
import com.monkeylessey.group.Add;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import lombok.RequiredArgsConstructor;
import java.util.List;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.monkeylessey.service.SessionMsgService;
import com.monkeylessey.response.Result;
import com.monkeylessey.domain.form.SessionMsgForm;
import com.monkeylessey.domain.query.SessionMsgQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
 * 会话消息 前端控制器
 *
 * @author 向培
 * @since 2025-04-18
 */
@Validated
@RequiredArgsConstructor
@Api(value = "会话消息", tags = "会话消息管理")
@RestController
@RequestMapping("/session-msg")
public class SessionMsgController {
    private final SessionMsgService sessionMsgService;
    @PostMapping
    @ApiOperation(value = "添加", notes = "添加")
    @PreAuthorize("hasAuthority('sessionMsg:add')")
    public Result add(@RequestBody @Validated(Add.class) SessionMsgForm form) {
        return sessionMsgService.add(form);
    }
    @PutMapping
    @ApiOperation(value = "修改", notes = "修改")
    @PreAuthorize("hasAuthority('sessionMsg:edit')")
    public Result update(@RequestBody @Validated(Update.class) SessionMsgForm form) {
        return sessionMsgService.update(form);
    }
    @DeleteMapping("/{id}")
    @ApiOperation(value = "ID删除", notes = "ID删除")
    @PreAuthorize("hasAuthority('sessionMsg:del')")
    public Result removeById(@PathVariable("id") String id) {
        return sessionMsgService.removeById(id);
    }
    @DeleteMapping("/batch")
    @ApiOperation(value = "批量删除", notes = "批量删除")
    @PreAuthorize("hasAuthority('sessionMsg:del:batch')")
    public Result remove(@RequestBody @NotEmpty(message = "请选择数据") List<String> ids) {
        return sessionMsgService.remove(ids);
    }
    @GetMapping("/page")
    @ApiOperation(value = "分页", notes = "分页")
    @PreAuthorize("hasAuthority('sessionMsg:page')")
    public Result page(SessionMsgQuery query) {
        return sessionMsgService.page(query);
    }
    @GetMapping("/{id}")
    @ApiOperation(value = "详情", notes = "详情")
    @PreAuthorize("hasAuthority('sessionMsg:detail')")
    public Result detail(@PathVariable("id") Integer id) {
        return sessionMsgService.detail(id);
    }
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sessionMsg:list')")
    @ApiOperation(value = "列表", notes = "列表")
    public Result list() {
        return sessionMsgService.all();
    }
}
ai-chat/src/main/java/com/monkeylessey/domain/entity/Session.java
New file
@@ -0,0 +1,70 @@
package com.monkeylessey.domain.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.monkeylessey.sys.domain.base.AbsEntity;
import java.io.Serializable;
import lombok.Data;
/**
 * chat对话
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@TableName("ai_session")
public class Session extends AbsEntity {
    private static final long serialVersionUID = 1L;
    @TableField("session_name")
    /** 会话名称 */
    private String sessionName;
    @TableField("mode")
    /** 会话模式 */
    private String mode;
    @TableField("kb_name")
    /** 知识库 */
    private String kbName;
    @TableField("top_k")
    /**  */
    private String topK;
    @TableField("score_threshold")
    /**  */
    private String scoreThreshold;
    @TableField("stream")
    /**  */
    private Integer stream;
    @TableField("model")
    /** 大模型 */
    private String model;
    @TableField("temperature")
    /**  */
    private String temperature;
    @TableField("max_tokens")
    /** 最大吐字数 */
    private Integer maxTokens;
    @TableField("prompt_name")
    /**  */
    private String promptName;
    @TableField("return_direct")
    /** 是否只返回检索结果不调用大模型 */
    private Integer returnDirect;
    @TableField("user_id")
    /**  */
    private String userId;
}
ai-chat/src/main/java/com/monkeylessey/domain/entity/SessionMsg.java
New file
@@ -0,0 +1,34 @@
package com.monkeylessey.domain.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.monkeylessey.sys.domain.base.AbsEntity;
import java.io.Serializable;
import lombok.Data;
/**
 * 会话消息
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@TableName("ai_session_msg")
public class SessionMsg extends AbsEntity {
    private static final long serialVersionUID = 1L;
    @TableField("session_id")
    /** 会话id */
    private String sessionId;
    @TableField("role")
    /** 角色:ai、user */
    private String role;
    @TableField("content")
    /** 对话内容 */
    private String content;
}
ai-chat/src/main/java/com/monkeylessey/domain/form/ChatForm.java
New file
@@ -0,0 +1,69 @@
package com.monkeylessey.domain.form;
import com.monkeylessey.group.Add;
import com.monkeylessey.group.Update;
import com.monkeylessey.sys.domain.base.AbsForm;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
/**
 * chat对话表单
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@ApiModel(value = "Session表单", description = "chat对话表单")
public class ChatForm extends AbsForm {
//    @NotBlank(message = "未选择会话")
    @ApiModelProperty("会话id")
    private String sessionId;
    @NotBlank(message = "请输入您的问题")
    @ApiModelProperty("当前用户提问内容")
    private String query;
    @NotBlank(message = "会话模式不能为空")
    @ApiModelProperty("会话模式")
    private String mode;
    @NotBlank(message = "知识库不能为空")
    @ApiModelProperty("知识库")
    private String kbName;
    @ApiModelProperty("")
    private String topK;
    @ApiModelProperty("")
    private String scoreThreshold;
    @ApiModelProperty("流式响应")
    private Boolean stream;
    @NotBlank(message = "模型不能为空")
    @ApiModelProperty("模型")
    private String model;
    @ApiModelProperty("")
    private String temperature;
    @ApiModelProperty("最大吐字数")
    private Integer maxTokens;
    @ApiModelProperty("")
    private String promptName;
    @ApiModelProperty("是否只返回检索结果不调用大模型")
    private Boolean returnDirect;
    @ApiModelProperty("历史消息")
    private List<SessionMsgForm> history = new ArrayList<>();
}
ai-chat/src/main/java/com/monkeylessey/domain/form/SessionForm.java
New file
@@ -0,0 +1,77 @@
package com.monkeylessey.domain.form;
import com.monkeylessey.domain.entity.Session;
import com.monkeylessey.group.Update;
import com.monkeylessey.group.Add;
import com.monkeylessey.sys.domain.base.AbsForm;
import org.springframework.beans.BeanUtils;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.springframework.lang.NonNull;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * chat对话表单
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@ApiModel(value = "Session表单", description = "chat对话表单")
public class SessionForm extends AbsForm {
    @NotBlank(message = "会话名称不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("会话名称")
    private String sessionName;
    @NotBlank(message = "会话模式不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("会话模式")
    private String mode;
    @NotBlank(message = "知识库不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("知识库")
    private String kbName;
    @NotBlank(message = "不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("")
    private String topK;
    @NotBlank(message = "不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("")
    private String scoreThreshold;
    @NotNull(message = "不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("")
    private Integer stream;
    @NotBlank(message = "大模型不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("大模型")
    private String model;
    @NotBlank(message = "不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("")
    private String temperature;
    @NotNull(message = "最大吐字数不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("最大吐字数")
    private Integer maxTokens;
    @NotBlank(message = "不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("")
    private String promptName;
    @NotNull(message = "是否只返回检索结果不调用大模型不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("是否只返回检索结果不调用大模型")
    private Integer returnDirect;
    public static Session getEntityByForm(@NonNull SessionForm form, Session entity) {
        if(entity == null) {
          entity = new Session();
        }
        BeanUtils.copyProperties(form, entity);
        return entity;
    }
}
ai-chat/src/main/java/com/monkeylessey/domain/form/SessionMsgForm.java
New file
@@ -0,0 +1,39 @@
package com.monkeylessey.domain.form;
import com.monkeylessey.group.Update;
import com.monkeylessey.group.Add;
import com.monkeylessey.sys.domain.base.AbsForm;
import com.monkeylessey.domain.entity.SessionMsg;
import org.springframework.beans.BeanUtils;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.springframework.lang.NonNull;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * 会话消息表单
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@ApiModel(value = "SessionMsg表单", description = "会话消息表单")
public class SessionMsgForm extends AbsForm {
    @ApiModelProperty("角色:ai、user")
    private String role;
    @ApiModelProperty("对话内容")
    private String content;
    public static SessionMsg getEntityByForm(@NonNull SessionMsgForm form, SessionMsg entity) {
        if(entity == null) {
          entity = new SessionMsg();
        }
        BeanUtils.copyProperties(form, entity);
        return entity;
    }
}
ai-chat/src/main/java/com/monkeylessey/domain/query/SessionMsgQuery.java
New file
@@ -0,0 +1,21 @@
package com.monkeylessey.domain.query;
import com.monkeylessey.sys.domain.base.AbsQuery;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * 会话消息查询
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@ApiModel(value = "SessionMsg查询参数", description = "会话消息查询参数")
public class SessionMsgQuery extends AbsQuery {
    @ApiModelProperty("对话内容")
    private String content;
}
ai-chat/src/main/java/com/monkeylessey/domain/query/SessionQuery.java
New file
@@ -0,0 +1,22 @@
package com.monkeylessey.domain.query;
import com.monkeylessey.sys.domain.base.AbsQuery;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * chat对话查询
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@ApiModel(value = "Session查询参数", description = "chat对话查询参数")
public class SessionQuery extends AbsQuery {
    @ApiModelProperty("会话名称")
    private String sessionName;
}
ai-chat/src/main/java/com/monkeylessey/domain/vo/SessionCountVO.java
New file
@@ -0,0 +1,30 @@
package com.monkeylessey.domain.vo;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
 * @author:xp
 * @date:2025/4/18 15:20
 */
@Data
public class SessionCountVO {
    /**
     * 今天的会话
     */
    private List<SessionVO> today = new ArrayList<>();
    /**
     * 昨天的会话
     */
    private List<SessionVO> yesterday = new ArrayList<>();
    /**
     * 昨天以前的所有会话
     */
    private List<SessionVO> old = new ArrayList<>();
}
ai-chat/src/main/java/com/monkeylessey/domain/vo/SessionMsgVO.java
New file
@@ -0,0 +1,37 @@
package com.monkeylessey.domain.vo;
import com.monkeylessey.domain.entity.SessionMsg;
import com.monkeylessey.sys.domain.base.AbsVo;
import org.springframework.lang.NonNull;
import org.springframework.beans.BeanUtils;
import io.swagger.annotations.ApiModel;
import lombok.Data;
/**
 * 会话消息展示
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@ApiModel(value = "会话消息响应数据", description = "会话消息响应数据")
public class SessionMsgVO extends AbsVo {
    /** 会话id */
    private String sessionId;
    /** 角色:ai、user */
    private String role;
    /** 对话内容 */
    private String content;
    public static SessionMsgVO getVoByEntity(@NonNull SessionMsg entity, SessionMsgVO vo) {
        if(vo == null) {
            vo = new SessionMsgVO();
        }
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}
ai-chat/src/main/java/com/monkeylessey/domain/vo/SessionVO.java
New file
@@ -0,0 +1,64 @@
package com.monkeylessey.domain.vo;
import com.monkeylessey.domain.entity.Session;
import com.monkeylessey.sys.domain.base.AbsVo;
import org.springframework.lang.NonNull;
import org.springframework.beans.BeanUtils;
import io.swagger.annotations.ApiModel;
import lombok.Data;
/**
 * chat对话展示
 *
 * @author 向培
 * @since 2025-04-18
 */
@Data
@ApiModel(value = "chat对话响应数据", description = "chat对话响应数据")
public class SessionVO extends AbsVo {
    /** 会话名称 */
    private String sessionName;
    /** 会话模式 */
    private String mode;
    /** 知识库 */
    private String kbName;
    /**  */
    private String topK;
    /**  */
    private String scoreThreshold;
    /**  */
    private Integer stream;
    /** 大模型 */
    private String model;
    /**  */
    private String temperature;
    /** 最大吐字数 */
    private Integer maxTokens;
    /**  */
    private String promptName;
    /** 是否只返回检索结果不调用大模型 */
    private Integer returnDirect;
    /**  */
    private String userId;
    public static SessionVO getVoByEntity(@NonNull Session entity, SessionVO vo) {
        if(vo == null) {
            vo = new SessionVO();
        }
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}
ai-chat/src/main/java/com/monkeylessey/mapper/SessionMapper.java
New file
@@ -0,0 +1,61 @@
package com.monkeylessey.mapper;
import com.monkeylessey.domain.entity.Session;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.Date;
import java.util.List;
import com.monkeylessey.domain.query.SessionQuery;
import com.monkeylessey.domain.vo.SessionVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * chat对话 Mapper 接口
 *
 * @author 向培
 * @since 2025-04-18
 */
@Mapper
public interface SessionMapper extends BaseMapper<Session> {
    /**
     * id查找chat对话
     * @param id
     * @return
     */
    SessionVO getById(Integer id);
    /**
    *  分页
    */
    IPage getPage(IPage page, @Param("query") SessionQuery query);
    /**
     * 今天的会话列表
     *
     * @param dayStart
     * @param dayEnd
     * @return
     */
    List<SessionVO> getTodaySessionList(@Param("dayStart") Date dayStart, @Param("dayEnd") Date dayEnd);
    /**
     * 昨天的会话
     *
     * @param dayStart
     * @param dayEnd
     * @return
     */
    List<SessionVO> getYesterdaySessionList(@Param("dayStart") Date dayStart, @Param("dayEnd") Date dayEnd);
    /**
     * 昨天之前的所有会话
     *
     * @param time
     * @return
     */
    List<SessionVO> getOldSessionList(@Param("time") Date time);
}
ai-chat/src/main/java/com/monkeylessey/mapper/SessionMsgMapper.java
New file
@@ -0,0 +1,33 @@
package com.monkeylessey.mapper;
import com.monkeylessey.domain.entity.SessionMsg;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.monkeylessey.domain.query.SessionMsgQuery;
import com.monkeylessey.domain.vo.SessionMsgVO;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * 会话消息 Mapper 接口
 *
 * @author 向培
 * @since 2025-04-18
 */
@Mapper
public interface SessionMsgMapper extends BaseMapper<SessionMsg> {
    /**
     * id查找会话消息
     * @param id
     * @return
     */
    SessionMsgVO getById(Integer id);
    /**
    *  分页
    */
    IPage getPage(IPage page, @Param("query") SessionMsgQuery query);
}
ai-chat/src/main/java/com/monkeylessey/service/ChatService.java
New file
@@ -0,0 +1,24 @@
package com.monkeylessey.service;
import com.monkeylessey.domain.form.ChatForm;
import com.monkeylessey.response.Result;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.servlet.http.HttpServletResponse;
/**
 * 对话
 *
 * @author:xp
 * @date:2025/4/18 14:21
 */
public interface ChatService {
    /**
     * 用户提问
     *
     * @param form
     */
    SseEmitter sendMsg(ChatForm form);
}
ai-chat/src/main/java/com/monkeylessey/service/SessionMsgService.java
New file
@@ -0,0 +1,65 @@
package com.monkeylessey.service;
import com.monkeylessey.domain.entity.SessionMsg;
import com.baomidou.mybatisplus.extension.service.IService;
import com.monkeylessey.response.Result;
import com.monkeylessey.domain.form.SessionMsgForm;
import com.monkeylessey.domain.query.SessionMsgQuery;
import java.util.List;
/**
 * 会话消息 服务类
 *
 * @author 向培
 * @since 2025-04-18
 */
public interface SessionMsgService extends IService<SessionMsg> {
    /**
     * 添加
     * @param form
     * @return
     */
    Result add(SessionMsgForm form);
    /**
     * 修改
     * @param form
     * @return
     */
    Result update(SessionMsgForm form);
    /**
     * 批量删除
     * @param ids
     * @return
     */
    Result remove(List<String> ids);
    /**
     * id删除
     * @param id
     * @return
     */
    Result removeById(String id);
    /**
     * 分页查询
     * @param query
     * @return
     */
    Result page(SessionMsgQuery query);
    /**
     * 根据id查找
     * @param id
     * @return
     */
    Result detail(Integer id);
    /**
     * 列表
     * @return
     */
    Result all();
}
ai-chat/src/main/java/com/monkeylessey/service/SessionService.java
New file
@@ -0,0 +1,72 @@
package com.monkeylessey.service;
import com.monkeylessey.domain.entity.Session;
import com.monkeylessey.domain.form.SessionForm;
import com.monkeylessey.domain.query.SessionQuery;
import com.baomidou.mybatisplus.extension.service.IService;
import com.monkeylessey.response.Result;
import java.util.List;
/**
 * chat对话 服务类
 *
 * @author 向培
 * @since 2025-04-18
 */
public interface SessionService extends IService<Session> {
    /**
     * 添加
     * @param form
     * @return
     */
    Result add(SessionForm form);
    /**
     * 修改
     * @param form
     * @return
     */
    Result update(SessionForm form);
    /**
     * 批量删除
     * @param ids
     * @return
     */
    Result remove(List<String> ids);
    /**
     * id删除
     * @param id
     * @return
     */
    Result removeById(String id);
    /**
     * 分页查询
     * @param query
     * @return
     */
    Result page(SessionQuery query);
    /**
     * 根据id查找
     * @param id
     * @return
     */
    Result detail(Integer id);
    /**
     * 列表
     * @return
     */
    Result all();
    /**
     * 客户端会话列表
     *
     * @return
     */
    Result clientList();
}
ai-chat/src/main/java/com/monkeylessey/service/impl/ChatServiceImpl.java
New file
@@ -0,0 +1,84 @@
package com.monkeylessey.service.impl;
import cn.hutool.http.HttpUtil;
import com.monkeylessey.config.AIConfig;
import com.monkeylessey.domain.form.ChatForm;
import com.monkeylessey.service.ChatService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
 * @author:xp
 * @date:2025/4/18 14:22
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatServiceImpl implements ChatService {
    private final AIConfig aiConfig;
    @Override
    public SseEmitter sendMsg(ChatForm form) {
        SseEmitter emitter = new SseEmitter(Long.MAX_VALUE); // 设置无限超时
        // 1. 构建请求体
        Map<String, Object> body = new HashMap<>();
        body.put("query", form.getQuery());
        body.put("mode", form.getMode());
        body.put("kb_name", form.getKbName());
        body.put("top_k", form.getTopK());
        body.put("score_threshold", form.getScoreThreshold());
        body.put("history", form.getHistory());
        body.put("stream", form.getStream());
        body.put("model", form.getModel());
        body.put("temperature", form.getTemperature());
        body.put("max_tokens", form.getMaxTokens());
        body.put("prompt_name", form.getPromptName());
        body.put("return_direct", form.getReturnDirect());
        // 2. 异步处理SSE转发
        CompletableFuture.runAsync(() -> {
            try {
                WebClient client = WebClient.create(aiConfig.getFullDomain());
                client.post()
                        .uri("/chat/kb_chat")
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.TEXT_EVENT_STREAM) // 声明接受SSE响应
                        .bodyValue(body)
                        .retrieve()
                        .bodyToFlux(String.class) // 使用Flux接收流式响应
                        .subscribe(
                                data -> {
                                    try {
                                        emitter.send(SseEmitter.event().data(data));
                                    } catch (IOException e) {
                                        log.error("发送失败", e.getMessage());
                                    }
                                },
                                error -> emitter.completeWithError(error),
                                () -> emitter.complete()
                        );
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        });
        // 3. 连接生命周期回调
        emitter.onCompletion(() -> log.info("SSE connection completed"));
        emitter.onTimeout(() -> log.warn("SSE connection timed out"));
        emitter.onError(ex -> log.error("SSE error: {}", ex.getMessage()));
        return emitter;
    }
}
ai-chat/src/main/java/com/monkeylessey/service/impl/SessionMsgServiceImpl.java
New file
@@ -0,0 +1,119 @@
package com.monkeylessey.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.monkeylessey.domain.entity.SessionMsg;
import com.monkeylessey.mapper.SessionMsgMapper;
import com.monkeylessey.service.SessionMsgService;
import com.monkeylessey.response.Result;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.monkeylessey.domain.form.SessionMsgForm;
import com.monkeylessey.domain.vo.SessionMsgVO;
import com.monkeylessey.domain.query.SessionMsgQuery;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import com.monkeylessey.utils.PageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 会话消息 服务实现类
 *
 * @author 向培
 * @since 2025-04-18
 */
@Service
@RequiredArgsConstructor
public class SessionMsgServiceImpl extends ServiceImpl<SessionMsgMapper, SessionMsg> implements SessionMsgService {
    private final SessionMsgMapper sessionMsgMapper;
    /**
     * 添加
     * @param form
     * @return
     */
    @Override
    public Result add(SessionMsgForm form) {
        SessionMsg entity = SessionMsgForm.getEntityByForm(form, null);
        baseMapper.insert(entity);
        return Result.ok("添加成功");
    }
    /**
     * 修改
     * @param form
     * @return
     */
    @Override
    public Result update(SessionMsgForm form) {
        SessionMsg entity = baseMapper.selectById(form.getId());
        // 为空抛IllegalArgumentException,做全局异常处理
        Assert.notNull(entity, "记录不存在");
        BeanUtils.copyProperties(form, entity);
        baseMapper.updateById(entity);
        return Result.ok("修改成功");
    }
    /**
     * 批量删除
     * @param ids
     * @return
     */
    @Override
    public Result remove(List<String> ids) {
        baseMapper.deleteBatchIds(ids);
        return Result.ok("删除成功");
    }
    /**
     * id删除
     * @param id
     * @return
     */
    @Override
    public Result removeById(String id) {
        baseMapper.deleteById(id);
        return Result.ok("删除成功");
    }
    /**
     * 分页查询
     * @param query
     * @return
     */
    @Override
    public Result page(SessionMsgQuery query) {
        IPage<SessionMsgVO> page = PageUtil.getPage(query, SessionMsgVO.class);
        baseMapper.getPage(page, query);
        return Result.ok().data(page.getRecords()).total(page.getTotal());
    }
    /**
     * 根据id查找
     * @param id
     * @return
     */
    @Override
    public Result detail(Integer id) {
        SessionMsgVO vo = baseMapper.getById(id);
        Assert.notNull(vo, "记录不存在");
        return Result.ok().data(vo);
    }
    /**
     * 列表
     * @return
     */
    @Override
    public Result all() {
        List<SessionMsg> entities = baseMapper.selectList(null);
        List<SessionMsgVO> vos = entities.stream()
                .map(entity -> SessionMsgVO.getVoByEntity(entity, null))
                .collect(Collectors.toList());
        return Result.ok().data(vos);
    }
}
ai-chat/src/main/java/com/monkeylessey/service/impl/SessionServiceImpl.java
New file
@@ -0,0 +1,146 @@
package com.monkeylessey.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.monkeylessey.domain.entity.Session;
import com.monkeylessey.domain.form.SessionForm;
import com.monkeylessey.domain.query.SessionQuery;
import com.monkeylessey.domain.vo.SessionCountVO;
import com.monkeylessey.domain.vo.SessionVO;
import com.monkeylessey.mapper.SessionMapper;
import com.monkeylessey.service.SessionService;
import com.monkeylessey.response.Result;
import com.monkeylessey.utils.DateUtil;
import com.monkeylessey.utils.PageUtil;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
 * chat对话 服务实现类
 *
 * @author 向培
 * @since 2025-04-18
 */
@Service
@RequiredArgsConstructor
public class SessionServiceImpl extends ServiceImpl<SessionMapper, Session> implements SessionService {
    private final SessionMapper sessionMapper;
    /**
     * 添加
     * @param form
     * @return
     */
    @Override
    public Result add(SessionForm form) {
        Session entity = SessionForm.getEntityByForm(form, null);
        baseMapper.insert(entity);
        return Result.ok("添加成功");
    }
    /**
     * 修改
     * @param form
     * @return
     */
    @Override
    public Result update(SessionForm form) {
        Session entity = baseMapper.selectById(form.getId());
        // 为空抛IllegalArgumentException,做全局异常处理
        Assert.notNull(entity, "记录不存在");
        BeanUtils.copyProperties(form, entity);
        baseMapper.updateById(entity);
        return Result.ok("修改成功");
    }
    /**
     * 批量删除
     * @param ids
     * @return
     */
    @Override
    public Result remove(List<String> ids) {
        baseMapper.deleteBatchIds(ids);
        return Result.ok("删除成功");
    }
    /**
     * id删除
     * @param id
     * @return
     */
    @Override
    public Result removeById(String id) {
        baseMapper.deleteById(id);
        return Result.ok("删除成功");
    }
    /**
     * 分页查询
     * @param query
     * @return
     */
    @Override
    public Result page(SessionQuery query) {
        IPage<SessionVO> page = PageUtil.getPage(query, SessionVO.class);
        baseMapper.getPage(page, query);
        return Result.ok().data(page.getRecords()).total(page.getTotal());
    }
    /**
     * 根据id查找
     * @param id
     * @return
     */
    @Override
    public Result detail(Integer id) {
        SessionVO vo = baseMapper.getById(id);
        Assert.notNull(vo, "记录不存在");
        return Result.ok().data(vo);
    }
    /**
     * 列表
     * @return
     */
    @Override
    public Result all() {
        List<Session> entities = baseMapper.selectList(null);
        List<SessionVO> vos = entities.stream()
                .map(entity -> SessionVO.getVoByEntity(entity, null))
                .collect(Collectors.toList());
        return Result.ok().data(vos);
    }
    @Override
    public Result clientList() {
        Date now = new Date();
        // TODO,userId查询
        // 今天
        List<SessionVO> todaySession = baseMapper.getTodaySessionList(DateUtil.getDayStart(now), DateUtil.getDayEnd(now));
        // 昨天
        Calendar instance = Calendar.getInstance();
        instance.setTime(now);
        instance.add(Calendar.DATE, -1);
        Date yesterday = instance.getTime();
        List<SessionVO> yesterdaySession = baseMapper.getYesterdaySessionList(DateUtil.getDayStart(yesterday), DateUtil.getDayEnd(yesterday));
        // 更早
        List<SessionVO> oldSession = baseMapper.getOldSessionList(DateUtil.getDayStart(yesterday));
        SessionCountVO vo = new SessionCountVO();
        vo.setToday(todaySession);
        vo.setYesterday(yesterdaySession);
        vo.setOld(oldSession);
        return Result.ok().data(vo);
    }
}
ai-chat/src/main/resources/mapper/SessionMapper.xml
New file
@@ -0,0 +1,86 @@
<?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="com.monkeylessey.mapper.SessionMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.monkeylessey.domain.vo.SessionVO">
        <result column="session_name" property="sessionName" />
        <result column="mode" property="mode" />
        <result column="kb_name" property="kbName" />
        <result column="top_k" property="topK" />
        <result column="score_threshold" property="scoreThreshold" />
        <result column="stream" property="stream" />
        <result column="model" property="model" />
        <result column="temperature" property="temperature" />
        <result column="max_tokens" property="maxTokens" />
        <result column="prompt_name" property="promptName" />
        <result column="return_direct" property="returnDirect" />
        <result column="user_id" property="userId" />
    </resultMap>
    <select id="getById" resultMap="BaseResultMap">
        SELECT
            SE.session_name,
            SE.mode,
            SE.kb_name,
            SE.top_k,
            SE.score_threshold,
            SE.stream,
            SE.model,
            SE.temperature,
            SE.max_tokens,
            SE.prompt_name,
            SE.return_direct,
            SE.user_id,
            SE.id
        FROM
            ai_session SE
        WHERE
            SE.id = #{id} AND SE.deleted = 0
    </select>
    <select id="getPage" resultMap="BaseResultMap">
        SELECT
            SE.session_name,
            SE.mode,
            SE.kb_name,
            SE.top_k,
            SE.score_threshold,
            SE.stream,
            SE.model,
            SE.temperature,
            SE.max_tokens,
            SE.prompt_name,
            SE.return_direct,
            SE.user_id,
            SE.id
        FROM
            ai_session SE
        WHERE
            SE.deleted = 0
            <if test="query.sessionName != null and query.sessionName != ''">
                AND SE.session_name = #{query.sessionName}
            </if>
    </select>
    <select id="getTodaySessionList" resultMap="BaseResultMap">
        SELECT * FROM ai_session WHERE gmt_create between #{dayStart} and #{dayEnd} AND deleted = 0 ORDER BY gmt_create DESC
    </select>
    <select id="getYesterdaySessionList" resultMap="BaseResultMap">
        SELECT * FROM ai_session WHERE gmt_create between #{dayStart} and #{dayEnd} AND deleted = 0 ORDER BY gmt_create DESC
    </select>
    <select id="getOldSessionList" resultMap="BaseResultMap">
        SELECT * FROM ai_session WHERE gmt_create &lt; #{time} AND deleted = 0 ORDER BY gmt_create DESC
    </select>
</mapper>
ai-chat/src/main/resources/mapper/SessionMsgMapper.xml
New file
@@ -0,0 +1,46 @@
<?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="com.monkeylessey.mapper.SessionMsgMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.monkeylessey.domain.vo.SessionMsgVO">
        <result column="session_id" property="sessionId" />
        <result column="role" property="role" />
        <result column="content" property="content" />
    </resultMap>
    <select id="getById" resultMap="BaseResultMap">
        SELECT
            ASM.session_id,
            ASM.role,
            ASM.content,
            ASM.id
        FROM
            ai_session_msg ASM
        WHERE
            ASM.id = #{id} AND ASM.deleted = 0
    </select>
    <select id="getPage" resultMap="BaseResultMap">
        SELECT
            ASM.session_id,
            ASM.role,
            ASM.content,
            ASM.id
        FROM
            ai_session_msg ASM
        WHERE
            ASM.deleted = 0
            <if test="query.content != null and query.content != ''">
                AND ASM.content = #{query.content}
            </if>
    </select>
</mapper>
dev-admin/src/main/resources/application-dev.yml
@@ -53,3 +53,10 @@
  domain: http://127.0.0.1:${server.port}/files/
# 知识库配置
ai:
  domain: http://i-1.gpushare.com
  port: 52574
dev-admin/src/main/resources/application-prod.yml
@@ -48,3 +48,9 @@
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  url: E:/ycl/file
  domain: http://127.0.0.1:${server.port}/files/
# 知识库配置
ai:
  domain: http://i-1.gpushare.com
  port: 52574
dev-sys/src/main/java/com/monkeylessey/framework/config/TokenSecurityConfig.java
@@ -65,6 +65,7 @@
                .authenticationEntryPoint(authenticationException);
        http.authorizeRequests()
                .antMatchers("/**").permitAll()
                .antMatchers(HttpMethod.POST, "/xpstart/login").permitAll()
                .antMatchers("/sys-table/columns/**").permitAll()
                .antMatchers("/ws/**").permitAll()
dev-sys/src/main/java/com/monkeylessey/gen/handler/QueryHandler.java
@@ -37,7 +37,7 @@
        queryTemplate.setFields(columnS);
        // 设置query的父类名
        queryTemplate.setBaseQueryName("AbsQuery");
        queryTemplate.setBaseQueryPath("com.monkeylessey.base");
        queryTemplate.setBaseQueryPath("com.monkeylessey.sys.domain.base");
        objectMap.put("queryInfo", queryTemplate);
        return new VueHandler().handler(objectMap, data);
    }
dev-sys/src/main/java/com/monkeylessey/gen/handler/VoHandler.java
@@ -42,7 +42,7 @@
        voTemplate.setFields(columns);
        // 设置vo的父类名
        voTemplate.setBaseVoName("AbsVo");
        voTemplate.setBaseVoPath("com.monkeylessey.base");
        voTemplate.setBaseVoPath("com.monkeylessey.sys.domain.base");
        voTemplate.setTableSimpleName(WordsUtils.extractFirstLetters(tableInfo.getName(), "_"));
dev-sys/src/main/java/com/monkeylessey/gen/utils/GenerateCodeUtil.java
@@ -116,12 +116,12 @@
                .packageConfig(builder -> {
                    builder.parent("com.monkeylessey")
                            //.moduleName("onceCode")
                            .entity("sys.domain.entity")
                            .entity("domain.entity")
                            .service("service")
                            .serviceImpl("service.impl")
                            .controller("controller")
                            .mapper("mapper")
                            .other("sys.domain")
                            .other("domain")
                            .xml("mapper")
                            .pathInfo(Collections.singletonMap(OutputFile.other, finalOutDir + "\\domain"))
                            .pathInfo(Collections.singletonMap(OutputFile.xml, finalMapperDir));
dev-sys/src/main/resources/templates/serviceImpl.java.vm
@@ -14,9 +14,10 @@
#if(${entityLombokModel})
import lombok.RequiredArgsConstructor;
#end
import com.ycl.jxkg.utils.PageUtil;
import com.monkeylessey.utils.PageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.util.List;
import java.util.stream.Collectors;
pom.xml
@@ -93,6 +93,13 @@
                <version>${version}</version>
            </dependency>
            <!-- 公共模块 -->
            <dependency>
                <groupId>com.monkeylessey</groupId>
                <artifactId>ai-chat</artifactId>
                <version>${version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>