diff --git a/api/ai-agent/.gitignore b/api/ai-agent/.gitignore index 5ff6309b..94dc921d 100644 --- a/api/ai-agent/.gitignore +++ b/api/ai-agent/.gitignore @@ -35,4 +35,5 @@ build/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store +*.log \ No newline at end of file diff --git a/api/ai-agent/src/main/java/cn/qihangerp/erp/controller/AiUserRoleController.java b/api/ai-agent/src/main/java/cn/qihangerp/erp/controller/AiUserRoleController.java new file mode 100644 index 00000000..b06b67d5 --- /dev/null +++ b/api/ai-agent/src/main/java/cn/qihangerp/erp/controller/AiUserRoleController.java @@ -0,0 +1,111 @@ +package cn.qihangerp.erp.controller; + +import java.util.List; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.http.ResponseEntity; +import org.springframework.http.HttpStatus; +import cn.qihangerp.security.LoginUser; +import cn.qihangerp.security.TokenService; +import cn.qihangerp.model.entity.AiUserRole; +import cn.qihangerp.service.IAiUserRoleService; + +/** + * 用户AI角色Controller + * + * @author qihang + * @date 2024-06-20 + */ +@RestController +@RequestMapping("/ai/user-role") +public class AiUserRoleController { + @Autowired + private IAiUserRoleService aiUserRoleService; + + @Autowired + private TokenService tokenService; + + /** + * 获取当前用户所有角色 + */ + @GetMapping("/list") + public ResponseEntity> list(HttpServletRequest request) { + LoginUser loginUser = tokenService.getLoginUser(request); + List list = aiUserRoleService.selectAiUserRolesByUserId(loginUser.getUserId()); + return ResponseEntity.ok(list); + } + + /** + * 获取当前用户默认角色 + */ + @GetMapping("/default") + public ResponseEntity getDefault(HttpServletRequest request) { + LoginUser loginUser = tokenService.getLoginUser(request); + AiUserRole aiUserRole = aiUserRoleService.selectDefaultAiUserRoleByUserId(loginUser.getUserId()); + return ResponseEntity.ok(aiUserRole); + } + + /** + * 新增用户AI角色 + */ + @PostMapping + public ResponseEntity add(@RequestBody AiUserRole aiUserRole, HttpServletRequest request) { + LoginUser loginUser = tokenService.getLoginUser(request); + aiUserRole.setUserId(loginUser.getUserId()); + int result = aiUserRoleService.insertAiUserRole(aiUserRole); + return ResponseEntity.ok(result); + } + + /** + * 修改用户AI角色 + */ + @PutMapping + public ResponseEntity edit(@RequestBody AiUserRole aiUserRole, HttpServletRequest request) { + LoginUser loginUser = tokenService.getLoginUser(request); + // 验证角色是否属于当前用户 + AiUserRole existingRole = aiUserRoleService.selectAiUserRoleById(aiUserRole.getId()); + if (existingRole == null || !existingRole.getUserId().equals(loginUser.getUserId())) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(0); + } + int result = aiUserRoleService.updateAiUserRole(aiUserRole); + return ResponseEntity.ok(result); + } + + /** + * 删除用户AI角色 + */ + @DeleteMapping("/{id}") + public ResponseEntity remove(@PathVariable Long id, HttpServletRequest request) { + LoginUser loginUser = tokenService.getLoginUser(request); + // 验证角色是否属于当前用户 + AiUserRole existingRole = aiUserRoleService.selectAiUserRoleById(id); + if (existingRole == null || !existingRole.getUserId().equals(loginUser.getUserId())) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(0); + } + int result = aiUserRoleService.deleteAiUserRoleById(id); + return ResponseEntity.ok(result); + } + + /** + * 设置默认角色 + */ + @PutMapping("/set-default/{roleId}") + public ResponseEntity setDefault(@PathVariable Long roleId, HttpServletRequest request) { + LoginUser loginUser = tokenService.getLoginUser(request); + // 验证角色是否属于当前用户 + AiUserRole existingRole = aiUserRoleService.selectAiUserRoleById(roleId); + if (existingRole == null || !existingRole.getUserId().equals(loginUser.getUserId())) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(0); + } + int result = aiUserRoleService.setDefaultAiUserRole(loginUser.getUserId(), roleId); + return ResponseEntity.ok(result); + } +} \ No newline at end of file diff --git a/docs/ai_user_role.sql b/docs/ai_user_role.sql new file mode 100644 index 00000000..8be2d1ca --- /dev/null +++ b/docs/ai_user_role.sql @@ -0,0 +1,18 @@ +-- 用户AI角色表 +CREATE TABLE `ai_user_role` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id,自增', + `user_id` bigint(20) NOT NULL COMMENT '用户id', + `role_name` varchar(255) NOT NULL COMMENT '角色名称', + `description` varchar(500) DEFAULT NULL COMMENT '角色描述', + `system_prompt` text NOT NULL COMMENT '角色系统提示词', + `is_default` int(11) NOT NULL DEFAULT '0' COMMENT '是否为默认角色:0-否,1-是', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_is_default` (`is_default`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户AI角色表'; + +-- 添加默认角色示例数据 +INSERT INTO `ai_user_role` (`user_id`, `role_name`, `description`, `system_prompt`, `is_default`) VALUES +(1, '默认ERP助手', '默认的ERP智能助手,用于查询订单、商品、库存等信息', '你是一个智能ERP助手,名叫启航助手,专门为电商企业提供服务。\n你的职责是帮助用户查询订单、商品、库存等信息,以及执行其他ERP相关操作。\n你可以使用提供的工具来获取实时数据,工具返回的结果要以用户友好的方式呈现。\n如果用户的请求超出你的能力范围,你应该礼貌地拒绝。\n回答问题时要简洁明了,避免使用过于技术化的术语。', 1); \ No newline at end of file diff --git a/mapper/src/main/java/cn/qihangerp/mapper/AiUserRoleMapper.java b/mapper/src/main/java/cn/qihangerp/mapper/AiUserRoleMapper.java new file mode 100644 index 00000000..92d648ff --- /dev/null +++ b/mapper/src/main/java/cn/qihangerp/mapper/AiUserRoleMapper.java @@ -0,0 +1,89 @@ +package cn.qihangerp.mapper; + +import cn.qihangerp.model.entity.AiUserRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 用户AI角色表Mapper接口 + * + * @author qihang + */ +@Mapper +public interface AiUserRoleMapper extends BaseMapper +{ + /** + * 查询用户AI角色表 + * + * @param id 用户AI角色表主键 + * @return 用户AI角色表 + */ + public AiUserRole selectAiUserRoleById(@Param("id") Long id); + + /** + * 查询用户AI角色表列表 + * + * @param aiUserRole 用户AI角色表 + * @return 用户AI角色表集合 + */ + public List selectAiUserRoleList(@Param("aiUserRole") AiUserRole aiUserRole); + + /** + * 查询用户的所有角色 + * + * @param userId 用户ID + * @return 用户角色集合 + */ + public List selectAiUserRolesByUserId(@Param("userId") Long userId); + + /** + * 查询用户的默认角色 + * + * @param userId 用户ID + * @return 默认角色 + */ + public AiUserRole selectDefaultAiUserRoleByUserId(@Param("userId") Long userId); + + /** + * 新增用户AI角色表 + * + * @param aiUserRole 用户AI角色表 + * @return 结果 + */ + public int insertAiUserRole(@Param("aiUserRole") AiUserRole aiUserRole); + + /** + * 修改用户AI角色表 + * + * @param aiUserRole 用户AI角色表 + * @return 结果 + */ + public int updateAiUserRole(@Param("aiUserRole") AiUserRole aiUserRole); + + /** + * 删除用户AI角色表 + * + * @param id 用户AI角色表主键 + * @return 结果 + */ + public int deleteAiUserRoleById(@Param("id") Long id); + + /** + * 批量删除用户AI角色表 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteAiUserRoleByIds(@Param("ids") Long[] ids); + + /** + * 更新用户的非默认角色 + * + * @param userId 用户ID + * @return 结果 + */ + public int updateNonDefaultRolesByUserId(@Param("userId") Long userId); +} \ No newline at end of file diff --git a/mapper/src/main/resources/mapper/AiUserRoleMapper.xml b/mapper/src/main/resources/mapper/AiUserRoleMapper.xml new file mode 100644 index 00000000..8c18a01a --- /dev/null +++ b/mapper/src/main/resources/mapper/AiUserRoleMapper.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + select id, user_id, role_name, system_prompt, is_default, create_time, update_time from ai_user_role + + + + + + + + + + + + insert into ai_user_role + + user_id, + role_name, + system_prompt, + is_default, + create_time, + update_time + + + #{userId}, + #{roleName}, + #{systemPrompt}, + #{isDefault}, + now(), + now() + + + + + update ai_user_role + + role_name = #{roleName}, + system_prompt = #{systemPrompt}, + is_default = #{isDefault}, + update_time = now() + + where id = #{id} + + + + update ai_user_role + set is_default = 0, update_time = now() + where user_id = #{userId} + + + + delete from ai_user_role where id = #{id} + + + + delete from ai_user_role where id in + + #{id} + + + \ No newline at end of file diff --git a/model/src/main/java/cn/qihangerp/model/entity/AiUserRole.java b/model/src/main/java/cn/qihangerp/model/entity/AiUserRole.java new file mode 100644 index 00000000..11078dba --- /dev/null +++ b/model/src/main/java/cn/qihangerp/model/entity/AiUserRole.java @@ -0,0 +1,62 @@ +package cn.qihangerp.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 用户AI角色表 + * @TableName ai_user_role + */ +@TableName(value = "ai_user_role") +@Data +public class AiUserRole implements Serializable { + /** + * 主键id,自增 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * 角色名称 + */ + private String roleName; + + /** + * 角色描述 + */ + private String description; + + /** + * 角色系统提示词 + */ + private String systemPrompt; + + /** + * 是否为默认角色:0-否,1-是 + */ + private Integer isDefault; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/service/src/main/java/cn/qihangerp/service/IAiUserRoleService.java b/service/src/main/java/cn/qihangerp/service/IAiUserRoleService.java new file mode 100644 index 00000000..9805e633 --- /dev/null +++ b/service/src/main/java/cn/qihangerp/service/IAiUserRoleService.java @@ -0,0 +1,88 @@ +package cn.qihangerp.service; + +import cn.qihangerp.model.entity.AiUserRole; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + * 用户AI角色Service接口 + * + * @author qihang + * @date 2024-05-21 + */ +public interface IAiUserRoleService extends IService +{ + /** + * 查询用户AI角色 + * + * @param id 用户AI角色主键 + * @return 用户AI角色 + */ + public AiUserRole selectAiUserRoleById(Long id); + + /** + * 查询用户AI角色列表 + * + * @param aiUserRole 用户AI角色 + * @return 用户AI角色集合 + */ + public List selectAiUserRoleList(AiUserRole aiUserRole); + + /** + * 根据用户ID查询用户AI角色列表 + * + * @param userId 用户ID + * @return 用户AI角色集合 + */ + public List selectAiUserRolesByUserId(Long userId); + + /** + * 根据用户ID查询默认用户AI角色 + * + * @param userId 用户ID + * @return 用户AI角色 + */ + public AiUserRole selectDefaultAiUserRoleByUserId(Long userId); + + /** + * 新增用户AI角色 + * + * @param aiUserRole 用户AI角色 + * @return 结果 + */ + public int insertAiUserRole(AiUserRole aiUserRole); + + /** + * 修改用户AI角色 + * + * @param aiUserRole 用户AI角色 + * @return 结果 + */ + public int updateAiUserRole(AiUserRole aiUserRole); + + /** + * 批量删除用户AI角色 + * + * @param ids 需要删除的用户AI角色主键集合 + * @return 结果 + */ + public int deleteAiUserRoleByIds(Long[] ids); + + /** + * 删除用户AI角色信息 + * + * @param id 用户AI角色主键 + * @return 结果 + */ + public int deleteAiUserRoleById(Long id); + + /** + * 设置默认角色 + * + * @param userId 用户ID + * @param roleId 角色ID + * @return 结果 + */ + public int setDefaultAiUserRole(Long userId, Long roleId); +} \ No newline at end of file diff --git a/service/src/main/java/cn/qihangerp/service/impl/AiUserRoleServiceImpl.java b/service/src/main/java/cn/qihangerp/service/impl/AiUserRoleServiceImpl.java new file mode 100644 index 00000000..8b0070c3 --- /dev/null +++ b/service/src/main/java/cn/qihangerp/service/impl/AiUserRoleServiceImpl.java @@ -0,0 +1,89 @@ +package cn.qihangerp.service.impl; + +import cn.qihangerp.mapper.AiUserRoleMapper; +import cn.qihangerp.model.entity.AiUserRole; +import cn.qihangerp.service.IAiUserRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 用户AI角色Service业务层处理 + * + * @author qihang + * @date 2024-05-21 + */ +@Service +public class AiUserRoleServiceImpl extends ServiceImpl implements IAiUserRoleService +{ + @Override + public AiUserRole selectAiUserRoleById(Long id) + { + return baseMapper.selectAiUserRoleById(id); + } + + @Override + public List selectAiUserRoleList(AiUserRole aiUserRole) + { + return baseMapper.selectAiUserRoleList(aiUserRole); + } + + @Override + public List selectAiUserRolesByUserId(Long userId) + { + return baseMapper.selectAiUserRolesByUserId(userId); + } + + @Override + public AiUserRole selectDefaultAiUserRoleByUserId(Long userId) + { + return baseMapper.selectDefaultAiUserRoleByUserId(userId); + } + + @Override + public int insertAiUserRole(AiUserRole aiUserRole) + { + // 如果设置为默认角色,则先将该用户的其他角色设置为非默认 + if (aiUserRole.getIsDefault() != null && aiUserRole.getIsDefault() == 1) + { + baseMapper.updateNonDefaultRolesByUserId(aiUserRole.getUserId()); + } + return baseMapper.insertAiUserRole(aiUserRole); + } + + @Override + public int updateAiUserRole(AiUserRole aiUserRole) + { + // 如果设置为默认角色,则先将该用户的其他角色设置为非默认 + if (aiUserRole.getIsDefault() != null && aiUserRole.getIsDefault() == 1) + { + baseMapper.updateNonDefaultRolesByUserId(aiUserRole.getUserId()); + } + return baseMapper.updateAiUserRole(aiUserRole); + } + + @Override + public int deleteAiUserRoleById(Long id) + { + return baseMapper.deleteAiUserRoleById(id); + } + + @Override + public int deleteAiUserRoleByIds(Long[] ids) + { + return baseMapper.deleteAiUserRoleByIds(ids); + } + + @Override + public int setDefaultAiUserRole(Long userId, Long roleId) + { + // 先将该用户的所有角色设置为非默认 + baseMapper.updateNonDefaultRolesByUserId(userId); + // 再将指定角色设置为默认 + AiUserRole aiUserRole = new AiUserRole(); + aiUserRole.setId(roleId); + aiUserRole.setIsDefault(1); + return baseMapper.updateAiUserRole(aiUserRole); + } +} \ No newline at end of file diff --git a/vue/src/api/ai/userRole.js b/vue/src/api/ai/userRole.js new file mode 100644 index 00000000..a2c6ae5c --- /dev/null +++ b/vue/src/api/ai/userRole.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 查询用户AI角色列表 +export function listAiUserRole(query) { + return request({ + url: '/api/ai-agent/aiUserRole/list', + method: 'get', + params: query + }) +} + +// 查询用户AI角色详细 +export function getAiUserRole(id) { + return request({ + url: '/api/ai-agent/aiUserRole/' + id, + method: 'get' + }) +} + +// 新增用户AI角色 +export function addAiUserRole(data) { + return request({ + url: '/api/ai-agent/aiUserRole', + method: 'post', + data: data + }) +} + +// 修改用户AI角色 +export function updateAiUserRole(data) { + return request({ + url: '/api/ai-agent/aiUserRole', + method: 'put', + data: data + }) +} + +// 删除用户AI角色 +export function delAiUserRole(id) { + return request({ + url: '/api/ai-agent/aiUserRole/' + id, + method: 'delete' + }) +} + +// 批量删除用户AI角色 +export function delAiUserRoles(ids) { + return request({ + url: '/api/ai-agent/aiUserRole/' + ids, + method: 'delete' + }) +} + +// 设置默认角色 +export function setDefaultRole(id) { + return request({ + url: '/api/ai-agent/aiUserRole/setDefault/' + id, + method: 'put' + }) +} \ No newline at end of file diff --git a/vue/src/views/ai/userRole.vue b/vue/src/views/ai/userRole.vue new file mode 100644 index 00000000..776b9efe --- /dev/null +++ b/vue/src/views/ai/userRole.vue @@ -0,0 +1,351 @@ + + +