diff --git a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java index 1d61ec6..2cd7a8a 100644 --- a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java +++ b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java @@ -66,7 +66,8 @@ public class SaTokenConfigure implements WebMvcConfigurer { "/user/verifyMailCode", "/character/listWithNotLogin", "/character/listByTagWithNotLogin", - "/ai-companion/report" + "/ai-companion/report", + "/apple/notification" }; } @Bean diff --git a/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCompanion.java b/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCompanion.java index a68aa61..0b6b49d 100644 --- a/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCompanion.java +++ b/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCompanion.java @@ -146,4 +146,8 @@ public class KeyboardAiCompanion { @TableField(value = "prologue_audio") @Schema(description="开场白音频") private String prologueAudio; + + @TableField(value = "voice_id") + @Schema(description="角色音频Id") + private String voiceId; } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/model/vo/AiCompanionVO.java b/src/main/java/com/yolo/keyborad/model/vo/AiCompanionVO.java index 28c39d3..38922b3 100644 --- a/src/main/java/com/yolo/keyborad/model/vo/AiCompanionVO.java +++ b/src/main/java/com/yolo/keyborad/model/vo/AiCompanionVO.java @@ -1,5 +1,6 @@ package com.yolo.keyborad.model.vo; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -66,4 +67,9 @@ public class AiCompanionVO { @Schema(description = "创建时间") private Date createdAt; + + @TableField(value = "voice_id") + @Schema(description="角色音频Id") + private String voiceId; + } diff --git a/src/main/java/com/yolo/keyborad/model/vo/products/KeyboardProductItemRespVO.java b/src/main/java/com/yolo/keyborad/model/vo/products/KeyboardProductItemRespVO.java index 0dda6c6..8b5966d 100644 --- a/src/main/java/com/yolo/keyborad/model/vo/products/KeyboardProductItemRespVO.java +++ b/src/main/java/com/yolo/keyborad/model/vo/products/KeyboardProductItemRespVO.java @@ -45,6 +45,6 @@ public class KeyboardProductItemRespVO { private String description; @Schema(description = "级别") - private Integer level; + private Integer level; } diff --git a/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java index fa414d9..e2be8e4 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java @@ -422,6 +422,7 @@ public class ApplePurchaseServiceImpl implements ApplePurchaseService { // 检查VIP是否已过期 if (user.getVipExpiry() != null && user.getVipExpiry().toInstant().isBefore(Instant.now())) { user.setIsVip(false); + user.setVipLevel(null); userService.updateById(user); log.info("User VIP expired: userId={}", userId); } @@ -464,6 +465,7 @@ public class ApplePurchaseServiceImpl implements ApplePurchaseService { } else { // 倒扣后已过期,取消VIP user.setIsVip(false); + user.setVipLevel(null); user.setVipExpiry(Date.from(newExpiry)); // 保留倒扣后的时间,而不是设为null log.info("Subscription refunded, VIP expired after deduction: userId={}, newExpiry={}", userId, newExpiry); @@ -607,6 +609,7 @@ public class ApplePurchaseServiceImpl implements ApplePurchaseService { // 4. 更新用户VIP状态 user.setIsVip(true); + user.setVipLevel(product.getLevel()); user.setVipExpiry(Date.from(newExpiry)); // 5. 保存用户信息到数据库 @@ -764,6 +767,7 @@ public class ApplePurchaseServiceImpl implements ApplePurchaseService { // 6. 更新用户VIP状态 user.setIsVip(true); // 设置为VIP用户 + user.setVipLevel(product.getLevel()); user.setVipExpiry(Date.from(newExpiry)); // 更新VIP过期时间 // 7. 保存用户信息到数据库 diff --git a/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java index ff78b70..303bc48 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java @@ -10,6 +10,7 @@ import com.yolo.keyborad.config.NacosAppConfigCenter; import com.yolo.keyborad.exception.BusinessException; import com.yolo.keyborad.model.dto.chat.ChatReq; import com.yolo.keyborad.model.dto.chat.ChatStreamMessage; +import com.yolo.keyborad.model.entity.KeyboardAiCompanion; import com.yolo.keyborad.model.entity.KeyboardAiChatMessage; import com.yolo.keyborad.model.entity.KeyboardCharacter; import com.yolo.keyborad.model.entity.KeyboardUser; @@ -406,8 +407,16 @@ public class ChatServiceImpl implements ChatService { long startTime = System.currentTimeMillis(); - // 获取AI人设的系统提示词 - String systemPrompt = aiCompanionService.getSystemPromptById(companionId); + // 获取AI角色信息(用于系统提示词 + voiceId) + KeyboardAiCompanion companion = aiCompanionService.getById(companionId); + if (companion == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "AI陪聊角色不存在"); + } + if (companion.getStatus() == null || companion.getStatus() != 1) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "AI陪聊角色已下线"); + } + String systemPrompt = companion.getSystemPrompt(); + String voiceId = companion.getVoiceId(); // 获取最近20条聊天记录作为上下文 List historyMessages = aiChatMessageService.getRecentMessages( @@ -444,8 +453,8 @@ public class ChatServiceImpl implements ChatService { // 初始化音频任务状态为 processing setAudioTaskStatus(audioId, AudioTaskVO.STATUS_PROCESSING, null, null); - // 异步执行 TTS + R2 上传 - CompletableFuture.runAsync(() -> processAudioAsync(audioId, response, userId)); + // 异步执行 TTS + R2 上传(优先使用角色配置的 voiceId) + CompletableFuture.runAsync(() -> processAudioAsync(audioId, response, userId, voiceId)); return ChatMessageVO.builder() .aiResponse(response) @@ -515,14 +524,14 @@ public class ChatServiceImpl implements ChatService { /** * 异步处理音频:TTS 转换 + 上传 R2 */ - private void processAudioAsync(String audioId, String text, String userId) { + private void processAudioAsync(String audioId, String text, String userId, String voiceId) { try { log.info("开始异步音频处理, audioId: {}", audioId); long startTime = System.currentTimeMillis(); // 1. TTS 转换 long ttsStart = System.currentTimeMillis(); - TextToSpeechVO ttsResult = elevenLabsService.textToSpeechWithTimestamps(text); + TextToSpeechVO ttsResult = elevenLabsService.textToSpeechWithTimestamps(text, voiceId); long ttsDuration = System.currentTimeMillis() - ttsStart; log.info("TTS 完成, audioId: {}, 耗时: {}ms", audioId, ttsDuration);