@@ -50,6 +50,7 @@ type SearchResourceSceneOptions struct { | |||
QueueId int64 | |||
ComputeResource string | |||
AccCardType string | |||
Cluster string | |||
} | |||
type ResourceSceneListRes struct { | |||
@@ -70,7 +71,7 @@ type ResourceSceneRes struct { | |||
JobType JobType | |||
IsExclusive bool | |||
ExclusiveOrg string | |||
Specs []ResourceSpecWithSceneId | |||
Specs []ResourceSpecInfo | |||
} | |||
func (ResourceSceneRes) TableName() string { | |||
@@ -86,7 +87,7 @@ func (ResourceSceneBriefRes) TableName() string { | |||
return "resource_scene" | |||
} | |||
type ResourceSpecWithSceneId struct { | |||
type ResourceSpecInfo struct { | |||
ID int64 | |||
SourceSpecId string | |||
AccCardsNum int | |||
@@ -108,7 +109,7 @@ type ResourceSpecWithSceneId struct { | |||
AccCardType string | |||
} | |||
func (ResourceSpecWithSceneId) TableName() string { | |||
func (ResourceSpecInfo) TableName() string { | |||
return "resource_specification" | |||
} | |||
@@ -264,6 +265,9 @@ func SearchResourceScene(opts SearchResourceSceneOptions) (int64, []ResourceScen | |||
if opts.AccCardType != "" { | |||
cond = cond.And(builder.Eq{"resource_queue.acc_card_type": opts.AccCardType}) | |||
} | |||
if opts.Cluster != "" { | |||
cond = cond.And(builder.Eq{"resource_queue.cluster": opts.Cluster}) | |||
} | |||
cond = cond.And(builder.NewCond().Or(builder.Eq{"resource_scene.delete_time": 0}).Or(builder.IsNull{"resource_scene.delete_time"})) | |||
cols := []string{"resource_scene.id", "resource_scene.scene_name", "resource_scene.job_type", "resource_scene.is_exclusive", | |||
"resource_scene.exclusive_org"} | |||
@@ -297,7 +301,7 @@ func SearchResourceScene(opts SearchResourceSceneOptions) (int64, []ResourceScen | |||
sceneIds = append(sceneIds, v.ID) | |||
} | |||
specs := make([]ResourceSpecWithSceneId, 0) | |||
specs := make([]ResourceSpecInfo, 0) | |||
if err := x.Cols("resource_specification.id", "resource_specification.source_spec_id", | |||
"resource_specification.acc_cards_num", "resource_specification.cpu_cores", | |||
@@ -316,10 +320,10 @@ func SearchResourceScene(opts SearchResourceSceneOptions) (int64, []ResourceScen | |||
return 0, nil, err | |||
} | |||
specsMap := make(map[int64][]ResourceSpecWithSceneId, 0) | |||
specsMap := make(map[int64][]ResourceSpecInfo, 0) | |||
for _, v := range specs { | |||
if _, ok := specsMap[v.SceneId]; !ok { | |||
specsMap[v.SceneId] = []ResourceSpecWithSceneId{v} | |||
specsMap[v.SceneId] = []ResourceSpecInfo{v} | |||
} else { | |||
specsMap[v.SceneId] = append(specsMap[v.SceneId], v) | |||
} | |||
@@ -328,7 +332,7 @@ func SearchResourceScene(opts SearchResourceSceneOptions) (int64, []ResourceScen | |||
for i, v := range r { | |||
s := specsMap[v.ID] | |||
if s == nil { | |||
s = make([]ResourceSpecWithSceneId, 0) | |||
s = make([]ResourceSpecInfo, 0) | |||
} | |||
r[i].Specs = s | |||
} | |||
@@ -159,6 +159,28 @@ func (r ResourceSpecAndQueue) ConvertToRes() *ResourceSpecAndQueueRes { | |||
} | |||
} | |||
func (r ResourceSpecAndQueue) ConvertToResourceSpecInfo() *ResourceSpecInfo { | |||
return &ResourceSpecInfo{ | |||
ID: r.ResourceSpecification.ID, | |||
SourceSpecId: r.SourceSpecId, | |||
AccCardsNum: r.AccCardsNum, | |||
CpuCores: r.CpuCores, | |||
MemGiB: r.MemGiB, | |||
GPUMemGiB: r.GPUMemGiB, | |||
ShareMemGiB: r.ShareMemGiB, | |||
UnitPrice: r.UnitPrice, | |||
Status: r.ResourceSpecification.Status, | |||
UpdatedTime: r.ResourceSpecification.UpdatedTime, | |||
Cluster: r.Cluster, | |||
AiCenterCode: r.AiCenterCode, | |||
AiCenterName: r.AiCenterName, | |||
QueueCode: r.QueueCode, | |||
QueueId: r.QueueId, | |||
ComputeResource: r.ComputeResource, | |||
AccCardType: r.AccCardType, | |||
} | |||
} | |||
type FindSpecsOptions struct { | |||
JobType JobType | |||
ComputeResource string | |||
@@ -209,7 +231,7 @@ func (Specification) TableName() string { | |||
return "resource_specification" | |||
} | |||
func (s *Specification) loadRelatedSpecs() { | |||
func (s *Specification) loadRelatedSpecs(jobType JobType) { | |||
if s.RelatedSpecs != nil { | |||
return | |||
} | |||
@@ -222,8 +244,9 @@ func (s *Specification) loadRelatedSpecs() { | |||
ComputeResource: s.ComputeResource, | |||
Cluster: s.Cluster, | |||
SourceSpecId: s.SourceSpecId, | |||
RequestAll: true, | |||
RequestAll: false, | |||
SpecStatus: SpecOnShelf, | |||
JobType: jobType, | |||
}) | |||
if err != nil { | |||
s.RelatedSpecs = defaultSpecs | |||
@@ -231,19 +254,15 @@ func (s *Specification) loadRelatedSpecs() { | |||
} | |||
s.RelatedSpecs = r | |||
} | |||
func (s *Specification) GetAvailableCenterIds(userIds ...int64) []string { | |||
s.loadRelatedSpecs() | |||
func (s *Specification) GetAvailableCenterIds(userId int64, jobType JobType) []string { | |||
s.loadRelatedSpecs(jobType) | |||
if len(s.RelatedSpecs) == 0 { | |||
return make([]string, 0) | |||
} | |||
var uId int64 | |||
if len(userIds) > 0 { | |||
uId = userIds[0] | |||
} | |||
//filter exclusive specs | |||
specs := FilterExclusiveSpecs(s.RelatedSpecs, uId) | |||
specs := FilterExclusiveSpecs(s.RelatedSpecs, userId) | |||
centerIds := make([]string, len(specs)) | |||
for i, v := range specs { | |||
@@ -275,7 +275,7 @@ func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (job | |||
AutoStopDuration: autoStopDurationMs, | |||
Capacity: setting.Capacity, | |||
Command: req.Command, | |||
CenterID: req.Spec.GetAvailableCenterIds(ctx.User.ID), | |||
CenterID: req.Spec.GetAvailableCenterIds(ctx.User.ID, models.JobTypeDebug), | |||
}, | |||
}, | |||
}) | |||
@@ -433,7 +433,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (jobId str | |||
ResourceSpecId: req.Spec.SourceSpecId, | |||
ImageId: req.ImageId, | |||
ImageUrl: req.ImageUrl, | |||
CenterID: req.Spec.GetAvailableCenterIds(ctx.User.ID), | |||
CenterID: req.Spec.GetAvailableCenterIds(ctx.User.ID, models.JobTypeTrain), | |||
ReplicaNum: 1, | |||
Datasets: datasetGrampus, | |||
Models: modelGrampus, | |||
@@ -144,24 +144,24 @@ func GetResourceSpecificationList(ctx *context.Context) { | |||
} | |||
func GetAllResourceSpecificationList(ctx *context.Context) { | |||
queue := ctx.QueryInt64("queue") | |||
status := ctx.QueryInt("status") | |||
cluster := ctx.Query("cluster") | |||
available := ctx.QueryInt("available") | |||
list, err := resource.GetAllDistinctResourceSpecification(models.SearchResourceSpecificationOptions{ | |||
QueueId: queue, | |||
computeResource := ctx.Query("resource") | |||
list, err := resource.GetAllResourceSpecification(models.SearchResourceSpecificationOptions{ | |||
Status: status, | |||
Cluster: cluster, | |||
AvailableCode: available, | |||
AccCardsNum: -1, | |||
ComputeResource: computeResource, | |||
}) | |||
if err != nil { | |||
log.Error("GetResourceSpecificationList error.%v", err) | |||
ctx.JSON(http.StatusOK, response.ServerError(err.Error())) | |||
return | |||
} | |||
ctx.JSON(http.StatusOK, response.SuccessWithData(list)) | |||
r := map[string]interface{}{"Specs": list} | |||
ctx.JSON(http.StatusOK, response.SuccessWithData(r)) | |||
} | |||
func GetResourceSpecificationScenes(ctx *context.Context) { | |||
@@ -234,6 +234,7 @@ func GetResourceSceneList(ctx *context.Context) { | |||
isExclusive := ctx.QueryInt("IsExclusive") | |||
computeResource := ctx.Query("resource") | |||
cardType := ctx.Query("cardType") | |||
cluster := ctx.Query("cluster") | |||
list, err := resource.GetResourceSceneList(models.SearchResourceSceneOptions{ | |||
ListOptions: models.ListOptions{Page: page, PageSize: 10}, | |||
JobType: jobType, | |||
@@ -242,6 +243,7 @@ func GetResourceSceneList(ctx *context.Context) { | |||
QueueId: queueId, | |||
ComputeResource: computeResource, | |||
AccCardType: cardType, | |||
Cluster: cluster, | |||
}) | |||
if err != nil { | |||
log.Error("GetResourceSceneList error.%v", err) | |||
@@ -75,7 +75,7 @@ func (g CloudbrainOneNotebookTaskTemplate) CallCreationAPI(ctx *context.Creation | |||
PreTrainModel: ctx.GetContainerDataArray(ai_task_entity.ContainerPreTrainModel), | |||
AutoStopDuration: autoStopDurationMs, | |||
Capacity: setting.Capacity, | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID), | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID, form.JobType), | |||
Spec: ctx.Spec, | |||
}, | |||
}, | |||
@@ -118,7 +118,7 @@ func (g CloudbrainOneNotebookTaskTemplate) CallRestartAPI(ctx *context.CreationC | |||
PreTrainModel: ctx.GetContainerDataArray(ai_task_entity.ContainerPreTrainModel), | |||
AutoStopDuration: autoStopDurationMs, | |||
Capacity: setting.Capacity, | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID), | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID, form.JobType), | |||
Spec: ctx.Spec, | |||
}, | |||
}, | |||
@@ -101,7 +101,7 @@ func (g GrampusNoteBookTaskTemplate) CallCreationAPI(ctx *context.CreationContex | |||
Code: ctx.GetContainerDataArray(ai_task_entity.ContainerCode), | |||
AutoStopDuration: autoStopDurationMs, | |||
Capacity: setting.Capacity, | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID), | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID, form.JobType), | |||
Spec: ctx.Spec, | |||
}, | |||
}, | |||
@@ -63,7 +63,7 @@ func (g GrampusTrainTaskTemplate) CallCreationAPI(ctx *context.CreationContext) | |||
ImageUrl: strings.TrimSpace(form.ImageUrl), | |||
Datasets: ctx.GetContainerDataArray(ai_task_entity.ContainerDataset), | |||
Code: ctx.GetContainerData(ai_task_entity.ContainerCode), | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID), | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID, form.JobType), | |||
Models: ctx.GetContainerDataArray(ai_task_entity.ContainerPreTrainModel), | |||
BootFile: form.BootFile, | |||
OutPut: ctx.GetContainerData(ai_task_entity.ContainerOutPutPath), | |||
@@ -106,7 +106,7 @@ func (g GrampusTrainTaskTemplate) CallRestartAPI(ctx *context.CreationContext) * | |||
ImageUrl: strings.TrimSpace(form.ImageUrl), | |||
Datasets: ctx.GetContainerDataArray(ai_task_entity.ContainerDataset), | |||
Code: ctx.GetContainerData(ai_task_entity.ContainerCode), | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID), | |||
CenterID: ctx.Spec.GetAvailableCenterIds(ctx.User.ID, form.JobType), | |||
Models: ctx.GetContainerDataArray(ai_task_entity.ContainerPreTrainModel), | |||
BootFile: form.BootFile, | |||
OutPut: ctx.GetContainerData(ai_task_entity.ContainerOutPutPath), | |||
@@ -147,6 +147,21 @@ func GetAllDistinctResourceSpecification(opts models.SearchResourceSpecification | |||
return models.NewResourceSpecAndQueueListRes(0, nr), nil | |||
} | |||
func GetAllResourceSpecification(opts models.SearchResourceSpecificationOptions) ([]*models.ResourceSpecInfo, error) { | |||
opts.Page = 0 | |||
opts.PageSize = 1000 | |||
opts.OrderBy = models.SearchSpecOrder4Standard | |||
_, r, err := models.SearchResourceSpecification(opts) | |||
if err != nil { | |||
return nil, err | |||
} | |||
res := make([]*models.ResourceSpecInfo, len(r)) | |||
for i := 0; i < len(r); i++ { | |||
res[i] = r[i].ConvertToResourceSpecInfo() | |||
} | |||
return res, nil | |||
} | |||
func distinctResourceSpecAndQueue(r []models.ResourceSpecAndQueue) []models.ResourceSpecAndQueue { | |||
specs := make([]models.ResourceSpecAndQueue, 0, len(r)) | |||
sourceSpecIdMap := make(map[string]models.ResourceSpecAndQueue, 0) | |||
@@ -117,6 +117,7 @@ export const getResSpecificationList = (params) => { | |||
// cluster 所属集群 :OpenI 启智集群,C2Net 智算集群 | |||
// queue 所属队列id | |||
// status 状态 : 1 待审核 2已上架 3已下架 | |||
// available 是否可用 -1全部 1可用 2不可用 | |||
export const getResSpecificationListAll = (params) => { | |||
return service({ | |||
url: '/admin/resources/specification/list/all', | |||
@@ -19,6 +19,8 @@ const en = { | |||
star: 'Star', | |||
unStar: 'UnStar', | |||
submit: 'Submit', | |||
selectAll: 'Select All', | |||
selectNone: 'Select None', | |||
accomplishTask: 'Accomplish Task', | |||
adminOperate: 'Administrator Operation', | |||
@@ -173,6 +175,9 @@ const en = { | |||
resourceSpecificationIsAvailableAll: 'Specification Is Available(All)', | |||
available: 'Available', | |||
notAvailable: 'Not Available', | |||
selectSpec: 'Select resource specification', | |||
accordingSpec: 'According to resource specification', | |||
accordingQueue: 'According to resources queue', | |||
}, | |||
user: { | |||
inviteFriends: 'Invite Friends', | |||
@@ -18,6 +18,8 @@ const zh = { | |||
star: '收藏', | |||
unStar: '取消收藏', | |||
submit: '提交', | |||
selectAll: '全选', | |||
selectNone: '全不选', | |||
accomplishTask: "积分任务", | |||
adminOperate: "管理员操作", | |||
@@ -172,6 +174,9 @@ const zh = { | |||
resourceSpecificationIsAvailableAll: "资源规格是否可用(全部)", | |||
available: "可用", | |||
notAvailable: "不可用", | |||
selectSpec: '选择资源规格', | |||
accordingSpec: '按资源规格', | |||
accordingQueue: '按资源池队列', | |||
}, | |||
user: { | |||
inviteFriends: "邀请好友", | |||
@@ -1,6 +1,6 @@ | |||
<template> | |||
<div class="base-dlg"> | |||
<BaseDialog :visible.sync="dialogShow" :width="`750px`" | |||
<BaseDialog :visible.sync="dialogShow" :width="`900px`" | |||
:title="type === 'add' ? $t('resourcesManagement.addResScene') : $t('resourcesManagement.editResScene')" | |||
@open="open" @opened="opened" @close="close" @closed="closed"> | |||
<div class="dlg-content"> | |||
@@ -53,30 +53,19 @@ | |||
</el-select> | |||
</div> | |||
</div> | |||
<div class="form-row"> | |||
<div class="title"> | |||
<span>{{ $t('resourcesManagement.resQueue') }}</span> | |||
</div> | |||
<div class="content"> | |||
<el-select v-model="dataInfo.QueueId" @change="changeQueue" :disabled="type === 'edit'"> | |||
<el-option v-for="item in queueList" :key="item.k" :label="item.v" :value="item.k" /> | |||
</el-select> | |||
</div> | |||
</div> | |||
<div class="form-row"> | |||
<div class="title required"> | |||
<span>{{ $t('resourcesManagement.resourceSpecification') }}</span> | |||
<span>{{ $t('resourcesManagement.computeResource') }}</span> | |||
</div> | |||
<div class="content"> | |||
<el-select v-model="dataInfo.SpecIds" multiple collapse-tags class="specSel"> | |||
<el-option v-for="item in specsList" :label="item.v" :key="item.k" :value="item.k"> | |||
<span v-html="item.v"></span> | |||
</el-option> | |||
<el-select v-model="dataInfo.Resource" @change="changeResource" :disabled="type === 'edit'"> | |||
<el-option v-for="item in resourceList" :key="item.k" :label="item.v" :value="item.k" /> | |||
</el-select> | |||
</div> | |||
</div> | |||
<SpecSelect v-model="dataInfo.SpecIds" :specs="specsList"></SpecSelect> | |||
<div class="form-row" style="margin-top:20px"> | |||
<div class="title"></div> | |||
<div class="title" style="width:285px;"></div> | |||
<div class="content"> | |||
<el-button type="primary" class="btn confirm-btn" @click="confirm">{{ $t('confirm') }}</el-button> | |||
<el-button class="btn" @click="cancel">{{ $t('cancel') }}</el-button> | |||
@@ -89,8 +78,9 @@ | |||
</template> | |||
<script> | |||
import BaseDialog from '~/components/BaseDialog.vue'; | |||
import SpecSelect from './SpecSelect.vue'; | |||
import { getResQueueCode, getResSpecificationListAll, addResScene, updateResScene } from '~/apis/modules/resources'; | |||
import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE, SPECIFICATION_STATUS } from '~/const'; | |||
import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE, SPECIFICATION_STATUS, COMPUTER_RESOURCES } from '~/const'; | |||
import { getListValueWithKey } from '~/utils'; | |||
export default { | |||
@@ -101,9 +91,7 @@ export default { | |||
type: { type: String, defalut: 'add' }, | |||
data: { type: Object, default: () => ({}) }, | |||
}, | |||
components: { | |||
BaseDialog | |||
}, | |||
components: { BaseDialog, SpecSelect }, | |||
data() { | |||
return { | |||
dialogShow: false, | |||
@@ -113,7 +101,7 @@ export default { | |||
accCardTypeList: [...ACC_CARD_TYPE], | |||
statusList: [...SPECIFICATION_STATUS], | |||
isExclusiveList: [{ k: '2', v: this.$t('resourcesManagement.commonUse') }, { k: '1', v: this.$t('resourcesManagement.exclusive') }], | |||
queueList: [], | |||
resourceList: [...COMPUTER_RESOURCES], | |||
specsList: [], | |||
}; | |||
}, | |||
@@ -129,61 +117,33 @@ export default { | |||
JobType: '', | |||
IsExclusive: '2', | |||
ExclusiveOrg: '', | |||
Cluster: '', | |||
QueueId: '', | |||
Cluster: 'OpenI', | |||
Resource: 'GPU', | |||
SpecIds: [], | |||
} | |||
this.queueList.splice(0, Infinity); | |||
this.specsList.splice(0, Infinity); | |||
}, | |||
getQueueList(next) { | |||
return getResQueueCode({ cluster: this.dataInfo.Cluster }).then(res => { | |||
res = res.data; | |||
if (res.Code === 0) { | |||
const data = res.Data; | |||
const list = []; | |||
for (let i = 0, iLen = data.length; i < iLen; i++) { | |||
const item = data[i]; | |||
list.push({ | |||
k: item.ID, | |||
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${item.AiCenterName})`, | |||
}); | |||
} | |||
list.unshift({ | |||
k: '-1', | |||
v: this.$t('resourcesManagement.allResQueue'), | |||
}); | |||
this.queueList.splice(0, Infinity, ...list); | |||
if (next) { | |||
if (this.type === 'add') { | |||
this.dataInfo.QueueId = '-1'; | |||
} | |||
this.getResSpecificationList(); | |||
} | |||
} | |||
}).catch(err => { | |||
console.log(err); | |||
}); | |||
}, | |||
getResSpecificationList() { | |||
const params = { | |||
cluster: this.dataInfo.Cluster, | |||
resource: this.dataInfo.Resource, | |||
queue: this.dataInfo.QueueId === '-1' ? '' : this.dataInfo.QueueId, | |||
available: 1, | |||
// status: 2, | |||
// page: 1, | |||
}; | |||
return getResSpecificationListAll(params).then(res => { | |||
res = res.data; | |||
if (res.Code === 0) { | |||
const list = res.Data.List; | |||
const list = res.Data.Specs; | |||
const data = list.map((item) => { | |||
const Queue = item.Queue; | |||
const Spec = item.Spec; | |||
const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`; | |||
const statusStr = Spec.Status != '2' ? `<span style="color:rgb(245, 34, 45)">(${getListValueWithKey(this.statusList, Spec.Status.toString())})</span>` : ''; | |||
const NGPU = `${item.ComputeResource}:${item.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, item.AccCardType)}`; | |||
const statusStr = item.Status != '2' ? `<span style="color:rgb(245, 34, 45)">(${getListValueWithKey(this.statusList, item.Status.toString())})</span>` : ''; | |||
return { | |||
k: Spec.ID, | |||
v: `${NGPU}, CPU:${Spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${Spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${Spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${Spec.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${Spec.UnitPrice}${this.$t('resourcesManagement.point_hr')}${statusStr}`, | |||
...item, | |||
StatusStr: statusStr, | |||
QueueStr: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${item.AiCenterName})`, | |||
SpecStr: `${NGPU}, CPU:${item.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${item.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${item.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${item.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${item.UnitPrice}${this.$t('resourcesManagement.point_hr')}`, | |||
} | |||
}); | |||
this.specsList.splice(0, Infinity, ...data); | |||
@@ -196,13 +156,11 @@ export default { | |||
this.dataInfo.ExclusiveOrg = ''; | |||
}, | |||
changeCluster() { | |||
this.dataInfo.QueueId = ''; | |||
this.dataInfo.SpecIds = []; | |||
this.queueList.splice(0, Infinity); | |||
this.specsList.splice(0, Infinity); | |||
this.getQueueList(true); | |||
this.getResSpecificationList(); | |||
}, | |||
changeQueue() { | |||
changeResource() { | |||
this.dataInfo.SpecIds = []; | |||
this.specsList.splice(0, Infinity); | |||
this.getResSpecificationList(); | |||
@@ -212,12 +170,19 @@ export default { | |||
if (this.type === 'add') { | |||
// | |||
} else if (this.type === 'edit') { | |||
Object.assign(this.dataInfo, { ...this.data, QueueId: this.data.QueueIds.length === 1 ? this.data.QueueIds[0] : '-1' }); | |||
this.queueList.splice(0, Infinity); | |||
this.specsList.splice(0, Infinity); | |||
this.getQueueList(true); | |||
Object.assign(this.dataInfo, { | |||
ID: this.data.ID, | |||
SceneName: this.data.SceneName, | |||
JobType: this.data.JobType, | |||
IsExclusive: this.data.IsExclusive, | |||
ExclusiveOrg: this.data.ExclusiveOrg, | |||
Cluster: this.data.Cluster, | |||
Resource: this.data.ComputeResource, | |||
SpecIds: [...this.data.SpecIds], | |||
}); | |||
} | |||
this.$emit("open"); | |||
this.getResSpecificationList(); | |||
}, | |||
opened() { | |||
this.$emit("opened"); | |||
@@ -237,6 +202,8 @@ export default { | |||
}); | |||
return; | |||
} | |||
// console.log('submit', this.dataInfo); | |||
// return; | |||
const setApi = this.type === 'add' ? addResScene : updateResScene; | |||
setApi({ | |||
...this.dataInfo, | |||
@@ -263,7 +230,6 @@ export default { | |||
message: this.$t('submittedFailed') | |||
}); | |||
}) | |||
}, | |||
cancel() { | |||
this.dialogShow = false; | |||
@@ -282,7 +248,7 @@ export default { | |||
justify-content: center; | |||
.form { | |||
width: 600px; | |||
width: 800px; | |||
.form-row { | |||
display: flex; | |||
@@ -290,7 +256,7 @@ export default { | |||
margin-bottom: 4px; | |||
.title { | |||
width: 160px; | |||
width: 255px; | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
@@ -0,0 +1,548 @@ | |||
<template> | |||
<div> | |||
<div class="form-row"> | |||
<div class="title required"> | |||
<span>{{ $t('resourcesManagement.resourceSpecification') }}</span> | |||
</div> | |||
<div class="content"></div> | |||
<div class="select-btn"> | |||
<a @click="dlgShow = true" href="javascript:;">{{ $t('resourcesManagement.selectSpec') }}</a> | |||
</div> | |||
<div class="base-dlg"> | |||
<BaseDialog :visible.sync="dlgShow" :width="`1200px`" :title="$t('resourcesManagement.selectSpec')" @open="open" | |||
@opened="opened" @close="close" :appendToBody="true" @closed="closed"> | |||
<div class="dlg-content"> | |||
<div class="left-area"> | |||
<div class="tabs"> | |||
<div class="tab" :class="tabIndex == '1' ? 'focused' : ''" @click="changeTab(1)">{{ | |||
$t('resourcesManagement.accordingSpec') }}</div> | |||
<div class="tab" :class="tabIndex == '2' ? 'focused' : ''" @click="changeTab(2)">{{ | |||
$t('resourcesManagement.accordingQueue') }}</div> | |||
</div> | |||
<div class="table-c"> | |||
<div v-if="tabIndex == '1'"> | |||
<div> | |||
<div class="header row"> | |||
<div class="row-l" style="width:760px;">{{ $t('resourcesManagement.resourceSpecification') }}</div> | |||
<div class="row-r" style="flex:1">{{ $t('resourcesManagement.resQueue') }}</div> | |||
</div> | |||
<div class="table-content"> | |||
<div class="row" v-for="item in tableData1"> | |||
<div class="row-l" style="width:760px;">{{ item.SpecStr }}</div> | |||
<div class="row-r" style="flex:1"> | |||
<div class="btn-c"> | |||
<button @click="selectAll(item.queues)">{{ $t('selectAll') }}</button> | |||
<button @click="clearSelectAll(item.queues)">{{ $t('selectNone') }}</button> | |||
</div> | |||
<div class="" v-for="_item in item.queues"> | |||
<el-checkbox :value="_item.checked" @change="selectChange(_item.ID)"> | |||
<span v-html="_item.QueueStr + _item.StatusStr"></span> | |||
</el-checkbox> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div v-if="tabIndex == '2'"> | |||
<div class="header row"> | |||
<div class="row-l" style="width:380px;">{{ $t('resourcesManagement.resQueue') }}</div> | |||
<div class="row-r" style="flex:2">{{ $t('resourcesManagement.resourceSpecification') }}</div> | |||
</div> | |||
<div class="table-content"> | |||
<div class="row" v-for="item in tableData2"> | |||
<div class="row-l" style="width:380px;">{{ item.QueueStr }}</div> | |||
<div class="row-r" style="flex:2"> | |||
<div class="btn-c"> | |||
<button @click="selectAll(item.specs)">{{ $t('selectAll') }}</button> | |||
<button @click="clearSelectAll(item.specs)">{{ $t('selectNone') }}</button> | |||
</div> | |||
<div class="" v-for="_item in item.specs"> | |||
<el-checkbox :value="_item.checked" @change="selectChange(_item.ID)"> | |||
<span v-html="_item.SpecStr + _item.StatusStr"></span> | |||
</el-checkbox> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="confirm-btn-c"> | |||
<el-button type="primary" class="btn confirm-btn" @click="confirm">{{ $t('confirm') }}</el-button> | |||
</div> | |||
</div> | |||
</div> | |||
</BaseDialog> | |||
</div> | |||
</div> | |||
<div class="row-detail"> | |||
<div class="table-c"> | |||
<div> | |||
<div class="header row"> | |||
<div class="row-l" style="width:500px;">{{ $t('resourcesManagement.resourceSpecification') }}</div> | |||
<div class="row-r" style="flex:1">{{ $t('resourcesManagement.resQueue') }}</div> | |||
</div> | |||
<div class="table-content"> | |||
<div class="row" v-for="item in tableDataShow"> | |||
<div class="row-l" style="width:500px;">{{ item.SpecStr }}</div> | |||
<div class="row-r" style="flex:1"> | |||
<div class="" v-for="_item in item.queues"> | |||
<span v-html="_item.QueueStr + _item.StatusStr"></span> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import BaseDialog from '~/components/BaseDialog.vue'; | |||
import { SPECIFICATION_STATUS } from '~/const'; | |||
export default { | |||
name: "SpecSelect", | |||
props: { | |||
visible: { type: Boolean, default: false }, | |||
value: { type: Array, required: true }, | |||
specs: { type: Array, required: true }, | |||
}, | |||
components: { BaseDialog }, | |||
data() { | |||
return { | |||
dlgShow: false, | |||
tabIndex: '1', | |||
selectList: [], | |||
statusList: [...SPECIFICATION_STATUS], | |||
}; | |||
}, | |||
watch: { | |||
visible: function (val) { | |||
this.dlgShow = val; | |||
}, | |||
value: { | |||
immediate: true, | |||
deep: true, | |||
handler(newVal) { | |||
newVal = newVal === undefined ? [] : newVal; | |||
this.selectList = [...newVal]; | |||
} | |||
} | |||
}, | |||
computed: { | |||
tableData1: function () { | |||
const map = {}; | |||
for (let i = 0, iLen = this.specs.length; i < iLen; i++) { | |||
const spec = this.specs[i]; | |||
const key = `${spec.Cluster}|${spec.ComputeResource}|${spec.SourceSpecId || Math.random()}`; | |||
const queue = { | |||
...spec, | |||
QueueId: spec.QueueId, | |||
QueueCode: spec.QueueCode, | |||
AiCenterCode: spec.AiCenterCode, | |||
AiCenterName: spec.AiCenterName, | |||
QueueStr: spec.QueueStr, | |||
checked: this.selectList.indexOf(spec.ID) > -1, | |||
}; | |||
if (map[key]) { | |||
map[key].queues.push(queue); | |||
} else { | |||
map[key] = { | |||
...spec, | |||
queues: [queue], | |||
} | |||
} | |||
} | |||
const data = []; | |||
for (let key in map) { | |||
data.push(map[key]); | |||
} | |||
return data; | |||
}, | |||
tableData2: function () { | |||
const map = {}; | |||
for (let i = 0, iLen = this.specs.length; i < iLen; i++) { | |||
const spec = this.specs[i]; | |||
const key = `${spec.Cluster}|${spec.ComputeResource}|${spec.QueueId}`; | |||
const _spec = { | |||
...spec, | |||
QueueId: spec.QueueId, | |||
QueueCode: spec.QueueCode, | |||
AiCenterCode: spec.AiCenterCode, | |||
AiCenterName: spec.AiCenterName, | |||
QueueStr: spec.QueueStr, | |||
checked: this.selectList.indexOf(spec.ID) > -1, | |||
}; | |||
if (map[key]) { | |||
map[key].specs.push(_spec); | |||
} else { | |||
map[key] = { | |||
...spec, | |||
specs: [_spec], | |||
} | |||
} | |||
} | |||
const data = []; | |||
for (let key in map) { | |||
data.push(map[key]); | |||
} | |||
return data; | |||
}, | |||
tableDataShow: function () { | |||
const map = {}; | |||
for (let i = 0, iLen = this.specs.length; i < iLen; i++) { | |||
const spec = this.specs[i]; | |||
if (this.value.indexOf(spec.ID) < 0) continue; | |||
const key = `${spec.Cluster}|${spec.ComputeResource}|${spec.SourceSpecId || Math.random()}`; | |||
const queue = { | |||
...spec, | |||
QueueId: spec.QueueId, | |||
QueueCode: spec.QueueCode, | |||
AiCenterCode: spec.AiCenterCode, | |||
AiCenterName: spec.AiCenterName, | |||
QueueStr: spec.QueueStr, | |||
}; | |||
if (map[key]) { | |||
map[key].queues.push(queue); | |||
} else { | |||
map[key] = { | |||
...spec, | |||
queues: [queue], | |||
} | |||
} | |||
} | |||
const data = []; | |||
for (let key in map) { | |||
data.push(map[key]); | |||
} | |||
return data; | |||
}, | |||
}, | |||
methods: { | |||
resetDataInfo() { | |||
this.dataInfo = {} | |||
}, | |||
changeTab(tabIndex) { | |||
if (this.tabIndex == tabIndex) return; | |||
this.tabIndex = tabIndex; | |||
}, | |||
selectChange(id) { | |||
const index = this.selectList.indexOf(id); | |||
if (index < 0) { | |||
this.selectList.push(id); | |||
} else { | |||
this.selectList.splice(index, 1); | |||
} | |||
}, | |||
selectAll(list) { | |||
list.forEach(_item => { | |||
if (this.selectList.indexOf(_item.ID) < 0) { | |||
this.selectList.push(_item.ID); | |||
} | |||
}); | |||
}, | |||
clearSelectAll(list) { | |||
list.forEach(_item => { | |||
const index = this.selectList.indexOf(_item.ID); | |||
if (index >= 0) { | |||
this.selectList.splice(index, 1); | |||
} | |||
}); | |||
}, | |||
open() { | |||
this.$emit("open"); | |||
this.selectList = [...this.value]; | |||
this.tabIndex = '1'; | |||
}, | |||
opened() { | |||
this.$emit("opened"); | |||
}, | |||
close() { | |||
this.$emit("close"); | |||
}, | |||
closed() { | |||
this.$emit("closed"); | |||
this.$emit("update:visible", false); | |||
}, | |||
confirm() { | |||
this.dlgShow = false; | |||
this.$emit('input', this.selectList); | |||
this.$emit('change', this.selectList); | |||
}, | |||
cancel() { | |||
this.dlgShow = false; | |||
this.$emit("update:visible", false); | |||
} | |||
}, | |||
mounted() { | |||
this.resetDataInfo(); | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
.form-row { | |||
display: flex; | |||
min-height: 42px; | |||
margin-bottom: 4px; | |||
.title { | |||
width: 255px; | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
margin-right: 20px; | |||
color: rgb(136, 136, 136); | |||
font-size: 14px; | |||
&.required { | |||
span { | |||
position: relative; | |||
} | |||
span::after { | |||
position: absolute; | |||
right: -10px; | |||
top: -2px; | |||
vertical-align: top; | |||
content: '*'; | |||
color: #db2828; | |||
} | |||
} | |||
} | |||
.content { | |||
width: 10px; | |||
display: flex; | |||
align-items: center; | |||
} | |||
.select-btn { | |||
display: flex; | |||
align-items: center; | |||
font-size: 13px; | |||
} | |||
} | |||
.row-detail { | |||
font-size: 12px; | |||
.table-c { | |||
padding-bottom: 2px; | |||
padding-right: 8px; | |||
.table-content { | |||
max-height: 300px; | |||
overflow: auto; | |||
margin-top: -1px; | |||
padding-bottom: 2px; | |||
} | |||
.row { | |||
display: flex; | |||
&.header { | |||
background-color: #f5f5f6; | |||
.row-l { | |||
justify-content: center; | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
.row-r { | |||
flex-direction: row; | |||
justify-content: center; | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
} | |||
.row-l { | |||
display: flex; | |||
align-items: center; | |||
border: 1px solid gainsboro; | |||
border-right: none; | |||
border-bottom: none; | |||
padding: 4px 8px; | |||
width: 0; | |||
overflow: hidden; | |||
} | |||
.row-r { | |||
border: 1px solid gainsboro; | |||
padding: 4px 8px; | |||
display: flex; | |||
flex-direction: column; | |||
border-bottom: none; | |||
width: 0; | |||
overflow: hidden; | |||
position: relative; | |||
} | |||
&:last-child { | |||
.row-l { | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
.row-r { | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
.dlg-content { | |||
margin: -30px 0 0 0; | |||
display: flex; | |||
font-size: 12px; | |||
.left-area { | |||
flex: 1; | |||
width: 0; | |||
.tabs { | |||
display: flex; | |||
align-items: center; | |||
margin-bottom: 10px; | |||
.tab { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
font-size: 12px; | |||
color: rgba(0, 0, 0, .87); | |||
border: 1px solid rgba(34, 36, 38, .15); | |||
margin-left: -1px; | |||
height: 30px; | |||
padding: 0 6px; | |||
border-left: none; | |||
&.focused { | |||
color: #0087f5; | |||
border-color: #0087f5; | |||
border-left: 1px solid #0087f5 !important; | |||
} | |||
&:first-child { | |||
border-radius: 0.28571429rem 0 0 0.28571429rem; | |||
border-left: 1px solid rgba(34, 36, 38, .15); | |||
&.focus { | |||
border-color: #0087f5; | |||
} | |||
} | |||
&:last-child { | |||
border-radius: 0 0.28571429rem 0.28571429rem 0; | |||
} | |||
&:hover:not(.focused) { | |||
background: rgba(0, 0, 0, .03); | |||
cursor: pointer; | |||
} | |||
} | |||
} | |||
.table-c { | |||
padding-bottom: 2px; | |||
padding-right: 8px; | |||
.table-content { | |||
height: 400px; | |||
overflow: auto; | |||
margin-top: -1px; | |||
padding-bottom: 2px; | |||
} | |||
.row { | |||
display: flex; | |||
&.header { | |||
background-color: #f5f5f6; | |||
.row-l { | |||
justify-content: center; | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
.row-r { | |||
flex-direction: row; | |||
justify-content: center; | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
} | |||
.row-l { | |||
display: flex; | |||
align-items: center; | |||
border: 1px solid gainsboro; | |||
border-right: none; | |||
border-bottom: none; | |||
padding: 4px 8px; | |||
width: 0; | |||
overflow: hidden; | |||
} | |||
.row-r { | |||
border: 1px solid gainsboro; | |||
padding: 4px 8px; | |||
display: flex; | |||
flex-direction: column; | |||
border-bottom: none; | |||
width: 0; | |||
overflow: hidden; | |||
position: relative; | |||
/deep/ .el-checkbox__label { | |||
font-size: 12px; | |||
} | |||
.btn-c { | |||
position: absolute; | |||
top: 5px; | |||
right: 5px; | |||
z-index: 1; | |||
button { | |||
background-color: #409EFF; | |||
color: #FFF; | |||
margin-left: 3px; | |||
outline: none; | |||
cursor: pointer; | |||
border: none; | |||
border-radius: 2px; | |||
padding: 2px 4px; | |||
&:focus, | |||
&:hover { | |||
background: #66b1ff; | |||
} | |||
&:active { | |||
background: #3a8ee6; | |||
} | |||
} | |||
} | |||
} | |||
&:last-child { | |||
.row-l { | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
.row-r { | |||
border-bottom: 1px solid gainsboro; | |||
} | |||
} | |||
} | |||
} | |||
.confirm-btn-c { | |||
margin-top: 15px; | |||
text-align: right; | |||
} | |||
} | |||
} | |||
</style> |
@@ -9,6 +9,9 @@ | |||
<el-select class="select" size="medium" v-model="selIsExclusive" @change="selectChange"> | |||
<el-option v-for="item in isExclusiveList" :key="item.k" :label="item.v" :value="item.k" /> | |||
</el-select> | |||
<el-select class="select" size="medium" v-model="selCluster" @change="selectChange"> | |||
<el-option v-for="item in clusterList" :key="item.k" :label="item.v" :value="item.k" /> | |||
</el-select> | |||
<el-select class="select" size="medium" v-model="selAiCenter" @change="selectChange"> | |||
<el-option v-for="item in aiCenterList" :key="item.k" :label="item.v" :value="item.k" /> | |||
</el-select> | |||
@@ -29,8 +32,8 @@ | |||
</div> | |||
<div class="table-container"> | |||
<div style="min-height:600px;"> | |||
<el-table border :data="tableData" style="width: 100%" v-loading="loading" stripe> | |||
<el-table-column prop="ID" label="ID" align="center" header-align="center" width="60"></el-table-column> | |||
<el-table border :data="tableData" style="width:100%" v-loading="loading" stripe :span-method="tableSpanMethod"> | |||
<el-table-column prop="_id_" label="ID" align="center" header-align="center" width="60"></el-table-column> | |||
<el-table-column prop="SceneName" :label="$t('resourcesManagement.resSceneName')" align="center" | |||
header-align="center"></el-table-column> | |||
<el-table-column prop="JobTypeStr" :label="$t('resourcesManagement.jobType')" align="center" | |||
@@ -48,29 +51,27 @@ | |||
<span>{{ scope.row.IsExclusive ? scope.row.ExclusiveOrg : '--' }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="AiCenterStr" :label="$t('resourcesManagement.aiCenter')" align="center" | |||
header-align="center"> | |||
<el-table-column prop="specStr" :label="$t('resourcesManagement.resourceSpecification')" align="left" | |||
header-align="center" min-width="180"> | |||
<template slot-scope="scope"> | |||
<div v-if="!scope.row.Queues.length">--</div> | |||
<div v-for="item in scope.row.Queues" :key="item.QueueId"> | |||
<span>{{ item.AiCenterName }}</span> | |||
</div> | |||
<span v-html="scope.row.specStr"></span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="QueueStr" :label="$t('resourcesManagement.resQueue')" align="center" | |||
header-align="center"> | |||
<el-table-column prop="AiCenterStr" :label="$t('resourcesManagement.aiCenter')" align="center" | |||
header-align="center" width="230"> | |||
<template slot-scope="scope"> | |||
<div v-if="!scope.row.Queues.length">--</div> | |||
<div v-for="item in scope.row.Queues" :key="item.QueueId"> | |||
<span>{{ item.QueueStr }}</span> | |||
<div v-if="!scope.row.queues.length">--</div> | |||
<div v-for="item in scope.row.queues " :key="item.key"> | |||
<span>{{ item.AiCenterName }}</span> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="SpecsList" :label="$t('resourcesManagement.resourceSpecification')" align="left" | |||
header-align="center" min-width="180"> | |||
<el-table-column prop="QueueStr" :label="$t('resourcesManagement.resQueue')" align="center" | |||
header-align="center" width="230"> | |||
<template slot-scope="scope"> | |||
<div v-for="item in scope.row.SpecsList" :key="item.k"> | |||
<span v-html="item.v"></span> | |||
<div v-if="!scope.row.queues.length">--</div> | |||
<div v-for=" item in scope.row.queues " :key="item.key"> | |||
<span v-html="item.QueueStr + item.statusStr"></span> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
@@ -119,7 +120,8 @@ export default { | |||
isExclusiveList: [{ k: '', v: this.$t('resourcesManagement.allExclusiveAndCommonUse') }, { k: '1', v: this.$t('resourcesManagement.exclusive') }, { k: '2', v: this.$t('resourcesManagement.commonUse') }], | |||
selQueue: '', | |||
queueList: [{ k: '', v: this.$t('resourcesManagement.allResQueue') }], | |||
clusterList: [...CLUSTERS], | |||
selCluster: '', | |||
clusterList: [{ k: '', v: this.$t('resourcesManagement.allCluster') }, ...CLUSTERS], | |||
selAiCenter: '', | |||
aiCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }], | |||
accCardTypeList: [...ACC_CARD_TYPE], | |||
@@ -143,6 +145,21 @@ export default { | |||
}, | |||
components: { SceneDialog }, | |||
methods: { | |||
tableSpanMethod({ row, column, rowIndex, columnIndex }) { | |||
if ([0, 1, 2, 3, 4, 8].indexOf(columnIndex) > -1) { | |||
if (row.rowspan) { | |||
return { | |||
rowspan: row.rowspan, | |||
colspan: 1, | |||
}; | |||
} else { | |||
return { | |||
rowspan: 0, | |||
colspan: 0 | |||
}; | |||
} | |||
} | |||
}, | |||
getAiCenterList() { | |||
getAiCenterList().then(res => { | |||
res = res.data; | |||
@@ -183,6 +200,7 @@ export default { | |||
const params = { | |||
jobType: this.selTaskType, | |||
IsExclusive: this.selIsExclusive, | |||
cluster: this.selCluster, | |||
queue: this.selQueue, | |||
center: this.selAiCenter, | |||
resource: this.selResource, | |||
@@ -196,46 +214,81 @@ export default { | |||
res = res.data; | |||
if (res.Code === 0) { | |||
const list = res.Data.List; | |||
const data = list.map((item) => { | |||
const Specs = item.Specs; | |||
const specsList = []; | |||
const data = []; | |||
for (let i = 0, iLen = list.length; i < iLen; i++) { | |||
const item = list[i]; | |||
const specs = item.Specs; | |||
const sourceSpecIdMap = {}; | |||
for (let j = 0, jLen = specs.length; j < jLen; j++) { | |||
const spec = specs[j]; | |||
const NGPU = `${spec.ComputeResource}:${spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, spec.AccCardType)}`; | |||
const statusStr = spec.Status != '2' ? `<span style="color:rgb(245, 34, 45)">(${getListValueWithKey(this.statusList, spec.Status.toString())})</span>` : ''; | |||
spec.specStr = `${NGPU}, CPU:${spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${spec.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${spec.UnitPrice}${this.$t('resourcesManagement.point_hr')}`; | |||
spec.JobTypeStr = getListValueWithKey(this.taskTypeList, item.JobType); | |||
spec.IsExclusiveStr = getListValueWithKey(this.isExclusiveList, item.IsExclusive ? '1' : '2'); | |||
spec.statusStr = statusStr; | |||
spec._id_ = item.ID; | |||
const sourceSpecId = spec.SourceSpecId; | |||
if (sourceSpecIdMap[sourceSpecId]) { | |||
sourceSpecIdMap[sourceSpecId].push({ ...spec }); | |||
} else { | |||
sourceSpecIdMap[sourceSpecId] = [{ ...item, ...spec }]; | |||
} | |||
} | |||
for (let key in sourceSpecIdMap) { | |||
const _specs = sourceSpecIdMap[key]; | |||
if (key) { | |||
const aiCenters = []; | |||
const queues = []; | |||
const queueIds = []; | |||
let cluster = ''; | |||
for (let i = 0, iLen = Specs.length; i < iLen; i++) { | |||
const Spec = Specs[i]; | |||
const NGPU = `${Spec.ComputeResource}:${Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Spec.AccCardType)}`; | |||
const statusStr = Spec.Status != '2' ? `<span style="color:rgb(245, 34, 45)">(${getListValueWithKey(this.statusList, Spec.Status.toString())})</span>` : ''; | |||
specsList.push({ | |||
k: Spec.ID, | |||
v: `${NGPU}, CPU:${Spec.CpuCores}, ${this.$t('resourcesManagement.gpuMem')}:${Spec.GPUMemGiB}GB, ${this.$t('resourcesManagement.mem')}:${Spec.MemGiB}GB, ${this.$t('resourcesManagement.shareMem')}:${Spec.ShareMemGiB}GB, ${this.$t('resourcesManagement.unitPrice')}:${Spec.UnitPrice}${this.$t('resourcesManagement.point_hr')}${statusStr}`, | |||
}); | |||
cluster = Spec.Cluster; | |||
if (queueIds.indexOf(Spec.QueueId) < 0) { | |||
for (let k = 0, kLen = _specs.length; k < kLen; k++) { | |||
const _spec = _specs[k]; | |||
queues.push({ | |||
QueueId: Spec.QueueId, | |||
QueueCode: Spec.QueueCode, | |||
AiCenterCode: Spec.AiCenterCode, | |||
AiCenterName: Spec.AiCenterName, | |||
QueueStr: `${Spec.QueueCode}(${getListValueWithKey(this.clusterList, Spec.Cluster)} - ${Spec.AiCenterName})`, | |||
QueueId: _spec.QueueId, | |||
QueueCode: _spec.QueueCode, | |||
AiCenterCode: _spec.AiCenterCode, | |||
AiCenterName: _spec.AiCenterName, | |||
QueueStr: `${_spec.QueueCode}(${getListValueWithKey(this.clusterList, _spec.Cluster)} - ${_spec.AiCenterName})`, | |||
statusStr: _spec.statusStr, | |||
key: Math.random(), | |||
}); | |||
queueIds.push(Spec.QueueId); | |||
} | |||
data.push({ ..._specs[0], aiCenters, queues }) | |||
} else { | |||
for (let k = 0, kLen = _specs.length; k < kLen; k++) { | |||
const _spec = _specs[k]; | |||
data.push({ | |||
..._spec, | |||
queues: [{ | |||
QueueId: _spec.QueueId, | |||
QueueCode: _spec.QueueCode, | |||
AiCenterCode: _spec.AiCenterCode, | |||
AiCenterName: _spec.AiCenterName, | |||
QueueStr: `${_spec.QueueCode}(${getListValueWithKey(this.clusterList, _spec.Cluster)} - ${_spec.AiCenterName})`, | |||
statusStr: _spec.statusStr, | |||
key: Math.random(), | |||
}] | |||
}) | |||
} | |||
} | |||
} | |||
} | |||
let rowspan = 1; | |||
let index = 0; | |||
for (let i = 0, iLen = data.length; i < iLen; i++) { | |||
if (i == 0) { | |||
data[i].rowspan = 1; | |||
continue; | |||
} | |||
if (data[i]._id_ == data[i - 1]._id_) { | |||
data[i].rowspan = 0; | |||
rowspan++; | |||
data[index].rowspan = rowspan; | |||
} else { | |||
index = i; | |||
rowspan = 1; | |||
data[index].rowspan = rowspan; | |||
} | |||
return { | |||
ID: item.ID, | |||
SceneName: item.SceneName, | |||
JobType: item.JobType, | |||
JobTypeStr: getListValueWithKey(this.taskTypeList, item.JobType), | |||
IsExclusive: item.IsExclusive, | |||
IsExclusiveStr: getListValueWithKey(this.isExclusiveList, item.IsExclusive ? '1' : '2'), | |||
ExclusiveOrg: item.ExclusiveOrg, | |||
Cluster: cluster, | |||
QueueIds: queueIds, | |||
Queues: queues, | |||
SpecsList: specsList, | |||
} | |||
}); | |||
this.tableData = data; | |||
this.pageInfo.total = res.Data.TotalSize; | |||
} | |||
@@ -261,7 +314,7 @@ export default { | |||
}).then(() => { | |||
updateResScene({ | |||
action: 'delete', | |||
ID: row.ID, | |||
ID: row._id_, | |||
}).then(res => { | |||
res = res.data; | |||
if (res.Code === 0) { | |||
@@ -287,14 +340,14 @@ export default { | |||
showDialog(type, data) { | |||
this.sceneDialogType = type; | |||
this.sceneDialogData = data ? { | |||
ID: data.ID, | |||
ID: data._id_, | |||
SceneName: data.SceneName, | |||
JobType: data.JobType, | |||
IsExclusive: data.IsExclusive ? '1' : '2', | |||
ExclusiveOrg: data.ExclusiveOrg, | |||
Cluster: data.Cluster, | |||
QueueIds: data.QueueIds, | |||
SpecIds: data.SpecsList.map((item) => item.k), | |||
ComputeResource: data.ComputeResource, | |||
SpecIds: data.Specs.map(item => item.ID), | |||
} : {}; | |||
this.sceneDialogShow = true; | |||
}, | |||
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》