feat: 启动TensorBoard
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 815 B |
After Width: | Height: | Size: 923 B |
After Width: | Height: | Size: 1.5 KiB |
|
@ -5,7 +5,7 @@
|
|||
border-radius: 21px;
|
||||
}
|
||||
.ant-modal-header {
|
||||
margin: 20px 0;
|
||||
margin: 20px 0 30px;
|
||||
background-color: transparent;
|
||||
}
|
||||
.ant-modal-footer {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
color: @kf-primary-color;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
|
||||
&_image {
|
||||
|
|
|
@ -37,3 +37,27 @@ export function useAntdModal(initialValue: boolean) {
|
|||
|
||||
return [visible, open, close];
|
||||
}
|
||||
|
||||
type Callback<T> = (state: T) => void;
|
||||
|
||||
/**
|
||||
* Generates a stateful value and a function to update it that triggers callbacks.
|
||||
*
|
||||
* @param initialValue - The initial value of the state.
|
||||
* @return A tuple containing the current state value and a function to update the state.
|
||||
*/
|
||||
export function useCallbackState<T>(initialValue: T) {
|
||||
const [state, _setState] = useState(initialValue);
|
||||
const callbackQueue = useRef<Callback<T>[]>([]);
|
||||
useEffect(() => {
|
||||
callbackQueue.current.forEach((cb) => cb(state));
|
||||
callbackQueue.current = [];
|
||||
}, [state]);
|
||||
const setState = (newValue: T, callback: Callback<T>) => {
|
||||
_setState(newValue);
|
||||
if (callback && typeof callback === 'function') {
|
||||
callbackQueue.current.push(callback);
|
||||
}
|
||||
};
|
||||
return [state, setState];
|
||||
}
|
||||
|
|
|
@ -59,16 +59,18 @@ const Dataset = () => {
|
|||
const locationParams = useParams(); //新版本获取路由参数接口
|
||||
const [wordList, setWordList] = useState([]);
|
||||
const [activeTabKey, setActiveTabKey] = useState('1');
|
||||
const [uuid, setUuid] = useState(Date.now());
|
||||
const getDatasetByDetail = () => {
|
||||
getDatasetById(locationParams.id).then((ret) => {
|
||||
console.log(ret);
|
||||
setDatasetDetailObj(ret.data);
|
||||
});
|
||||
};
|
||||
// 获取数据集版本
|
||||
const getDatasetVersionList = () => {
|
||||
getDatasetVersionsById(locationParams.id).then((ret) => {
|
||||
console.log(ret);
|
||||
if (ret.data && ret.data.length > 0) {
|
||||
if (ret && ret.data && ret.data.length > 0) {
|
||||
setVersionList(
|
||||
ret.data.map((item) => {
|
||||
return {
|
||||
|
@ -77,6 +79,8 @@ const Dataset = () => {
|
|||
};
|
||||
}),
|
||||
);
|
||||
setVersion(ret.data[0]);
|
||||
getDatasetVersions({ version: ret.data[0], dataset_id: locationParams.id });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -90,6 +94,7 @@ const Dataset = () => {
|
|||
form.setFieldsValue({ name: datasetDetailObj.name });
|
||||
|
||||
setDialogTitle('创建新版本');
|
||||
setUuid(Date.now());
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
const handleCancel = () => {
|
||||
|
@ -109,9 +114,7 @@ const Dataset = () => {
|
|||
|
||||
onOk: () => {
|
||||
deleteDatasetVersion({ dataset_id: locationParams.id, version }).then((ret) => {
|
||||
setVersion(null);
|
||||
getDatasetVersionList();
|
||||
getDatasetVersions({ version, dataset_id: locationParams.id });
|
||||
message.success('删除成功');
|
||||
});
|
||||
},
|
||||
|
@ -124,6 +127,7 @@ const Dataset = () => {
|
|||
message.success('创建成功');
|
||||
});
|
||||
};
|
||||
// 获取版本下的文件列表
|
||||
const getDatasetVersions = (params) => {
|
||||
getDatasetVersionIdList(params).then((res) => {
|
||||
setWordList(res?.data?.content ?? []);
|
||||
|
@ -368,7 +372,7 @@ const Dataset = () => {
|
|||
},
|
||||
]}
|
||||
>
|
||||
<Upload {...props}>
|
||||
<Upload {...props} data={{ uuid: uuid }}>
|
||||
<Button
|
||||
style={{
|
||||
fontSize: '14px',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { getDatasetList } from '@/services/dataset/index.js';
|
||||
import { Form, Input, Tabs } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Styles from './index.less';
|
||||
import PersonalData from './personalData';
|
||||
|
@ -9,7 +9,7 @@ const { Search } = Input;
|
|||
const { TabPane } = Tabs;
|
||||
const leftdataList = [1, 2, 3];
|
||||
|
||||
const Dataset = (React.FC = () => {
|
||||
const Dataset = () => {
|
||||
const [queryFlow, setQueryFlow] = useState({
|
||||
page: 0,
|
||||
size: 10,
|
||||
|
@ -52,7 +52,7 @@ const Dataset = (React.FC = () => {
|
|||
console.log('Failed:', errorInfo);
|
||||
};
|
||||
useEffect(() => {
|
||||
getDatasetlist();
|
||||
//getDatasetlist();
|
||||
return () => {};
|
||||
}, []);
|
||||
return (
|
||||
|
@ -70,5 +70,5 @@ const Dataset = (React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
export default Dataset;
|
||||
|
|
|
@ -51,6 +51,7 @@ const PublicData = (React.FC = () => {
|
|||
const [total, setTotal] = useState(0);
|
||||
const [form] = Form.useForm();
|
||||
const [dialogTitle, setDialogTitle] = useState('新建数据');
|
||||
const [uuid, setUuid] = useState(Date.now());
|
||||
const getDatasetlist = (queryFlow) => {
|
||||
getDatasetList(queryFlow).then((ret) => {
|
||||
console.log(ret);
|
||||
|
@ -64,6 +65,7 @@ const PublicData = (React.FC = () => {
|
|||
const showModal = () => {
|
||||
form.resetFields();
|
||||
setDialogTitle('新建数据集');
|
||||
setUuid(Date.now());
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
const getAssetIconList = (params) => {
|
||||
|
@ -400,7 +402,7 @@ const PublicData = (React.FC = () => {
|
|||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="数据文件" name="dataset_version_vos">
|
||||
<Upload {...props}>
|
||||
<Upload {...props} data={{ uuid: uuid }}>
|
||||
<Button
|
||||
style={{
|
||||
fontSize: '14px',
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
.tensorBoard-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgba(29, 29, 32, 0.75);
|
||||
|
||||
&__label {
|
||||
color: rgba(29, 29, 32, 0.75);
|
||||
font-size: 15px;
|
||||
|
||||
&--running {
|
||||
color: #6ac21d;
|
||||
}
|
||||
&--failed {
|
||||
color: #df6d6d;
|
||||
}
|
||||
}
|
||||
&__icon {
|
||||
width: 14px;
|
||||
color: #6ac21d;
|
||||
cursor: pointer;
|
||||
|
||||
& + & {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
import exportImg from '@/assets/img/tensor-board-export.png';
|
||||
import pendingImg from '@/assets/img/tensor-board-pending.png';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import classNames from 'classnames';
|
||||
import styles from './index.less';
|
||||
// import stopImg from '@/assets/img/tensor-board-stop.png';
|
||||
import terminatedImg from '@/assets/img/tensor-board-terminated.png';
|
||||
|
||||
export enum TensorBoardStatusEnum {
|
||||
Unknown = 'Unknown', // 未知
|
||||
Pending = 'Pending', // 启动中
|
||||
Running = 'Running', // 运行中
|
||||
Terminated = 'Terminated', // 未启动或者已终止
|
||||
Failed = 'Failed', // 失败
|
||||
}
|
||||
|
||||
const statusConfig = {
|
||||
Unknown: {
|
||||
label: '未知',
|
||||
icon: terminatedImg,
|
||||
classname: '',
|
||||
},
|
||||
Terminated: {
|
||||
label: '未启动',
|
||||
icon: terminatedImg,
|
||||
classname: '',
|
||||
},
|
||||
Failed: {
|
||||
label: '失败',
|
||||
icon: terminatedImg,
|
||||
classname: 'tensorBoard-status__label--failed',
|
||||
},
|
||||
Pending: {
|
||||
label: '启动中',
|
||||
icon: pendingImg,
|
||||
classname: '',
|
||||
},
|
||||
Running: {
|
||||
label: '运行中',
|
||||
icon: exportImg,
|
||||
classname: 'tensorBoard-status__label--running',
|
||||
},
|
||||
};
|
||||
|
||||
type TensorBoardStatusProps = {
|
||||
status: TensorBoardStatusEnum;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
function TensorBoardStatus({
|
||||
status = TensorBoardStatusEnum.Unknown,
|
||||
onClick,
|
||||
}: TensorBoardStatusProps) {
|
||||
return (
|
||||
<div className={styles['tensorBoard-status']}>
|
||||
<div
|
||||
className={classNames(
|
||||
styles['tensorBoard-status__label'],
|
||||
styles[statusConfig[status].classname],
|
||||
)}
|
||||
>
|
||||
{statusConfig[status].label}
|
||||
</div>
|
||||
{statusConfig[status].icon ? (
|
||||
<>
|
||||
<div style={{ margin: '0 6px' }}>|</div>
|
||||
{status === TensorBoardStatusEnum.Pending ? (
|
||||
<LoadingOutlined className={styles['tensorBoard-status__icon']} />
|
||||
) : (
|
||||
<img
|
||||
className={styles['tensorBoard-status__icon']}
|
||||
src={statusConfig[status].icon}
|
||||
onClick={onClick}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TensorBoardStatus;
|
|
@ -1,6 +1,6 @@
|
|||
.params_container {
|
||||
max-height: 230px;
|
||||
padding: 15px;
|
||||
padding: 15px 15px 0;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 8px;
|
||||
|
||||
|
|
|
@ -4,10 +4,12 @@ import {
|
|||
getExperiment,
|
||||
getExperimentById,
|
||||
getQueryByExperimentId,
|
||||
getTensorBoardStatusReq,
|
||||
postExperiment,
|
||||
putExperiment,
|
||||
putQueryByExperimentInsId,
|
||||
runExperiments,
|
||||
runTensorBoardReq,
|
||||
} from '@/services/experiment/index.js';
|
||||
import { getWorkflow } from '@/services/pipeline/index.js';
|
||||
import { elapsedTime } from '@/utils/date';
|
||||
|
@ -23,10 +25,14 @@ import { Button, Modal, Space, Table, message } from 'antd';
|
|||
import momnet from 'moment';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import TensorBoardStatus, { TensorBoardStatusEnum } from './components/TensorBoardStatus';
|
||||
import AddExperimentModal from './experimentText/addExperimentModal';
|
||||
import Styles from './index.less';
|
||||
import { experimentStatusInfo } from './status';
|
||||
|
||||
// 定时器
|
||||
const timerIds = new Map();
|
||||
|
||||
function Experiment() {
|
||||
const navgite = useNavigate();
|
||||
const [experimentList, setExperimentList] = useState([]);
|
||||
|
@ -44,9 +50,13 @@ function Experiment() {
|
|||
const [isAdd, setIsAdd] = useState(true);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [addFormData, setAddFormData] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
getList();
|
||||
getWorkflowList();
|
||||
return () => {
|
||||
clearExperimentInTimers();
|
||||
};
|
||||
}, []);
|
||||
// 获取实验列表
|
||||
const getList = async () => {
|
||||
|
@ -72,11 +82,32 @@ function Experiment() {
|
|||
setWorkflowList(res.data.content);
|
||||
}
|
||||
};
|
||||
// 获取实验实例
|
||||
const getQueryByExperiment = (val) => {
|
||||
getQueryByExperimentId(val).then((ret) => {
|
||||
setExpandedRowKeys(val);
|
||||
if (ret.code === 200 && ret.data && ret.data.length > 0) {
|
||||
setExperimentInList(ret.data);
|
||||
if (ret && ret.data && ret.data.length > 0) {
|
||||
try {
|
||||
const list = ret.data.map((v) => {
|
||||
const nodes_result = v.nodes_result ? JSON.parse(v.nodes_result) : {};
|
||||
return {
|
||||
...v,
|
||||
nodes_result,
|
||||
};
|
||||
});
|
||||
setExperimentInList(list);
|
||||
// 获取 TensorBoard 状态
|
||||
list.forEach((item) => {
|
||||
if (item.nodes_result.tensorboard_log) {
|
||||
const timerId = setTimeout(() => {
|
||||
getTensorBoardStatus(item);
|
||||
}, 0);
|
||||
timerIds.set(item.id, timerId);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
setExperimentInList([]);
|
||||
}
|
||||
getList();
|
||||
} else {
|
||||
setExperimentInList([]);
|
||||
|
@ -84,13 +115,66 @@ function Experiment() {
|
|||
}
|
||||
});
|
||||
};
|
||||
// 运行 TensorBoard
|
||||
const runTensorBoard = async (experimentIn) => {
|
||||
const params = {
|
||||
namespace: experimentIn.nodes_result.tensorboard_log.namespace,
|
||||
path: experimentIn.nodes_result.tensorboard_log.path,
|
||||
pvc_name: experimentIn.nodes_result.tensorboard_log.pvc_name,
|
||||
};
|
||||
const [res] = await to(runTensorBoardReq(params));
|
||||
if (res) {
|
||||
experimentIn.tensorboardUrl = res.data;
|
||||
const timerId = timerIds.get(experimentIn.id);
|
||||
if (timerId) {
|
||||
clearTimeout(timerId);
|
||||
timerIds.delete(experimentIn.id);
|
||||
getTensorBoardStatus(experimentIn);
|
||||
}
|
||||
}
|
||||
};
|
||||
// 获取 TensorBoard 状态
|
||||
const getTensorBoardStatus = async (experimentIn) => {
|
||||
const params = {
|
||||
namespace: experimentIn.nodes_result.tensorboard_log.namespace,
|
||||
path: experimentIn.nodes_result.tensorboard_log.path,
|
||||
pvc_name: experimentIn.nodes_result.tensorboard_log.pvc_name,
|
||||
};
|
||||
const [res] = await to(getTensorBoardStatusReq(params));
|
||||
if (res && res.data) {
|
||||
setExperimentInList((prevList) => {
|
||||
const newList = [...prevList];
|
||||
const index = prevList.findIndex((item) => item.id === experimentIn.id);
|
||||
const preObj = prevList[index];
|
||||
const newObj = {
|
||||
...preObj,
|
||||
tensorBoardStatus: res.data.status,
|
||||
tensorboardUrl: res.data.url,
|
||||
};
|
||||
newList.splice(index, 1, newObj);
|
||||
return newList;
|
||||
});
|
||||
const timerId = setTimeout(() => {
|
||||
getTensorBoardStatus(experimentIn);
|
||||
}, 10000);
|
||||
timerIds.set(experimentIn.id, timerId);
|
||||
}
|
||||
};
|
||||
const expandChange = (e, record) => {
|
||||
if (record.id === expandedRowKeys) {
|
||||
clearExperimentInTimers();
|
||||
setExpandedRowKeys(null);
|
||||
} else {
|
||||
getQueryByExperiment(record.id);
|
||||
}
|
||||
};
|
||||
// 终止实验实例获取 TensorBoard 状态的定时器
|
||||
const clearExperimentInTimers = () => {
|
||||
timerIds.values().forEach((timerId) => {
|
||||
clearTimeout(timerId);
|
||||
});
|
||||
timerIds.clear();
|
||||
};
|
||||
// 创建实验
|
||||
const createExperiment = () => {
|
||||
setIsAdd(true);
|
||||
|
@ -174,6 +258,19 @@ function Experiment() {
|
|||
navgite({ pathname: `/experiment/pytorchtext/${record.workflow_id}/${item.id}` });
|
||||
};
|
||||
|
||||
const handleTensorboard = async (experimentIn) => {
|
||||
if (
|
||||
experimentIn.tensorBoardStatus === TensorBoardStatusEnum.Terminated ||
|
||||
experimentIn.tensorBoardStatus === TensorBoardStatusEnum.Failed
|
||||
) {
|
||||
await runTensorBoard(experimentIn);
|
||||
} else if (
|
||||
experimentIn.tensorBoardStatus === TensorBoardStatusEnum.Running &&
|
||||
experimentIn.tensorboardUrl
|
||||
) {
|
||||
window.open(experimentIn.tensorboardUrl, '_blank');
|
||||
}
|
||||
};
|
||||
const columns = [
|
||||
{
|
||||
title: '实验名称',
|
||||
|
@ -198,7 +295,6 @@ function Experiment() {
|
|||
key: 'status_list',
|
||||
render: (text) => {
|
||||
let newText = text && text.replace(/\s+/g, '').split(',');
|
||||
console.log(newText);
|
||||
return (
|
||||
<>
|
||||
{newText && newText.length > 0
|
||||
|
@ -306,15 +402,17 @@ function Experiment() {
|
|||
columns={columns}
|
||||
dataSource={experimentList}
|
||||
pagination={paginationProps}
|
||||
rowKey="id"
|
||||
expandable={{
|
||||
expandedRowRender: (record) => (
|
||||
<div>
|
||||
{experimentInList && experimentInList.length > 0 ? (
|
||||
<div className={Styles.tableExpandBox} style={{ paddingBottom: '16px' }}>
|
||||
<div style={{ width: '50px' }}>序号</div>
|
||||
<div style={{ width: '200px' }}>状态</div>
|
||||
<div style={{ width: '150px' }}>序号</div>
|
||||
<div style={{ width: '300px' }}>TensorBoard</div>
|
||||
<div style={{ width: '300px' }}>运行时长</div>
|
||||
<div style={{ width: '300px' }}>开始时间</div>
|
||||
<div style={{ width: '200px' }}>状态</div>
|
||||
<div style={{ width: '200px' }}>操作</div>
|
||||
</div>
|
||||
) : (
|
||||
|
@ -332,9 +430,27 @@ function Experiment() {
|
|||
height: '45px',
|
||||
}}
|
||||
>
|
||||
<a style={{ width: '50px' }} onClick={(e) => routerToText(e, item, record)}>
|
||||
<a style={{ width: '150px' }} onClick={(e) => routerToText(e, item, record)}>
|
||||
{index + 1}
|
||||
</a>
|
||||
<div style={{ width: '300px' }}>
|
||||
{item.nodes_result.tensorboard_log ? (
|
||||
<TensorBoardStatus
|
||||
status={item.tensorBoardStatus}
|
||||
onClick={() => handleTensorboard(item)}
|
||||
></TensorBoardStatus>
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</div>
|
||||
<div style={{ width: '300px' }}>
|
||||
{item.finish_time
|
||||
? elapsedTime(new Date(item.create_time), new Date(item.finish_time))
|
||||
: elapsedTime(new Date(item.create_time), new Date())}
|
||||
</div>
|
||||
<div style={{ width: '300px' }}>
|
||||
{momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
<div className={Styles.statusBox} style={{ width: '200px' }}>
|
||||
<img
|
||||
style={{ width: '17px', marginRight: '7px' }}
|
||||
|
@ -347,14 +463,6 @@ function Experiment() {
|
|||
{experimentStatusInfo[item.status]?.label}
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ width: '300px' }}>
|
||||
{item.finish_time
|
||||
? elapsedTime(new Date(item.create_time), new Date(item.finish_time))
|
||||
: elapsedTime(new Date(item.create_time), new Date())}
|
||||
</div>
|
||||
<div style={{ width: '300px' }}>
|
||||
{momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
<div style={{ width: '200px' }}>
|
||||
<Button
|
||||
type="link"
|
||||
|
|
|
@ -59,6 +59,7 @@ const Dataset = () => {
|
|||
const locationParams = useParams(); //新版本获取路由参数接口
|
||||
console.log(locationParams);
|
||||
const [wordList, setWordList] = useState([]);
|
||||
const [uuid, setUuid] = useState(Date.now());
|
||||
const getModelByDetail = () => {
|
||||
getModelById(locationParams.id).then((ret) => {
|
||||
console.log(ret);
|
||||
|
@ -68,7 +69,7 @@ const Dataset = () => {
|
|||
const getModelVersionsList = () => {
|
||||
getModelVersionsById(locationParams.id).then((ret) => {
|
||||
console.log(ret);
|
||||
if (ret.data && ret.data.length > 0) {
|
||||
if (ret && ret.data && ret.data.length > 0) {
|
||||
setVersionList(
|
||||
ret.data.map((item) => {
|
||||
return {
|
||||
|
@ -77,6 +78,8 @@ const Dataset = () => {
|
|||
};
|
||||
}),
|
||||
);
|
||||
setVersion(ret.data[0]);
|
||||
getModelVersions({ version: ret.data[0], models_id: locationParams.id });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -90,6 +93,7 @@ const Dataset = () => {
|
|||
form.setFieldsValue({ name: datasetDetailObj.name });
|
||||
|
||||
setDialogTitle('创建新版本');
|
||||
setUuid(Date.now());
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
const handleCancel = () => {
|
||||
|
@ -104,9 +108,7 @@ const Dataset = () => {
|
|||
|
||||
onOk: () => {
|
||||
deleteModelVersion({ models_id: locationParams.id, version }).then((ret) => {
|
||||
setVersion(null);
|
||||
getModelVersionsList();
|
||||
getModelVersions({ version, models_id: locationParams.id });
|
||||
message.success('删除成功');
|
||||
});
|
||||
},
|
||||
|
@ -368,7 +370,7 @@ const Dataset = () => {
|
|||
},
|
||||
]}
|
||||
>
|
||||
<Upload {...props}>
|
||||
<Upload {...props} data={{ uuid: uuid }}>
|
||||
<Button
|
||||
style={{
|
||||
fontSize: '14px',
|
||||
|
|
|
@ -49,6 +49,7 @@ const PublicData = () => {
|
|||
const [total, setTotal] = useState(0);
|
||||
const [form] = Form.useForm();
|
||||
const [dialogTitle, setDialogTitle] = useState('新建模型');
|
||||
const [uuid, setUuid] = useState(Date.now());
|
||||
const getModelLists = (queryFlow) => {
|
||||
getModelList(queryFlow).then((ret) => {
|
||||
console.log(ret);
|
||||
|
@ -62,6 +63,7 @@ const PublicData = () => {
|
|||
const showModal = () => {
|
||||
form.resetFields();
|
||||
setDialogTitle('新建模型');
|
||||
setUuid(Date.now());
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
const getAssetIconList = (params) => {
|
||||
|
@ -375,7 +377,7 @@ const PublicData = () => {
|
|||
<Select allowClear placeholder="请选择模型标签" options={[]} />
|
||||
</Form.Item>
|
||||
<Form.Item label="模型文件" name="dataset_version_vos">
|
||||
<Upload {...props}>
|
||||
<Upload {...props} data={{ uuid: uuid }}>
|
||||
<Button icon={<UploadOutlined style={{ color: '#1664ff' }} />}>上传文件</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
|
|
|
@ -241,7 +241,7 @@ const Pipeline = () => {
|
|||
新建流水线
|
||||
</Button>
|
||||
</div>
|
||||
<Table columns={columns} dataSource={pipeList} pagination={paginationProps} />
|
||||
<Table columns={columns} dataSource={pipeList} pagination={paginationProps} rowKey="id" />
|
||||
<Modal
|
||||
title={
|
||||
<div style={{ display: 'flex', alignItems: 'center', fontWeight: 500 }}>
|
||||
|
|
|
@ -100,3 +100,19 @@ export function putExperiment(data) {
|
|||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 启动tensorBoard
|
||||
export function runTensorBoardReq(data) {
|
||||
return request(`/api/mmp/tensorBoard/run`, {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 启动tensorBoard
|
||||
export function getTensorBoardStatusReq(data) {
|
||||
return request(`/api/mmp/tensorBoard/getStatus`, {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
|