From 4954d3978cf1967729a5a2d5b90f6baef18974da Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期一, 23 三月 2026 09:35:10 +0800
Subject: [PATCH] #ai redis+页面优化
---
rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 151 insertions(+), 0 deletions(-)
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java
index 957c7b0..4e1e83e 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.ai.config.AiDefaults;
+import com.vincent.rsf.server.ai.dto.AiChatModelOptionDto;
import com.vincent.rsf.server.ai.dto.AiParamValidateResultDto;
import com.vincent.rsf.server.ai.entity.AiParam;
import com.vincent.rsf.server.ai.mapper.AiParamMapper;
@@ -11,16 +12,19 @@
import com.vincent.rsf.server.system.enums.StatusType;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.List;
@Service("aiParamService")
@RequiredArgsConstructor
public class AiParamServiceImpl extends ServiceImpl<AiParamMapper, AiParam> implements AiParamService {
private final AiParamValidationSupport aiParamValidationSupport;
+ private final AiRedisSupport aiRedisSupport;
@Override
public AiParam getActiveParam(Long tenantId) {
@@ -34,6 +38,67 @@
throw new CoolException("鏈壘鍒板惎鐢ㄤ腑鐨� AI 鍙傛暟閰嶇疆");
}
return aiParam;
+ }
+
+ @Override
+ public AiParam getChatParam(Long tenantId, Long aiParamId) {
+ ensureTenantId(tenantId);
+ if (aiParamId == null) {
+ return getActiveParam(tenantId);
+ }
+ AiParam aiParam = requireOwnedRecord(aiParamId, tenantId);
+ if (!AiDefaults.PARAM_VALIDATE_VALID.equals(aiParam.getValidateStatus())) {
+ throw new CoolException("鎵�閫� AI 妯″瀷鏈�氳繃鏍¢獙锛屾殏涓嶅彲鐢ㄤ簬瀵硅瘽");
+ }
+ return aiParam;
+ }
+
+ @Override
+ public List<AiChatModelOptionDto> listChatModelOptions(Long tenantId) {
+ ensureTenantId(tenantId);
+ List<AiParam> params = this.list(new LambdaQueryWrapper<AiParam>()
+ .eq(AiParam::getTenantId, tenantId)
+ .eq(AiParam::getDeleted, 0)
+ .eq(AiParam::getValidateStatus, AiDefaults.PARAM_VALIDATE_VALID)
+ .orderByDesc(AiParam::getStatus)
+ .orderByDesc(AiParam::getUpdateTime)
+ .orderByDesc(AiParam::getCreateTime)
+ .orderByDesc(AiParam::getId));
+ if (params.isEmpty()) {
+ return List.of(toChatModelOption(getActiveParam(tenantId)));
+ }
+ return params.stream()
+ .map(this::toChatModelOption)
+ .toList();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public AiParam setDefaultParam(Long id, Long tenantId, Long userId) {
+ ensureTenantId(tenantId);
+ if (id == null) {
+ throw new CoolException("AI 鍙傛暟 ID 涓嶈兘涓虹┖");
+ }
+ AiParam target = requireOwnedRecord(id, tenantId);
+ if (!AiDefaults.PARAM_VALIDATE_VALID.equals(target.getValidateStatus())) {
+ throw new CoolException("浠呭厑璁稿皢鏍¢獙閫氳繃鐨� AI 鍙傛暟璁剧疆涓洪粯璁�");
+ }
+ Date now = new Date();
+ this.lambdaUpdate()
+ .eq(AiParam::getTenantId, tenantId)
+ .eq(AiParam::getDeleted, 0)
+ .set(AiParam::getStatus, StatusType.DISABLE.val)
+ .set(AiParam::getUpdateBy, userId)
+ .set(AiParam::getUpdateTime, now)
+ .update();
+ target.setStatus(StatusType.ENABLE.val);
+ target.setUpdateBy(userId);
+ target.setUpdateTime(now);
+ if (!super.updateById(target)) {
+ throw new CoolException("璁剧疆榛樿 AI 鍙傛暟澶辫触");
+ }
+ aiRedisSupport.evictTenantConfigCaches(tenantId);
+ return target;
}
@Override
@@ -56,6 +121,7 @@
AiParam current = requireOwnedRecord(aiParam.getId(), tenantId);
aiParam.setTenantId(current.getTenantId());
ensureBaseFields(aiParam);
+ ensureDefaultStillExists(tenantId, current, aiParam.getStatus());
ensureSingleActive(tenantId, aiParam.getId(), aiParam.getStatus());
applyValidation(aiParam);
}
@@ -66,6 +132,43 @@
fillDefaults(aiParam);
ensureBaseFields(aiParam);
return aiParamValidationSupport.validate(aiParam);
+ }
+
+ @Override
+ public boolean save(AiParam entity) {
+ boolean saved = super.save(entity);
+ if (saved && entity != null && entity.getTenantId() != null) {
+ aiRedisSupport.evictTenantConfigCaches(entity.getTenantId());
+ }
+ return saved;
+ }
+
+ @Override
+ public boolean updateById(AiParam entity) {
+ boolean updated = super.updateById(entity);
+ if (updated && entity != null && entity.getTenantId() != null) {
+ aiRedisSupport.evictTenantConfigCaches(entity.getTenantId());
+ }
+ return updated;
+ }
+
+ @Override
+ public boolean removeByIds(java.util.Collection<?> list) {
+ java.util.List<java.io.Serializable> ids = list == null ? java.util.List.of() : list.stream()
+ .filter(java.util.Objects::nonNull)
+ .map(item -> (java.io.Serializable) item)
+ .toList();
+ java.util.List<AiParam> records = this.listByIds(ids);
+ ensureRemovingDefaultIsSafe(records);
+ boolean removed = super.removeByIds(list);
+ if (removed) {
+ records.stream()
+ .map(AiParam::getTenantId)
+ .filter(java.util.Objects::nonNull)
+ .distinct()
+ .forEach(aiRedisSupport::evictTenantConfigCaches);
+ }
+ return removed;
}
private void ensureBaseFields(AiParam aiParam) {
@@ -99,6 +202,44 @@
}
if (this.count(wrapper) > 0) {
throw new CoolException("鍚屼竴绉熸埛浠呭厑璁镐竴鏉″惎鐢ㄤ腑鐨� AI 鍙傛暟閰嶇疆");
+ }
+ }
+
+ private void ensureDefaultStillExists(Long tenantId, AiParam current, Integer nextStatus) {
+ if (current == null || current.getStatus() == null || current.getStatus() != StatusType.ENABLE.val) {
+ return;
+ }
+ if (nextStatus != null && nextStatus == StatusType.ENABLE.val) {
+ return;
+ }
+ long otherDefaultCount = this.count(new LambdaQueryWrapper<AiParam>()
+ .eq(AiParam::getTenantId, tenantId)
+ .eq(AiParam::getDeleted, 0)
+ .eq(AiParam::getStatus, StatusType.ENABLE.val)
+ .ne(AiParam::getId, current.getId()));
+ if (otherDefaultCount == 0) {
+ throw new CoolException("璇峰厛灏嗗叾浠� AI 鍙傛暟璁剧疆涓洪粯璁わ紝鍐嶅彇娑堝綋鍓嶉粯璁�");
+ }
+ }
+
+ private void ensureRemovingDefaultIsSafe(List<AiParam> records) {
+ if (records == null || records.isEmpty()) {
+ return;
+ }
+ records.stream()
+ .filter(item -> item.getTenantId() != null && item.getStatus() != null && item.getStatus() == StatusType.ENABLE.val)
+ .map(AiParam::getTenantId)
+ .distinct()
+ .forEach(this::ensureTenantHasRemainingDefaultAfterRemove);
+ }
+
+ private void ensureTenantHasRemainingDefaultAfterRemove(Long tenantId) {
+ long defaultCount = this.count(new LambdaQueryWrapper<AiParam>()
+ .eq(AiParam::getTenantId, tenantId)
+ .eq(AiParam::getDeleted, 0)
+ .eq(AiParam::getStatus, StatusType.ENABLE.val));
+ if (defaultCount <= 1) {
+ throw new CoolException("榛樿 AI 鍙傛暟涓嶈兘鐩存帴鍒犻櫎锛岃鍏堝皢鍏朵粬閰嶇疆璁句负榛樿");
}
}
@@ -165,4 +306,14 @@
throw new CoolException("瑙f瀽鏍¢獙鏃堕棿澶辫触: " + e.getMessage());
}
}
+
+ private AiChatModelOptionDto toChatModelOption(AiParam aiParam) {
+ return AiChatModelOptionDto.builder()
+ .aiParamId(aiParam.getId())
+ .name(aiParam.getName())
+ .model(aiParam.getModel())
+ .providerType(aiParam.getProviderType())
+ .active(aiParam.getStatus() != null && aiParam.getStatus() == StatusType.ENABLE.val)
+ .build();
+ }
}
--
Gitblit v1.9.1