From 82624affb0251b75b62b35567d3eb260c06efe78 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期一, 23 三月 2026 12:48:07 +0800
Subject: [PATCH] #ai 代码优化

---
 rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamServiceImpl.java |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 160 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..7901060 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,23 +4,30 @@
 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;
+import com.vincent.rsf.server.ai.store.AiConfigCacheStore;
+import com.vincent.rsf.server.ai.store.AiConversationCacheStore;
 import com.vincent.rsf.server.ai.service.AiParamService;
 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 AiConfigCacheStore aiConfigCacheStore;
+    private final AiConversationCacheStore aiConversationCacheStore;
 
     @Override
     public AiParam getActiveParam(Long tenantId) {
@@ -34,6 +41,68 @@
             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 鍙傛暟澶辫触");
+        }
+        aiConfigCacheStore.evictTenantConfigCaches(tenantId);
+        aiConversationCacheStore.evictTenantRuntimeCaches(tenantId);
+        return target;
     }
 
     @Override
@@ -56,6 +125,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 +136,48 @@
         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) {
+            aiConfigCacheStore.evictTenantConfigCaches(entity.getTenantId());
+            aiConversationCacheStore.evictTenantRuntimeCaches(entity.getTenantId());
+        }
+        return saved;
+    }
+
+    @Override
+    public boolean updateById(AiParam entity) {
+        boolean updated = super.updateById(entity);
+        if (updated && entity != null && entity.getTenantId() != null) {
+            aiConfigCacheStore.evictTenantConfigCaches(entity.getTenantId());
+            aiConversationCacheStore.evictTenantRuntimeCaches(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(tenantId -> {
+                        aiConfigCacheStore.evictTenantConfigCaches(tenantId);
+                        aiConversationCacheStore.evictTenantRuntimeCaches(tenantId);
+                    });
+        }
+        return removed;
     }
 
     private void ensureBaseFields(AiParam aiParam) {
@@ -99,6 +211,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 +315,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