diff --git a/web-api/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/web-api/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java index f12e4d8..31a9a25 100644 --- a/web-api/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java +++ b/web-api/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -54,6 +54,9 @@ public class SysDept extends BaseEntity /** Byte API Key */ private String byteApiKey; + + /** Byte project */ + private String project; /** 子部门 */ private List children = new ArrayList(); @@ -184,6 +187,16 @@ public class SysDept extends BaseEntity this.byteApiKey = byteApiKey; } + public String getProject() + { + return project; + } + + public void setProject(String project) + { + this.project = project; + } + public List getChildren() { return children; @@ -206,6 +219,7 @@ public class SysDept extends BaseEntity .append("phone", getPhone()) .append("email", getEmail()) .append("byteApiKey", getByteApiKey()) + .append("project", getProject()) .append("status", getStatus()) .append("delFlag", getDelFlag()) .append("createBy", getCreateBy()) diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/BaseByteApiService.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/BaseByteApiService.java index 4b11c14..2c3f32f 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/BaseByteApiService.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/BaseByteApiService.java @@ -6,18 +6,35 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.ruoyi.ai.mapper.AiUserMapper; +import com.ruoyi.common.core.domain.entity.AiUser; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.http.OkHttpUtils; +import com.ruoyi.system.mapper.SysDeptMapper; +import com.ruoyi.system.mapper.SysUserMapper; +import lombok.extern.slf4j.Slf4j; import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import org.apache.catalina.User; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import javax.annotation.Resource; import java.io.IOException; +@Slf4j @Service public class BaseByteApiService { + @Resource + private SysDeptMapper deptMapper; + @Resource + private AiUserMapper userMapper; + protected final ObjectMapper objectMapper = new ObjectMapper() .setSerializationInclusion(JsonInclude.Include.NON_NULL) .setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE) @@ -29,13 +46,12 @@ public class BaseByteApiService { @Value("${byteapi.url}") protected String API_URL; - @Value("${byteapi.apiKey}") - protected String apiKey; + protected String DEPT_ANCESTORS_SPLIT = ","; /** - * POST JSON 调用方舟 OpenAPI;若响应含 {@code Result} 节点则解析为业务对象(与 api.docx 返回示例一致)。 + * 执行 POST,成功则返回响应体字符串(可能为空字符串)。 */ - protected T httpExecute(String path, Object request, Class clz) throws IOException { + private String doPost(String path, Object request) throws IOException { String jsonBody = objectMapper.writeValueAsString(request); RequestBody body = RequestBody.create( MediaType.parse("application/json; charset=utf-8"), @@ -43,7 +59,7 @@ public class BaseByteApiService { Request httpRequest = new Request.Builder() .url(API_URL + path) .header("Content-Type", "application/json") - .header("Authorization", "Bearer " + apiKey) + .header("Authorization", "Bearer " + getUserDeptApiKey()) .post(body) .build(); try (Response response = OkHttpUtils.newCall(httpRequest).execute()) { @@ -52,46 +68,96 @@ public class BaseByteApiService { throw new RuntimeException("execute error:" + errorMsg); } if (response.body() == null) { - throw new RuntimeException("response body null"); + return ""; } - String responseBody = response.body().string(); - JsonNode root = objectMapper.readTree(responseBody); - JsonNode result = root.get("Result"); - if (result != null && !result.isNull()) { - return objectMapper.treeToValue(result, clz); - } - return objectMapper.readValue(responseBody, clz); + return response.body().string(); } } + /** + * POST JSON 调用方舟 OpenAPI;若响应含 {@code Result} 节点则解析为业务对象(与 api.docx 返回示例一致)。 + */ + protected T httpExecute(String path, Object request, Class clz) throws IOException { + String responseBody = doPost(path, request); + if (responseBody == null || responseBody.isEmpty()) { + throw new RuntimeException("response body null"); + } + JsonNode root = objectMapper.readTree(responseBody); + JsonNode result = root.get("Result"); + if (result != null && !result.isNull()) { + return objectMapper.treeToValue(result, clz); + } + return objectMapper.readValue(responseBody, clz); + } + /** * 无业务体返回的 OpenAPI 调用(如 DeleteAsset)。 */ protected void httpExecuteNoContent(String path, Object request) throws IOException { - String jsonBody = objectMapper.writeValueAsString(request); - RequestBody body = RequestBody.create( - MediaType.parse("application/json; charset=utf-8"), - jsonBody); - Request httpRequest = new Request.Builder() - .url(API_URL + path) - .header("Content-Type", "application/json") - .header("Authorization", "Bearer " + apiKey) - .post(body) - .build(); - try (Response response = OkHttpUtils.newCall(httpRequest).execute()) { - if (!response.isSuccessful()) { - String errorMsg = response.body() != null ? response.body().string() : "execute error"; - throw new RuntimeException("execute error:" + errorMsg); - } - } + doPost(path, request); } - /** * 根据用户找到对应的project */ protected String getUserProject() { - // TODO - return "default"; + Long userId = SecurityUtils.getAiUserId(); + if (userId == null) { + return null; + } + AiUser user = userMapper.selectAiUserById(userId); + if (user == null) { + return null; + } + // 第二层部门ID,API_KEY放在这里 + Long secondLvDeptId = getSecondLevelDept(user.getDeptId()); + if (secondLvDeptId == null) { + return null; + } + SysDept secondDept = deptMapper.selectDeptById(secondLvDeptId); + return secondDept.getProject(); + } + + /** + * 根据用户所在部门找到对应的火山方舟ApiKey + */ + protected String getUserDeptApiKey() { + Long userId = SecurityUtils.getAiUserId(); + if (userId == null) { + return null; + } + AiUser user = userMapper.selectAiUserById(userId); + if (user == null) { + return null; + } + // 第二层部门ID,API_KEY放在这里 + Long secondLvDeptId = getSecondLevelDept(user.getDeptId()); + if (secondLvDeptId == null) { + return null; + } + SysDept secondDept = deptMapper.selectDeptById(secondLvDeptId); + return secondDept.getByteApiKey(); + } + + /** + * 找到当前部门所属第二部门ID + * @param deptId 当前部门 + */ + protected Long getSecondLevelDept(long deptId) { + SysDept dept = deptMapper.selectDeptById(deptId); + String ancestors = dept.getAncestors(); + // 判断是第几层 + if (ancestors == null || ancestors.isEmpty() || "0".equals(ancestors)) { + // 第一层 + return null; + } + String[] parentDeptArray = ancestors.split(DEPT_ANCESTORS_SPLIT); + int length = parentDeptArray.length; + if (length == 1) { + // 只有一个上级,所以当前节点是第二层,直接返回 + return deptId; + } + // 大于二级 + return Long.parseLong(parentDeptArray[1]); } } \ No newline at end of file diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetGroupService.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetGroupService.java index 650d172..344ec2b 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetGroupService.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetGroupService.java @@ -23,6 +23,7 @@ public class ByteAssetGroupService extends BaseByteApiService implements IByteAs @Override public ListAssetsGroupResponse listAssetGroups(ListAssetsGroupRequest request) throws IOException { + request.setProjectName(getUserProject()); return httpExecute(LIST_ASSET_GROUPS_URL, request, ListAssetsGroupResponse.class); } @@ -36,11 +37,13 @@ public class ByteAssetGroupService extends BaseByteApiService implements IByteAs @Override public GetAssetGroupResponse getAssetGroup(GetAssetGroupRequest request) throws IOException { + request.setProjectName(getUserProject()); return httpExecute(GET_ASSET_GROUP_URL, request, GetAssetGroupResponse.class); } @Override public UpdateAssetGroupResponse updateAssetGroup(UpdateAssetGroupRequest request) throws IOException { + request.setProjectName(getUserProject()); return httpExecute(UPDATE_ASSET_GROUP_URL, request, UpdateAssetGroupResponse.class); } } diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetService.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetService.java index 7b5497f..4d1f669 100644 --- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetService.java +++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/ByteAssetService.java @@ -39,32 +39,36 @@ public class ByteAssetService extends BaseByteApiService implements IByteAssetSe throw new IllegalArgumentException("groupId、assetType 不能为空"); } String publicUrl = tencentCosUtil.uploadMultipartFile(file, true); - CreateAssetRequest body = new CreateAssetRequest(); - body.setGroupId(groupId); - body.setUrl(publicUrl); - body.setName(name); - body.setAssetType(assetType); - body.setProjectName(getUserProject()); - return httpExecute(CREATE_ASSET_URL, body, CreateAssetResponse.class); + CreateAssetRequest request = new CreateAssetRequest(); + request.setGroupId(groupId); + request.setUrl(publicUrl); + request.setName(name); + request.setAssetType(assetType); + request.setProjectName(getUserProject()); + return httpExecute(CREATE_ASSET_URL, request, CreateAssetResponse.class); } @Override public ListAssetsResponse listAssets(ListAssetsRequest request) throws IOException { + request.setProjectName(getUserProject()); return httpExecute(LIST_ASSETS_URL, request, ListAssetsResponse.class); } @Override public GetAssetResponse getAsset(GetAssetRequest request) throws IOException { + request.setProjectName(getUserProject()); return httpExecute(GET_ASSET_URL, request, GetAssetResponse.class); } @Override public UpdateAssetResponse updateAsset(UpdateAssetRequest request) throws IOException { + request.setProjectName(getUserProject()); return httpExecute(UPDATE_ASSET_URL, request, UpdateAssetResponse.class); } @Override public void deleteAsset(DeleteAssetRequest request) throws IOException { + request.setProjectName(getUserProject()); httpExecuteNoContent(DELETE_ASSET_URL, request); } }