diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/PortalVideoController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/PortalVideoController.java index 052ae25..d0f2646 100644 --- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/PortalVideoController.java +++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/PortalVideoController.java @@ -109,6 +109,16 @@ public class PortalVideoController extends BaseController { } } + /** 二级部门 sys_dept.model_parm 中 JSON 数组第一项的 value(与 parseModelParmJson 规则一致)。 */ + private String resolveFirstModelValueFromModelParm(Long aiUserId) { + String json = byteDeptApiKeyService.resolveSecondLevelModelParm(aiUserId); + List list = parseModelParmJson(json); + if (list == null || list.isEmpty()) { + return null; + } + return list.get(0).getValue(); + } + private static boolean isModelInOptions(String modelId, List options) { if (modelId == null || modelId.isEmpty() || options == null) { return false; @@ -523,6 +533,10 @@ public class PortalVideoController extends BaseController { Long secondDeptId = byteDeptApiKeyService.resolveSecondLevelDeptId(uid); List models = loadModelOptionsForAiUser(uid, secondDeptId); PortalVideoProperties.Defaults defs = portalVideoProperties.resolveEffectiveDefaults(secondDeptId); + String modelFromDeptParm = resolveFirstModelValueFromModelParm(uid); + if (StringUtils.isNotEmpty(modelFromDeptParm)) { + defs.setModel(modelFromDeptParm); + } alignDefaultsModelToOptions(defs, models); Map data = new LinkedHashMap<>(); data.put("defaults", defs); diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiUserMapper.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiUserMapper.java index d5c8c74..5a2fadc 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiUserMapper.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiUserMapper.java @@ -26,6 +26,11 @@ public interface AiUserMapper extends BaseMapper { int countAiUserByDeptId(@Param("deptId") Long deptId); + /** + * 部门下启用中的 AI 用户(未删除且 status=0) + */ + int countNormalAiUsersByDeptId(@Param("deptId") Long deptId, @Param("excludeUserId") Long excludeUserId); + @Update("update ai_user set dept_id = #{deptId}, update_time = sysdate() where id = #{userId}") int updateAiUserDeptId(@Param("userId") Long userId, @Param("deptId") Long deptId); } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiUserServiceImpl.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiUserServiceImpl.java index 1b12ca5..1f96e9e 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiUserServiceImpl.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/AiUserServiceImpl.java @@ -20,8 +20,10 @@ import com.ruoyi.common.core.domain.model.RegisterAiUserBody; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.*; import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; +import com.ruoyi.system.service.ISysDeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -65,6 +67,29 @@ public class AiUserServiceImpl implements IAiUserService { @Autowired private AiRechargeMapper aiRechargeMapper; + @Autowired + private ISysDeptService deptService; + + /** + * 校验部门下启用中 AI 账号未超过 max_user_count(为空或≤0 表示不限制) + */ + private void assertDeptAiUserWithinLimit(Long deptId, Long excludeUserId) { + if (deptId == null) { + return; + } + SysDept dept = deptService.selectDeptById(deptId); + if (dept == null) { + return; + } + Integer max = dept.getMaxUserCount(); + if (max == null || max <= 0) { + return; + } + int others = aiUserMapper.countNormalAiUsersByDeptId(deptId, excludeUserId); + if (others + 1 > max) { + throw new ServiceException("团队人数已经超过上限", HttpStatus.BAD_REQUEST); + } + } /** * 查询ai-用户信息 @@ -133,6 +158,9 @@ public class AiUserServiceImpl implements IAiUserService { if (aiUser.getStatus() == null) { aiUser.setStatus(0); } + if (aiUser.getStatus() == 0) { + assertDeptAiUserWithinLimit(aiUser.getDeptId(), null); + } aiUser.setDelFlag("0"); aiUser.setCreateBy(SecurityUtils.getUsername()); aiUser.setCreateTime(DateUtils.getNowDate()); @@ -147,6 +175,14 @@ public class AiUserServiceImpl implements IAiUserService { */ @Override public int updateAiUser(AiUser aiUser) { + AiUser old = aiUser.getId() != null ? aiUserMapper.selectById(aiUser.getId()) : null; + if (old != null) { + Long newDeptId = aiUser.getDeptId() != null ? aiUser.getDeptId() : old.getDeptId(); + Integer newStatus = aiUser.getStatus() != null ? aiUser.getStatus() : old.getStatus(); + if (newStatus != null && newStatus == 0) { + assertDeptAiUserWithinLimit(newDeptId, aiUser.getId()); + } + } aiUser.setUpdateTime(DateUtils.getNowDate()); if (StringUtils.isNotEmpty(aiUser.getPassword())) { // 登录后 update 常带上库里的 BCrypt 密文;勿对密文再 encrypt,否则第二次登录永远密码错误 @@ -176,6 +212,16 @@ public class AiUserServiceImpl implements IAiUserService { @Override public int updateAiUserDept(Long userId, Long deptId) { + if (deptId != null) { + AiUser u = aiUserMapper.selectById(userId); + if (u != null) { + Integer st = u.getStatus(); + boolean normal = (st == null || st == 0); + if (normal) { + assertDeptAiUserWithinLimit(deptId, userId); + } + } + } return aiUserMapper.updateAiUserDeptId(userId, deptId); } @@ -204,6 +250,11 @@ public class AiUserServiceImpl implements IAiUserService { @Override public int updateUserStatus(AiUser aiUser) { + AiUser old = aiUser.getId() != null ? aiUserMapper.selectById(aiUser.getId()) : null; + Integer newStatus = aiUser.getStatus() != null ? aiUser.getStatus() : (old != null ? old.getStatus() : null); + if (old != null && newStatus != null && newStatus == 0 && old.getDeptId() != null) { + assertDeptAiUserWithinLimit(old.getDeptId(), aiUser.getId()); + } return aiUserMapper.updateById(aiUser); } diff --git a/web-api/ruoyi-system/src/main/resources/mapper/system/AiUserMapper.xml b/web-api/ruoyi-system/src/main/resources/mapper/system/AiUserMapper.xml index 5af6704..fd96547 100644 --- a/web-api/ruoyi-system/src/main/resources/mapper/system/AiUserMapper.xml +++ b/web-api/ruoyi-system/src/main/resources/mapper/system/AiUserMapper.xml @@ -86,6 +86,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + diff --git a/web-api/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/web-api/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml index 29c7ad5..c390522 100644 --- a/web-api/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/web-api/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -219,5 +219,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{userId} + + + + + + \ No newline at end of file