| @@ -1,6 +1,6 @@ | |||
| # 基础镜像 | |||
| #FROM openjdk:8-jre | |||
| FROM 172.20.32.187/ci4s/openjdk-dvc:2024829 | |||
| FROM 172.20.32.187/ci4s/openjdk:8u162 | |||
| #FROM 172.20.32.187/ci4s/openjdk-dvc:2024829 | |||
| # author | |||
| MAINTAINER ruoyi | |||
| @@ -22,6 +22,7 @@ export { requestConfig as request } from './requestConfig'; | |||
| // const isDev = process.env.NODE_ENV === 'development'; | |||
| import { type GlobalInitialState } from '@/types'; | |||
| import { menuItemRender } from '@/utils/menuRender'; | |||
| import ErrorBoundary from './components/ErrorBoundary'; | |||
| import { gotoLoginPage } from './utils/ui'; | |||
| /** | |||
| @@ -65,6 +66,7 @@ export async function getInitialState(): Promise<GlobalInitialState> { | |||
| // ProLayout 支持的api https://procomponents.ant.design/components/layout | |||
| export const layout: RuntimeConfig['layout'] = ({ initialState }) => { | |||
| return { | |||
| ErrorBoundary: ErrorBoundary, | |||
| rightContentRender: false, | |||
| waterMarkProps: { | |||
| // content: initialState?.currentUser?.nickName, | |||
| @@ -0,0 +1,78 @@ | |||
| import KFEmpty, { EmptyType } from '@/components/KFEmpty'; | |||
| import { Button } from 'antd'; | |||
| import { Component, ReactNode } from 'react'; | |||
| interface ErrorBoundaryProps { | |||
| children: ReactNode; | |||
| fallback?: ReactNode; // Optional fallback UI to show in case of error | |||
| } | |||
| interface ErrorBoundaryState { | |||
| hasError: boolean; | |||
| error: Error | null; | |||
| } | |||
| class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> { | |||
| constructor(props: ErrorBoundaryProps) { | |||
| super(props); | |||
| this.state = { | |||
| hasError: false, | |||
| error: null, | |||
| }; | |||
| } | |||
| static getDerivedStateFromError(error: Error): ErrorBoundaryState { | |||
| // Update state so the next render shows the fallback UI | |||
| return { hasError: true, error }; | |||
| } | |||
| // componentDidCatch(error: Error, errorInfo: ErrorInfo) { | |||
| // // You can log the error to an error reporting service here | |||
| // console.error('Error caught by ErrorBoundary:', error.message, errorInfo.componentStack); | |||
| // } | |||
| render() { | |||
| if (this.state.hasError) { | |||
| return this.props.fallback || <ErrorBoundaryFallback error={this.state.error} />; | |||
| } | |||
| return this.props.children; | |||
| } | |||
| } | |||
| function ErrorBoundaryFallback({ error }: { error: Error | null }) { | |||
| const message = error && error instanceof Error ? error.message : 'Unknown error'; | |||
| const errorMsg = | |||
| process.env.NODE_ENV === 'development' ? message : '非常抱歉,程序运行错误,\n我们会尽快修复。'; | |||
| return ( | |||
| <KFEmpty | |||
| style={{ height: '100vh' }} | |||
| type={EmptyType.NotFound} | |||
| title="出错了" | |||
| content={errorMsg} | |||
| footer={() => { | |||
| return ( | |||
| <> | |||
| <Button | |||
| type="default" | |||
| onClick={() => { | |||
| window.history.pushState({}, '', '/'); | |||
| window.location.reload(); | |||
| }} | |||
| > | |||
| 返回首页 | |||
| </Button> | |||
| <Button | |||
| type="primary" | |||
| style={{ marginLeft: 20 }} | |||
| onClick={() => window.location.reload()} | |||
| > | |||
| 刷新 | |||
| </Button> | |||
| </> | |||
| ); | |||
| }} | |||
| ></KFEmpty> | |||
| ); | |||
| } | |||
| export default ErrorBoundary; | |||
| @@ -18,6 +18,7 @@ | |||
| } | |||
| &__content { | |||
| max-width: 50%; | |||
| margin-top: 15px; | |||
| color: @text-color-secondary; | |||
| font-size: 15px; | |||
| @@ -37,7 +37,7 @@ function KFEmpty({ | |||
| type, | |||
| title, | |||
| content, | |||
| hasFooter = false, | |||
| hasFooter = true, | |||
| footer, | |||
| buttonTitle = '刷新', | |||
| onRefresh, | |||
| @@ -1,146 +1,159 @@ | |||
| import BasicInfo, { BasicInfoData } from '@/components/BasicInfo'; | |||
| import SubAreaTitle from '@/components/SubAreaTitle'; | |||
| import { ResourceData, ResourceType } from '@/pages/Dataset/config'; | |||
| import { DatasetData, ModelData, ResourceType } from '@/pages/Dataset/config'; | |||
| import styles from './index.less'; | |||
| type ResourceIntroProps = { | |||
| resourceType: ResourceType; | |||
| info: ResourceData; | |||
| info: DatasetData | ModelData; | |||
| }; | |||
| const formatArray = (arr?: string[]) => { | |||
| // const formatArray = (arr?: ResourceData[]) => { | |||
| // if (!arr || arr.length === 0) { | |||
| // return '--'; | |||
| // } | |||
| // return arr.map((item) => item.name).join('\n'); | |||
| // }; | |||
| const formatDataset = (arr?: DatasetData[]) => { | |||
| if (!arr || arr.length === 0) { | |||
| return '--'; | |||
| return undefined; | |||
| } | |||
| return arr.join('\n'); | |||
| return arr.map((item) => item.name).join('\n'); | |||
| }; | |||
| const formatMap = (map?: Record<string, string>) => { | |||
| if (!map || Object.keys(map).length === 0) { | |||
| return '--'; | |||
| return undefined; | |||
| } | |||
| return Object.entries(map) | |||
| .map(([key, value]) => `${key} = ${value}`) | |||
| .join('\n'); | |||
| }; | |||
| function ResourceIntro({ resourceType, info }: ResourceIntroProps) { | |||
| const datasetDatas: BasicInfoData[] = [ | |||
| { | |||
| label: '数据集名称', | |||
| value: info.name, | |||
| }, | |||
| { | |||
| label: '版本', | |||
| value: info.version, | |||
| }, | |||
| { | |||
| label: '创建人', | |||
| value: info.create_by, | |||
| }, | |||
| { | |||
| label: '更新时间', | |||
| value: info.update_time, | |||
| }, | |||
| { | |||
| label: '数据来源', | |||
| value: info.dataset_source, | |||
| }, | |||
| { | |||
| label: '处理代码', | |||
| value: info.processing_code, | |||
| }, | |||
| { | |||
| label: '数据集分类', | |||
| value: info.data_type, | |||
| }, | |||
| { | |||
| label: '研究方向', | |||
| value: info.data_tag, | |||
| }, | |||
| { | |||
| label: '数据集描述', | |||
| value: info.description, | |||
| }, | |||
| { | |||
| label: '版本描述', | |||
| value: info.version_desc, | |||
| }, | |||
| ]; | |||
| const getDatasetDatas = (data: DatasetData): BasicInfoData[] => [ | |||
| { | |||
| label: '数据集名称', | |||
| value: data.name, | |||
| }, | |||
| { | |||
| label: '版本', | |||
| value: data.version, | |||
| }, | |||
| { | |||
| label: '创建人', | |||
| value: data.create_by, | |||
| }, | |||
| { | |||
| label: '更新时间', | |||
| value: data.update_time, | |||
| }, | |||
| { | |||
| label: '数据来源', | |||
| value: data.dataset_source, | |||
| }, | |||
| { | |||
| label: '处理代码', | |||
| value: data.processing_code, | |||
| }, | |||
| { | |||
| label: '数据集分类', | |||
| value: data.data_type, | |||
| }, | |||
| { | |||
| label: '研究方向', | |||
| value: data.data_tag, | |||
| }, | |||
| { | |||
| label: '数据集描述', | |||
| value: data.description, | |||
| }, | |||
| { | |||
| label: '版本描述', | |||
| value: data.version_desc, | |||
| }, | |||
| ]; | |||
| const modelDatas: BasicInfoData[] = [ | |||
| { | |||
| label: '模型名称', | |||
| value: info.name, | |||
| }, | |||
| { | |||
| label: '版本', | |||
| value: info.version, | |||
| }, | |||
| { | |||
| label: '创建人', | |||
| value: info.create_by, | |||
| }, | |||
| { | |||
| label: '更新时间', | |||
| value: info.update_time, | |||
| }, | |||
| { | |||
| label: '训练镜像', | |||
| value: info.image, | |||
| }, | |||
| { | |||
| label: '训练代码', | |||
| value: info.code, | |||
| }, | |||
| { | |||
| label: '训练数据集', | |||
| value: info.train_datasets, | |||
| format: formatArray, | |||
| }, | |||
| { | |||
| label: '测试数据集', | |||
| value: info.test_datasets, | |||
| format: formatArray, | |||
| }, | |||
| { | |||
| label: '参数', | |||
| value: info.params, | |||
| format: formatMap, | |||
| }, | |||
| { | |||
| label: '指标', | |||
| value: info.metrics, | |||
| format: formatMap, | |||
| }, | |||
| { | |||
| label: '训练任务', | |||
| value: info.train_task, | |||
| }, | |||
| { | |||
| label: '模型来源', | |||
| value: info.model_source, | |||
| }, | |||
| { | |||
| label: '模型框架', | |||
| value: info.model_type, | |||
| }, | |||
| { | |||
| label: '模型能力', | |||
| value: info.model_tag, | |||
| }, | |||
| { | |||
| label: '模型描述', | |||
| value: info.description, | |||
| }, | |||
| { | |||
| label: '版本描述', | |||
| value: info.version_desc, | |||
| }, | |||
| ]; | |||
| const getModelDatas = (data: ModelData): BasicInfoData[] => [ | |||
| { | |||
| label: '模型名称', | |||
| value: data.name, | |||
| }, | |||
| { | |||
| label: '版本', | |||
| value: data.version, | |||
| }, | |||
| { | |||
| label: '创建人', | |||
| value: data.create_by, | |||
| }, | |||
| { | |||
| label: '更新时间', | |||
| value: data.update_time, | |||
| }, | |||
| { | |||
| label: '训练镜像', | |||
| value: data.image, | |||
| }, | |||
| { | |||
| label: '训练代码', | |||
| value: data.code, | |||
| }, | |||
| { | |||
| label: '训练数据集', | |||
| value: data.train_datasets, | |||
| format: formatDataset, | |||
| }, | |||
| { | |||
| label: '测试数据集', | |||
| value: data.test_datasets, | |||
| format: formatDataset, | |||
| }, | |||
| { | |||
| label: '参数', | |||
| value: data.params, | |||
| format: formatMap, | |||
| }, | |||
| { | |||
| label: '指标', | |||
| value: data.metrics, | |||
| format: formatMap, | |||
| }, | |||
| { | |||
| label: '训练任务', | |||
| value: data.train_task, | |||
| format: (value?: any) => value?.name, | |||
| externalLink: data.train_task | |||
| ? `${location.origin}/pipeline/experiment/instance/${data.train_task.task_id}/${data.train_task.ins_id}` | |||
| : '', | |||
| }, | |||
| { | |||
| label: '模型来源', | |||
| value: data.model_source, | |||
| }, | |||
| { | |||
| label: '模型框架', | |||
| value: data.model_type, | |||
| }, | |||
| { | |||
| label: '模型能力', | |||
| value: data.model_tag, | |||
| }, | |||
| { | |||
| label: '模型描述', | |||
| value: data.description, | |||
| }, | |||
| { | |||
| label: '版本描述', | |||
| value: data.version_desc, | |||
| }, | |||
| ]; | |||
| function ResourceIntro({ resourceType, info }: ResourceIntroProps) { | |||
| const basicDatas: BasicInfoData[] = | |||
| resourceType === ResourceType.Dataset ? datasetDatas : modelDatas; | |||
| resourceType === ResourceType.Dataset | |||
| ? getDatasetDatas(info as DatasetData) | |||
| : getModelDatas(info as ModelData); | |||
| return ( | |||
| <div className={styles['resource-intro']}> | |||
| @@ -128,7 +128,7 @@ export type CategoryData = { | |||
| }; | |||
| // 数据集、模型列表数据 | |||
| export type ResourceData = { | |||
| export interface ResourceData { | |||
| id: number; | |||
| name: string; | |||
| identifier: string; | |||
| @@ -142,25 +142,34 @@ export type ResourceData = { | |||
| version_desc?: string; | |||
| usage?: string; | |||
| relative_paths?: string; | |||
| // 数据集 | |||
| resourceType: ResourceType.Dataset | ResourceType.Model; | |||
| } | |||
| // 数据集数据 | |||
| export interface DatasetData extends ResourceData { | |||
| resourceType: ResourceType.Dataset; // 用于区别类型 | |||
| data_type?: string; // 数据集分类 | |||
| data_tag?: string; // 研究方向 | |||
| processing_code?: string; // 处理代码 | |||
| dataset_source?: string; // 数据来源 | |||
| dataset_version_vos: ResourceFileData[]; | |||
| // 模型 | |||
| dataset_version_vos?: ResourceFileData[]; | |||
| } | |||
| // 模型数据 | |||
| export interface ModelData extends ResourceData { | |||
| resourceType: ResourceType.Model; // 用于区别类型 | |||
| model_type?: string; // 模型框架 | |||
| model_tag?: string; // 模型能力 | |||
| image?: string; // 训练镜像 | |||
| code?: string; // 训练镜像 | |||
| train_datasets?: string[]; // 训练数据集 | |||
| test_datasets?: string[]; // 测试数据集 | |||
| train_datasets?: DatasetData[]; // 训练数据集 | |||
| test_datasets?: DatasetData[]; // 测试数据集 | |||
| params?: Record<string, string>; // 参数 | |||
| metrics?: Record<string, string>; // 指标 | |||
| train_task?: string; // 训练任务 | |||
| train_task?: TrainTask; // 训练任务 | |||
| model_source?: string; // 模型来源 | |||
| model_version_vos: ResourceFileData[]; | |||
| }; | |||
| model_version_vos?: ResourceFileData[]; | |||
| } | |||
| // 版本数据 | |||
| export type ResourceVersionData = { | |||
| @@ -177,3 +186,10 @@ export type ResourceFileData = { | |||
| url: string; | |||
| update_time?: string; | |||
| }; | |||
| // 训练任务 | |||
| export type TrainTask = { | |||
| ins_id: number; | |||
| name: string; | |||
| task_id: string; | |||
| }; | |||
| @@ -1,3 +1,4 @@ | |||
| import { TrainTask } from '@/pages/Dataset/config'; | |||
| import { changePropertyName, fittingString } from '@/utils'; | |||
| import { EdgeConfig, GraphData, LayoutConfig, NodeConfig, TreeGraphData, Util } from '@antv/g6'; | |||
| // @ts-ignore | |||
| @@ -31,12 +32,6 @@ export type Rect = { | |||
| height: number; | |||
| }; | |||
| export type TrainTask = { | |||
| ins_id: number; | |||
| name: string; | |||
| task_id: string; | |||
| }; | |||
| export interface TrainDataset extends NodeConfig { | |||
| repo_id: number; | |||
| name: string; | |||
| @@ -1,14 +1,12 @@ | |||
| package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.platform.domain.ExperimentIns; | |||
| import com.ruoyi.platform.domain.ModelDependency; | |||
| import com.ruoyi.platform.service.AimService; | |||
| import com.ruoyi.platform.service.ExperimentInsService; | |||
| import com.ruoyi.platform.service.ModelDependencyService; | |||
| import com.ruoyi.platform.utils.AIM64EncoderUtil; | |||
| import com.ruoyi.platform.utils.HttpUtils; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import com.ruoyi.platform.utils.JsonUtils; | |||
| import com.ruoyi.platform.utils.NewHttpUtils; | |||
| import com.ruoyi.platform.vo.InsMetricInfoVo; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| @@ -28,6 +26,8 @@ public class AimServiceImpl implements AimService { | |||
| private String aimUrl; | |||
| @Value("${aim.proxyUrl}") | |||
| private String aimProxyUrl; | |||
| @Resource | |||
| private NewHttpUtils httpUtils; | |||
| @Override | |||
| public List<InsMetricInfoVo> getExpTrainInfos(Integer experimentId) throws Exception { | |||
| @@ -52,7 +52,7 @@ public class AimServiceImpl implements AimService { | |||
| } | |||
| String encodedUrlString = URLEncoder.encode("run.experiment==\""+experimentName+"\"", "UTF-8"); | |||
| String url = aimProxyUrl+"/api/runs/search/run?query="+encodedUrlString; | |||
| String s = HttpUtils.sendGetRequest(url); | |||
| String s = httpUtils.sendGet(url,null); | |||
| List<Map<String, Object>> response = JacksonUtil.parseJSONStr2MapList(s); | |||
| System.out.println("response: "+JacksonUtil.toJSONString(response)); | |||
| if (response == null || response.size() == 0){ | |||
| @@ -56,6 +56,8 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| @Value("${minio.endpoint}") | |||
| private String minioEndpoint; | |||
| @Resource | |||
| private NewHttpUtils httpUtils; | |||
| @Resource | |||
| private K8sClientUtil k8sClientUtil; | |||
| private final MinioUtil minioUtil; | |||
| public ExperimentInsServiceImpl(MinioUtil minioUtil) { | |||
| @@ -263,7 +265,7 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| try { | |||
| // 发送POST请求到Argo工作流状态查询接口,并将请求数据转换为JSON | |||
| String req = HttpUtils.sendPost(argoUrl + argoWorkflowStatus, JsonUtils.mapToJson(res)); | |||
| String req = httpUtils.sendPost(argoUrl + argoWorkflowStatus,null, JsonUtils.mapToJson(res)); | |||
| // 检查响应是否为空或无内容 | |||
| if (req == null || StringUtils.isEmpty(req)) { | |||
| throw new RuntimeException("工作流状态响应为空。"); | |||
| @@ -357,7 +359,7 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| try { | |||
| // 发送POST请求到Argo工作流状态查询接口,并将请求数据转换为JSON | |||
| String req = HttpUtils.sendPost(argoUrl + argoWorkflowTermination, JsonUtils.mapToJson(res)); | |||
| String req = httpUtils.sendPost(argoUrl + argoWorkflowTermination,null, JsonUtils.mapToJson(res)); | |||
| // 检查响应是否为空或无内容 | |||
| if (StringUtils.isEmpty(req)) { | |||
| throw new RuntimeException("终止响应内容为空。"); | |||
| @@ -415,7 +417,7 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| try { | |||
| // 发送POST请求到Argo工作流日志查询接口,并将请求数据转换为JSON | |||
| String req = HttpUtils.sendPost(argoUrl + argoWorkflowLog, JsonUtils.mapToJson(res)); | |||
| String req = httpUtils.sendPost(argoUrl + argoWorkflowLog, null,JsonUtils.mapToJson(res)); | |||
| // 检查响应是否为空或无内容 | |||
| if (StringUtils.isEmpty(req)) { | |||
| throw new RuntimeException("响应内容为空"); | |||
| @@ -8,9 +8,9 @@ import com.ruoyi.platform.domain.dependencydomain.TrainTaskDepency; | |||
| import com.ruoyi.platform.mapper.ExperimentDao; | |||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | |||
| import com.ruoyi.platform.service.*; | |||
| import com.ruoyi.platform.utils.HttpUtils; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import com.ruoyi.platform.utils.JsonUtils; | |||
| import com.ruoyi.platform.utils.NewHttpUtils; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import org.apache.commons.collections4.MapUtils; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| @@ -55,7 +55,8 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| @Resource | |||
| @Lazy | |||
| private ExperimentInsService experimentInsService; | |||
| @Resource | |||
| private NewHttpUtils httpUtils; | |||
| @Value("${argo.url}") | |||
| private String argoUrl; | |||
| @Value("${argo.convert}") | |||
| @@ -222,7 +223,7 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| String dag = workflow.getDag(); | |||
| // 调argo转换接口 | |||
| try { | |||
| String convertRes = HttpUtils.sendPost(argoUrl + argoConvert, dag); | |||
| String convertRes = httpUtils.sendPost(argoUrl + argoConvert,null, dag); | |||
| if (convertRes == null || StringUtils.isEmpty(convertRes)) { | |||
| throw new RuntimeException("转换流水线失败"); | |||
| } | |||
| @@ -241,7 +242,7 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| Map<String ,Object> output = (Map<String, Object>) converMap.get("output"); | |||
| // 调argo运行接口 | |||
| String runRes = HttpUtils.sendPost(argoUrl + argoWorkflowRun, JsonUtils.mapToJson(runReqMap)); | |||
| String runRes = httpUtils.sendPost(argoUrl + argoWorkflowRun,null, JsonUtils.mapToJson(runReqMap)); | |||
| if (runRes == null || StringUtils.isEmpty(runRes)) { | |||
| throw new RuntimeException("Failed to run workflow."); | |||
| @@ -2,9 +2,9 @@ package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.service.GitService; | |||
| import com.ruoyi.platform.utils.HttpUtils; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import com.ruoyi.platform.utils.JsonUtils; | |||
| import com.ruoyi.platform.utils.NewHttpUtils; | |||
| import com.ruoyi.platform.vo.GitProjectVo; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| @@ -16,9 +16,9 @@ import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Service; | |||
| import redis.clients.jedis.Jedis; | |||
| import javax.annotation.Resource; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.util.Collections; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @@ -30,6 +30,10 @@ public class GitServiceImpl implements GitService { | |||
| private String redisHost; | |||
| @Value("${spring.redis.port}") | |||
| private Integer redisPort; | |||
| @Value("${git.endpoint}") | |||
| String gitendpoint; | |||
| @Resource | |||
| private NewHttpUtils httpUtils; | |||
| private static final Logger log = LoggerFactory.getLogger(GitServiceImpl.class); | |||
| @Override | |||
| @@ -43,7 +47,7 @@ public class GitServiceImpl implements GitService { | |||
| params.put("client_secret", "L3wBKTNnRo-wPen7bxR3F1myCvtVDgpWa6MnpfyWeJE"); | |||
| try { | |||
| // 发送POST请求 | |||
| String req = HttpUtils.sendPostRequest("https://www.gitlink.org.cn/oauth/token", null, JsonUtils.mapToJson(params)); | |||
| String req = httpUtils.sendPost(gitendpoint + "/oauth/token", null,JsonUtils.mapToJson(params)); | |||
| // 解析响应JSON | |||
| if (StringUtils.isEmpty(req)) { | |||
| throw new RuntimeException("终止响应内容为空。"); | |||
| @@ -55,7 +59,7 @@ public class GitServiceImpl implements GitService { | |||
| String accessToken = (String) runResMap.get("access_token"); | |||
| //通过access_token获取用户信息 | |||
| String userReq = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/users/get_user_info.json", null, accessToken); | |||
| String userReq = httpUtils.sendGetWithToken(gitendpoint + "/api/users/get_user_info.json", null, accessToken); | |||
| if (StringUtils.isEmpty(userReq)) { | |||
| throw new RuntimeException("终止响应内容为空。"); | |||
| } | |||
| @@ -100,7 +104,7 @@ public class GitServiceImpl implements GitService { | |||
| @Override | |||
| public Map createProject(String token,GitProjectVo gitProjectVo) throws Exception { | |||
| String userReq = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/projects.json", JsonUtils.objectToJson(gitProjectVo), token); | |||
| String userReq = httpUtils.sendPostWithToken(gitendpoint + "/api/projects.json",null, token,JsonUtils.objectToJson(gitProjectVo)); | |||
| return JsonUtils.jsonToMap(userReq); | |||
| } | |||
| @@ -115,7 +119,7 @@ public class GitServiceImpl implements GitService { | |||
| Map<String, Object> resMap = new HashMap<>(); | |||
| resMap.put("new_branch_name", branchName); | |||
| resMap.put("old_branch_name", oldBranchName); | |||
| String req = HttpUtils.sendPostWithToken(createBranchUrl, JsonUtils.objectToJson(resMap), token); | |||
| String req = httpUtils.sendPostWithToken(createBranchUrl, null, token,JsonUtils.objectToJson(resMap)); | |||
| System.out.println(req); | |||
| } | |||
| @@ -125,12 +129,12 @@ public class GitServiceImpl implements GitService { | |||
| Map<String, Object> resMap = new HashMap<>(); | |||
| resMap.put("project_id", id); | |||
| resMap.put("name", topicName); | |||
| String req = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/v1/project_topics.json", JsonUtils.objectToJson(resMap), token); | |||
| String req = httpUtils.sendPostWithToken(gitendpoint + "/api/v1/project_topics.json",null, token ,JsonUtils.objectToJson(resMap)); | |||
| } | |||
| @Override | |||
| public List<Map<String, Object>> getBrancheList(String token,String owner, String projectName) throws Exception { | |||
| String req = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/all.json", null, token); | |||
| String req = httpUtils.sendGetWithToken(gitendpoint + "/api/v1/" + owner + "/" + projectName + "/branches/all.json", null, token); | |||
| // 解析响应JSON | |||
| if (StringUtils.isEmpty(req)) { | |||
| throw new RuntimeException("终止响应内容为空。"); | |||
| @@ -142,7 +146,7 @@ public class GitServiceImpl implements GitService { | |||
| @Override | |||
| public void deleteProject(String token,String owner, String projectName) throws Exception { | |||
| HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/" + owner + "/" + projectName + ".json", token); | |||
| httpUtils.sendDeleteWithToken(gitendpoint + "/api/" + owner + "/" + projectName + ".json", null, token); | |||
| } | |||
| @Override | |||
| @@ -153,12 +157,12 @@ public class GitServiceImpl implements GitService { | |||
| } catch (IOException | GitAPIException e) { | |||
| log.error("Exception occurred while creating local branch based on master",e); | |||
| } | |||
| HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/" + branchName + ".json", token); | |||
| httpUtils.sendDeleteWithToken(gitendpoint + "/api/v1/" + owner + "/" + projectName + "/branches/" + branchName + ".json", null, token); | |||
| } | |||
| @Override | |||
| public Map getUserInfo(String token) throws Exception { | |||
| String userReq = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/users/get_user_info.json",null, token); | |||
| String userReq = httpUtils.sendGetWithToken(gitendpoint + "/api/users/get_user_info.json",null, token); | |||
| if (StringUtils.isEmpty(userReq)){ | |||
| return null; | |||
| } | |||
| @@ -76,7 +76,8 @@ public class ModelsServiceImpl implements ModelsService { | |||
| @Resource | |||
| private AssetIconService assetIconService; | |||
| @Resource | |||
| private NewHttpUtils httpUtils; | |||
| // 固定存储桶名 | |||
| @Value("${minio.dataReleaseBucketName}") | |||
| @@ -832,7 +833,7 @@ public class ModelsServiceImpl implements ModelsService { | |||
| url = url + "&search=" + name; | |||
| } | |||
| String req = HttpUtils.sendGetWithToken(url, null, token); | |||
| String req = httpUtils.sendGetWithToken(url, null, token); | |||
| Map<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req); | |||
| Integer total = (Integer) stringObjectMap.get("count"); | |||
| List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects"); | |||
| @@ -863,7 +864,7 @@ public class ModelsServiceImpl implements ModelsService { | |||
| url = url + "&search=" + name; | |||
| } | |||
| String req = HttpUtils.sendGetWithToken(url, null, token); | |||
| String req = httpUtils.sendGetWithToken(url, null, token); | |||
| Map<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req); | |||
| Integer total = (Integer) stringObjectMap.get("total_count"); | |||
| List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects"); | |||
| @@ -63,6 +63,8 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||
| @Value("${git.localPath}") | |||
| String localPathlocal; | |||
| @Resource | |||
| private NewHttpUtils httpUtils; | |||
| @Resource | |||
| private DatasetTempStorageService datasetTempStorageService; | |||
| @Override | |||
| public String newCreateDataset(NewDatasetVo datasetVo) throws Exception { | |||
| @@ -236,7 +238,7 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||
| if (StringUtils.isNotEmpty(name)){ | |||
| url =url + "&search=" + name; | |||
| } | |||
| String req = HttpUtils.sendGetWithToken(url, null, token); | |||
| String req = httpUtils.sendGetWithToken(url, null, token); | |||
| Map<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req); | |||
| Integer total = (Integer) stringObjectMap.get("count"); | |||
| List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects"); | |||
| @@ -264,7 +266,7 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||
| url =url + "&search=" + name; | |||
| } | |||
| String req = HttpUtils.sendGetWithToken(url, null, token); | |||
| String req = httpUtils.sendGetWithToken(url, null, token); | |||
| Map<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req); | |||
| Integer total = (Integer) stringObjectMap.get("total_count"); | |||
| List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects"); | |||
| @@ -2,15 +2,14 @@ package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.annotations.CheckDuplicate; | |||
| import com.ruoyi.platform.domain.Dataset; | |||
| import com.ruoyi.platform.domain.Experiment; | |||
| import com.ruoyi.platform.domain.Workflow; | |||
| import com.ruoyi.platform.mapper.WorkflowDao; | |||
| import com.ruoyi.platform.service.ExperimentService; | |||
| import com.ruoyi.platform.service.WorkflowService; | |||
| import com.ruoyi.platform.utils.HttpUtils; | |||
| import com.ruoyi.platform.utils.JsonUtils; | |||
| import com.ruoyi.platform.utils.MinioUtil; | |||
| import com.ruoyi.platform.utils.NewHttpUtils; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import org.apache.commons.lang.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| @@ -45,7 +44,8 @@ public class WorkflowServiceImpl implements WorkflowService { | |||
| @Value("${argo.workflowCopy}") | |||
| private String argoWorkflowCopy; | |||
| @Resource | |||
| private NewHttpUtils httpUtils; | |||
| private final MinioUtil minioUtil; | |||
| public WorkflowServiceImpl(MinioUtil minioUtil) { | |||
| @@ -172,7 +172,7 @@ public class WorkflowServiceImpl implements WorkflowService { | |||
| Map<String,Object> requestData = new HashMap<>(); | |||
| requestData.put("data", oldDag); | |||
| // 发送POST请求到Argo工作流复制接口,并将请求数据转换为JSON | |||
| String req = HttpUtils.sendPost(argoUrl + argoWorkflowCopy , JsonUtils.mapToJson(requestData)); | |||
| String req = httpUtils.sendPost(argoUrl + argoWorkflowCopy,null , JsonUtils.mapToJson(requestData)); | |||
| // 检查响应是否为空或无内容 | |||
| if (StringUtils.isEmpty(req)) { | |||
| throw new RuntimeException("工作流复制接口响应内容为空"); | |||
| @@ -110,6 +110,7 @@ public class HttpUtils { | |||
| * @return 所代表远程资源的响应结果 | |||
| */ | |||
| public static String sendGetWithToken(String url, String param, String token) { | |||
| System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2"); | |||
| String result = ""; | |||
| try (CloseableHttpClient httpClient = HttpClients.createDefault()) { | |||
| URIBuilder uriBuilder = new URIBuilder(url); | |||
| @@ -0,0 +1,132 @@ | |||
| package com.ruoyi.platform.utils; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.client.methods.*; | |||
| import org.apache.http.client.utils.URIBuilder; | |||
| import org.apache.http.conn.ssl.SSLConnectionSocketFactory; | |||
| import org.apache.http.conn.ssl.TrustSelfSignedStrategy; | |||
| import org.apache.http.entity.StringEntity; | |||
| import org.apache.http.impl.client.CloseableHttpClient; | |||
| import org.apache.http.impl.client.HttpClients; | |||
| import org.apache.http.ssl.SSLContextBuilder; | |||
| import org.apache.http.util.EntityUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.net.ssl.SSLContext; | |||
| import java.io.IOException; | |||
| import java.net.URI; | |||
| import java.net.URISyntaxException; | |||
| import java.nio.charset.StandardCharsets; | |||
| @Component | |||
| public class NewHttpUtils { | |||
| private static final Logger log = LoggerFactory.getLogger(NewHttpUtils.class); | |||
| @Value("${proxy.useProxy:false}") | |||
| private boolean useProxy; | |||
| @Value("${proxy.host}") | |||
| private String host; | |||
| @Value("${proxy.port}") | |||
| private Integer port; | |||
| private static CloseableHttpClient httpClient; | |||
| @PostConstruct | |||
| public void init() { | |||
| try { | |||
| SSLContext sslContext = SSLContextBuilder.create() | |||
| .loadTrustMaterial(new TrustSelfSignedStrategy()) | |||
| .build(); | |||
| SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext); | |||
| if (useProxy) { | |||
| httpClient = HttpClients.custom() | |||
| .setSSLSocketFactory(sslSocketFactory) | |||
| .setProxy(new HttpHost(host, port)) | |||
| .build(); | |||
| } else { | |||
| httpClient = HttpClients.custom() | |||
| .setSSLSocketFactory(sslSocketFactory) | |||
| .build(); | |||
| } | |||
| } catch (Exception e) { | |||
| throw new RuntimeException("Failed to initialize HttpClient", e); | |||
| } | |||
| } | |||
| public static String sendGet(String url, String param) { | |||
| return sendRequest(new HttpGet(), url, param, null, null); | |||
| } | |||
| public static String sendPost(String url, String param, String body) { | |||
| return sendRequest(new HttpPost(), url, param, null, body); | |||
| } | |||
| public static String sendGetWithToken(String url, String param, String token) { | |||
| return sendRequest(new HttpGet(), url, param, token, null); | |||
| } | |||
| public static String sendPostWithToken(String url, String param, String token, String body) { | |||
| return sendRequest(new HttpPost(), url, param, token, body); | |||
| } | |||
| public static String sendDeleteWithToken(String url, String param, String token) { | |||
| return sendRequest(new HttpDelete(), url, param, token, null); | |||
| } | |||
| private static String sendRequest(HttpRequestBase request, String url, String param, String token, String body) { | |||
| if (httpClient == null) { | |||
| throw new IllegalStateException("HttpClient is not initialized"); | |||
| } | |||
| String result = ""; | |||
| try { | |||
| URIBuilder uriBuilder = new URIBuilder(url); | |||
| if (param != null && !param.isEmpty()) { | |||
| String[] pairs = param.split("&"); | |||
| for (String pair : pairs) { | |||
| int idx = pair.indexOf("="); | |||
| if (idx != -1) { | |||
| uriBuilder.setParameter(pair.substring(0, idx), pair.substring(idx + 1)); | |||
| } | |||
| } | |||
| } | |||
| URI uri = uriBuilder.build(); | |||
| request.setURI(uri); | |||
| request.setHeader("Content-Type", "application/json"); | |||
| if (token != null) { | |||
| request.setHeader("Authorization", "Bearer " + token); | |||
| } | |||
| if (request instanceof HttpEntityEnclosingRequestBase && body != null) { | |||
| ((HttpEntityEnclosingRequestBase) request).setEntity(new StringEntity(body, StandardCharsets.UTF_8)); | |||
| } | |||
| log.info("Executing request: " + request.getRequestLine()); | |||
| try (CloseableHttpResponse response = httpClient.execute(request)) { | |||
| int statusCode = response.getStatusLine().getStatusCode(); | |||
| if (statusCode >= 200 && statusCode < 300) { | |||
| result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); | |||
| } else { | |||
| throw new IOException("HTTP request failed with response code: " + statusCode); | |||
| } | |||
| log.info("Response: " + result); | |||
| } | |||
| } catch (URISyntaxException e) { | |||
| log.error("URISyntaxException, url=" + url + ", param=" + param, e); | |||
| } catch (IOException e) { | |||
| log.error("IOException, url=" + url + ", param=" + param, e); | |||
| } | |||
| return result; | |||
| } | |||
| } | |||
| @@ -3,7 +3,7 @@ server: | |||
| port: 9201 | |||
| # Spring | |||
| spring: | |||
| spring: | |||
| application: | |||
| # 应用名称 | |||
| name: ruoyi-system | |||
| @@ -13,21 +13,13 @@ spring: | |||
| cloud: | |||
| nacos: | |||
| discovery: | |||
| namespace: 6caf5d79-c4ce-4e3b-a357-141b74e52a01 | |||
| # 服务注册地址 | |||
| server-addr: 172.20.32.181:8848 | |||
| username: nacos | |||
| password: h1n2x3j4y5@ | |||
| retry: | |||
| enabled: true | |||
| server-addr: 172.20.32.181:18847 | |||
| config: | |||
| namespace: 6caf5d79-c4ce-4e3b-a357-141b74e52a01 | |||
| # 配置中心地址 | |||
| server-addr: 172.20.32.181:8848 | |||
| server-addr: 172.20.32.181:18847 | |||
| # 配置文件格式 | |||
| file-extension: yml | |||
| # 共享配置 | |||
| shared-configs: | |||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||
| group: DEFAULT_GROUP | |||
| refresh: true | |||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||