feat(pet): 添加宠物医疗上下文功能模块
- 新增宠物医疗上下文实体类BizPetMedicalContext - 创建宠物医疗上下文业务对象BizPetMedicalContextBo - 实现宠物医疗上下文控制器BizPetMedicalContextController - 添加宠物医疗上下文数据访问层BizPetMedicalContextMapper - 实现宠物医疗上下文服务层BizPetMedicalContextServiceImpl - 创建宠物医疗上下文视图对象BizPetMedicalContextVo - 生成前端API接口文件api.d.ts.vm和api.ts.vm - 创建Vue组件模板index.vue.vm和操作抽屉operate-drawer.vue.vm - 更新代码生成配置generator.yml支持宠物模块 - 添加树形表格支持index-tree.vue.vm模板
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
package org.dromara.chat.client;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
|
||||
public class ChatSdk {
|
||||
private final HttpClient client = HttpClient.newHttpClient();
|
||||
private final String baseUrl;
|
||||
private String token;
|
||||
|
||||
public ChatSdk(String baseUrl) {
|
||||
this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
||||
}
|
||||
|
||||
public ChatSdk withToken(String token) {
|
||||
this.token = token;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String chat(String jsonBody) {
|
||||
HttpRequest.Builder b = HttpRequest.newBuilder()
|
||||
.uri(URI.create(baseUrl + "/api/ai/chat"))
|
||||
.header("Content-Type", "application/json");
|
||||
if (token != null && !token.isEmpty()) {
|
||||
b.header("Authorization", token);
|
||||
}
|
||||
HttpRequest req = b.POST(HttpRequest.BodyPublishers.ofString(jsonBody)).build();
|
||||
try {
|
||||
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
|
||||
return resp.body();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package org.dromara.chat.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSocketMessageBroker
|
||||
public class StompWebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/ws/chat").setAllowedOriginPatterns("*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
||||
registry.setApplicationDestinationPrefixes("/app");
|
||||
ThreadPoolTaskScheduler scheduler = taskScheduler();
|
||||
registry.enableSimpleBroker("/topic")
|
||||
.setHeartbeatValue(new long[]{30000, 30000})
|
||||
.setTaskScheduler(scheduler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ThreadPoolTaskScheduler taskScheduler() {
|
||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||
scheduler.setPoolSize(1);
|
||||
scheduler.setThreadNamePrefix("stomp-heartbeat-");
|
||||
scheduler.initialize();
|
||||
return scheduler;
|
||||
}
|
||||
}
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.chat.domain.vo.ChatMessageVo;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
import org.dromara.chat.service.AiKnowledgeChatService;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 知识库聊天控制器
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chat/knowledge")
|
||||
public class AIKnowledgeChatController extends BaseController {
|
||||
|
||||
private final AiKnowledgeChatService knowledgeChatService;
|
||||
|
||||
/**
|
||||
* 基于知识库进行智能问答
|
||||
*/
|
||||
@SaCheckPermission("chat:knowledge:chat")
|
||||
@Log(title = "知识库问答", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/chat")
|
||||
public R<ChatMessageVo> chatWithKnowledge(
|
||||
@RequestParam Long sessionId,
|
||||
@RequestParam Long userId,
|
||||
@RequestParam String question,
|
||||
@RequestParam Long knowledgeId,
|
||||
@RequestParam String modelName) {
|
||||
ChatMessageVo response = knowledgeChatService.chatWithKnowledge(sessionId, userId, question, knowledgeId, modelName);
|
||||
return R.ok(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建知识库聊天会话
|
||||
*/
|
||||
@SaCheckPermission("chat:knowledge:session")
|
||||
@Log(title = "创建知识库会话", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/session")
|
||||
public R<ChatSessionVo> createKnowledgeSession(
|
||||
@RequestParam Long userId,
|
||||
@RequestParam Long knowledgeId,
|
||||
@RequestParam(required = false) String sessionTitle) {
|
||||
ChatSessionVo session = knowledgeChatService.createKnowledgeSession(userId, knowledgeId, sessionTitle);
|
||||
return R.ok(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索知识库内容
|
||||
*/
|
||||
@SaCheckPermission("chat:knowledge:search")
|
||||
@GetMapping("/search")
|
||||
public R<List<String>> searchKnowledgeContent(
|
||||
@RequestParam Long knowledgeId,
|
||||
@RequestParam String query,
|
||||
@RequestParam(defaultValue = "5") Integer limit) {
|
||||
List<String> results = knowledgeChatService.searchKnowledgeContent(knowledgeId, query, limit);
|
||||
return R.ok(results);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建知识库上下文
|
||||
*/
|
||||
@SaCheckPermission("chat:knowledge:context")
|
||||
@GetMapping("/context")
|
||||
public R<String> buildKnowledgeContext(
|
||||
@RequestParam Long knowledgeId,
|
||||
@RequestParam String question) {
|
||||
String context = knowledgeChatService.buildKnowledgeContext(knowledgeId, question);
|
||||
return R.ok(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识库聊天历史
|
||||
*/
|
||||
@SaCheckPermission("chat:knowledge:history")
|
||||
@GetMapping("/history/{sessionId}")
|
||||
public R<List<ChatMessageVo>> getKnowledgeChatHistory(
|
||||
@PathVariable Long sessionId,
|
||||
@RequestParam(defaultValue = "20") Integer limit) {
|
||||
List<ChatMessageVo> history = knowledgeChatService.getKnowledgeChatHistory(sessionId, limit);
|
||||
return R.ok(history);
|
||||
}
|
||||
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
package org.dromara.pet.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.pet.domain.vo.BizPetMedicalContextVo;
|
||||
import org.dromara.pet.domain.bo.BizPetMedicalContextBo;
|
||||
import org.dromara.pet.service.IBizPetMedicalContextService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 宠物医疗上下文
|
||||
*
|
||||
* @author shuo
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pet/petMedicalContext")
|
||||
public class BizPetMedicalContextController extends BaseController {
|
||||
|
||||
private final IBizPetMedicalContextService bizPetMedicalContextService;
|
||||
|
||||
/**
|
||||
* 查询宠物医疗上下文列表
|
||||
*/
|
||||
@SaCheckPermission("pet:petMedicalContext:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<BizPetMedicalContextVo> list(BizPetMedicalContextBo bo, PageQuery pageQuery) {
|
||||
return bizPetMedicalContextService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出宠物医疗上下文列表
|
||||
*/
|
||||
@SaCheckPermission("pet:petMedicalContext:export")
|
||||
@Log(title = "宠物医疗上下文", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(BizPetMedicalContextBo bo, HttpServletResponse response) {
|
||||
List<BizPetMedicalContextVo> list = bizPetMedicalContextService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "宠物医疗上下文", BizPetMedicalContextVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宠物医疗上下文详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("pet:petMedicalContext:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<BizPetMedicalContextVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(bizPetMedicalContextService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增宠物医疗上下文
|
||||
*/
|
||||
@SaCheckPermission("pet:petMedicalContext:add")
|
||||
@Log(title = "宠物医疗上下文", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody BizPetMedicalContextBo bo) {
|
||||
return toAjax(bizPetMedicalContextService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改宠物医疗上下文
|
||||
*/
|
||||
@SaCheckPermission("pet:petMedicalContext:edit")
|
||||
@Log(title = "宠物医疗上下文", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody BizPetMedicalContextBo bo) {
|
||||
return toAjax(bizPetMedicalContextService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除宠物医疗上下文
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("pet:petMedicalContext:remove")
|
||||
@Log(title = "宠物医疗上下文", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(bizPetMedicalContextService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.chat.domain.bo.ChatConfigBo;
|
||||
import org.dromara.chat.domain.vo.ChatConfigVo;
|
||||
import org.dromara.chat.service.ChatConfigService;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天配置控制器
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chat/config")
|
||||
public class ChatConfigController extends BaseController {
|
||||
|
||||
private final ChatConfigService chatConfigService;
|
||||
|
||||
/**
|
||||
* 查询聊天配置列表
|
||||
*/
|
||||
@SaCheckPermission("chat:config:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ChatConfigVo> list(ChatConfigBo bo, PageQuery pageQuery) {
|
||||
return chatConfigService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出聊天配置列表
|
||||
*/
|
||||
@SaCheckPermission("chat:config:export")
|
||||
@Log(title = "聊天配置", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(ChatConfigBo bo, HttpServletResponse response) {
|
||||
List<ChatConfigVo> list = chatConfigService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "聊天配置", ChatConfigVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天配置详细信息
|
||||
*/
|
||||
@SaCheckPermission("chat:config:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<ChatConfigVo> getInfo(@PathVariable Long id) {
|
||||
return R.ok(chatConfigService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天配置
|
||||
*/
|
||||
@SaCheckPermission("chat:config:add")
|
||||
@Log(title = "聊天配置", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated @RequestBody ChatConfigBo bo) {
|
||||
return toAjax(chatConfigService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天配置
|
||||
*/
|
||||
@SaCheckPermission("chat:config:edit")
|
||||
@Log(title = "聊天配置", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public R<Void> edit(@Validated @RequestBody ChatConfigBo bo) {
|
||||
return toAjax(chatConfigService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除聊天配置
|
||||
*/
|
||||
@SaCheckPermission("chat:config:remove")
|
||||
@Log(title = "聊天配置", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@PathVariable Long[] ids) {
|
||||
return toAjax(chatConfigService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置分类查询配置列表
|
||||
*/
|
||||
@SaCheckPermission("chat:config:query")
|
||||
@GetMapping("/category/{category}")
|
||||
public R<List<ChatConfigVo>> getByCategory(@PathVariable String category) {
|
||||
return R.ok(chatConfigService.queryListByCategory(category));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置名称查询配置
|
||||
*/
|
||||
@SaCheckPermission("chat:config:query")
|
||||
@GetMapping("/name/{configName}")
|
||||
public R<ChatConfigVo> getByConfigName(@PathVariable String configName) {
|
||||
return R.ok(chatConfigService.queryByConfigName(configName));
|
||||
}
|
||||
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.chat.domain.bo.ChatMessageBo;
|
||||
import org.dromara.chat.domain.vo.ChatMessageVo;
|
||||
import org.dromara.chat.service.ChatMessageService;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天消息控制器
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chat/message")
|
||||
public class ChatMessageController extends BaseController {
|
||||
|
||||
private final ChatMessageService chatMessageService;
|
||||
|
||||
/**
|
||||
* 查询聊天消息列表
|
||||
*/
|
||||
@SaCheckPermission("chat:message:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ChatMessageVo> list(ChatMessageBo bo, PageQuery pageQuery) {
|
||||
return chatMessageService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出聊天消息列表
|
||||
*/
|
||||
@SaCheckPermission("chat:message:export")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(ChatMessageBo bo, HttpServletResponse response) {
|
||||
List<ChatMessageVo> list = chatMessageService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "聊天消息", ChatMessageVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天消息详细信息
|
||||
*/
|
||||
@SaCheckPermission("chat:message:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<ChatMessageVo> getInfo(@PathVariable Long id) {
|
||||
return R.ok(chatMessageService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天消息
|
||||
*/
|
||||
@SaCheckPermission("chat:message:add")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated @RequestBody ChatMessageBo bo) {
|
||||
return toAjax(chatMessageService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天消息
|
||||
*/
|
||||
@SaCheckPermission("chat:message:edit")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public R<Void> edit(@Validated @RequestBody ChatMessageBo bo) {
|
||||
return toAjax(chatMessageService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除聊天消息
|
||||
*/
|
||||
@SaCheckPermission("chat:message:remove")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@PathVariable Long[] ids) {
|
||||
return toAjax(chatMessageService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据会话ID查询消息列表
|
||||
*/
|
||||
@SaCheckPermission("chat:message:query")
|
||||
@GetMapping("/session/{sessionId}")
|
||||
public R<List<ChatMessageVo>> getBySessionId(@PathVariable Long sessionId) {
|
||||
return R.ok(chatMessageService.queryListBySessionId(sessionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询消息列表
|
||||
*/
|
||||
@SaCheckPermission("chat:message:query")
|
||||
@GetMapping("/user/{userId}")
|
||||
public R<List<ChatMessageVo>> getByUserId(@PathVariable Long userId) {
|
||||
return R.ok(chatMessageService.queryListByUserId(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据会话ID和用户ID查询消息列表
|
||||
*/
|
||||
@SaCheckPermission("chat:message:query")
|
||||
@GetMapping("/session/{sessionId}/user/{userId}")
|
||||
public R<List<ChatMessageVo>> getBySessionIdAndUserId(@PathVariable Long sessionId, @PathVariable Long userId) {
|
||||
return R.ok(chatMessageService.queryListBySessionIdAndUserId(sessionId, userId));
|
||||
}
|
||||
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.chat.domain.bo.ChatModelBo;
|
||||
import org.dromara.chat.domain.vo.ChatModelVo;
|
||||
import org.dromara.chat.service.ChatModelService;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天模型控制器
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chat/model")
|
||||
public class ChatModelController extends BaseController {
|
||||
|
||||
private final ChatModelService chatModelService;
|
||||
|
||||
/**
|
||||
* 查询聊天模型列表
|
||||
*/
|
||||
@SaCheckPermission("chat:model:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ChatModelVo> list(ChatModelBo bo, PageQuery pageQuery) {
|
||||
return chatModelService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出聊天模型列表
|
||||
*/
|
||||
@SaCheckPermission("chat:model:export")
|
||||
@Log(title = "聊天模型", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(ChatModelBo bo, HttpServletResponse response) {
|
||||
List<ChatModelVo> list = chatModelService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "聊天模型", ChatModelVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天模型详细信息
|
||||
*/
|
||||
@SaCheckPermission("chat:model:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<ChatModelVo> getInfo(@PathVariable Long id) {
|
||||
return R.ok(chatModelService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天模型
|
||||
*/
|
||||
@SaCheckPermission("chat:model:add")
|
||||
@Log(title = "聊天模型", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated @RequestBody ChatModelBo bo) {
|
||||
return toAjax(chatModelService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天模型
|
||||
*/
|
||||
@SaCheckPermission("chat:model:edit")
|
||||
@Log(title = "聊天模型", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public R<Void> edit(@Validated @RequestBody ChatModelBo bo) {
|
||||
return toAjax(chatModelService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除聊天模型
|
||||
*/
|
||||
@SaCheckPermission("chat:model:remove")
|
||||
@Log(title = "聊天模型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@PathVariable Long[] ids) {
|
||||
return toAjax(chatModelService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型分类查询模型列表
|
||||
*/
|
||||
@SaCheckPermission("chat:model:query")
|
||||
@GetMapping("/category/{category}")
|
||||
public R<List<ChatModelVo>> getByCategory(@PathVariable String category) {
|
||||
return R.ok(chatModelService.queryListByCategory(category));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型名称查询模型
|
||||
*/
|
||||
@SaCheckPermission("chat:model:query")
|
||||
@GetMapping("/name/{modelName}")
|
||||
public R<ChatModelVo> getByModelName(@PathVariable String modelName) {
|
||||
return R.ok(chatModelService.queryByModelName(modelName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询显示的模型列表
|
||||
*/
|
||||
@SaCheckPermission("chat:model:query")
|
||||
@GetMapping("/show")
|
||||
public R<List<ChatModelVo>> getShowModelList() {
|
||||
return R.ok(chatModelService.queryShowModelList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型类型查询模型列表
|
||||
*/
|
||||
@SaCheckPermission("chat:model:query")
|
||||
@GetMapping("/type/{modelType}")
|
||||
public R<List<ChatModelVo>> getByModelType(@PathVariable String modelType) {
|
||||
return R.ok(chatModelService.queryListByModelType(modelType));
|
||||
}
|
||||
|
||||
}
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.ai.domain.dto.AiChatRequest;
|
||||
import org.dromara.ai.domain.dto.AiChatResponse;
|
||||
import org.dromara.ai.service.AiChatService;
|
||||
import org.dromara.chat.domain.bo.ChatMessageBo;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
import org.dromara.chat.service.ChatMessageService;
|
||||
import org.dromara.chat.service.ChatSessionService;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.springframework.http.MediaType;
|
||||
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.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 开放聊天接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Slf4j
|
||||
@SaCheckLogin
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/chat")
|
||||
public class ChatOpenApiController {
|
||||
|
||||
private final AiChatService aiChatService;
|
||||
private final ChatSessionService chatSessionService;
|
||||
private final ChatMessageService chatMessageService;
|
||||
|
||||
@PostMapping(value = "/send", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
public SseEmitter send(@RequestBody Map<String, Object> body) {
|
||||
SseEmitter emitter = new SseEmitter(TimeUnit.MINUTES.toMillis(10));
|
||||
Long userId;
|
||||
try {
|
||||
userId = LoginHelper.getUserId();
|
||||
} catch (Exception e) {
|
||||
emitter.completeWithError(new RuntimeException("未登录"));
|
||||
return emitter;
|
||||
}
|
||||
|
||||
try {
|
||||
AiChatRequest req = toRequest(body);
|
||||
req.setUserId(String.valueOf(userId));
|
||||
|
||||
// 获取或创建会话
|
||||
String firstMsgContent = "";
|
||||
if (req.getMessages() != null && !req.getMessages().isEmpty()) {
|
||||
firstMsgContent = req.getMessages().get(req.getMessages().size() - 1).getContent();
|
||||
}
|
||||
Long sessionId = getOrCreateSession(userId, req.getSessionId(), firstMsgContent);
|
||||
req.setSessionId(String.valueOf(sessionId));
|
||||
|
||||
// 如果是新会话,尝试通知前端sessionId
|
||||
if (StrUtil.isBlank(req.getSessionId())) {
|
||||
try {
|
||||
emitter.send(SseEmitter.event().name("session").data("{\"sessionId\":\"" + sessionId + "\"}"));
|
||||
} catch (IOException e) {
|
||||
log.error("发送会话ID失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存用户消息
|
||||
saveUserMessage(sessionId, userId, firstMsgContent, req.getModel());
|
||||
|
||||
final StringBuilder fullText = new StringBuilder();
|
||||
final Long finalSessionId = sessionId;
|
||||
final String modelName = req.getModel();
|
||||
|
||||
aiChatService.chatStream(req, new AiChatService.StreamCallback() {
|
||||
@Override
|
||||
public void onChunk(String chunk) {
|
||||
String c = normalizeChunk(chunk);
|
||||
if ("[DONE]".equals(c)) {
|
||||
// ignore
|
||||
} else {
|
||||
fullText.append(c);
|
||||
try {
|
||||
emitter.send(toOpenAiDelta(c, false));
|
||||
} catch (IOException e) {
|
||||
log.debug("发送SSE失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(AiChatResponse response) {
|
||||
try {
|
||||
emitter.send(toOpenAiDelta("", true));
|
||||
emitter.send("[DONE]");
|
||||
emitter.complete();
|
||||
|
||||
// 保存AI响应消息
|
||||
saveAiMessage(finalSessionId, userId, fullText.toString(), modelName);
|
||||
} catch (IOException e) {
|
||||
log.error("发送SSE完成标记失败", e);
|
||||
emitter.completeWithError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable error) {
|
||||
log.error("AI聊天出错", error);
|
||||
try {
|
||||
emitter.send("{\"error\":\"" + error.getMessage().replace("\"", "\\\"") + "\"}");
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
emitter.completeWithError(error);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理聊天请求失败", e);
|
||||
try {
|
||||
emitter.send("{\"error\":\"" + e.getMessage().replace("\"", "\\\"") + "\"}");
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
emitter.completeWithError(e);
|
||||
}
|
||||
return emitter;
|
||||
}
|
||||
|
||||
private Long getOrCreateSession(Long userId, String sessionIdStr, String firstMsgContent) {
|
||||
if (StrUtil.isNotBlank(sessionIdStr)) {
|
||||
Long sessionId = Long.parseLong(sessionIdStr);
|
||||
ChatSessionVo session = chatSessionService.queryById(sessionId);
|
||||
if (session == null) {
|
||||
throw new RuntimeException("会话不存在");
|
||||
}
|
||||
if (!session.getUserId().equals(userId)) {
|
||||
throw new RuntimeException("无权访问该会话");
|
||||
}
|
||||
return sessionId;
|
||||
} else {
|
||||
String title = "新对话";
|
||||
if (StrUtil.isNotBlank(firstMsgContent)) {
|
||||
title = StringUtils.substring(firstMsgContent, 0, 20);
|
||||
}
|
||||
ChatSessionVo session = chatSessionService.createNewSession(userId, title);
|
||||
return session.getId();
|
||||
}
|
||||
}
|
||||
|
||||
private void saveUserMessage(Long sessionId, Long userId, String content, String modelName) {
|
||||
if (StrUtil.isNotBlank(content)) {
|
||||
ChatMessageBo userMsg = new ChatMessageBo();
|
||||
userMsg.setSessionId(sessionId);
|
||||
userMsg.setUserId(userId);
|
||||
userMsg.setRole("user");
|
||||
userMsg.setContent(content);
|
||||
userMsg.setModelName(modelName);
|
||||
userMsg.setCreateTime(new Date());
|
||||
chatMessageService.insertByBo(userMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveAiMessage(Long sessionId, Long userId, String content, String modelName) {
|
||||
if (StrUtil.isNotBlank(content)) {
|
||||
ChatMessageBo aiMsg = new ChatMessageBo();
|
||||
aiMsg.setSessionId(sessionId);
|
||||
aiMsg.setUserId(userId);
|
||||
aiMsg.setRole("assistant");
|
||||
aiMsg.setContent(content);
|
||||
aiMsg.setModelName(modelName);
|
||||
aiMsg.setCreateTime(new Date());
|
||||
aiMsg.setTotalTokens(0L);
|
||||
aiMsg.setDeductCost(BigDecimal.ZERO);
|
||||
chatMessageService.insertByBo(aiMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private AiChatRequest toRequest(Map<String, Object> body) {
|
||||
AiChatRequest req = new AiChatRequest();
|
||||
req.setModel(asString(body.get("model")));
|
||||
req.setTemperature(asDouble(body.get("temperature")));
|
||||
req.setTopP(asDouble(body.get("top_p")));
|
||||
req.setPresencePenalty(asDouble(body.get("presence_penalty")));
|
||||
req.setFrequencyPenalty(asDouble(body.get("frequency_penalty")));
|
||||
req.setMaxTokens(asInt(body.get("max_tokens")));
|
||||
req.setStream(Boolean.TRUE);
|
||||
req.setSessionId(asString(body.get("sessionId")));
|
||||
Object msgs = body.get("messages");
|
||||
if (msgs instanceof List<?> list) {
|
||||
java.util.ArrayList<AiChatRequest.AiMessage> arr = new java.util.ArrayList<>();
|
||||
for (Object o : list) {
|
||||
if (o instanceof Map<?, ?> m) {
|
||||
AiChatRequest.AiMessage am = new AiChatRequest.AiMessage();
|
||||
am.setRole(asString(m.get("role")));
|
||||
am.setContent(asString(m.get("content")));
|
||||
arr.add(am);
|
||||
}
|
||||
}
|
||||
req.setMessages(arr);
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
private String asString(Object o) {
|
||||
return o == null ? null : String.valueOf(o);
|
||||
}
|
||||
|
||||
private Double asDouble(Object o) {
|
||||
try {
|
||||
return o == null ? null : Double.valueOf(String.valueOf(o));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Integer asInt(Object o) {
|
||||
try {
|
||||
return o == null ? null : Integer.valueOf(String.valueOf(o));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String toOpenAiDelta(String content, boolean finish) {
|
||||
String c = content == null ? "" : content;
|
||||
String esc = c.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t");
|
||||
String finishReason = finish ? "\"stop\"" : "null";
|
||||
return "{\"choices\":[{\"delta\":{\"content\":\"" + esc + "\"},\"finish_reason\":" + finishReason + "}]}";
|
||||
}
|
||||
|
||||
private String normalizeChunk(String chunk) {
|
||||
if (chunk == null) return "";
|
||||
String s = chunk.trim();
|
||||
if ("[DONE]".equals(s)) return "[DONE]";
|
||||
try {
|
||||
Map<?, ?> m = JsonUtils.parseObject(s, Map.class);
|
||||
if (m != null) {
|
||||
Object choices = m.get("choices");
|
||||
if (choices instanceof List<?> list && !list.isEmpty()) {
|
||||
Object first = list.get(0);
|
||||
if (first instanceof Map<?, ?> fm) {
|
||||
Object delta = fm.get("delta");
|
||||
if (delta instanceof Map<?, ?> dm) {
|
||||
Object c = dm.get("content");
|
||||
if (c == null) c = dm.get("reasoning_content");
|
||||
if (c != null) return String.valueOf(c);
|
||||
}
|
||||
Object text = fm.get("text");
|
||||
if (text != null) return String.valueOf(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.chat.domain.bo.ChatSessionBo;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
import org.dromara.chat.service.ChatSessionService;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天会话控制器
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chat/session")
|
||||
public class ChatSessionController extends BaseController {
|
||||
|
||||
private final ChatSessionService chatSessionService;
|
||||
|
||||
/**
|
||||
* 查询聊天会话列表
|
||||
*/
|
||||
@SaCheckPermission("chat:session:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ChatSessionVo> list(ChatSessionBo bo, PageQuery pageQuery) {
|
||||
return chatSessionService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出聊天会话列表
|
||||
*/
|
||||
@SaCheckPermission("chat:session:export")
|
||||
@Log(title = "聊天会话", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(ChatSessionBo bo, HttpServletResponse response) {
|
||||
List<ChatSessionVo> list = chatSessionService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "聊天会话", ChatSessionVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天会话详细信息
|
||||
*/
|
||||
@SaCheckPermission("chat:session:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<ChatSessionVo> getInfo(@PathVariable Long id) {
|
||||
return R.ok(chatSessionService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天会话
|
||||
*/
|
||||
@SaCheckPermission("chat:session:add")
|
||||
@Log(title = "聊天会话", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated @RequestBody ChatSessionBo bo) {
|
||||
return toAjax(chatSessionService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天会话
|
||||
*/
|
||||
@SaCheckPermission("chat:session:edit")
|
||||
@Log(title = "聊天会话", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public R<Void> edit(@Validated @RequestBody ChatSessionBo bo) {
|
||||
return toAjax(chatSessionService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除聊天会话
|
||||
*/
|
||||
@SaCheckPermission("chat:session:remove")
|
||||
@Log(title = "聊天会话", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@PathVariable Long[] ids) {
|
||||
return toAjax(chatSessionService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询会话列表
|
||||
*/
|
||||
@SaCheckPermission("chat:session:query")
|
||||
@GetMapping("/user/{userId}")
|
||||
public R<List<ChatSessionVo>> getByUserId(@PathVariable Long userId) {
|
||||
return R.ok(chatSessionService.queryListByUserId(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
*/
|
||||
@SaCheckPermission("chat:session:add")
|
||||
@Log(title = "聊天会话", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/create")
|
||||
public R<ChatSessionVo> createNewSession(@RequestParam Long userId, @RequestParam(required = false) String sessionTitle) {
|
||||
return R.ok(chatSessionService.createNewSession(userId, sessionTitle));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新会话标题
|
||||
*/
|
||||
@SaCheckPermission("chat:session:edit")
|
||||
@Log(title = "聊天会话", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{sessionId}/title")
|
||||
public R<Void> updateSessionTitle(@PathVariable Long sessionId, @RequestParam String sessionTitle) {
|
||||
return toAjax(chatSessionService.updateSessionTitle(sessionId, sessionTitle));
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.chat.domain.bo.ChatMessageBo;
|
||||
import org.dromara.chat.service.ChatMessageService;
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class ChatStompController {
|
||||
private final SimpMessagingTemplate messagingTemplate;
|
||||
private final ChatMessageService chatMessageService;
|
||||
|
||||
@MessageMapping("/chat/send")
|
||||
public void send(@Payload Map<String, Object> payload) {
|
||||
Long sessionId = toLong(payload.get("sessionId"));
|
||||
Long userId = toLong(payload.get("userId"));
|
||||
String content = String.valueOf(payload.get("content"));
|
||||
ChatMessageBo bo = new ChatMessageBo();
|
||||
bo.setSessionId(sessionId);
|
||||
bo.setUserId(userId);
|
||||
bo.setContent(content);
|
||||
bo.setRole("user");
|
||||
chatMessageService.insertByBo(bo);
|
||||
messagingTemplate.convertAndSend("/topic/session/" + sessionId, Map.of(
|
||||
"sessionId", sessionId, "userId", userId, "content", content));
|
||||
}
|
||||
|
||||
private Long toLong(Object o) {
|
||||
if (o == null) return null;
|
||||
if (o instanceof Number) return ((Number) o).longValue();
|
||||
try {
|
||||
return Long.parseLong(String.valueOf(o));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package org.dromara.chat.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.chat.domain.bo.ChatUsageTokenBo;
|
||||
import org.dromara.chat.domain.vo.ChatUsageTokenVo;
|
||||
import org.dromara.chat.service.ChatUsageTokenService;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天Token使用记录控制器
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chat/token")
|
||||
public class ChatUsageTokenController extends BaseController {
|
||||
|
||||
private final ChatUsageTokenService chatUsageTokenService;
|
||||
|
||||
/**
|
||||
* 查询聊天Token使用记录列表
|
||||
*/
|
||||
@SaCheckPermission("chat:token:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ChatUsageTokenVo> list(ChatUsageTokenBo bo, PageQuery pageQuery) {
|
||||
return chatUsageTokenService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出聊天Token使用记录列表
|
||||
*/
|
||||
@SaCheckPermission("chat:token:export")
|
||||
@Log(title = "聊天Token使用记录", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(ChatUsageTokenBo bo, HttpServletResponse response) {
|
||||
List<ChatUsageTokenVo> list = chatUsageTokenService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "聊天Token使用记录", ChatUsageTokenVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天Token使用记录详细信息
|
||||
*/
|
||||
@SaCheckPermission("chat:token:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<ChatUsageTokenVo> getInfo(@PathVariable Long id) {
|
||||
return R.ok(chatUsageTokenService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天Token使用记录
|
||||
*/
|
||||
@SaCheckPermission("chat:token:add")
|
||||
@Log(title = "聊天Token使用记录", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated @RequestBody ChatUsageTokenBo bo) {
|
||||
return toAjax(chatUsageTokenService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天Token使用记录
|
||||
*/
|
||||
@SaCheckPermission("chat:token:edit")
|
||||
@Log(title = "聊天Token使用记录", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public R<Void> edit(@Validated @RequestBody ChatUsageTokenBo bo) {
|
||||
return toAjax(chatUsageTokenService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除聊天Token使用记录
|
||||
*/
|
||||
@SaCheckPermission("chat:token:remove")
|
||||
@Log(title = "聊天Token使用记录", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@PathVariable Long[] ids) {
|
||||
return toAjax(chatUsageTokenService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询Token使用记录列表
|
||||
*/
|
||||
@SaCheckPermission("chat:token:query")
|
||||
@GetMapping("/user/{userId}")
|
||||
public R<List<ChatUsageTokenVo>> getByUserId(@PathVariable Long userId) {
|
||||
return R.ok(chatUsageTokenService.queryListByUserId(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型名称查询Token使用记录列表
|
||||
*/
|
||||
@SaCheckPermission("chat:token:query")
|
||||
@GetMapping("/model/{modelName}")
|
||||
public R<List<ChatUsageTokenVo>> getByModelName(@PathVariable String modelName) {
|
||||
return R.ok(chatUsageTokenService.queryListByModelName(modelName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户总Token使用量
|
||||
*/
|
||||
@SaCheckPermission("chat:token:query")
|
||||
@GetMapping("/total/user/{userId}")
|
||||
public R<Long> getTotalTokenByUserId(@PathVariable Long userId) {
|
||||
return R.ok(chatUsageTokenService.getTotalTokenByUserId(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型总Token使用量
|
||||
*/
|
||||
@SaCheckPermission("chat:token:query")
|
||||
@GetMapping("/total/model/{modelName}")
|
||||
public R<Long> getTotalTokenByModelName(@PathVariable String modelName) {
|
||||
return R.ok(chatUsageTokenService.getTotalTokenByModelName(modelName));
|
||||
}
|
||||
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package org.dromara.pet.domain;
|
||||
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 宠物医疗上下文对象 biz_pet_medical_context
|
||||
*
|
||||
* @author shuo
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("biz_pet_medical_context")
|
||||
public class BizPetMedicalContext extends
|
||||
|
||||
BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 关联宠物ID
|
||||
*/
|
||||
private Long petId;
|
||||
|
||||
/**
|
||||
* 过敏史
|
||||
*/
|
||||
private String allergies;
|
||||
|
||||
/**
|
||||
* 疫苗接种记录
|
||||
*/
|
||||
private String vaccinations;
|
||||
|
||||
/**
|
||||
* 慢性病史
|
||||
*/
|
||||
private String chronicConditions;
|
||||
|
||||
/**
|
||||
* 日常用药
|
||||
*/
|
||||
private String regularMedications;
|
||||
|
||||
/**
|
||||
* 业务更新时间
|
||||
*/
|
||||
private Date updatedAt;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.dromara.chat.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天配置对象 chat_config
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@TableName("chat_config")
|
||||
public class ChatConfig implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 配置分类
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 配置名称
|
||||
*/
|
||||
private String configName;
|
||||
|
||||
/**
|
||||
* 配置值
|
||||
*/
|
||||
private String configValue;
|
||||
|
||||
/**
|
||||
* 配置字典
|
||||
*/
|
||||
private String configDict;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 2代表删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private String delFlag;
|
||||
|
||||
/**
|
||||
* 更新IP
|
||||
*/
|
||||
private String updateIp;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package org.dromara.chat.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天消息对象 chat_message
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@TableName("chat_message")
|
||||
public class ChatMessage implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会话ID
|
||||
*/
|
||||
private Long sessionId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 角色(user/assistant/system)
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 扣费成本
|
||||
*/
|
||||
private BigDecimal deductCost;
|
||||
|
||||
/**
|
||||
* 总token数
|
||||
*/
|
||||
private Long totalTokens;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.dromara.chat.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天模型对象 chat_model
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@TableName("chat_model")
|
||||
public class ChatModel implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 模型描述
|
||||
*/
|
||||
private String modelDescribe;
|
||||
|
||||
/**
|
||||
* 模型价格
|
||||
*/
|
||||
private BigDecimal modelPrice;
|
||||
|
||||
/**
|
||||
* 模型类型
|
||||
*/
|
||||
private String modelType;
|
||||
|
||||
/**
|
||||
* 是否显示(0隐藏 1显示)
|
||||
*/
|
||||
private String modelShow;
|
||||
|
||||
/**
|
||||
* 系统提示词
|
||||
*/
|
||||
private String systemPrompt;
|
||||
|
||||
/**
|
||||
* API主机地址
|
||||
*/
|
||||
private String apiHost;
|
||||
|
||||
/**
|
||||
* API密钥
|
||||
*/
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.dromara.chat.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天会话对象 chat_session
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@TableName("chat_session")
|
||||
public class ChatSession implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 会话标题
|
||||
*/
|
||||
private String sessionTitle;
|
||||
|
||||
/**
|
||||
* 会话内容
|
||||
*/
|
||||
private String sessionContent;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.dromara.chat.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 聊天使用令牌对象 chat_usage_token
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@TableName("chat_usage_token")
|
||||
public class ChatUsageToken implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 令牌数量
|
||||
*/
|
||||
private Long token;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 总令牌数
|
||||
*/
|
||||
private Long totalToken;
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package org.dromara.pet.domain.bo;
|
||||
|
||||
import org.dromara.pet.domain.BizPetMedicalContext;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 宠物医疗上下文业务对象 biz_pet_medical_context
|
||||
*
|
||||
* @author shuo
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = BizPetMedicalContext.class,reverseConvertGenerate =false)
|
||||
|
||||
public class BizPetMedicalContextBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 关联宠物ID
|
||||
*/
|
||||
private Long petId;
|
||||
|
||||
/**
|
||||
* 过敏史
|
||||
*/
|
||||
@NotBlank(message = "过敏史不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String allergies;
|
||||
|
||||
/**
|
||||
* 疫苗接种记录
|
||||
*/
|
||||
@NotBlank(message = "疫苗接种记录不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String vaccinations;
|
||||
|
||||
/**
|
||||
* 慢性病史
|
||||
*/
|
||||
@NotBlank(message = "慢性病史不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String chronicConditions;
|
||||
|
||||
/**
|
||||
* 日常用药
|
||||
*/
|
||||
@NotBlank(message = "日常用药不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String regularMedications;
|
||||
|
||||
/**
|
||||
* 业务更新时间
|
||||
*/
|
||||
@NotNull(message = "业务更新时间不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Date updatedAt;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
@NotBlank(message = "租户编号不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String tenantId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.dromara.chat.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.chat.domain.ChatConfig;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 聊天配置业务对象 chat_config
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = ChatConfig.class, reverseConvertGenerate = false)
|
||||
public class ChatConfigBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 配置分类
|
||||
*/
|
||||
@NotBlank(message = "配置分类不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 配置名称
|
||||
*/
|
||||
@NotBlank(message = "配置名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String configName;
|
||||
|
||||
/**
|
||||
* 配置值
|
||||
*/
|
||||
@NotBlank(message = "配置值不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String configValue;
|
||||
|
||||
/**
|
||||
* 配置字典
|
||||
*/
|
||||
private String configDict;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 更新IP
|
||||
*/
|
||||
private String updateIp;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.dromara.chat.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.chat.domain.ChatMessage;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 聊天消息业务对象 chat_message
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = ChatMessage.class, reverseConvertGenerate = false)
|
||||
public class ChatMessageBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会话ID
|
||||
*/
|
||||
@NotNull(message = "会话ID不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long sessionId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 消息类型(text/image/file)
|
||||
*/
|
||||
@NotBlank(message = "消息类型不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String messageType;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@NotBlank(message = "消息内容不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 角色(user/assistant/system)
|
||||
*/
|
||||
@NotBlank(message = "角色不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 扣费成本
|
||||
*/
|
||||
private BigDecimal deductCost;
|
||||
|
||||
/**
|
||||
* 总token数
|
||||
*/
|
||||
private Long totalTokens;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.dromara.chat.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.chat.domain.ChatModel;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 聊天模型业务对象 chat_model
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = ChatModel.class, reverseConvertGenerate = false)
|
||||
public class ChatModelBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
@NotBlank(message = "模型分类不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
@NotBlank(message = "模型名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 模型描述
|
||||
*/
|
||||
private String modelDescribe;
|
||||
|
||||
/**
|
||||
* 模型价格
|
||||
*/
|
||||
private BigDecimal modelPrice;
|
||||
|
||||
/**
|
||||
* 模型类型
|
||||
*/
|
||||
private String modelType;
|
||||
|
||||
/**
|
||||
* 是否显示(0隐藏 1显示)
|
||||
*/
|
||||
private String modelShow;
|
||||
|
||||
/**
|
||||
* 系统提示词
|
||||
*/
|
||||
private String systemPrompt;
|
||||
|
||||
/**
|
||||
* API主机地址
|
||||
*/
|
||||
private String apiHost;
|
||||
|
||||
/**
|
||||
* API密钥
|
||||
*/
|
||||
private String apiKey;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.dromara.chat.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.chat.domain.ChatSession;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 聊天会话业务对象 chat_session
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = ChatSession.class, reverseConvertGenerate = false)
|
||||
public class ChatSessionBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 会话标题
|
||||
*/
|
||||
@NotBlank(message = "会话标题不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String sessionTitle;
|
||||
|
||||
/**
|
||||
* 会话内容
|
||||
*/
|
||||
private String sessionContent;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.dromara.chat.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.dromara.chat.domain.ChatUsageToken;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 聊天使用令牌业务对象 chat_usage_token
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = ChatUsageToken.class, reverseConvertGenerate = false)
|
||||
public class ChatUsageTokenBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 令牌数量
|
||||
*/
|
||||
@NotNull(message = "令牌数量不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long token;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 总令牌数
|
||||
*/
|
||||
private Long totalToken;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.dromara.chat.domain.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 聊天请求基础类
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
public class ChatRequest {
|
||||
|
||||
/**
|
||||
* 会话ID
|
||||
*/
|
||||
@NotBlank(message = "会话ID不能为空")
|
||||
private String sessionId;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@NotBlank(message = "消息内容不能为空")
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package org.dromara.chat.domain.request;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 多Provider聊天请求
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MultiProviderChatRequest extends ChatRequest {
|
||||
|
||||
/**
|
||||
* Provider名称列表
|
||||
*/
|
||||
@NotNull(message = "Provider列表不能为空")
|
||||
@NotEmpty(message = "Provider列表不能为空")
|
||||
private List<String> providerNames;
|
||||
|
||||
/**
|
||||
* 是否合并结果
|
||||
*/
|
||||
private Boolean mergeResults = true;
|
||||
|
||||
/**
|
||||
* 最大并发数
|
||||
*/
|
||||
private Integer maxConcurrency = 3;
|
||||
|
||||
/**
|
||||
* 超时时间(秒)
|
||||
*/
|
||||
private Integer timeoutSeconds = 30;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.dromara.chat.domain.request;
|
||||
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 回答质量评估请求
|
||||
*
|
||||
* @author pengles
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
public class RateRequest {
|
||||
|
||||
/**
|
||||
* 消息ID
|
||||
*/
|
||||
@NotBlank(message = "消息ID不能为空")
|
||||
private String messageId;
|
||||
|
||||
/**
|
||||
* 评分(1-5分)
|
||||
*/
|
||||
@NotNull(message = "评分不能为空")
|
||||
@Min(value = 1, message = "评分不能小于1")
|
||||
@Max(value = 5, message = "评分不能大于5")
|
||||
private Integer rating;
|
||||
|
||||
/**
|
||||
* 反馈内容
|
||||
*/
|
||||
private String feedback;
|
||||
|
||||
/**
|
||||
* 评估维度
|
||||
*/
|
||||
private String dimension;
|
||||
|
||||
/**
|
||||
* 是否匿名
|
||||
*/
|
||||
private Boolean anonymous = false;
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package org.dromara.pet.domain.vo;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.dromara.pet.domain.BizPetMedicalContext;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 宠物医疗上下文视图对象 biz_pet_medical_context
|
||||
*
|
||||
* @author shuo
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = BizPetMedicalContext.class)
|
||||
|
||||
public class BizPetMedicalContextVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 关联宠物ID
|
||||
*/
|
||||
@ExcelProperty(value = "关联宠物ID")
|
||||
private Long petId;
|
||||
|
||||
/**
|
||||
* 过敏史
|
||||
*/
|
||||
@ExcelProperty(value = "过敏史")
|
||||
private String allergies;
|
||||
|
||||
/**
|
||||
* 疫苗接种记录
|
||||
*/
|
||||
@ExcelProperty(value = "疫苗接种记录")
|
||||
private String vaccinations;
|
||||
|
||||
/**
|
||||
* 慢性病史
|
||||
*/
|
||||
@ExcelProperty(value = "慢性病史")
|
||||
private String chronicConditions;
|
||||
|
||||
/**
|
||||
* 日常用药
|
||||
*/
|
||||
@ExcelProperty(value = "日常用药")
|
||||
private String regularMedications;
|
||||
|
||||
/**
|
||||
* 业务更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "业务更新时间")
|
||||
private Date updatedAt;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
@ExcelProperty(value = "租户编号")
|
||||
private String tenantId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.dromara.chat.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.chat.domain.ChatConfig;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天配置视图对象 chat_config
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = ChatConfig.class)
|
||||
public class ChatConfigVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 配置分类
|
||||
*/
|
||||
@ExcelProperty(value = "配置分类")
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 配置名称
|
||||
*/
|
||||
@ExcelProperty(value = "配置名称")
|
||||
private String configName;
|
||||
|
||||
/**
|
||||
* 配置值
|
||||
*/
|
||||
@ExcelProperty(value = "配置值")
|
||||
private String configValue;
|
||||
|
||||
/**
|
||||
* 配置字典
|
||||
*/
|
||||
@ExcelProperty(value = "配置字典")
|
||||
private String configDict;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
@ExcelProperty(value = "版本号")
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 删除标志
|
||||
*/
|
||||
@ExcelProperty(value = "删除标志", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "0=正常,2=删除")
|
||||
private String delFlag;
|
||||
|
||||
/**
|
||||
* 更新IP
|
||||
*/
|
||||
@ExcelProperty(value = "更新IP")
|
||||
private String updateIp;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.dromara.chat.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.chat.domain.ChatMessage;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天消息视图对象 chat_message
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = ChatMessage.class)
|
||||
public class ChatMessageVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会话ID
|
||||
*/
|
||||
@ExcelProperty(value = "会话ID")
|
||||
private Long sessionId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@ExcelProperty(value = "消息内容")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 角色(user/assistant/system)
|
||||
*/
|
||||
@ExcelProperty(value = "角色")
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 扣费成本
|
||||
*/
|
||||
@ExcelProperty(value = "扣费成本")
|
||||
private BigDecimal deductCost;
|
||||
|
||||
/**
|
||||
* 总token数
|
||||
*/
|
||||
@ExcelProperty(value = "总token数")
|
||||
private Long totalTokens;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
@ExcelProperty(value = "模型名称")
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.dromara.chat.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.chat.domain.ChatModel;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天模型视图对象 chat_model
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = ChatModel.class)
|
||||
public class ChatModelVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
@ExcelProperty(value = "模型分类")
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
@ExcelProperty(value = "模型名称")
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 模型描述
|
||||
*/
|
||||
@ExcelProperty(value = "模型描述")
|
||||
private String modelDescribe;
|
||||
|
||||
/**
|
||||
* 模型价格
|
||||
*/
|
||||
@ExcelProperty(value = "模型价格")
|
||||
private BigDecimal modelPrice;
|
||||
|
||||
/**
|
||||
* 模型类型
|
||||
*/
|
||||
@ExcelProperty(value = "模型类型")
|
||||
private String modelType;
|
||||
|
||||
/**
|
||||
* 是否显示(0隐藏 1显示)
|
||||
*/
|
||||
@ExcelProperty(value = "是否显示", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "0=隐藏,1=显示")
|
||||
private String modelShow;
|
||||
|
||||
/**
|
||||
* 系统提示词
|
||||
*/
|
||||
@ExcelProperty(value = "系统提示词")
|
||||
private String systemPrompt;
|
||||
|
||||
/**
|
||||
* API主机地址
|
||||
*/
|
||||
@ExcelProperty(value = "API主机地址")
|
||||
private String apiHost;
|
||||
|
||||
/**
|
||||
* API密钥
|
||||
*/
|
||||
@ExcelProperty(value = "API密钥")
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.dromara.chat.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.chat.domain.ChatSession;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天会话视图对象 chat_session
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = ChatSession.class)
|
||||
public class ChatSessionVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 会话标题
|
||||
*/
|
||||
@ExcelProperty(value = "会话标题")
|
||||
private String sessionTitle;
|
||||
|
||||
/**
|
||||
* 会话内容
|
||||
*/
|
||||
@ExcelProperty(value = "会话内容")
|
||||
private String sessionContent;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.dromara.chat.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.chat.domain.ChatUsageToken;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天Token使用记录视图对象 chat_usage_token
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = ChatUsageToken.class)
|
||||
public class ChatUsageTokenVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 使用token数
|
||||
*/
|
||||
@ExcelProperty(value = "使用token数")
|
||||
private Long token;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
@ExcelProperty(value = "模型名称")
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 总token数
|
||||
*/
|
||||
@ExcelProperty(value = "总token数")
|
||||
private Long totalToken;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package org.dromara.pet.mapper;
|
||||
|
||||
import org.dromara.pet.domain.BizPetMedicalContext;
|
||||
import org.dromara.pet.domain.vo.BizPetMedicalContextVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 宠物医疗上下文Mapper接口
|
||||
*
|
||||
* @author shuo
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
public interface BizPetMedicalContextMapper extends BaseMapperPlus<BizPetMedicalContext, BizPetMedicalContextVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.chat.mapper;
|
||||
|
||||
import org.dromara.chat.domain.ChatConfig;
|
||||
import org.dromara.chat.domain.vo.ChatConfigVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 聊天配置Mapper接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatConfigMapper extends BaseMapperPlus<ChatConfig, ChatConfigVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.chat.mapper;
|
||||
|
||||
import org.dromara.chat.domain.ChatMessage;
|
||||
import org.dromara.chat.domain.vo.ChatMessageVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 聊天消息Mapper接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatMessageMapper extends BaseMapperPlus<ChatMessage, ChatMessageVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.chat.mapper;
|
||||
|
||||
import org.dromara.chat.domain.ChatModel;
|
||||
import org.dromara.chat.domain.vo.ChatModelVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 聊天模型Mapper接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatModelMapper extends BaseMapperPlus<ChatModel, ChatModelVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.chat.mapper;
|
||||
|
||||
import org.dromara.chat.domain.ChatSession;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 聊天会话Mapper接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatSessionMapper extends BaseMapperPlus<ChatSession, ChatSessionVo> {
|
||||
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package org.dromara.chat.mapper;
|
||||
|
||||
import org.dromara.chat.domain.ChatUsageToken;
|
||||
import org.dromara.chat.domain.vo.ChatUsageTokenVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 聊天Token使用记录Mapper接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatUsageTokenMapper extends BaseMapperPlus<ChatUsageToken, ChatUsageTokenVo> {
|
||||
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package org.dromara.chat.service;
|
||||
|
||||
import org.dromara.chat.domain.vo.ChatMessageVo;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 知识库聊天服务接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface AiKnowledgeChatService {
|
||||
|
||||
/**
|
||||
* 基于知识库进行智能问答
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @param userId 用户ID
|
||||
* @param question 用户问题
|
||||
* @param knowledgeId 知识库ID
|
||||
* @param modelName 使用的模型名称
|
||||
* @return 聊天回复消息
|
||||
*/
|
||||
ChatMessageVo chatWithKnowledge(Long sessionId, Long userId, String question, Long knowledgeId, String modelName);
|
||||
|
||||
/**
|
||||
* 创建知识库聊天会话
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param knowledgeId 知识库ID
|
||||
* @param sessionTitle 会话标题
|
||||
* @return 聊天会话
|
||||
*/
|
||||
ChatSessionVo createKnowledgeSession(Long userId, Long knowledgeId, String sessionTitle);
|
||||
|
||||
/**
|
||||
* 搜索相关知识库内容
|
||||
*
|
||||
* @param knowledgeId 知识库ID
|
||||
* @param query 查询内容
|
||||
* @param limit 返回数量限制
|
||||
* @return 相关知识库内容列表
|
||||
*/
|
||||
List<String> searchKnowledgeContent(Long knowledgeId, String query, Integer limit);
|
||||
|
||||
/**
|
||||
* 构建知识库上下文
|
||||
*
|
||||
* @param knowledgeId 知识库ID
|
||||
* @param question 用户问题
|
||||
* @return 构建的上下文内容
|
||||
*/
|
||||
String buildKnowledgeContext(Long knowledgeId, String question);
|
||||
|
||||
/**
|
||||
* 获取知识库聊天历史
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @param limit 返回数量限制
|
||||
* @return 聊天历史消息列表
|
||||
*/
|
||||
List<ChatMessageVo> getKnowledgeChatHistory(Long sessionId, Integer limit);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.dromara.chat.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.dromara.chat.domain.ChatConfig;
|
||||
import org.dromara.chat.domain.bo.ChatConfigBo;
|
||||
import org.dromara.chat.domain.vo.ChatConfigVo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天配置Service接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatConfigService extends IService<ChatConfig> {
|
||||
|
||||
/**
|
||||
* 查询聊天配置
|
||||
*/
|
||||
ChatConfigVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询聊天配置列表
|
||||
*/
|
||||
TableDataInfo<ChatConfigVo> queryPageList(ChatConfigBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询聊天配置列表
|
||||
*/
|
||||
List<ChatConfigVo> queryList(ChatConfigBo bo);
|
||||
|
||||
/**
|
||||
* 新增聊天配置
|
||||
*/
|
||||
Boolean insertByBo(ChatConfigBo bo);
|
||||
|
||||
/**
|
||||
* 修改聊天配置
|
||||
*/
|
||||
Boolean updateByBo(ChatConfigBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天配置
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 根据配置分类查询配置列表
|
||||
*/
|
||||
List<ChatConfigVo> queryListByCategory(String category);
|
||||
|
||||
/**
|
||||
* 根据配置名称查询配置
|
||||
*/
|
||||
ChatConfigVo queryByConfigName(String configName);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.dromara.chat.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.dromara.chat.domain.ChatMessage;
|
||||
import org.dromara.chat.domain.bo.ChatMessageBo;
|
||||
import org.dromara.chat.domain.vo.ChatMessageVo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天消息Service接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatMessageService extends IService<ChatMessage> {
|
||||
|
||||
/**
|
||||
* 查询聊天消息
|
||||
*/
|
||||
ChatMessageVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询聊天消息列表
|
||||
*/
|
||||
TableDataInfo<ChatMessageVo> queryPageList(ChatMessageBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询聊天消息列表
|
||||
*/
|
||||
List<ChatMessageVo> queryList(ChatMessageBo bo);
|
||||
|
||||
/**
|
||||
* 新增聊天消息
|
||||
*/
|
||||
Boolean insertByBo(ChatMessageBo bo);
|
||||
|
||||
/**
|
||||
* 修改聊天消息
|
||||
*/
|
||||
Boolean updateByBo(ChatMessageBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 根据会话ID查询消息列表
|
||||
*/
|
||||
List<ChatMessageVo> queryListBySessionId(Long sessionId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询消息列表
|
||||
*/
|
||||
List<ChatMessageVo> queryListByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据会话ID和用户ID查询消息列表
|
||||
*/
|
||||
List<ChatMessageVo> queryListBySessionIdAndUserId(Long sessionId, Long userId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.dromara.chat.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.dromara.chat.domain.ChatModel;
|
||||
import org.dromara.chat.domain.bo.ChatModelBo;
|
||||
import org.dromara.chat.domain.vo.ChatModelVo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天模型Service接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatModelService extends IService<ChatModel> {
|
||||
|
||||
/**
|
||||
* 查询聊天模型
|
||||
*/
|
||||
ChatModelVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询聊天模型列表
|
||||
*/
|
||||
TableDataInfo<ChatModelVo> queryPageList(ChatModelBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询聊天模型列表
|
||||
*/
|
||||
List<ChatModelVo> queryList(ChatModelBo bo);
|
||||
|
||||
/**
|
||||
* 新增聊天模型
|
||||
*/
|
||||
Boolean insertByBo(ChatModelBo bo);
|
||||
|
||||
/**
|
||||
* 修改聊天模型
|
||||
*/
|
||||
Boolean updateByBo(ChatModelBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天模型
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 根据模型分类查询模型列表
|
||||
*/
|
||||
List<ChatModelVo> queryListByCategory(String category);
|
||||
|
||||
/**
|
||||
* 根据模型名称查询模型
|
||||
*/
|
||||
ChatModelVo queryByModelName(String modelName);
|
||||
|
||||
/**
|
||||
* 查询显示的模型列表
|
||||
*/
|
||||
List<ChatModelVo> queryShowModelList();
|
||||
|
||||
/**
|
||||
* 根据模型类型查询模型列表
|
||||
*/
|
||||
List<ChatModelVo> queryListByModelType(String modelType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.dromara.chat.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.dromara.chat.domain.ChatSession;
|
||||
import org.dromara.chat.domain.bo.ChatSessionBo;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天会话Service接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatSessionService extends IService<ChatSession> {
|
||||
|
||||
/**
|
||||
* 查询聊天会话
|
||||
*/
|
||||
ChatSessionVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询聊天会话列表
|
||||
*/
|
||||
TableDataInfo<ChatSessionVo> queryPageList(ChatSessionBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询聊天会话列表
|
||||
*/
|
||||
List<ChatSessionVo> queryList(ChatSessionBo bo);
|
||||
|
||||
/**
|
||||
* 新增聊天会话
|
||||
*/
|
||||
Boolean insertByBo(ChatSessionBo bo);
|
||||
|
||||
/**
|
||||
* 修改聊天会话
|
||||
*/
|
||||
Boolean updateByBo(ChatSessionBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天会话
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询会话列表
|
||||
*/
|
||||
List<ChatSessionVo> queryListByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
*/
|
||||
ChatSessionVo createNewSession(Long userId, String sessionTitle);
|
||||
|
||||
/**
|
||||
* 更新会话标题
|
||||
*/
|
||||
Boolean updateSessionTitle(Long sessionId, String sessionTitle);
|
||||
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package org.dromara.chat.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.dromara.chat.domain.ChatUsageToken;
|
||||
import org.dromara.chat.domain.bo.ChatUsageTokenBo;
|
||||
import org.dromara.chat.domain.vo.ChatUsageTokenVo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天Token使用记录Service接口
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
public interface ChatUsageTokenService extends IService<ChatUsageToken> {
|
||||
|
||||
/**
|
||||
* 查询聊天Token使用记录
|
||||
*/
|
||||
ChatUsageTokenVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询聊天Token使用记录列表
|
||||
*/
|
||||
TableDataInfo<ChatUsageTokenVo> queryPageList(ChatUsageTokenBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询聊天Token使用记录列表
|
||||
*/
|
||||
List<ChatUsageTokenVo> queryList(ChatUsageTokenBo bo);
|
||||
|
||||
/**
|
||||
* 新增聊天Token使用记录
|
||||
*/
|
||||
Boolean insertByBo(ChatUsageTokenBo bo);
|
||||
|
||||
/**
|
||||
* 修改聊天Token使用记录
|
||||
*/
|
||||
Boolean updateByBo(ChatUsageTokenBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天Token使用记录
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询Token使用记录列表
|
||||
*/
|
||||
List<ChatUsageTokenVo> queryListByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据模型名称查询Token使用记录列表
|
||||
*/
|
||||
List<ChatUsageTokenVo> queryListByModelName(String modelName);
|
||||
|
||||
/**
|
||||
* 统计用户总Token使用量
|
||||
*/
|
||||
Long getTotalTokenByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 统计模型总Token使用量
|
||||
*/
|
||||
Long getTotalTokenByModelName(String modelName);
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package org.dromara.pet.service;
|
||||
|
||||
import org.dromara.pet.domain.vo.BizPetMedicalContextVo;
|
||||
import org.dromara.pet.domain.bo.BizPetMedicalContextBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 宠物医疗上下文Service接口
|
||||
*
|
||||
* @author shuo
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
public interface IBizPetMedicalContextService {
|
||||
|
||||
/**
|
||||
* 查询宠物医疗上下文
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 宠物医疗上下文
|
||||
*/
|
||||
BizPetMedicalContextVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询宠物医疗上下文列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 宠物医疗上下文分页列表
|
||||
*/
|
||||
TableDataInfo<BizPetMedicalContextVo> queryPageList(BizPetMedicalContextBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的宠物医疗上下文列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 宠物医疗上下文列表
|
||||
*/
|
||||
List<BizPetMedicalContextVo> queryList(BizPetMedicalContextBo bo);
|
||||
|
||||
/**
|
||||
* 新增宠物医疗上下文
|
||||
*
|
||||
* @param bo 宠物医疗上下文
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(BizPetMedicalContextBo bo);
|
||||
|
||||
/**
|
||||
* 修改宠物医疗上下文
|
||||
*
|
||||
* @param bo 宠物医疗上下文
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(BizPetMedicalContextBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除宠物医疗上下文信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
package org.dromara.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.ai.domain.dto.AiChatRequest;
|
||||
import org.dromara.ai.domain.dto.AiChatResponse;
|
||||
import org.dromara.ai.service.AiChatService;
|
||||
import org.dromara.chat.domain.bo.ChatMessageBo;
|
||||
import org.dromara.chat.domain.bo.ChatSessionBo;
|
||||
import org.dromara.chat.domain.vo.ChatMessageVo;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
import org.dromara.chat.service.AiKnowledgeChatService;
|
||||
import org.dromara.chat.service.ChatMessageService;
|
||||
import org.dromara.chat.service.ChatSessionService;
|
||||
import org.dromara.knowledge.domain.vo.KnowledgeInfoVo;
|
||||
import org.dromara.knowledge.domain.vo.KnowledgeSearchResultVo;
|
||||
import org.dromara.knowledge.service.KnowledgeInfoService;
|
||||
import org.dromara.knowledge.service.KnowledgeVectorService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 知识库聊天服务实现
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiKnowledgeChatServiceImpl implements AiKnowledgeChatService {
|
||||
|
||||
private final ChatSessionService chatSessionService;
|
||||
private final ChatMessageService chatMessageService;
|
||||
private final KnowledgeInfoService knowledgeInfoService;
|
||||
private final KnowledgeVectorService knowledgeVectorService;
|
||||
private final AiChatService aiChatService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ChatMessageVo chatWithKnowledge(Long sessionId, Long userId, String question, Long knowledgeId, String modelName) {
|
||||
// 验证会话是否存在
|
||||
ChatSessionVo session = chatSessionService.queryById(sessionId);
|
||||
if (ObjectUtil.isNull(session)) {
|
||||
throw new RuntimeException("会话不存在");
|
||||
}
|
||||
|
||||
// 验证知识库是否存在
|
||||
KnowledgeInfoVo knowledge = knowledgeInfoService.queryById(knowledgeId);
|
||||
if (ObjectUtil.isNull(knowledge)) {
|
||||
throw new RuntimeException("知识库不存在");
|
||||
}
|
||||
|
||||
// 保存用户问题
|
||||
ChatMessageBo userMessageBo = new ChatMessageBo();
|
||||
userMessageBo.setSessionId(sessionId);
|
||||
userMessageBo.setUserId(userId);
|
||||
userMessageBo.setMessageType("text");
|
||||
userMessageBo.setContent(question);
|
||||
userMessageBo.setRole("user");
|
||||
userMessageBo.setModelName(modelName);
|
||||
userMessageBo.setCreateTime(new Date());
|
||||
chatMessageService.insertByBo(userMessageBo);
|
||||
|
||||
try {
|
||||
AiChatRequest req = new AiChatRequest()
|
||||
.setUserId(String.valueOf(userId))
|
||||
.setSessionId(String.valueOf(sessionId))
|
||||
.setModel(modelName)
|
||||
.setEnableKnowledge(true)
|
||||
.setKnowledgeId(String.valueOf(knowledgeId))
|
||||
.setKnowledgeLimit(5)
|
||||
.setKnowledgeThreshold(0.7)
|
||||
.setMessages(java.util.List.of(
|
||||
new AiChatRequest.AiMessage().setRole("user").setContent(question)
|
||||
));
|
||||
|
||||
AiChatResponse resp = aiChatService.chat(req);
|
||||
String aiAnswer = "";
|
||||
if (resp != null && resp.getChoices() != null && !resp.getChoices().isEmpty()) {
|
||||
AiChatRequest.AiMessage msg = resp.getChoices().get(0).getMessage();
|
||||
if (msg != null && StrUtil.isNotBlank(msg.getContent())) {
|
||||
aiAnswer = msg.getContent();
|
||||
}
|
||||
}
|
||||
if (StrUtil.isBlank(aiAnswer)) {
|
||||
throw new RuntimeException("AI服务返回空回答");
|
||||
}
|
||||
|
||||
// 保存AI回复
|
||||
ChatMessageBo aiMessageBo = new ChatMessageBo();
|
||||
aiMessageBo.setSessionId(sessionId);
|
||||
aiMessageBo.setUserId(userId);
|
||||
aiMessageBo.setMessageType("text");
|
||||
aiMessageBo.setContent(aiAnswer);
|
||||
aiMessageBo.setRole("assistant");
|
||||
aiMessageBo.setModelName(modelName);
|
||||
aiMessageBo.setTotalTokens(0L); // 简化版本不统计token
|
||||
aiMessageBo.setDeductCost(BigDecimal.ZERO); // 简化版本不计费
|
||||
aiMessageBo.setCreateTime(new Date());
|
||||
chatMessageService.insertByBo(aiMessageBo);
|
||||
|
||||
return chatMessageService.queryById(aiMessageBo.getId());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("知识库聊天失败 - 用户: {}, 会话: {}, 知识库: {}", userId, sessionId, knowledgeId, e);
|
||||
|
||||
// 保存错误回复
|
||||
ChatMessageBo errorMessageBo = new ChatMessageBo();
|
||||
errorMessageBo.setSessionId(sessionId);
|
||||
errorMessageBo.setUserId(userId);
|
||||
errorMessageBo.setMessageType("text");
|
||||
errorMessageBo.setContent("抱歉,AI服务暂时不可用,请稍后重试。");
|
||||
errorMessageBo.setRole("assistant");
|
||||
errorMessageBo.setModelName(modelName);
|
||||
errorMessageBo.setCreateTime(new Date());
|
||||
chatMessageService.insertByBo(errorMessageBo);
|
||||
|
||||
return chatMessageService.queryById(errorMessageBo.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ChatSessionVo createKnowledgeSession(Long userId, Long knowledgeId, String sessionTitle) {
|
||||
// 验证知识库是否存在
|
||||
KnowledgeInfoVo knowledge = knowledgeInfoService.queryById(knowledgeId);
|
||||
if (ObjectUtil.isNull(knowledge)) {
|
||||
throw new RuntimeException("知识库不存在");
|
||||
}
|
||||
|
||||
// 如果没有提供标题,使用知识库名称作为默认标题
|
||||
if (StrUtil.isBlank(sessionTitle)) {
|
||||
sessionTitle = "基于" + knowledge.getKnowledgeName() + "的对话";
|
||||
}
|
||||
|
||||
// 创建会话
|
||||
ChatSessionBo sessionBo = new ChatSessionBo();
|
||||
sessionBo.setUserId(userId);
|
||||
sessionBo.setSessionTitle(sessionTitle);
|
||||
sessionBo.setSessionContent("知识库ID: " + knowledgeId);
|
||||
sessionBo.setCreateTime(new Date());
|
||||
chatSessionService.insertByBo(sessionBo);
|
||||
|
||||
return chatSessionService.queryById(sessionBo.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> searchKnowledgeContent(Long knowledgeId, String query, Integer limit) {
|
||||
try {
|
||||
log.info("搜索知识库内容 - 知识库: {}, 查询: {}, 限制: {}", knowledgeId, query, limit);
|
||||
List<KnowledgeSearchResultVo> searchResults = knowledgeVectorService.vectorSimilaritySearch(
|
||||
String.valueOf(knowledgeId), query, "default", limit != null ? limit : 5, 0.7
|
||||
);
|
||||
return searchResults.stream().map(KnowledgeSearchResultVo::getContent).toList();
|
||||
} catch (Exception e) {
|
||||
log.error("搜索知识库内容失败 - 知识库: {}, 查询: {}", knowledgeId, query, e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildKnowledgeContext(Long knowledgeId, String question) {
|
||||
// 搜索相关知识库内容
|
||||
List<String> relevantContent = searchKnowledgeContent(knowledgeId, question, 3);
|
||||
|
||||
StringBuilder context = new StringBuilder();
|
||||
context.append("以下是相关的知识库内容:\n\n");
|
||||
|
||||
for (int i = 0; i < relevantContent.size(); i++) {
|
||||
context.append("参考资料 ").append(i + 1).append(": ");
|
||||
context.append(relevantContent.get(i)).append("\n\n");
|
||||
}
|
||||
|
||||
return context.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChatMessageVo> getKnowledgeChatHistory(Long sessionId, Integer limit) {
|
||||
// 获取会话的聊天历史
|
||||
List<ChatMessageVo> messages = chatMessageService.queryListBySessionId(sessionId);
|
||||
|
||||
// 如果指定了限制数量,返回最近的消息
|
||||
if (limit != null && limit > 0 && messages.size() > limit) {
|
||||
return messages.subList(Math.max(0, messages.size() - limit), messages.size());
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package org.dromara.pet.service.impl;
|
||||
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.pet.domain.bo.BizPetMedicalContextBo;
|
||||
import org.dromara.pet.domain.vo.BizPetMedicalContextVo;
|
||||
import org.dromara.pet.domain.BizPetMedicalContext;
|
||||
import org.dromara.pet.mapper.BizPetMedicalContextMapper;
|
||||
import org.dromara.pet.service.IBizPetMedicalContextService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 宠物医疗上下文Service业务层处理
|
||||
*
|
||||
* @author shuo
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class BizPetMedicalContextServiceImpl implements IBizPetMedicalContextService {
|
||||
|
||||
private final BizPetMedicalContextMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询宠物医疗上下文
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 宠物医疗上下文
|
||||
*/
|
||||
@Override
|
||||
public BizPetMedicalContextVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询宠物医疗上下文列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 宠物医疗上下文分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<BizPetMedicalContextVo> queryPageList(BizPetMedicalContextBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<BizPetMedicalContext> lqw = buildQueryWrapper(bo);
|
||||
Page<BizPetMedicalContextVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的宠物医疗上下文列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 宠物医疗上下文列表
|
||||
*/
|
||||
@Override
|
||||
public List<BizPetMedicalContextVo> queryList(BizPetMedicalContextBo bo) {
|
||||
LambdaQueryWrapper<BizPetMedicalContext> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<BizPetMedicalContext> buildQueryWrapper(BizPetMedicalContextBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<BizPetMedicalContext> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByAsc(BizPetMedicalContext::getId);
|
||||
lqw.eq(bo.getPetId() != null, BizPetMedicalContext::getPetId, bo.getPetId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getAllergies()), BizPetMedicalContext::getAllergies, bo.getAllergies());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getVaccinations()), BizPetMedicalContext::getVaccinations, bo.getVaccinations());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getChronicConditions()), BizPetMedicalContext::getChronicConditions, bo.getChronicConditions());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getRegularMedications()), BizPetMedicalContext::getRegularMedications, bo.getRegularMedications());
|
||||
lqw.eq(bo.getUpdatedAt() != null, BizPetMedicalContext::getUpdatedAt, bo.getUpdatedAt());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTenantId()), BizPetMedicalContext::getTenantId, bo.getTenantId());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增宠物医疗上下文
|
||||
*
|
||||
* @param bo 宠物医疗上下文
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(BizPetMedicalContextBo bo) {
|
||||
BizPetMedicalContext add = MapstructUtils.convert(bo, BizPetMedicalContext. class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改宠物医疗上下文
|
||||
*
|
||||
* @param bo 宠物医疗上下文
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(BizPetMedicalContextBo bo) {
|
||||
BizPetMedicalContext update = MapstructUtils.convert(bo, BizPetMedicalContext. class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(BizPetMedicalContext entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除宠物医疗上下文信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package org.dromara.chat.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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 org.dromara.chat.domain.ChatConfig;
|
||||
import org.dromara.chat.domain.bo.ChatConfigBo;
|
||||
import org.dromara.chat.domain.vo.ChatConfigVo;
|
||||
import org.dromara.chat.mapper.ChatConfigMapper;
|
||||
import org.dromara.chat.service.ChatConfigService;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天配置Service业务层处理
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ChatConfigServiceImpl extends ServiceImpl<ChatConfigMapper, ChatConfig> implements ChatConfigService {
|
||||
|
||||
/**
|
||||
* 查询聊天配置
|
||||
*/
|
||||
@Override
|
||||
public ChatConfigVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天配置列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ChatConfigVo> queryPageList(ChatConfigBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<ChatConfig> lqw = buildQueryWrapper(bo);
|
||||
Page<ChatConfigVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天配置列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatConfigVo> queryList(ChatConfigBo bo) {
|
||||
LambdaQueryWrapper<ChatConfig> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ChatConfig> buildQueryWrapper(ChatConfigBo bo) {
|
||||
LambdaQueryWrapper<ChatConfig> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getCategory()), ChatConfig::getCategory, bo.getCategory());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getConfigName()), ChatConfig::getConfigName, bo.getConfigName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getConfigValue()), ChatConfig::getConfigValue, bo.getConfigValue());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getVersion()), ChatConfig::getVersion, bo.getVersion());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(ChatConfigBo bo) {
|
||||
ChatConfig add = MapstructUtils.convert(bo, ChatConfig.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(ChatConfigBo bo) {
|
||||
ChatConfig update = MapstructUtils.convert(bo, ChatConfig.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(ChatConfig entity) {
|
||||
// TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置分类查询配置列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatConfigVo> queryListByCategory(String category) {
|
||||
LambdaQueryWrapper<ChatConfig> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatConfig::getCategory, category);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置名称查询配置
|
||||
*/
|
||||
@Override
|
||||
public ChatConfigVo queryByConfigName(String configName) {
|
||||
LambdaQueryWrapper<ChatConfig> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatConfig::getConfigName, configName);
|
||||
return baseMapper.selectVoOne(lqw);
|
||||
}
|
||||
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
package org.dromara.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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 org.dromara.chat.domain.ChatMessage;
|
||||
import org.dromara.chat.domain.bo.ChatMessageBo;
|
||||
import org.dromara.chat.domain.vo.ChatMessageVo;
|
||||
import org.dromara.chat.mapper.ChatMessageMapper;
|
||||
import org.dromara.chat.service.ChatMessageService;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天消息Service业务层处理
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ChatMessageServiceImpl extends ServiceImpl<ChatMessageMapper, ChatMessage> implements ChatMessageService {
|
||||
|
||||
/**
|
||||
* 查询聊天消息
|
||||
*/
|
||||
@Override
|
||||
public ChatMessageVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天消息列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ChatMessageVo> queryPageList(ChatMessageBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<ChatMessage> lqw = buildQueryWrapper(bo);
|
||||
Page<ChatMessageVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天消息列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatMessageVo> queryList(ChatMessageBo bo) {
|
||||
LambdaQueryWrapper<ChatMessage> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ChatMessage> buildQueryWrapper(ChatMessageBo bo) {
|
||||
LambdaQueryWrapper<ChatMessage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ObjectUtil.isNotNull(bo.getSessionId()), ChatMessage::getSessionId, bo.getSessionId());
|
||||
lqw.eq(ObjectUtil.isNotNull(bo.getUserId()), ChatMessage::getUserId, bo.getUserId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getContent()), ChatMessage::getContent, bo.getContent());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getRole()), ChatMessage::getRole, bo.getRole());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getModelName()), ChatMessage::getModelName, bo.getModelName());
|
||||
lqw.orderByDesc(ChatMessage::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天消息
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(ChatMessageBo bo) {
|
||||
ChatMessage add = MapstructUtils.convert(bo, ChatMessage.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天消息
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(ChatMessageBo bo) {
|
||||
ChatMessage update = MapstructUtils.convert(bo, ChatMessage.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(ChatMessage entity) {
|
||||
if (StringUtils.isBlank(entity.getContent())) {
|
||||
throw new IllegalArgumentException("消息内容不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(entity.getRole())) {
|
||||
entity.setRole("user");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据会话ID查询消息列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatMessageVo> queryListBySessionId(Long sessionId) {
|
||||
LambdaQueryWrapper<ChatMessage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatMessage::getSessionId, sessionId);
|
||||
lqw.orderByAsc(ChatMessage::getCreateTime);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询消息列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatMessageVo> queryListByUserId(Long userId) {
|
||||
LambdaQueryWrapper<ChatMessage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatMessage::getUserId, userId);
|
||||
lqw.orderByDesc(ChatMessage::getCreateTime);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据会话ID和用户ID查询消息列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatMessageVo> queryListBySessionIdAndUserId(Long sessionId, Long userId) {
|
||||
LambdaQueryWrapper<ChatMessage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatMessage::getSessionId, sessionId);
|
||||
lqw.eq(ChatMessage::getUserId, userId);
|
||||
lqw.orderByAsc(ChatMessage::getCreateTime);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
package org.dromara.chat.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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 org.dromara.chat.domain.ChatModel;
|
||||
import org.dromara.chat.domain.bo.ChatModelBo;
|
||||
import org.dromara.chat.domain.vo.ChatModelVo;
|
||||
import org.dromara.chat.mapper.ChatModelMapper;
|
||||
import org.dromara.chat.service.ChatModelService;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天模型Service业务层处理
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel> implements ChatModelService {
|
||||
|
||||
/**
|
||||
* 查询聊天模型
|
||||
*/
|
||||
@Override
|
||||
public ChatModelVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天模型列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ChatModelVo> queryPageList(ChatModelBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<ChatModel> lqw = buildQueryWrapper(bo);
|
||||
Page<ChatModelVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatModelVo> queryList(ChatModelBo bo) {
|
||||
LambdaQueryWrapper<ChatModel> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ChatModel> buildQueryWrapper(ChatModelBo bo) {
|
||||
LambdaQueryWrapper<ChatModel> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getCategory()), ChatModel::getCategory, bo.getCategory());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getModelName()), ChatModel::getModelName, bo.getModelName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getModelDescribe()), ChatModel::getModelDescribe, bo.getModelDescribe());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getModelType()), ChatModel::getModelType, bo.getModelType());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getModelShow()), ChatModel::getModelShow, bo.getModelShow());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天模型
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(ChatModelBo bo) {
|
||||
ChatModel add = MapstructUtils.convert(bo, ChatModel.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天模型
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(ChatModelBo bo) {
|
||||
ChatModel update = MapstructUtils.convert(bo, ChatModel.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(ChatModel entity) {
|
||||
// TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天模型
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型分类查询模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatModelVo> queryListByCategory(String category) {
|
||||
LambdaQueryWrapper<ChatModel> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatModel::getCategory, category);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型名称查询模型
|
||||
*/
|
||||
@Override
|
||||
public ChatModelVo queryByModelName(String modelName) {
|
||||
LambdaQueryWrapper<ChatModel> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatModel::getModelName, modelName);
|
||||
return baseMapper.selectVoOne(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询显示的模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatModelVo> queryShowModelList() {
|
||||
LambdaQueryWrapper<ChatModel> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatModel::getModelShow, "1");
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型类型查询模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatModelVo> queryListByModelType(String modelType) {
|
||||
LambdaQueryWrapper<ChatModel> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatModel::getModelType, modelType);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
package org.dromara.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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 org.dromara.chat.domain.ChatMessage;
|
||||
import org.dromara.chat.domain.ChatSession;
|
||||
import org.dromara.chat.domain.bo.ChatSessionBo;
|
||||
import org.dromara.chat.domain.vo.ChatSessionVo;
|
||||
import org.dromara.chat.mapper.ChatMessageMapper;
|
||||
import org.dromara.chat.mapper.ChatSessionMapper;
|
||||
import org.dromara.chat.service.ChatSessionService;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天会话Service业务层处理
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ChatSessionServiceImpl extends ServiceImpl<ChatSessionMapper, ChatSession> implements ChatSessionService {
|
||||
|
||||
private final ChatMessageMapper chatMessageMapper;
|
||||
|
||||
/**
|
||||
* 查询聊天会话
|
||||
*/
|
||||
@Override
|
||||
public ChatSessionVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天会话列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ChatSessionVo> queryPageList(ChatSessionBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<ChatSession> lqw = buildQueryWrapper(bo);
|
||||
Page<ChatSessionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天会话列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatSessionVo> queryList(ChatSessionBo bo) {
|
||||
LambdaQueryWrapper<ChatSession> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ChatSession> buildQueryWrapper(ChatSessionBo bo) {
|
||||
LambdaQueryWrapper<ChatSession> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ObjectUtil.isNotNull(bo.getUserId()), ChatSession::getUserId, bo.getUserId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getSessionTitle()), ChatSession::getSessionTitle, bo.getSessionTitle());
|
||||
lqw.orderByDesc(ChatSession::getUpdateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天会话
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(ChatSessionBo bo) {
|
||||
ChatSession add = MapstructUtils.convert(bo, ChatSession.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天会话
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(ChatSessionBo bo) {
|
||||
ChatSession update = MapstructUtils.convert(bo, ChatSession.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(ChatSession entity) {
|
||||
if (StringUtils.isBlank(entity.getSessionTitle())) {
|
||||
entity.setSessionTitle("新会话");
|
||||
}
|
||||
if (entity.getSessionTitle().length() > 50) {
|
||||
entity.setSessionTitle(entity.getSessionTitle().substring(0, 50));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天会话
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// 删除关联的消息
|
||||
LambdaQueryWrapper<ChatMessage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.in(ChatMessage::getSessionId, ids);
|
||||
chatMessageMapper.delete(lqw);
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询会话列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatSessionVo> queryListByUserId(Long userId) {
|
||||
LambdaQueryWrapper<ChatSession> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatSession::getUserId, userId);
|
||||
lqw.orderByDesc(ChatSession::getUpdateTime);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
*/
|
||||
@Override
|
||||
public ChatSessionVo createNewSession(Long userId, String sessionTitle) {
|
||||
ChatSession session = new ChatSession();
|
||||
session.setUserId(userId);
|
||||
session.setSessionTitle(sessionTitle);
|
||||
baseMapper.insert(session);
|
||||
return baseMapper.selectVoById(session.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新会话标题
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateSessionTitle(Long sessionId, String sessionTitle) {
|
||||
ChatSession session = new ChatSession();
|
||||
session.setId(sessionId);
|
||||
session.setSessionTitle(sessionTitle);
|
||||
return baseMapper.updateById(session) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
package org.dromara.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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 org.dromara.chat.domain.ChatUsageToken;
|
||||
import org.dromara.chat.domain.bo.ChatUsageTokenBo;
|
||||
import org.dromara.chat.domain.vo.ChatUsageTokenVo;
|
||||
import org.dromara.chat.mapper.ChatUsageTokenMapper;
|
||||
import org.dromara.chat.service.ChatUsageTokenService;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天Token使用记录Service业务层处理
|
||||
*
|
||||
* @author pengles
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ChatUsageTokenServiceImpl extends ServiceImpl<ChatUsageTokenMapper, ChatUsageToken> implements ChatUsageTokenService {
|
||||
|
||||
/**
|
||||
* 查询聊天Token使用记录
|
||||
*/
|
||||
@Override
|
||||
public ChatUsageTokenVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天Token使用记录列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<ChatUsageTokenVo> queryPageList(ChatUsageTokenBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<ChatUsageToken> lqw = buildQueryWrapper(bo);
|
||||
Page<ChatUsageTokenVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天Token使用记录列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatUsageTokenVo> queryList(ChatUsageTokenBo bo) {
|
||||
LambdaQueryWrapper<ChatUsageToken> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ChatUsageToken> buildQueryWrapper(ChatUsageTokenBo bo) {
|
||||
LambdaQueryWrapper<ChatUsageToken> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ObjectUtil.isNotNull(bo.getUserId()), ChatUsageToken::getUserId, bo.getUserId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getModelName()), ChatUsageToken::getModelName, bo.getModelName());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天Token使用记录
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(ChatUsageTokenBo bo) {
|
||||
ChatUsageToken add = MapstructUtils.convert(bo, ChatUsageToken.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天Token使用记录
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(ChatUsageTokenBo bo) {
|
||||
ChatUsageToken update = MapstructUtils.convert(bo, ChatUsageToken.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(ChatUsageToken entity) {
|
||||
// TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天Token使用记录
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询Token使用记录列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatUsageTokenVo> queryListByUserId(Long userId) {
|
||||
LambdaQueryWrapper<ChatUsageToken> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatUsageToken::getUserId, userId);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型名称查询Token使用记录列表
|
||||
*/
|
||||
@Override
|
||||
public List<ChatUsageTokenVo> queryListByModelName(String modelName) {
|
||||
LambdaQueryWrapper<ChatUsageToken> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatUsageToken::getModelName, modelName);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计用户总Token使用量
|
||||
*/
|
||||
@Override
|
||||
public Long getTotalTokenByUserId(Long userId) {
|
||||
LambdaQueryWrapper<ChatUsageToken> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatUsageToken::getUserId, userId);
|
||||
lqw.select(ChatUsageToken::getToken);
|
||||
List<ChatUsageToken> list = baseMapper.selectList(lqw);
|
||||
return list.stream().mapToLong(ChatUsageToken::getToken).sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计模型总Token使用量
|
||||
*/
|
||||
@Override
|
||||
public Long getTotalTokenByModelName(String modelName) {
|
||||
LambdaQueryWrapper<ChatUsageToken> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(ChatUsageToken::getModelName, modelName);
|
||||
lqw.select(ChatUsageToken::getToken);
|
||||
List<ChatUsageToken> list = baseMapper.selectList(lqw);
|
||||
return list.stream().mapToLong(ChatUsageToken::getToken).sum();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?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="org.dromara.pet.mapper.BizPetMedicalContextMapper">
|
||||
|
||||
</mapper>
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package org.dromara.chat.service;
|
||||
|
||||
import org.dromara.chat.domain.ChatSession;
|
||||
import org.dromara.chat.domain.bo.ChatSessionBo;
|
||||
import org.dromara.chat.mapper.ChatSessionMapper;
|
||||
import org.dromara.chat.service.impl.ChatSessionServiceImpl;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/**
|
||||
* ChatSessionService单元测试
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class ChatSessionServiceTest {
|
||||
|
||||
@Mock
|
||||
private ChatSessionMapper chatSessionMapper;
|
||||
|
||||
@InjectMocks
|
||||
private ChatSessionServiceImpl chatSessionService;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertByBo() {
|
||||
ChatSessionBo bo = new ChatSessionBo();
|
||||
bo.setUserId(1L);
|
||||
bo.setSessionTitle("Test Session");
|
||||
|
||||
Mockito.when(chatSessionMapper.insert(Mockito.any(ChatSession.class))).thenReturn(1);
|
||||
|
||||
Boolean result = chatSessionService.insertByBo(bo);
|
||||
Assertions.assertTrue(result);
|
||||
Mockito.verify(chatSessionMapper).insert(Mockito.any(ChatSession.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateSessionTitle() {
|
||||
Long sessionId = 1L;
|
||||
String newTitle = "Updated Title";
|
||||
|
||||
Mockito.when(chatSessionMapper.updateById(Mockito.any(ChatSession.class))).thenReturn(1);
|
||||
|
||||
Boolean result = chatSessionService.updateSessionTitle(sessionId, newTitle);
|
||||
Assertions.assertTrue(result);
|
||||
Mockito.verify(chatSessionMapper).updateById(Mockito.any(ChatSession.class));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user