Browse Source

【新增】AI:聊天角色管理(100%)

YunaiV 11 months ago
parent
commit
7344ec8aea

+ 46 - 4
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java

@@ -1,10 +1,12 @@
 package cn.iocoder.yudao.module.ai.controller.admin.model;
 
+import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO;
 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleRespVO;
+import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO;
 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO;
 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
@@ -17,7 +19,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
 @Tag(name = "管理后台 - AI 聊天角色")
 @RestController
@@ -28,13 +33,50 @@ public class AiChatRoleController {
     @Resource
     private AiChatRoleService chatRoleService;
 
-    // TODO 芋艿:我的分页
+    @GetMapping("/my-page")
+    @Operation(summary = "获得【我的】聊天角色分页")
+    public CommonResult<PageResult<AiChatRoleRespVO>> getChatRoleMyPage(@Valid AiChatRolePageReqVO pageReqVO) {
+        PageResult<AiChatRoleDO> pageResult = chatRoleService.getChatRoleMyPage(pageReqVO, getLoginUserId());
+        return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class));
+    }
+
+    @GetMapping("/get-my")
+    @Operation(summary = "获得【我的】聊天角色")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    public CommonResult<AiChatRoleRespVO> getChatRoleMy(@RequestParam("id") Long id) {
+        AiChatRoleDO chatRole = chatRoleService.getChatRole(id);
+        if (ObjUtil.notEqual(chatRole.getUserId(), getLoginUserId())) {
+            return success(null);
+        }
+        return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class));
+    }
+
+    @PostMapping("/create-my")
+    @Operation(summary = "创建【我的】聊天角色")
+    public CommonResult<Long> createChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO createReqVO) {
+        return success(chatRoleService.createChatRoleMy(createReqVO, getLoginUserId()));
+    }
 
-    // TODO 芋艿:我的新增
+    @PutMapping("/update-my")
+    @Operation(summary = "更新【我的】聊天角色")
+    public CommonResult<Boolean> updateChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO updateReqVO) {
+        chatRoleService.updateChatRoleMy(updateReqVO, getLoginUserId());
+        return success(true);
+    }
 
-    // TODO 芋艿:我的修改
+    @DeleteMapping("/delete-my")
+    @Operation(summary = "删除【我的】聊天角色")
+    @Parameter(name = "id", description = "编号", required = true)
+    public CommonResult<Boolean> deleteChatRoleMy(@RequestParam("id") Long id) {
+        chatRoleService.deleteChatRoleMy(id, getLoginUserId());
+        return success(true);
+    }
 
-    // TODO 芋艿:我的删除
+    @GetMapping("/category-list")
+    @Operation(summary = "获得聊天角色的分类列表")
+    public CommonResult<List<String>> getChatRoleCategoryList() {
+         return success(chatRoleService.getChatRoleCategoryList());
+    }
 
     // ========== 角色管理 ==========
 

+ 36 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.Data;
+import org.hibernate.validator.constraints.URL;
+
+@Schema(description = "管理后台 - AI 聊天角色新增/修改【我的】 Request VO")
+@Data
+public class AiChatRoleSaveMyReqVO {
+
+    @Schema(description = "角色编号", example = "32746")
+    private Long id;
+
+    @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+    @NotEmpty(message = "角色名称不能为空")
+    private String name;
+
+    @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
+    @NotEmpty(message = "角色头像不能为空")
+    @URL(message = "角色头像必须是 URL 格式")
+    private String avatar;
+
+    @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
+    @NotEmpty(message = "角色描述不能为空")
+    private String description;
+
+    @Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED, example = "Talk is cheap, i will show code")
+    @NotEmpty(message = "角色欢迎语不能为空")
+    private String welcomeMessage;
+
+    @Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题")
+    @NotEmpty(message = "角色上下文不能为空")
+    private String systemMessage;
+
+}

+ 21 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.ai.dal.mysql;
 
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -7,6 +8,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleP
 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 /**
  * AI 聊天角色 Mapper
  *
@@ -23,4 +26,22 @@ public interface AiChatRoleMapper extends BaseMapperX<AiChatRoleDO> {
                 .orderByAsc(AiChatRoleDO::getSort));
     }
 
+    default PageResult<AiChatRoleDO> selectPageByMy(AiChatRolePageReqVO reqVO, Long userId) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<AiChatRoleDO>()
+                .likeIfPresent(AiChatRoleDO::getName, reqVO.getName())
+                .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory())
+                // 情况一:公开
+                .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus())
+                // 情况二:私有
+                .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getUserId, userId)
+                .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
+                .orderByAsc(AiChatRoleDO::getSort));
+    }
+
+    default List<AiChatRoleDO> selectListGroupByCategory(Integer status) {
+        return selectList(new LambdaQueryWrapperX<AiChatRoleDO>()
+                .eq(AiChatRoleDO::getStatus, status)
+                .apply("GROUP BY category"));
+    }
+
 }

+ 47 - 3
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java

@@ -2,10 +2,13 @@ package cn.iocoder.yudao.module.ai.service.model;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO;
+import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO;
 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO;
 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
 import jakarta.validation.Valid;
 
+import java.util.List;
+
 /**
  * AI 聊天角色 Service 接口
  *
@@ -21,6 +24,15 @@ public interface AiChatRoleService {
      */
     Long createChatRole(@Valid AiChatRoleSaveReqVO createReqVO);
 
+    /**
+     * 创建【我的】聊天角色
+     *
+     * @param createReqVO 创建信息
+     * @param userId 用户编号
+     * @return 编号
+     */
+    Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId);
+
     /**
      * 更新聊天角色
      *
@@ -28,6 +40,14 @@ public interface AiChatRoleService {
      */
     void updateChatRole(@Valid AiChatRoleSaveReqVO updateReqVO);
 
+    /**
+     * 创建【我的】聊天角色
+     *
+     * @param updateReqVO 更新信息
+     * @param userId 用户编号
+     */
+    void updateChatRoleMy(AiChatRoleSaveMyReqVO updateReqVO, Long userId);
+
     /**
      * 删除聊天角色
      *
@@ -35,6 +55,14 @@ public interface AiChatRoleService {
      */
     void deleteChatRole(Long id);
 
+    /**
+     * 删除【我的】聊天角色
+     *
+     * @param id 编号
+     * @param userId 用户编号
+     */
+    void deleteChatRoleMy(Long id, Long userId);
+
     /**
      * 获得聊天角色
      *
@@ -44,18 +72,34 @@ public interface AiChatRoleService {
     AiChatRoleDO getChatRole(Long id);
 
     /**
-     * 校验角色是否存在
+     * 校验聊天角色是否合法
      *
      * @param id 角色编号
      */
     AiChatRoleDO validateChatRole(Long id);
 
     /**
-     * 获得AI 聊天角色分页
+     * 获得聊天角色分页
      *
      * @param pageReqVO 分页查询
-     * @return AI 聊天角色分页
+     * @return 聊天角色分页
      */
     PageResult<AiChatRoleDO> getChatRolePage(AiChatRolePageReqVO pageReqVO);
 
+    /**
+     * 获得【我的】聊天角色分页
+     *
+     * @param pageReqVO 分页查询
+     * @param userId 用户编号
+     * @return 聊天角色分页
+     */
+    PageResult<AiChatRoleDO> getChatRoleMyPage(AiChatRolePageReqVO pageReqVO, Long userId);
+
+    /**
+     * 获得聊天角色的分类列表
+     *
+     * @return 分类列表
+     */
+    List<String> getChatRoleCategoryList();
+
 }

+ 48 - 2
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java

@@ -1,18 +1,22 @@
 package cn.iocoder.yudao.module.ai.service.model;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO;
+import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO;
 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO;
 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
 import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper;
 import jakarta.annotation.Resource;
-import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_DISABLE;
 import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_NOT_EXISTS;
 
@@ -22,7 +26,6 @@ import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_NOT_EXISTS
  * @author fansili
  */
 @Service
-@AllArgsConstructor
 @Slf4j
 public class AiChatRoleServiceImpl implements AiChatRoleService {
 
@@ -36,6 +39,14 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
         return chatRole.getId();
     }
 
+    @Override
+    public Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId) {
+        AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class).setUserId(userId)
+                .setStatus(CommonStatusEnum.ENABLE.getStatus()).setPublicStatus(false);
+        chatRoleMapper.insert(chatRole);
+        return chatRole.getId();
+    }
+
     @Override
     public void updateChatRole(AiChatRoleSaveReqVO updateReqVO) {
         // 校验存在
@@ -45,6 +56,19 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
         chatRoleMapper.updateById(updateObj);
     }
 
+    @Override
+    public void updateChatRoleMy(AiChatRoleSaveMyReqVO updateReqVO, Long userId) {
+        // 校验存在
+        AiChatRoleDO chatRole = validateChatRoleExists(updateReqVO.getId());
+        if (ObjectUtil.notEqual(chatRole.getUserId(), userId)) {
+            throw exception(CHAT_ROLE_NOT_EXISTS);
+        }
+
+        // 更新
+        AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class);
+        chatRoleMapper.updateById(updateObj);
+    }
+
     @Override
     public void deleteChatRole(Long id) {
         // 校验存在
@@ -53,6 +77,17 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
         chatRoleMapper.deleteById(id);
     }
 
+    @Override
+    public void deleteChatRoleMy(Long id, Long userId) {
+        // 校验存在
+        AiChatRoleDO chatRole = validateChatRoleExists(id);
+        if (ObjectUtil.notEqual(chatRole.getUserId(), userId)) {
+            throw exception(CHAT_ROLE_NOT_EXISTS);
+        }
+        // 删除
+        chatRoleMapper.deleteById(id);
+    }
+
     private AiChatRoleDO validateChatRoleExists(Long id) {
         AiChatRoleDO chatRole = chatRoleMapper.selectById(id);
         if (chatRole == null) {
@@ -80,5 +115,16 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
         return chatRoleMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public PageResult<AiChatRoleDO> getChatRoleMyPage(AiChatRolePageReqVO pageReqVO, Long userId) {
+        return chatRoleMapper.selectPageByMy(pageReqVO, userId);
+    }
+
+    @Override
+    public List<String> getChatRoleCategoryList() {
+        List<AiChatRoleDO> list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus());
+        return convertList(list, AiChatRoleDO::getName);
+    }
+
 }
 

+ 1 - 1
yudao-server/src/main/resources/application-local.yaml

@@ -52,7 +52,7 @@ spring:
           #          url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例
           #          url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例
           username: root
-          password: root
+          password: 123456
         #          username: sa # SQL Server 连接的示例
         #          password: Yudao@2024 # SQL Server 连接的示例
         #          username: SYSDBA # DM 连接的示例