fix: 页面优化,工具栏显示

This commit is contained in:
old burden 2026-03-30 13:05:04 +08:00
parent fc1ecf7bc9
commit 8436c3515c
8 changed files with 63 additions and 16 deletions

2
.gitignore vendored
View File

@ -4,7 +4,7 @@
.gradle .gradle
/build/ /build/
!gradle/wrapper/gradle-wrapper.jar !gradle/wrapper/gradle-wrapper.jar
*.sql
target/ target/
!.mvn/wrapper/maven-wrapper.jar !.mvn/wrapper/maven-wrapper.jar

View File

@ -51,6 +51,9 @@ public class AiManagerApiController extends BaseController {
@Anonymous @Anonymous
public AjaxResult selectInfo(String aiType) { public AjaxResult selectInfo(String aiType) {
AiManager aiManager = aiManagerService.selectAiManagerByType(aiType); AiManager aiManager = aiManagerService.selectAiManagerByType(aiType);
if (aiManager == null) {
return AjaxResult.error("该功能未配置或已停用");
}
aiManager.setPrompt(null); aiManager.setPrompt(null);
return AjaxResult.success(aiManager); return AjaxResult.success(aiManager);
} }

View File

@ -60,6 +60,17 @@ public class PortalVideoController extends BaseController {
return byteDeptApiKeyService.resolveVolcApiKey(SecurityUtils.getAiUserId()); return byteDeptApiKeyService.resolveVolcApiKey(SecurityUtils.getAiUserId());
} }
/** 与 ai_manager.type、portal.video.function-type 对齐,用于扣费 */
private String resolveFunctionType(PortalVideoGenRequest req) {
if (StringUtils.isNotEmpty(req.getFunctionType())) {
return req.getFunctionType();
}
if (StringUtils.isNotEmpty(portalVideoProperties.getFunctionType())) {
return portalVideoProperties.getFunctionType();
}
return "21";
}
private void applyOptionalParams(ByteBodyReq body, PortalVideoGenRequest req) { private void applyOptionalParams(ByteBodyReq body, PortalVideoGenRequest req) {
PortalVideoProperties.Defaults d = portalVideoProperties.getDefaults(); PortalVideoProperties.Defaults d = portalVideoProperties.getDefaults();
body.setDuration(req.getDuration() != null ? req.getDuration() : d.getDuration()); body.setDuration(req.getDuration() != null ? req.getDuration() : d.getDuration());
@ -97,7 +108,7 @@ public class PortalVideoController extends BaseController {
/** /**
* 写入订单提示词生成模式图床 URL以及模型/时长/分辨率/比例与完整 JSON 参数便于对账与审计 * 写入订单提示词生成模式图床 URL以及模型/时长/分辨率/比例与完整 JSON 参数便于对账与审计
*/ */
private void fillVideoOrderRecord(AiOrder aiOrder, PortalVideoGenRequest req, String mode, ByteBodyReq body) { private void fillVideoOrderRecord(AiOrder aiOrder, PortalVideoGenRequest req, String mode, ByteBodyReq body, String functionTypeResolved) {
aiOrder.setText(req.getText()); aiOrder.setText(req.getText());
aiOrder.setMode(mode); aiOrder.setMode(mode);
applyOrderImages(aiOrder, req); applyOrderImages(aiOrder, req);
@ -119,7 +130,7 @@ public class PortalVideoController extends BaseController {
Map<String, Object> snap = new LinkedHashMap<>(); Map<String, Object> snap = new LinkedHashMap<>();
snap.put("generationMode", mode); snap.put("generationMode", mode);
snap.put("prompt", req.getText()); snap.put("prompt", req.getText());
snap.put("functionType", StringUtils.isNotEmpty(req.getFunctionType()) ? req.getFunctionType() : "21"); snap.put("functionType", functionTypeResolved);
snap.put("model", body.getModel()); snap.put("model", body.getModel());
snap.put("duration", body.getDuration()); snap.put("duration", body.getDuration());
snap.put("resolution", body.getResolution()); snap.put("resolution", body.getResolution());
@ -143,13 +154,13 @@ public class PortalVideoController extends BaseController {
} }
private AjaxResult submitOrderAndCreate(PortalVideoGenRequest req, String mode, ByteBodyReq byteBodyReq) { private AjaxResult submitOrderAndCreate(PortalVideoGenRequest req, String mode, ByteBodyReq byteBodyReq) {
AiOrder aiOrder = aiOrderService.getAiOrder( String functionType = resolveFunctionType(req);
StringUtils.isNotEmpty(req.getFunctionType()) ? req.getFunctionType() : "21"); AiOrder aiOrder = aiOrderService.getAiOrder(functionType);
if (aiOrder == null) { if (aiOrder == null) {
return AjaxResult.error(-1, "You have a low balance, please recharge"); return AjaxResult.error(-1, "You have a low balance, please recharge");
} }
try { try {
fillVideoOrderRecord(aiOrder, req, mode, byteBodyReq); fillVideoOrderRecord(aiOrder, req, mode, byteBodyReq, functionType);
aiOrderService.updateAiOrder(aiOrder); aiOrderService.updateAiOrder(aiOrder);
String key = apiKey(); String key = apiKey();

View File

@ -23,6 +23,19 @@ public class PortalVideoProperties {
private List<String> resolutions = new ArrayList<>(); private List<String> resolutions = new ArrayList<>();
/**
* ai_manager.type 一致用于扣费与订单库中需存在对应记录且 status=0del_flag=0
*/
private String functionType = "21";
public String getFunctionType() {
return functionType;
}
public void setFunctionType(String functionType) {
this.functionType = functionType != null ? functionType : "21";
}
public Defaults getDefaults() { public Defaults getDefaults() {
return defaults; return defaults;
} }

View File

@ -238,6 +238,8 @@ volcengine:
# 门户视频生成页:模型 / 比例 / 时长 / 分辨率均由此处维护,前后端不写死业务枚举 # 门户视频生成页:模型 / 比例 / 时长 / 分辨率均由此处维护,前后端不写死业务枚举
portal: portal:
video: video:
# 与库表 ai_manager.type 一致(用于扣费);若报错 functionType does not exist请插入对应 type 或改此处与库一致
function-type: "21"
defaults: defaults:
model: ep-20260326165811-dlkth model: ep-20260326165811-dlkth
duration: 4 duration: 4

View File

@ -124,6 +124,8 @@ public class AiManagerServiceImpl implements IAiManagerService {
public AiManager selectAiManagerByType(String aiType) { public AiManager selectAiManagerByType(String aiType) {
QueryWrapper<AiManager> queryWrapper = new QueryWrapper<>(); QueryWrapper<AiManager> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("type", aiType); queryWrapper.eq("type", aiType);
queryWrapper.eq("del_flag", "0");
queryWrapper.eq("status", 0);
return aiManagerMapper.selectOne(queryWrapper); return aiManagerMapper.selectOne(queryWrapper);
} }
} }

View File

@ -147,7 +147,9 @@ public class AiOrderServiceImpl implements IAiOrderService {
public AiOrder getAiOrder(String aiType) { public AiOrder getAiOrder(String aiType) {
AiManager aiManager = aiManagerService.selectAiManagerByType(aiType); AiManager aiManager = aiManagerService.selectAiManagerByType(aiType);
if (aiManager == null) { if (aiManager == null) {
throw new ServiceException("Corresponding functionType does not exist", HttpStatus.BAD_REQUEST); throw new ServiceException(
"未找到可用的功能类型请在「AI管理」中新增 type=" + aiType + " 且状态为正常的记录,或执行 sql/seed_ai_manager_type_21.sql 初始化",
HttpStatus.BAD_REQUEST);
} }
// 判断用户余额是否足够 // 判断用户余额是否足够
AiUser aiUser = aiUserService.selectAiUserById(SecurityUtils.getAiUserId()); AiUser aiUser = aiUserService.selectAiUserById(SecurityUtils.getAiUserId());

View File

@ -16,7 +16,9 @@ import java.util.concurrent.TimeUnit;
@Service @Service
public class ByteDeptApiKeyServiceImpl implements IByteDeptApiKeyService { public class ByteDeptApiKeyServiceImpl implements IByteDeptApiKeyService {
private static final String NO_PERM_MSG = "用户没有权限,请联系管理员分配部门"; private static final String NO_DEPT_MSG = "用户未分配部门:请在后台为门户用户设置 ai_user.dept_id关联 sys_dept.dept_id";
private static final String NO_DEPT_ROW_MSG = "用户所属部门不存在或已删除,请核对 ai_user.dept_id";
private static final String NO_API_KEY_MSG = "部门未配置火山 API Key请在 sys_dept 为用户所在部门(或其上级二级部门)配置 byte_api_key";
private static final int CACHE_HOURS = 1; private static final int CACHE_HOURS = 1;
@Autowired @Autowired
@ -31,7 +33,7 @@ public class ByteDeptApiKeyServiceImpl implements IByteDeptApiKeyService {
@Override @Override
public String resolveVolcApiKey(Long aiUserId) { public String resolveVolcApiKey(Long aiUserId) {
if (aiUserId == null) { if (aiUserId == null) {
throw new ServiceException(NO_PERM_MSG); throw new ServiceException(NO_DEPT_MSG);
} }
String cacheKey = aiUserId + "_byte_api_key"; String cacheKey = aiUserId + "_byte_api_key";
String cached = redisCache.getCacheObject(cacheKey); String cached = redisCache.getCacheObject(cacheKey);
@ -40,22 +42,34 @@ public class ByteDeptApiKeyServiceImpl implements IByteDeptApiKeyService {
} }
AiUser aiUser = aiUserService.selectAiUserById(aiUserId); AiUser aiUser = aiUserService.selectAiUserById(aiUserId);
if (aiUser == null || aiUser.getDeptId() == null) { if (aiUser == null || aiUser.getDeptId() == null) {
throw new ServiceException(NO_PERM_MSG); throw new ServiceException(NO_DEPT_MSG);
} }
SysDept userDept = sysDeptService.selectDeptById(aiUser.getDeptId()); SysDept userDept = sysDeptService.selectDeptById(aiUser.getDeptId());
if (userDept == null) { if (userDept == null) {
throw new ServiceException(NO_PERM_MSG); throw new ServiceException(NO_DEPT_ROW_MSG);
} }
Long secondLevelDeptId = resolveSecondLevelDeptId(userDept); // 优先使用用户直接归属部门的 Key多数业务把用户挂在分公司 101并在该节点配 byte_api_key
SysDept keyDept = sysDeptService.selectDeptById(secondLevelDeptId); String apiKey = trimKey(userDept.getByteApiKey());
if (keyDept == null || StringUtils.isEmpty(keyDept.getByteApiKey())) { if (StringUtils.isEmpty(apiKey)) {
throw new ServiceException(NO_PERM_MSG); Long fallbackDeptId = resolveSecondLevelDeptId(userDept);
if (!fallbackDeptId.equals(userDept.getDeptId())) {
SysDept keyDept = sysDeptService.selectDeptById(fallbackDeptId);
if (keyDept != null) {
apiKey = trimKey(keyDept.getByteApiKey());
}
}
}
if (StringUtils.isEmpty(apiKey)) {
throw new ServiceException(NO_API_KEY_MSG);
} }
String apiKey = keyDept.getByteApiKey().trim();
redisCache.setCacheObject(cacheKey, apiKey, CACHE_HOURS, TimeUnit.HOURS); redisCache.setCacheObject(cacheKey, apiKey, CACHE_HOURS, TimeUnit.HOURS);
return apiKey; return apiKey;
} }
private static String trimKey(String raw) {
return raw == null ? null : raw.trim();
}
/** /**
* 二级部门祖级路径中紧接在一级ancestors 第二段之下的部门节点 * 二级部门祖级路径中紧接在一级ancestors 第二段之下的部门节点
* 深度不足时退回用户当前部门 * 深度不足时退回用户当前部门