Browse Source

update

pull/13/head
陈钰楠 2 years ago
parent
commit
7fbd135501
20 changed files with 132 additions and 294 deletions
  1. +3
    -3
      webapp/.env.pre
  2. +2
    -1
      webapp/.eslintignore
  3. +4
    -7
      webapp/babel.config.js
  4. +12
    -0
      webapp/package.json
  5. +2
    -10
      webapp/src/api/trainingImage/index.js
  6. +4
    -0
      webapp/src/assets/styles/atomic.scss
  7. +3
    -0
      webapp/src/components/BaseTooltip/index.vue
  8. +3
    -2
      webapp/src/components/Training/jobForm.vue
  9. +1
    -1
      webapp/src/utils/VisualUtils/download.js
  10. +18
    -0
      webapp/src/utils/constant.js
  11. +1
    -1
      webapp/src/utils/download.js
  12. +2
    -2
      webapp/src/views/algorithm/components/algorithmForm.vue
  13. +2
    -3
      webapp/src/views/cloudServing/components/forms/batchServingForm.vue
  14. +3
    -4
      webapp/src/views/cloudServing/components/forms/servingModelConfig.vue
  15. +7
    -3
      webapp/src/views/dataset/modelService/CreateModelService.vue
  16. +7
    -3
      webapp/src/views/dataset/modelService/ModifyModelService.vue
  17. +3
    -3
      webapp/src/views/dataset/pointCloud/components/auto-annotate-modal.vue
  18. +3
    -4
      webapp/src/views/development/components/CreateDialog.vue
  19. +52
    -238
      webapp/src/views/trainingImage/index.vue
  20. +0
    -9
      webapp/src/views/trainingJob/utils.js

+ 3
- 3
webapp/.env.pre View File

@@ -14,16 +14,16 @@ VUE_APP_DATA_API = '/'
VUE_APP_VISUAL_API = '/' VUE_APP_VISUAL_API = '/'


# minio # minio
VUE_APP_MINIO_API = 'http://127.0.0.1:9000/minio'
VUE_APP_MINIO_API = 'http://10.105.1.132:9000/minio'


# atlas # atlas
VUE_APP_ATLAS_HOST = 'http://127.0.0.1'
VUE_APP_ATLAS_HOST = 'http://183.129.174.186'


# DCM4CHEE # DCM4CHEE
VUE_APP_DCM_API = 'http://pre.dubhe.club/dcm4chee/dcm4chee-arc/aets/DCM4CHEE_ADMIN' VUE_APP_DCM_API = 'http://pre.dubhe.club/dcm4chee/dcm4chee-arc/aets/DCM4CHEE_ADMIN'


# minIO 服务 IP # minIO 服务 IP
VUE_APP_MINIO_ENDPOINT = '127.0.0.1'
VUE_APP_MINIO_ENDPOINT = '10.105.1.132'
# minIO 服务 端口 # minIO 服务 端口
VUE_APP_MINIO_PORT = '9000' VUE_APP_MINIO_PORT = '9000'
# 是否开启 SSL # 是否开启 SSL


+ 2
- 1
webapp/.eslintignore View File

@@ -5,4 +5,5 @@ dist
src/components/Crud src/components/Crud
mock mock
src/views/visual src/views/visual
src/store/modules/Visual
src/store/modules/Visual
src/utils/VisualUtils

+ 4
- 7
webapp/babel.config.js View File

@@ -1,12 +1,9 @@
const plugins = [
"@vue/babel-plugin-transform-vue-jsx",
"@babel/plugin-proposal-optional-chaining",
];
const plugins = ['@vue/babel-plugin-transform-vue-jsx', '@babel/plugin-proposal-optional-chaining'];
// 生产环境移除console // 生产环境移除console
if (process.env.NODE_ENV === "production") {
plugins.push("transform-remove-console");
if (process.env.NODE_ENV === 'production') {
plugins.push('transform-remove-console');
} }
module.exports = { module.exports = {
plugins, plugins,
presets: [["@vue/app",{ useBuiltIns: "entry" }]],
presets: [['@vue/app', { useBuiltIns: 'entry' }]],
}; };

+ 12
- 0
webapp/package.json View File

@@ -24,6 +24,18 @@
"lint:style": "stylelint src/**/*.{html,vue,css,sass,scss}", "lint:style": "stylelint src/**/*.{html,vue,css,sass,scss}",
"fix:style": "stylelint src/**/*.{html,vue,css,sass,scss} --fix" "fix:style": "stylelint src/**/*.{html,vue,css,sass,scss} --fix"
}, },
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git@codeup.teambition.com:zhejianglab/dubhe-web.git" "url": "git@codeup.teambition.com:zhejianglab/dubhe-web.git"


+ 2
- 10
webapp/src/api/trainingImage/index.js View File

@@ -19,7 +19,7 @@ import { API_MODULE_NAME } from '@/config';


export function list(params) { export function list(params) {
return request({ return request({
url: `/${API_MODULE_NAME.IMAGE}/ptImage/info`,
url: `/${API_MODULE_NAME.IMAGE}/ptImage/list`,
method: 'get', method: 'get',
params, params,
}); });
@@ -27,7 +27,7 @@ export function list(params) {


export function add(data) { export function add(data) {
return request({ return request({
url: `/${API_MODULE_NAME.IMAGE}/ptImage/uploadImage`,
url: `/${API_MODULE_NAME.IMAGE}/ptImage`,
method: 'post', method: 'post',
data, data,
}); });
@@ -65,14 +65,6 @@ export function getImageTagList(params) {
}); });
} }


export function setPrecast(params) {
return request({
url: `/${API_MODULE_NAME.IMAGE}/ptImage/imageResource`,
method: 'put',
params,
});
}

// 设置notebook默认镜像-获取默认镜像 // 设置notebook默认镜像-获取默认镜像
export function getDefaultImage(params) { export function getDefaultImage(params) {
return request({ return request({


+ 4
- 0
webapp/src/assets/styles/atomic.scss View File

@@ -332,6 +332,10 @@
width: 320px; width: 320px;
} }


.w-400 {
width: 400px;
}

.w-500 { .w-500 {
width: 500px; width: 500px;
} }


+ 3
- 0
webapp/src/components/BaseTooltip/index.vue View File

@@ -9,6 +9,9 @@ the License. * ============================================================= */
<template> <template>
<el-tooltip v-bind="mergedAttrs"> <el-tooltip v-bind="mergedAttrs">
<i class="primary f18 vm" :class="[icon]" /> <i class="primary f18 vm" :class="[icon]" />
<template #content>
<slot name="content" />
</template>
</el-tooltip> </el-tooltip>
</template> </template>




+ 3
- 2
webapp/src/components/Training/jobForm.vue View File

@@ -541,6 +541,7 @@ import {
RESOURCES_MODULE_ENUM, RESOURCES_MODULE_ENUM,
RESOURCES_POOL_TYPE_ENUM, RESOURCES_POOL_TYPE_ENUM,
RESOURCES_POOL_TYPE_MAP, RESOURCES_POOL_TYPE_MAP,
IMAGE_TYPE_ENUM,
} from '@/utils'; } from '@/utils';
import { list as getAlgorithmList, getAlgorithmInfo } from '@/api/algorithm/algorithm'; import { list as getAlgorithmList, getAlgorithmInfo } from '@/api/algorithm/algorithm';
import { getModelByResource } from '@/api/model/model'; import { getModelByResource } from '@/api/model/model';
@@ -551,7 +552,7 @@ import { list as getSpecsNames } from '@/api/system/resources';
import { list as getNotebooks } from '@/api/development/notebook'; import { list as getNotebooks } from '@/api/development/notebook';
import { trainConfig } from '@/config'; import { trainConfig } from '@/config';
import { NOTEBOOK_STATUS_ENUM } from '@/views/development/utils'; import { NOTEBOOK_STATUS_ENUM } from '@/views/development/utils';
import { IMAGE_TYPE, TRAINING_TYPE_ENUM } from '@/views/trainingJob/utils';
import { TRAINING_TYPE_ENUM } from '@/views/trainingJob/utils';
import BaseTooltip from '@/components/BaseTooltip'; import BaseTooltip from '@/components/BaseTooltip';
import DataSourceSelector from './dataSourceSelector'; import DataSourceSelector from './dataSourceSelector';


@@ -929,7 +930,7 @@ export default {
}, },
async getHarborProjects() { async getHarborProjects() {
this.harborProjectList = await getImageNameList({ this.harborProjectList = await getImageNameList({
imageTypes: [IMAGE_TYPE.TRAIN],
imageTypes: [IMAGE_TYPE_ENUM.TRAIN],
}); });
if ( if (
this.form.imageName && this.form.imageName &&


+ 1
- 1
webapp/src/utils/VisualUtils/download.js View File

@@ -39,7 +39,7 @@ const covertSVG2Image = (node, name, width, height, type = 'png') => {
const context = canvas.getContext('2d'); const context = canvas.getContext('2d');
context.fillStyle = '#fff'; context.fillStyle = '#fff';
context.fillRect(0, 0, 10000, 10000); context.fillRect(0, 0, 10000, 10000);
image.onload = function() {
image.onload = () => {
context.drawImage(image, 0, 0); context.drawImage(image, 0, 0);
const a = document.createElement('a'); const a = document.createElement('a');
a.download = `${name}.${type}`; a.download = `${name}.${type}`;


+ 18
- 0
webapp/src/utils/constant.js View File

@@ -133,6 +133,24 @@ export const K8S_BUSINESS_LABEL_MAP = {
[K8S_BUSINESS_LABEL_ENUM.POINT_CLOUD]: '点云数据集', [K8S_BUSINESS_LABEL_ENUM.POINT_CLOUD]: '点云数据集',
}; };


// 镜像分类枚举
export const IMAGE_TYPE_ENUM = {
NOTEBOOK: 0, // notebook镜像类型
TRAIN: 1, // 训练镜像和预置镜像类型
SERVING: 2, // serving镜像
TERMINAL: 3, // 终端镜像
POINTCLOUD: 4, // 点云镜像
DATASETMARKED: 5, // 数据标注镜像
};
export const IMAGE_TYPE_MAP = {
[IMAGE_TYPE_ENUM.NOTEBOOK]: 'Notebook镜像',
[IMAGE_TYPE_ENUM.TRAIN]: '训练镜像',
[IMAGE_TYPE_ENUM.SERVING]: 'Serving镜像',
[IMAGE_TYPE_ENUM.TERMINAL]: '终端镜像',
[IMAGE_TYPE_ENUM.POINTCLOUD]: '点云镜像',
[IMAGE_TYPE_ENUM.DATASETMARKED]: '数据标注镜像',
};

// 默认进度条颜色 // 默认进度条颜色
export const defaultProcessColors = [ export const defaultProcessColors = [
{ color: '#909399', percentage: 40 }, { color: '#909399', percentage: 40 },


+ 1
- 1
webapp/src/utils/download.js View File

@@ -20,7 +20,7 @@ import ZIP from './zip';


const pMap = require('p-map'); const pMap = require('p-map');


//streamSaver.mitm = 'https://static.zhejianglab.com/mitm.html';
streamSaver.mitm = 'https://static.zhejianglab.com/mitm.html';


// 默认名字解析 // 默认名字解析
const defaultName = (file) => file.name; const defaultName = (file) => file.name;


+ 2
- 2
webapp/src/views/algorithm/components/algorithmForm.vue View File

@@ -171,13 +171,13 @@ import {
invalidFileNameChar, invalidFileNameChar,
defaultProcessColors, defaultProcessColors,
ALGORITHM_RESOURCE_ENUM, ALGORITHM_RESOURCE_ENUM,
IMAGE_TYPE_ENUM,
} from '@/utils'; } from '@/utils';
import UploadInline from '@/components/UploadForm/inline'; import UploadInline from '@/components/UploadForm/inline';
import UploadProgress from '@/components/UploadProgress'; import UploadProgress from '@/components/UploadProgress';
import { useMapGetters } from '@/hooks'; import { useMapGetters } from '@/hooks';
import { algorithmConfig } from '@/config'; import { algorithmConfig } from '@/config';
import { getImageNameList, getImageTagList } from '@/api/trainingImage'; import { getImageNameList, getImageTagList } from '@/api/trainingImage';
import { IMAGE_TYPE } from '@/views/trainingJob/utils';


const defaultForm = { const defaultForm = {
id: null, id: null,
@@ -289,7 +289,7 @@ export default {
}; };
// 获取镜像名列表 // 获取镜像名列表
const getImageNames = async (keepValue = false) => { const getImageNames = async (keepValue = false) => {
state.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE.TRAIN] });
state.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE_ENUM.TRAIN] });
if (!keepValue || !form.imageName) { if (!keepValue || !form.imageName) {
form.imageTag = null; form.imageTag = null;
} else if (!state.imageNameList.includes(form.imageName)) { } else if (!state.imageNameList.includes(form.imageName)) {


+ 2
- 3
webapp/src/views/cloudServing/components/forms/batchServingForm.vue View File

@@ -199,14 +199,13 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';


import { getUniqueId, invalidFileNameChar, RESOURCES_MODULE_ENUM } from '@/utils';
import { getUniqueId, invalidFileNameChar, RESOURCES_MODULE_ENUM, IMAGE_TYPE_ENUM } from '@/utils';
import { getServingModel } from '@/api/model/model'; import { getServingModel } from '@/api/model/model';
import { list as getModelVersions } from '@/api/model/modelVersion'; import { list as getModelVersions } from '@/api/model/modelVersion';
import { getImageNameList, getImageTagList } from '@/api/trainingImage'; import { getImageNameList, getImageTagList } from '@/api/trainingImage';
import { getInferenceAlgorithm, add as addAlgorithm } from '@/api/algorithm/algorithm'; import { getInferenceAlgorithm, add as addAlgorithm } from '@/api/algorithm/algorithm';
import { list as getSpecsNames } from '@/api/system/resources'; import { list as getSpecsNames } from '@/api/system/resources';
import { validateNameWithHyphen } from '@/utils/validate'; import { validateNameWithHyphen } from '@/utils/validate';
import { IMAGE_TYPE } from '@/views/trainingJob/utils';
import RunParamForm from '@/components/Training/runParamForm'; import RunParamForm from '@/components/Training/runParamForm';
import BaseModal from '@/components/BaseModal'; import BaseModal from '@/components/BaseModal';
import AlgorithmForm from '@/views/algorithm/components/algorithmForm'; import AlgorithmForm from '@/views/algorithm/components/algorithmForm';
@@ -541,7 +540,7 @@ export default {


// 镜像选择 // 镜像选择
async getImageNames(keepValue = false) { async getImageNames(keepValue = false) {
this.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE.SERVING] });
this.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE_ENUM.SERVING] });
if (!keepValue || !this.form.imageName) { if (!keepValue || !this.form.imageName) {
this.form.imageTag = null; this.form.imageTag = null;
} else if (!this.imageNameList.includes(this.form.imageName)) { } else if (!this.imageNameList.includes(this.form.imageName)) {


+ 3
- 4
webapp/src/views/cloudServing/components/forms/servingModelConfig.vue View File

@@ -204,8 +204,7 @@ import { getImageNameList, getImageTagList } from '@/api/trainingImage';
import { getInferenceAlgorithm, add as addAlgorithm } from '@/api/algorithm/algorithm'; import { getInferenceAlgorithm, add as addAlgorithm } from '@/api/algorithm/algorithm';
import { list as getSpecsNames } from '@/api/system/resources'; import { list as getSpecsNames } from '@/api/system/resources';
import { servingConfig } from '@/config'; import { servingConfig } from '@/config';
import { RESOURCES_MODULE_ENUM } from '@/utils';
import { IMAGE_TYPE } from '@/views/trainingJob/utils';
import { RESOURCES_MODULE_ENUM, IMAGE_TYPE_ENUM } from '@/utils';
import RunParamForm from '@/components/Training/runParamForm'; import RunParamForm from '@/components/Training/runParamForm';
import BaseModal from '@/components/BaseModal'; import BaseModal from '@/components/BaseModal';
import AlgorithmForm from '@/views/algorithm/components/algorithmForm'; import AlgorithmForm from '@/views/algorithm/components/algorithmForm';
@@ -540,7 +539,7 @@ export default {
// 镜像选择 // 镜像选择
// 获取镜像名称列表 // 获取镜像名称列表
async getImageNames(keepValue = false) { async getImageNames(keepValue = false) {
this.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE.SERVING] });
this.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE_ENUM.SERVING] });
if (!keepValue || !this.form.imageName) { if (!keepValue || !this.form.imageName) {
this.form.imageTag = null; this.form.imageTag = null;
} else if (!this.imageNameList.includes(this.form.imageName)) { } else if (!this.imageNameList.includes(this.form.imageName)) {
@@ -554,7 +553,7 @@ export default {
async getImageTags(imageName, keepValue = false) { async getImageTags(imageName, keepValue = false) {
this.imageTagList = await getImageTagList({ this.imageTagList = await getImageTagList({
imageName, imageName,
imageTypes: [IMAGE_TYPE.SERVING],
imageTypes: [IMAGE_TYPE_ENUM.SERVING],
}); });
if (keepValue && this.form.imageTag) { if (keepValue && this.form.imageTag) {
if (!this.imageTagList.some((image) => image.imageTag === this.form.imageTag)) { if (!this.imageTagList.some((image) => image.imageTag === this.form.imageTag)) {


+ 7
- 3
webapp/src/views/dataset/modelService/CreateModelService.vue View File

@@ -134,8 +134,12 @@ import { list as listBranchModel } from '@/api/model/modelVersion';
import { getImageNameList, getImageTagList } from '@/api/trainingImage'; import { getImageNameList, getImageTagList } from '@/api/trainingImage';
import { list as listResourceSpec } from '@/api/system/resources'; import { list as listResourceSpec } from '@/api/system/resources';
import { types } from '@/utils/validate'; import { types } from '@/utils/validate';
import { RESOURCES_POOL_TYPE_ENUM, RESOURCES_MODULE_ENUM, modelTypeSymbol } from '@/utils/constant';
import { IMAGE_TYPE } from '@/views/trainingJob/utils';
import {
RESOURCES_POOL_TYPE_ENUM,
RESOURCES_MODULE_ENUM,
modelTypeSymbol,
IMAGE_TYPE_ENUM,
} from '@/utils/constant';


const initialForm = { const initialForm = {
name: undefined, name: undefined,
@@ -246,7 +250,7 @@ export default {
}; };


const queryImages = () => { const queryImages = () => {
return getImageNameList({ imageTypes: [IMAGE_TYPE.DATASETMARKED] });
return getImageNameList({ imageTypes: [IMAGE_TYPE_ENUM.DATASETMARKED] });
}; };


const handleModelParentChange = () => { const handleModelParentChange = () => {


+ 7
- 3
webapp/src/views/dataset/modelService/ModifyModelService.vue View File

@@ -143,8 +143,12 @@ import { list as listBranchModel } from '@/api/model/modelVersion';
import { getImageNameList, getImageTagList } from '@/api/trainingImage'; import { getImageNameList, getImageTagList } from '@/api/trainingImage';
import { list as listResourceSpec } from '@/api/system/resources'; import { list as listResourceSpec } from '@/api/system/resources';
import { types } from '@/utils/validate'; import { types } from '@/utils/validate';
import { RESOURCES_POOL_TYPE_ENUM, RESOURCES_MODULE_ENUM, modelTypeSymbol } from '@/utils/constant';
import { IMAGE_TYPE } from '@/views/trainingJob/utils';
import {
RESOURCES_POOL_TYPE_ENUM,
RESOURCES_MODULE_ENUM,
modelTypeSymbol,
IMAGE_TYPE_ENUM,
} from '@/utils/constant';


const initialForm = { const initialForm = {
name: undefined, name: undefined,
@@ -283,7 +287,7 @@ export default {


// 查询镜像列表 // 查询镜像列表
const queryImages = () => { const queryImages = () => {
return getImageNameList({ imageTypes: [IMAGE_TYPE.DATASETMARKED] });
return getImageNameList({ imageTypes: [IMAGE_TYPE_ENUM.DATASETMARKED] });
}; };


// 查询镜像版本列表 // 查询镜像版本列表


+ 3
- 3
webapp/src/views/dataset/pointCloud/components/auto-annotate-modal.vue View File

@@ -163,8 +163,8 @@ import {
ALGORITHM_RESOURCE_ENUM, ALGORITHM_RESOURCE_ENUM,
MODEL_RESOURCE_ENUM, MODEL_RESOURCE_ENUM,
RESOURCES_POOL_TYPE_ENUM, RESOURCES_POOL_TYPE_ENUM,
IMAGE_TYPE_ENUM,
} from '@/utils'; } from '@/utils';
import { IMAGE_TYPE } from '@/views/trainingJob/utils';


const initFormState = { const initFormState = {
modelId: null, modelId: null,
@@ -285,7 +285,7 @@ export default {
return Promise.reject(); return Promise.reject();
} }
return getImageTagList({ return getImageTagList({
imageTypes: IMAGE_TYPE.POINTCLOUD,
imageTypes: IMAGE_TYPE_ENUM.POINTCLOUD,
imageName: modelState.imageName, imageName: modelState.imageName,
}).then((res) => { }).then((res) => {
state.imageTagList = res; state.imageTagList = res;
@@ -294,7 +294,7 @@ export default {


// 镜像选择 // 镜像选择
const getImageNames = async () => { const getImageNames = async () => {
state.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE.POINTCLOUD] });
state.imageNameList = await getImageNameList({ imageTypes: [IMAGE_TYPE_ENUM.POINTCLOUD] });
if ( if (
modelState.imageName && modelState.imageName &&
!state.imageNameList.some((image) => image === modelState.imageName) !state.imageNameList.some((image) => image === modelState.imageName)


+ 3
- 4
webapp/src/views/development/components/CreateDialog.vue View File

@@ -122,14 +122,13 @@
</template> </template>


<script> <script>
import { validateNameWithHyphen, RESOURCES_MODULE_ENUM } from '@/utils';
import { validateNameWithHyphen, RESOURCES_MODULE_ENUM, IMAGE_TYPE_ENUM } from '@/utils';
import BaseModal from '@/components/BaseModal'; import BaseModal from '@/components/BaseModal';
import InfoSelect from '@/components/InfoSelect'; import InfoSelect from '@/components/InfoSelect';
import { getPublishedDatasets, getDatasetVersions } from '@/api/preparation/dataset'; import { getPublishedDatasets, getDatasetVersions } from '@/api/preparation/dataset';
import { add as addNotebook } from '@/api/development/notebook'; import { add as addNotebook } from '@/api/development/notebook';
import { list as getSpecsNames } from '@/api/system/resources'; import { list as getSpecsNames } from '@/api/system/resources';
import { getImageNameList, getImageTagList } from '@/api/trainingImage/index'; import { getImageNameList, getImageTagList } from '@/api/trainingImage/index';
import { IMAGE_TYPE } from '@/views/trainingJob/utils';


const defaultForm = { const defaultForm = {
noteBookName: null, noteBookName: null,
@@ -208,7 +207,7 @@ export default {
} }
}, },
async getHarborProjects() { async getHarborProjects() {
this.harborProjectList = await getImageNameList({ imageTypes: [IMAGE_TYPE.NOTEBOOK] });
this.harborProjectList = await getImageNameList({ imageTypes: [IMAGE_TYPE_ENUM.NOTEBOOK] });
if ( if (
this.form.imageName && this.form.imageName &&
!this.harborProjectList.some((project) => project === this.form.imageName) !this.harborProjectList.some((project) => project === this.form.imageName)
@@ -237,7 +236,7 @@ export default {
} }
return getImageTagList({ return getImageTagList({
imageName: this.form.imageName, imageName: this.form.imageName,
imageTypes: [IMAGE_TYPE.NOTEBOOK],
imageTypes: [IMAGE_TYPE_ENUM.NOTEBOOK],
}).then((res) => { }).then((res) => {
this.harborImageList = res; this.harborImageList = res;
}); });


+ 52
- 238
webapp/src/views/trainingImage/index.vue View File

@@ -48,7 +48,7 @@
<el-table <el-table
v-if="prefabricate" v-if="prefabricate"
ref="table" ref="table"
v-loading="crud.loading || disableEdit"
v-loading="crud.loading"
:data="crud.data" :data="crud.data"
highlight-current-row highlight-current-row
@selection-change="crud.selectionChangeHandler" @selection-change="crud.selectionChangeHandler"
@@ -57,21 +57,6 @@
<el-table-column v-if="!isPreset" prop="id" label="ID" sortable="custom" width="80px" /> <el-table-column v-if="!isPreset" prop="id" label="ID" sortable="custom" width="80px" />
<el-table-column prop="imageName" label="镜像名称" sortable="custom" /> <el-table-column prop="imageName" label="镜像名称" sortable="custom" />
<el-table-column prop="imageTag" label="镜像版本号" sortable="custom" /> <el-table-column prop="imageTag" label="镜像版本号" sortable="custom" />
<el-table-column prop="imageStatus" label="状态" width="130px">
<template #header>
<dropdown-header
title="状态"
:list="imageStatusList"
:filtered="Boolean(localQuery.imageStatus)"
@command="filterStatus"
/>
</template>
<template slot-scope="scope">
<el-tag effect="plain" :type="map[scope.row.imageStatus]">
{{ statusMap[scope.row.imageStatus] }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="imageTypes" label="镜像用途" width="180px"> <el-table-column prop="imageTypes" label="镜像用途" width="180px">
<template #header> <template #header>
<dropdown-header <dropdown-header
@@ -91,31 +76,8 @@
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="isNotebook" prop="imageResource" label="是否为默认" align="center">
<template slot-scope="scope">
<i
:class="resourceObj(scope.row.imageResource).icon"
:style="{ color: resourceObj(scope.row.imageResource).color, fontSize: '20px' }"
></i>
</template>
</el-table-column>
<el-table-column v-if="isAdmin || isCustom" label="操作" width="200px" fixed="right"> <el-table-column v-if="isAdmin || isCustom" label="操作" width="200px" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tooltip
v-if="isAdmin && isNotebook"
effect="dark"
content="设为在线编辑算法时创建nootbook的默认镜像"
placement="top"
>
<el-button
:id="`doPrecast_` + scope.$index"
:disabled="Boolean(scope.row.imageResource)"
type="text"
@click.stop="doPrecast(scope.row.id)"
>
{{ resourceObj(scope.row.imageResource).butText }}
</el-button>
</el-tooltip>
<el-button <el-button
v-if="(hasPermission('training:image:edit') && isCustom) || (isPreset && isAdmin)" v-if="(hasPermission('training:image:edit') && isCustom) || (isPreset && isAdmin)"
:id="`doEdit_` + scope.$index" :id="`doEdit_` + scope.$index"
@@ -143,15 +105,13 @@
:visible="crud.status.cu > 0" :visible="crud.status.cu > 0"
:title="crud.status.title" :title="crud.status.title"
:loading="crud.status.cu === 2" :loading="crud.status.cu === 2"
:disabled="loading"
width="600px" width="600px"
@open="onDialogOpen" @open="onDialogOpen"
@close="onDialogClose"
@cancel="crud.cancelCU" @cancel="crud.cancelCU"
@ok="crud.submitCU" @ok="crud.submitCU"
> >
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item v-if="isEdit && isAdmin" label="镜像类别" prop="imageResource">
<el-form-item v-if="isFormAdd && isAdmin" label="镜像类别" prop="imageResource">
<el-radio-group v-model="form.imageResource" @change="imageResourceChange"> <el-radio-group v-model="form.imageResource" @change="imageResourceChange">
<el-radio :label="Number(IMAGE_RESOURCE_ENUM.CUSTOM)" border class="mr-0" <el-radio :label="Number(IMAGE_RESOURCE_ENUM.CUSTOM)" border class="mr-0"
>我的镜像</el-radio >我的镜像</el-radio
@@ -159,21 +119,20 @@
<el-radio :label="Number(IMAGE_RESOURCE_ENUM.PRESET)" border>预置镜像</el-radio> <el-radio :label="Number(IMAGE_RESOURCE_ENUM.PRESET)" border>预置镜像</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item v-if="isEdit" label="镜像名称" prop="imageName">
<el-form-item label="镜像名称" prop="imageName">
<el-autocomplete <el-autocomplete
ref="imageName" ref="imageName"
v-model="form.imageName" v-model="form.imageName"
class="inline-input"
class="inline-input w-400"
:fetch-suggestions="querySearchAsync" :fetch-suggestions="querySearchAsync"
placeholder="请选择或输入镜像名称" placeholder="请选择或输入镜像名称"
style="width: 400px;"
></el-autocomplete> ></el-autocomplete>
</el-form-item> </el-form-item>
<el-form-item label="镜像用途"> <el-form-item label="镜像用途">
<el-select <el-select
v-model="form.imageTypes" v-model="form.imageTypes"
placeholder="请选择或输入镜像用途" placeholder="请选择或输入镜像用途"
style="width: 400px;"
class="w-400"
multiple multiple
filterable filterable
allow-create allow-create
@@ -187,36 +146,18 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item v-if="isEdit" ref="imagePath" label="镜像文件路径" prop="imagePath">
<upload-inline
v-if="crud.status.cu > 0"
ref="upload"
action="fakeApi"
accept=".zip,.tar,.rar,.gz"
list-type="text"
:acceptSize="imageConfig.uploadFileAcceptSize"
:acceptSizeFormat="uploadSizeFomatter"
:params="uploadParams"
:show-file-count="false"
:auto-upload="true"
:filters="uploadFilters"
:limit="1"
:on-remove="onFileRemove"
@uploadStart="uploadStart"
@uploadSuccess="uploadSuccess"
@uploadError="uploadError"
/>
<upload-progress
v-if="loading"
:progress="progress"
:color="customColors"
:status="status"
:size="size"
@onSetProgress="onSetProgress"
/>
<el-form-item ref="imageUrl" label="镜像地址" prop="imageUrl">
<el-input v-model="form.imageUrl" placeholder="请输入镜像地址" class="w-400" />
<BaseTooltip icon="el-icon-warning" class="c-info">
<template #content>
<div>
镜像地址标准格式:镜像仓库域名/命名空间/镜像名:镜像版本号<br />示例:registry.cn-hangzhou.aliyuncs.com/enlin/notebook:v1
</div>
</template>
</BaseTooltip>
</el-form-item> </el-form-item>
<el-form-item v-if="isEdit" label="镜像版本号" prop="imageTag">
<el-input id="imageTag" v-model="form.imageTag" style="width: 400px;" />
<el-form-item label="镜像版本号" prop="imageTag">
<el-input id="imageTag" v-model="form.imageTag" class="w-400" />
</el-form-item> </el-form-item>
<el-form-item label="描述" prop="remark"> <el-form-item label="描述" prop="remark">
<el-input <el-input
@@ -227,19 +168,19 @@
maxlength="1024" maxlength="1024"
show-word-limit show-word-limit
placeholder placeholder
style="width: 400px;"
class="w-400"
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
</BaseModal> </BaseModal>
<!--Notebook默认镜像设置表单--> <!--Notebook默认镜像设置表单-->
<BaseModal <BaseModal
:visible.sync="formVisible"
:visible.sync="notebookFormVisible"
title="Notebook默认镜像设置" title="Notebook默认镜像设置"
:loading="formSubmitting"
:loading="notebookFormSubmitting"
width="800px" width="800px"
@cancel="formVisible = false"
@ok="onSubmitForm"
@cancel="notebookFormVisible = false"
@ok="onSubmitNotebookForm"
> >
<el-form <el-form
ref="noteBookFormRef" ref="noteBookFormRef"
@@ -253,7 +194,7 @@
id="defaultImage" id="defaultImage"
v-model="noteBookForm.defaultImage" v-model="noteBookForm.defaultImage"
placeholder="请选择镜像" placeholder="请选择镜像"
style="width: 400px;"
class="w-400"
filterable filterable
allow-create allow-create
default-first-option default-first-option
@@ -283,8 +224,6 @@


<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
// eslint-disable-next-line import/no-extraneous-dependencies
import { debounce } from 'throttle-debounce';


import cdOperation from '@crud/CD.operation'; import cdOperation from '@crud/CD.operation';
import rrOperation from '@crud/RR.operation'; import rrOperation from '@crud/RR.operation';
@@ -292,40 +231,36 @@ import pagination from '@crud/Pagination';
import CRUD, { presenter, header, form, crud } from '@crud/crud'; import CRUD, { presenter, header, form, crud } from '@crud/crud';
import trainingImageApi, { import trainingImageApi, {
del, del,
setPrecast,
setDefaultImage, setDefaultImage,
getDefaultImage, getDefaultImage,
getImageNameList, getImageNameList,
getImageTagList, getImageTagList,
} from '@/api/trainingImage/index'; } from '@/api/trainingImage/index';
import { import {
getUniqueId,
uploadSizeFomatter,
invalidFileNameChar,
ADMIN_ROLE_ID, ADMIN_ROLE_ID,
hasPermission, hasPermission,
validateImageName, validateImageName,
validateImageTag, validateImageTag,
IMAGE_TYPE_ENUM,
IMAGE_TYPE_MAP,
} from '@/utils'; } from '@/utils';
import BaseModal from '@/components/BaseModal'; import BaseModal from '@/components/BaseModal';
import UploadInline from '@/components/UploadForm/inline';
import BaseTooltip from '@/components/BaseTooltip';
import DropdownHeader from '@/components/DropdownHeader'; import DropdownHeader from '@/components/DropdownHeader';
import UploadProgress from '@/components/UploadProgress';
import { imageConfig } from '@/config'; import { imageConfig } from '@/config';


import { IMAGE_RESOURCE_ENUM, IMAGE_TYPE } from '../trainingJob/utils';
import { IMAGE_RESOURCE_ENUM } from '../trainingJob/utils';


const defaultForm = { const defaultForm = {
imagePath: null,
imageUrl: null,
imageTag: null, imageTag: null,
remark: null, remark: null,
imageTypes: Number(IMAGE_TYPE),
imageTypes: Number(IMAGE_TYPE_ENUM),
imageResource: Number(IMAGE_RESOURCE_ENUM.CUSTOM), imageResource: Number(IMAGE_RESOURCE_ENUM.CUSTOM),
imageName: null, imageName: null,
}; };


const defaultQuery = { const defaultQuery = {
imageStatus: null,
imageNameOrId: null, imageNameOrId: null,
imageTypes: null, imageTypes: null,
}; };
@@ -334,28 +269,27 @@ export default {
name: 'TrainingImage', name: 'TrainingImage',
components: { components: {
BaseModal, BaseModal,
BaseTooltip,
pagination, pagination,
cdOperation, cdOperation,
rrOperation, rrOperation,
UploadInline,
DropdownHeader, DropdownHeader,
UploadProgress,
}, },
cruds() { cruds() {
return CRUD({ return CRUD({
title: '镜像', title: '镜像',
crudMethod: { ...trainingImageApi }, crudMethod: { ...trainingImageApi },
optShow: { optShow: {
add: imageConfig.allowUploadImage && hasPermission('training:image:upload'),
add: imageConfig.allowUploadImage && hasPermission('training:image:save'),
del: false, del: false,
}, },
queryOnPresenterCreated: false, queryOnPresenterCreated: false,
props: { props: {
optText: { optText: {
add: '上传镜像',
add: '创建镜像',
}, },
optTitle: { optTitle: {
add: '上传',
add: '创建',
}, },
}, },
}); });
@@ -365,24 +299,6 @@ export default {
return { return {
active: IMAGE_RESOURCE_ENUM.CUSTOM, active: IMAGE_RESOURCE_ENUM.CUSTOM,
localQuery: { ...defaultQuery }, localQuery: { ...defaultQuery },
map: {
0: 'info',
1: 'success',
2: 'danger',
},
statusMap: {
0: '制作中',
1: '制作成功',
2: '制作失败',
},
imageTypesMap: {
0: 'Notebook镜像',
1: '训练镜像',
2: 'Serving镜像',
3: '终端镜像',
4: '点云镜像',
5: '数据标注镜像',
},
rules: { rules: {
imageTypes: [{ required: true, message: '请选择镜像类型', trigger: 'change' }], imageTypes: [{ required: true, message: '请选择镜像类型', trigger: 'change' }],
imageResource: [{ required: true, message: '请选择镜像来源', trigger: 'change' }], imageResource: [{ required: true, message: '请选择镜像来源', trigger: 'change' }],
@@ -390,7 +306,7 @@ export default {
{ required: true, message: '请选择项目名称', trigger: 'change' }, { required: true, message: '请选择项目名称', trigger: 'change' },
{ validator: validateImageName, trigger: ['blur', 'change'] }, { validator: validateImageName, trigger: ['blur', 'change'] },
], ],
imagePath: [{ required: true, message: '请输入镜像路径', trigger: ['blur', 'manual'] }],
imageUrl: [{ required: true, message: '请输入镜像地址', trigger: ['blur', 'manual'] }],
imageTag: [ imageTag: [
{ required: true, message: '请输入镜像版本号', trigger: 'blur' }, { required: true, message: '请输入镜像版本号', trigger: 'blur' },
{ validator: validateImageTag, trigger: ['blur', 'change'] }, { validator: validateImageTag, trigger: ['blur', 'change'] },
@@ -401,32 +317,17 @@ export default {
id: [{ required: true, message: '请选择默认镜像版本', trigger: 'blur' }], id: [{ required: true, message: '请选择默认镜像版本', trigger: 'blur' }],
}, },
harborProjectList: [], harborProjectList: [],
drawer: false,
uploadParams: {
objectPath: null, // 对象存储路径
},
progress: 0,
size: 0,
customColors: [
{ color: '#909399', percentage: 40 },
{ color: '#e6a23c', percentage: 80 },
{ color: '#67c23a', percentage: 100 },
],
disableEdit: false,
loading: false,
isEdit: false,
prefabricate: true, prefabricate: true,
// 以下为配置参数及常量参数 // 以下为配置参数及常量参数
imageConfig,
IMAGE_RESOURCE_ENUM, IMAGE_RESOURCE_ENUM,
IMAGE_TYPE,
uploadFilters: [invalidFileNameChar],
// 设置notebook默认镜像相关参数 // 设置notebook默认镜像相关参数
noteBookImages: [], noteBookImages: [],
noteBookTags: [], noteBookTags: [],
noteBookForm: { defaultImage: '', defaultTag: '', id: '' }, noteBookForm: { defaultImage: '', defaultTag: '', id: '' },
formVisible: false,
formSubmitting: false,

formType: 'add',
notebookFormVisible: false,
notebookFormSubmitting: false,
}; };
}, },
computed: { computed: {
@@ -441,14 +342,8 @@ export default {
isPreset() { isPreset() {
return this.active === IMAGE_RESOURCE_ENUM.PRESET; return this.active === IMAGE_RESOURCE_ENUM.PRESET;
}, },
isNotebook() {
return this.active === IMAGE_RESOURCE_ENUM.NOTEBOOK;
},
isTerminal() {
return this.active === IMAGE_RESOURCE_ENUM.TERMINAL;
},
disableAdd() { disableAdd() {
if (this.isAdmin) return this.isTerminal; // 管理员只有在终端镜像处无法点击上传
if (this.isAdmin) return false; // 管理员可以创建我的镜像和预置镜像
return !this.isCustom; // 其他角色只有在我的镜像处可以点击上传 return !this.isCustom; // 其他角色只有在我的镜像处可以点击上传
}, },
operationProps() { operationProps() {
@@ -456,37 +351,24 @@ export default {
disabled: this.disableAdd, disabled: this.disableAdd,
}; };
}, },
imageStatusList() {
const arr = [{ label: '全部', value: null }];
for (const key in this.statusMap) {
arr.push({ label: this.statusMap[key], value: key });
}
return arr;
},
imageTypesList() { imageTypesList() {
const arr = [{ label: '全部', value: null }]; const arr = [{ label: '全部', value: null }];
for (const key in this.imageTypesMap) {
arr.push({ label: this.imageTypesMap[key], value: +key });
for (const key in IMAGE_TYPE_MAP) {
arr.push({ label: IMAGE_TYPE_MAP[key], value: +key });
} }
return arr; return arr;
}, },
status() {
return this.progress === 100 ? 'success' : null;
isFormAdd() {
return this.formType === 'add';
}, },
}, },
mounted() { mounted() {
this.crud.refresh(); this.crud.refresh();
this.refetch = debounce(3000, this.crud.refresh);
this.updateImagePath();
}, },
methods: { methods: {
hasPermission, hasPermission,
getImageTypes(imageTypes) { getImageTypes(imageTypes) {
const usageStr = [];
imageTypes.forEach((item) => {
usageStr.push(this.imageTypesMap[item]);
});
return usageStr.join(',');
return imageTypes.map((type) => IMAGE_TYPE_MAP[type]).join(',');
}, },
getNoteBookTags() { getNoteBookTags() {
this.noteBookForm.defaultTag = null; this.noteBookForm.defaultTag = null;
@@ -497,7 +379,7 @@ export default {
} }
return getImageTagList({ return getImageTagList({
imageName: this.noteBookForm.defaultImage, imageName: this.noteBookForm.defaultImage,
imageTypes: IMAGE_TYPE.NOTEBOOK,
imageTypes: IMAGE_TYPE_ENUM.NOTEBOOK,
imageResource: Number(IMAGE_RESOURCE_ENUM.PRESET), imageResource: Number(IMAGE_RESOURCE_ENUM.PRESET),
}).then((res) => { }).then((res) => {
this.noteBookTags = res; this.noteBookTags = res;
@@ -513,46 +395,11 @@ export default {
this.prefabricate = true; this.prefabricate = true;
}); });
}, },
onFileRemove() {
this.form.imagePath = null;
this.loading = false;
this.$refs.imagePath.validate('manual');
},
uploadStart(files) {
this.updateImagePath();
[this.loading, this.size, this.progress] = [true, files.size, 0];
},
onSetProgress(val) {
this.progress += val;
},
uploadSuccess(res) {
this.progress = 100;
setTimeout(() => {
this.loading = false;
}, 1000);
if (this.loading) {
this.form.imagePath = res[0].data.objectName;
this.$refs.imagePath.validate('manual');
}
},
uploadError() {
this.$message({
message: '上传文件失败',
type: 'error',
});
this.loading = false;
},
// hook // hook
[CRUD.HOOK.afterRefresh]() {
this.checkStatus();
},
[CRUD.HOOK.beforeToAdd]() { [CRUD.HOOK.beforeToAdd]() {
this.isEdit = true;
this.formType = 'add'; this.formType = 'add';
if (this.isPreset) { if (this.isPreset) {
this.form.imageResource = Number(IMAGE_RESOURCE_ENUM.PRESET); this.form.imageResource = Number(IMAGE_RESOURCE_ENUM.PRESET);
} else if (this.isNotebook) {
this.form.imageTypes = IMAGE_TYPE.NOTEBOOK;
} }
}, },
[CRUD.HOOK.beforeRefresh]() { [CRUD.HOOK.beforeRefresh]() {
@@ -567,7 +414,7 @@ export default {
} }
}, },
[CRUD.HOOK.beforeToEdit]() { [CRUD.HOOK.beforeToEdit]() {
this.isEdit = false;
this.formType = 'edit';
}, },
async querySearchAsync(queryString, cb) { async querySearchAsync(queryString, cb) {
let { harborProjectList } = this; let { harborProjectList } = this;
@@ -597,24 +444,9 @@ export default {
this.form.imageResource = Number(IMAGE_RESOURCE_ENUM.CUSTOM); this.form.imageResource = Number(IMAGE_RESOURCE_ENUM.CUSTOM);
this.getImageNameList(); this.getImageNameList();
}, },
onDialogClose() {
if (this.isEdit) {
this.$refs.upload.formRef.reset();
}
this.loading = false;
},
async onDialogOpen() { async onDialogOpen() {
this.getImageNameList(); this.getImageNameList();
}, },
checkStatus() {
if (this.crud.data.some((item) => [0].includes(item.imageStatus))) {
this.refetch();
}
},
filterStatus(status) {
this.localQuery.imageStatus = status;
this.crud.toQuery();
},
filterImageTypes(imageTypes) { filterImageTypes(imageTypes) {
this.localQuery.imageTypes = imageTypes; this.localQuery.imageTypes = imageTypes;
this.crud.toQuery(); this.crud.toQuery();
@@ -622,9 +454,6 @@ export default {
resetQuery() { resetQuery() {
this.localQuery = { ...defaultQuery }; this.localQuery = { ...defaultQuery };
}, },
updateImagePath() {
this.uploadParams.objectPath = `upload-temp/${this.user.id}/${getUniqueId()}`;
},
async doEdit(imageObj) { async doEdit(imageObj) {
const dataObj = { const dataObj = {
ids: [imageObj.id], ids: [imageObj.id],
@@ -642,21 +471,6 @@ export default {
this.crud.refresh(); this.crud.refresh();
}); });
}, },
doPrecast(i) {
setPrecast({ id: i }).then(() => {
this.$message({
message: '设置成功',
type: 'success',
});
this.crud.refresh();
});
},
resourceObj(resource) {
return resource
? { icon: 'el-icon-circle-check', color: '#67C23A', butText: '当前为默认' }
: { icon: 'el-icon-circle-close', color: '#F56C6C', butText: '设为默认' };
},
uploadSizeFomatter,


async doSetDefaultImage() { async doSetDefaultImage() {
// 获取默认镜像 // 获取默认镜像
@@ -666,20 +480,20 @@ export default {
this.noteBookForm.id = defaultImage.length ? defaultImage[0].id : ''; this.noteBookForm.id = defaultImage.length ? defaultImage[0].id : '';
// 获取镜像列表 // 获取镜像列表
this.noteBookImages = await getImageNameList({ this.noteBookImages = await getImageNameList({
imageTypes: IMAGE_TYPE.NOTEBOOK,
imageTypes: IMAGE_TYPE_ENUM.NOTEBOOK,
imageResource: Number(IMAGE_RESOURCE_ENUM.PRESET), imageResource: Number(IMAGE_RESOURCE_ENUM.PRESET),
}); });
if (this.noteBookForm.defaultImage) { if (this.noteBookForm.defaultImage) {
this.noteBookTags = await getImageTagList({ this.noteBookTags = await getImageTagList({
imageName: this.noteBookForm.defaultImage, imageName: this.noteBookForm.defaultImage,
imageTypes: IMAGE_TYPE.NOTEBOOK,
imageTypes: IMAGE_TYPE_ENUM.NOTEBOOK,
imageResource: Number(IMAGE_RESOURCE_ENUM.PRESET), imageResource: Number(IMAGE_RESOURCE_ENUM.PRESET),
}); });
} else { } else {
this.noteBookTags = []; this.noteBookTags = [];
} }


this.formVisible = true;
this.notebookFormVisible = true;
this.$nextTick(() => { this.$nextTick(() => {
this.clearValidate(); this.clearValidate();
}); });
@@ -690,17 +504,17 @@ export default {
validateField(field) { validateField(field) {
this.$refs.noteBookFormRef.validateField(field); this.$refs.noteBookFormRef.validateField(field);
}, },
onSubmitForm() {
onSubmitNotebookForm() {
this.$refs.noteBookFormRef.validate((valid) => { this.$refs.noteBookFormRef.validate((valid) => {
if (valid) { if (valid) {
this.formSubmitting = true;
this.notebookFormSubmitting = true;
setDefaultImage({ id: this.noteBookForm.id }) setDefaultImage({ id: this.noteBookForm.id })
.then(() => { .then(() => {
this.formVisible = false;
this.notebookFormVisible = false;
this.crud.toQuery(); this.crud.toQuery();
}) })
.finally(() => { .finally(() => {
this.formSubmitting = false;
this.notebookFormSubmitting = false;
}); });
} }
}); });


+ 0
- 9
webapp/src/views/trainingJob/utils.js View File

@@ -96,15 +96,6 @@ export const ATLAS_ALGORITHM_TYPE_ENUM = {
DDRL: 4, // ddrl DDRL: 4, // ddrl
}; };


export const IMAGE_TYPE = {
NOTEBOOK: 0, // notebook镜像类型
TRAIN: 1, // 训练镜像和预置镜像类型
SERVING: 2, // serving镜像
TERMINAL: 3, // 终端镜像
POINTCLOUD: 4, // 点云镜像
DATASETMARKED: 5, // 数据标注镜像
};

// 训练可视化列表页查询项 // 训练可视化列表页查询项
export const trainVisualQueryFormItems = [ export const trainVisualQueryFormItems = [
{ {


Loading…
Cancel
Save