feat(ai-companion): 新增AI伴侣模块及白名单路径

This commit is contained in:
2026-01-26 15:06:26 +08:00
parent 8783a4c2af
commit fd4c381d33
7 changed files with 270 additions and 1 deletions

View File

@@ -111,7 +111,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
"/themes/restore",
"/chat/message",
"/chat/voice",
"/chat/audio/*"
"/chat/audio/*",
"/ai-companion/page"
};
}
@Bean

View File

@@ -0,0 +1,34 @@
package com.yolo.keyborad.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yolo.keyborad.common.BaseResponse;
import com.yolo.keyborad.common.ResultUtils;
import com.yolo.keyborad.model.dto.PageDTO;
import com.yolo.keyborad.model.entity.KeyboardAiCompanion;
import com.yolo.keyborad.service.KeyboardAiCompanionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/*
* @author: ziin
* @date: 2026/1/26
*/
@RestController
@Slf4j
@RequestMapping("/ai-companion")
@Tag(name = "AI陪聊角色", description = "AI陪聊角色管理接口")
public class AiCompanionController {
@Resource
private KeyboardAiCompanionService aiCompanionService;
@PostMapping("/page")
@Operation(summary = "分页查询AI陪聊角色", description = "分页查询已上线的AI陪聊角色列表")
public BaseResponse<IPage<KeyboardAiCompanion>> pageList(@RequestBody PageDTO pageDTO) {
IPage<KeyboardAiCompanion> result = aiCompanionService.pageList(pageDTO.getPageNum(), pageDTO.getPageSize());
return ResultUtils.success(result);
}
}

View File

@@ -0,0 +1,12 @@
package com.yolo.keyborad.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yolo.keyborad.model.entity.KeyboardAiCompanion;
/*
* @author: ziin
* @date: 2026/1/26 13:51
*/
public interface KeyboardAiCompanionMapper extends BaseMapper<KeyboardAiCompanion> {
}

View File

@@ -0,0 +1,141 @@
package com.yolo.keyborad.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 io.swagger.v3.oas.annotations.media.Schema;
import java.util.Date;
import lombok.Data;
/*
* @author: ziin
* @date: 2026/1/26 13:51
*/
/**
* AI陪聊角色表用于定义恋爱/陪伴型虚拟角色的基础信息与人设
*/
@Schema(description="AI陪聊角色表用于定义恋爱/陪伴型虚拟角色的基础信息与人设")
@Data
@TableName(value = "keyboard_ai_companion")
public class KeyboardAiCompanion {
/**
* 陪聊角色唯一ID
*/
@TableId(value = "id", type = IdType.AUTO)
@Schema(description="陪聊角色唯一ID")
private Long id;
/**
* 角色名称展示用Katie Leona
*/
@TableField(value = "\"name\"")
@Schema(description="角色名称展示用Katie Leona")
private String name;
/**
* 角色头像URL用于列表页和聊天页
*/
@TableField(value = "avatar_url")
@Schema(description="角色头像URL用于列表页和聊天页")
private String avatarUrl;
/**
* 角色封面图URL用于角色详情页
*/
@TableField(value = "cover_image_url")
@Schema(description="角色封面图URL用于角色详情页")
private String coverImageUrl;
/**
* 角色性别male / female / other
*/
@TableField(value = "gender")
@Schema(description="角色性别male / female / other")
private String gender;
/**
* 角色年龄段描述20s、25-30
*/
@TableField(value = "age_range")
@Schema(description="角色年龄段描述20s、25-30")
private String ageRange;
/**
* 一句话人设描述,用于卡片或列表展示
*/
@TableField(value = "short_desc")
@Schema(description="一句话人设描述,用于卡片或列表展示")
private String shortDesc;
/**
* 角色详细介绍文案,用于角色详情页
*/
@TableField(value = "intro_text")
@Schema(description="角色详细介绍文案,用于角色详情页")
private String introText;
/**
* 角色性格标签数组(如:温柔、黏人、治愈)
*/
@TableField(value = "personality_tags")
@Schema(description="角色性格标签数组(如:温柔、黏人、治愈)")
private String personalityTags;
/**
* 角色说话风格(如:撒娇型、理性型、活泼型)
*/
@TableField(value = "speaking_style")
@Schema(description="角色说话风格(如:撒娇型、理性型、活泼型)")
private String speakingStyle;
/**
* AI系统Prompt定义角色核心人设仅供模型使用
*/
@TableField(value = "system_prompt")
@Schema(description="AI系统Prompt定义角色核心人设仅供模型使用")
private String systemPrompt;
/**
* 角色状态1=上线0=下线
*/
@TableField(value = "\"status\"")
@Schema(description="角色状态1=上线0=下线")
private Short status;
/**
* 角色可见性1=公开2=内测3=隐藏
*/
@TableField(value = "visibility")
@Schema(description="角色可见性1=公开2=内测3=隐藏")
private Short visibility;
/**
* 排序权重,数值越大排序越靠前
*/
@TableField(value = "sort_order")
@Schema(description="排序权重,数值越大排序越靠前")
private Integer sortOrder;
/**
* 角色热度评分,用于推荐排序
*/
@TableField(value = "popularity_score")
@Schema(description="角色热度评分,用于推荐排序")
private Integer popularityScore;
/**
* 创建时间
*/
@TableField(value = "created_at")
@Schema(description="创建时间")
private Date createdAt;
/**
* 更新时间
*/
@TableField(value = "updated_at")
@Schema(description="更新时间")
private Date updatedAt;
}

View File

@@ -0,0 +1,21 @@
package com.yolo.keyborad.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yolo.keyborad.model.entity.KeyboardAiCompanion;
import com.baomidou.mybatisplus.extension.service.IService;
/*
* @author: ziin
* @date: 2026/1/26 13:51
*/
public interface KeyboardAiCompanionService extends IService<KeyboardAiCompanion> {
/**
* 分页查询已上线的AI陪聊角色
*
* @param pageNum 页码
* @param pageSize 每页数量
* @return 分页结果
*/
IPage<KeyboardAiCompanion> pageList(Integer pageNum, Integer pageSize);
}

View File

@@ -0,0 +1,29 @@
package com.yolo.keyborad.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yolo.keyborad.model.entity.KeyboardAiCompanion;
import com.yolo.keyborad.mapper.KeyboardAiCompanionMapper;
import com.yolo.keyborad.service.KeyboardAiCompanionService;
/*
* @author: ziin
* @date: 2026/1/26 13:51
*/
@Service
public class KeyboardAiCompanionServiceImpl extends ServiceImpl<KeyboardAiCompanionMapper, KeyboardAiCompanion> implements KeyboardAiCompanionService {
@Override
public IPage<KeyboardAiCompanion> pageList(Integer pageNum, Integer pageSize) {
Page<KeyboardAiCompanion> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<KeyboardAiCompanion> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(KeyboardAiCompanion::getStatus, 1)
.eq(KeyboardAiCompanion::getVisibility, 1)
.orderByDesc(KeyboardAiCompanion::getSortOrder)
.orderByDesc(KeyboardAiCompanion::getPopularityScore);
return this.page(page, queryWrapper);
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yolo.keyborad.mapper.KeyboardAiCompanionMapper">
<resultMap id="BaseResultMap" type="com.yolo.keyborad.model.entity.KeyboardAiCompanion">
<!--@mbg.generated-->
<!--@Table keyboard_ai_companion-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="avatar_url" jdbcType="VARCHAR" property="avatarUrl" />
<result column="cover_image_url" jdbcType="VARCHAR" property="coverImageUrl" />
<result column="gender" jdbcType="VARCHAR" property="gender" />
<result column="age_range" jdbcType="VARCHAR" property="ageRange" />
<result column="short_desc" jdbcType="VARCHAR" property="shortDesc" />
<result column="intro_text" jdbcType="VARCHAR" property="introText" />
<result column="personality_tags" jdbcType="VARCHAR" property="personalityTags" />
<result column="speaking_style" jdbcType="VARCHAR" property="speakingStyle" />
<result column="system_prompt" jdbcType="VARCHAR" property="systemPrompt" />
<result column="status" jdbcType="SMALLINT" property="status" />
<result column="visibility" jdbcType="SMALLINT" property="visibility" />
<result column="sort_order" jdbcType="INTEGER" property="sortOrder" />
<result column="popularity_score" jdbcType="INTEGER" property="popularityScore" />
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
<result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, "name", avatar_url, cover_image_url, gender, age_range, short_desc, intro_text,
personality_tags, speaking_style, system_prompt, "status", visibility, sort_order,
popularity_score, created_at, updated_at
</sql>
</mapper>