| @@ -1,13 +1,5 @@ | |||
| import service from '../service'; | |||
| export const getQueueList = (params) => { | |||
| return service({ | |||
| url: '/admin/resources/queue', | |||
| method: 'get', | |||
| params, | |||
| }); | |||
| } | |||
| // 查询资源队列列表 | |||
| // page 当前页数,从1开始 | |||
| // cluster 所属集群 :OpenI 启智集群,C2Net 智算集群 | |||
| @@ -43,11 +35,11 @@ export const updateResQueue = (data) => { // CardsTotalNum,Remark | |||
| } | |||
| // 查询所有资源队列名称列表 | |||
| export const getResQueueCode = () => { | |||
| export const getResQueueCode = (params) => { // cluster | |||
| return service({ | |||
| url: '/admin/resources/queue/codes', | |||
| method: 'get', | |||
| params: {}, | |||
| params, | |||
| data: {}, | |||
| }); | |||
| } | |||
| @@ -70,12 +62,13 @@ export const updateResSpecification = (data) => { // data => { ID: 1, action: 'e | |||
| url: `/admin/resources/specification/update/${data.ID}`, | |||
| method: 'post', | |||
| params: { action: data.action }, | |||
| data: { UnitPrice: data.action === 'edit' ? data.UnitPrice : undefined } | |||
| data: { UnitPrice: data.action === 'edit' || data.action === 'on-shelf' ? data.UnitPrice : undefined } | |||
| }); | |||
| } | |||
| // 查询资源队列列表 | |||
| // 查询资源规格列表 | |||
| // page | |||
| // cluster 所属集群 :OpenI 启智集群,C2Net 智算集群 | |||
| // queue 所属队列id | |||
| // status 状态 : 1 待审核 2已上架 3已下架 | |||
| export const getResSpecificationList = (params) => { | |||
| @@ -86,3 +79,57 @@ export const getResSpecificationList = (params) => { | |||
| data: {}, | |||
| }); | |||
| } | |||
| // 新增资源应用场景 | |||
| /* | |||
| { | |||
| "SceneName":"启智集群调试任务", //应用场景名 | |||
| "JobType":"TRAIN", //任务类型 DEBUG调试任务 BENCHMARK 评测任务 TRAIN 训练 INFERENCE 推理 | |||
| "IsExclusive":true, //是否专属 | |||
| "ExclusiveOrg":"123,456", //专属组织 | |||
| "QueueId":2, //队列id | |||
| "SpecIds":[2,3] // 资源规格id | |||
| } | |||
| */ | |||
| export const addResScene = (data) => { | |||
| return service({ | |||
| url: '/admin/resources/scene/add', | |||
| method: 'post', | |||
| params: {}, | |||
| data, | |||
| }); | |||
| } | |||
| // 更新资源应用场景 | |||
| // params: action:edit-编辑 delete-删除, | |||
| // data: { | |||
| // "SceneName":"启智集群调试任务", //应用场景名 | |||
| // "IsExclusive":true, //是否专属 | |||
| // "ExclusiveOrg":"123,456", //专属组织 | |||
| // "SpecIds":[2,3] // 资源规格id | |||
| //} | |||
| export const updateResScene = (data) => { | |||
| return service({ | |||
| url: `/admin/resources/scene/update/${data.ID}`, | |||
| method: 'post', | |||
| params: { action: data.action }, | |||
| data: { | |||
| ...data | |||
| }, | |||
| }); | |||
| } | |||
| // 查询资源应用场景 | |||
| // page | |||
| // jobType | |||
| // center | |||
| // queue 所属队列 | |||
| // IsExclusive 是否专属 1 专属 2 非专属 | |||
| export const getResSceneList = (params) => { | |||
| return service({ | |||
| url: '/admin/resources/scene/list', | |||
| method: 'get', | |||
| params, | |||
| data: {}, | |||
| }); | |||
| } | |||
| @@ -9,8 +9,8 @@ export const POINT_ACTIONS = [ | |||
| export const JOB_TYPE = [{ k: 'DEBUG', v: i18n.t('debugTask') }, { k: 'TRAIN', v: i18n.t('trainTask') }, { k: 'INFERENCE', v: i18n.t('inferenceTask') }, { k: 'BENCHMARK', v: i18n.t('benchmarkTask') }]; | |||
| // 资源管理 | |||
| export const CLUSTERS = [{ k: 'OpenI', v: '启智集群' }, { k: 'C2Net', v: '智算集群' }]; | |||
| export const AI_CENTER = [{ k: 'OpenIOne', v: '云脑一' }, { k: 'OpenITwo', v: '云脑二' }, { k: 'chendu', v: '成都人工智能计算中心' }, { k: 'pclcci', v: '鹏城云计算所' }, { k: 'hefei', v: '合肥类脑类脑智能开放平台' }, { k: 'xuchang', v: '中原人工智能计算中心' }]; | |||
| export const CLUSTERS = [{ k: 'OpenI', v: i18n.t('resourcesManagement.OpenI') }, { k: 'C2Net', v: i18n.t('resourcesManagement.C2Net') }]; | |||
| export const AI_CENTER = [{ k: 'OpenIOne', v: i18n.t('resourcesManagement.OpenIOne') }, { k: 'OpenITwo', v: i18n.t('resourcesManagement.OpenITwo') }, { k: 'chendu', v: i18n.t('resourcesManagement.chenduCenter') }, { k: 'pclcci', v: i18n.t('resourcesManagement.pclcci') }, { k: 'hefei', v: i18n.t('resourcesManagement.hefeiCenter') }, { k: 'xuchang', v: i18n.t('resourcesManagement.xuchangCenter') }]; | |||
| export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }]; | |||
| export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'Ascend910', v: 'Ascend 910' }]; | |||
| export const SPECIFICATION_STATUS = [{ k: '1', v: '待上架' }, { k: '2', v: '已上架' }, { k: '3', v: '已下架' }]; | |||
| export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.toOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }]; | |||
| @@ -3,6 +3,16 @@ const en = { | |||
| noData: 'No Data', | |||
| date: 'Date', | |||
| confirm: 'Confirm', | |||
| cancel: 'Cancel', | |||
| pleaseCompleteTheInformationFirst: 'Please Complete the Information first!', | |||
| submittedSuccessfully: 'Submitted Successfully!', | |||
| submittedFailed: 'Submitted Failed!', | |||
| operation: 'Operation', | |||
| edit: 'Edit', | |||
| delete: 'Delete', | |||
| tips: 'Tips', | |||
| accomplishTask: 'Accomplish Task', | |||
| adminOperate: 'Administrator Operation', | |||
| runCloudBrainTask: 'Run CloudBrain Task', | |||
| @@ -65,6 +75,78 @@ const en = { | |||
| noPointGainRecord: 'No Point Earn Record Yet', | |||
| noPointConsumeRecord: 'No Point Consume Record Yet', | |||
| resourcesManagement: { | |||
| OpenI: 'OpenI', | |||
| C2Net: 'C2Net', | |||
| OpenIOne: 'OpenI One', | |||
| OpenITwo: 'OpenI Two', | |||
| chenduCenter: 'ChenDu AI Center', | |||
| pclcci: 'PCL Cloud Computer Institute', | |||
| hefeiCenter: 'HeFei AI Center', | |||
| xuchangCenter: 'XuChang AI Center', | |||
| toOnShelf: 'To Be On Shelf', | |||
| onShelf: 'On Shelf', | |||
| offShelf: 'Off Shelf', | |||
| toOnShelf: 'To On Shelf', | |||
| toOffShelf: 'To Off Shelf', | |||
| toSetPriceAndOnShelf: 'To Set Price and On Shelf', | |||
| status: 'Status', | |||
| allStatus: 'All Status', | |||
| syncAiNetwork: 'Sync AI Network', | |||
| resQueue: 'Resources Queue', | |||
| allResQueue: 'All Resources Queues', | |||
| addResQueue: 'Add Resources Queue', | |||
| addResQueueBtn: 'Add Resources Queue', | |||
| editResQueue: 'Edit Resources Queue', | |||
| resQueueName: 'Resources Queue Name', | |||
| whichCluster: 'Cluster', | |||
| allCluster: 'All Clusters', | |||
| aiCenter: 'AI Center', | |||
| aiCenterID: 'AI Center ID', | |||
| allAiCenter: 'All AI Centers', | |||
| computeResource: 'Compute Resource', | |||
| allComputeResource: 'All Compute Resources', | |||
| accCardType: 'Acc Card Type', | |||
| allAccCardType: 'All Acc Card Type', | |||
| cardsTotalNum: 'Cards Total Number', | |||
| accCardsNum: 'Acc Cards Number', | |||
| remark: 'Remark', | |||
| pleaseEnterRemark: 'Please Enter Remark', | |||
| pleaseEnterPositiveIntegerCardsTotalNum: 'Please Enter Positive Integer Cards Total Number!', | |||
| addResSpecificationAndPriceInfo: 'Add Resources Specification and Price Info', | |||
| addResSpecificationBtn: 'Add Resources Specification', | |||
| editResSpecificationAndPriceInfo: 'Edit Resources Specification and Price Info', | |||
| resSpecificationAndPriceManagement: 'Resources Specification and Price Management', | |||
| sourceSpecCode: 'Source Specification Code', | |||
| sourceSpecCodeTips: 'OpenI Two Should Enter the Source Specification Code', | |||
| sourceSpecId: 'Source Specification ID', | |||
| cpuNum: 'CPU Number', | |||
| gpuMem: 'GPU Memory', | |||
| mem: 'Memory', | |||
| shareMem: 'Share Memory', | |||
| unitPrice: 'Unit Price', | |||
| point_hr: 'Point/hr', | |||
| onShelfConfirm: 'Are you sure to on shelf the resources specification?', | |||
| offShelfConfirm: 'Are you sure to off shelf the resources specification?', | |||
| resSceneManagement: 'Resources Scene Management', | |||
| addResScene: 'Add Resources Scene', | |||
| addResSceneBtn: 'Add Resources Scene', | |||
| editResScene: 'Edit Resources Scene', | |||
| resSceneName: 'Resources Scene Name', | |||
| jobType: 'Job Type', | |||
| allJobType: 'All Job Type', | |||
| isExclusive: 'Is Exclusive?', | |||
| allExclusiveAndCommonUse: 'All Exclusive and Common Use', | |||
| exclusive: 'Exclusive', | |||
| commonUse: 'Common Use', | |||
| exclusiveOrg: 'Exclusive Organization', | |||
| exclusiveOrgTips: 'Multiple organization names are separated by semicolons', | |||
| computeCluster: 'Compute Cluster', | |||
| resourceSpecification: 'Resource Specification', | |||
| lastUpdateTime: 'Last Update Time', | |||
| resSceneDeleteConfirm: 'Are you sure to delete the current Resource Scene?', | |||
| }, | |||
| } | |||
| export default en; | |||
| @@ -3,6 +3,16 @@ const zh = { | |||
| noData: '暂无数据', | |||
| date: '日期', | |||
| confirm: '确认', | |||
| cancel: '取消', | |||
| pleaseCompleteTheInformationFirst: '请先完善信息!', | |||
| submittedSuccessfully: '提交成功!', | |||
| submittedFailed: '提交失败!', | |||
| operation: '操作', | |||
| edit: '修改', | |||
| delete: '删除', | |||
| tips: '提示', | |||
| accomplishTask: '积分任务', | |||
| adminOperate: '管理员操作', | |||
| runCloudBrainTask: '运行云脑任务', | |||
| @@ -65,6 +75,78 @@ const zh = { | |||
| noPointGainRecord: '还没有积分获取记录', | |||
| noPointConsumeRecord: '还没有积分消耗记录', | |||
| resourcesManagement: { | |||
| OpenI: '启智集群', | |||
| C2Net: '智算集群', | |||
| OpenIOne: '云脑一', | |||
| OpenITwo: '云脑二', | |||
| chenduCenter: '成都人工智能计算中心', | |||
| pclcci: '鹏城云计算所', | |||
| hefeiCenter: '合肥类脑类脑智能开放平台', | |||
| xuchangCenter: '中原人工智能计算中心', | |||
| toOnShelf: '待上架', | |||
| onShelf: '已上架', | |||
| offShelf: '已下架', | |||
| toOnShelf: '上架', | |||
| toOffShelf: '下架', | |||
| toSetPriceAndOnShelf: '定价上架', | |||
| status: '状态', | |||
| allStatus: '全部状态', | |||
| syncAiNetwork: '同步智算网络', | |||
| resQueue: '资源池(队列)', | |||
| allResQueue: '全部资源池(队列)', | |||
| addResQueue: '新建资源池(队列)', | |||
| addResQueueBtn: '新增资源池', | |||
| editResQueue: '修改资源池(队列)', | |||
| resQueueName: '资源池(队列)名称', | |||
| whichCluster: '所属集群', | |||
| allCluster: '全部集群', | |||
| aiCenter: '智算中心', | |||
| aiCenterID: '智算中心ID', | |||
| allAiCenter: '全部智算中心', | |||
| computeResource: '计算资源', | |||
| allComputeResource: '全部计算资源', | |||
| accCardType: '卡类型', | |||
| allAccCardType: '全部卡类型', | |||
| cardsTotalNum: '卡数', | |||
| accCardsNum: '卡数', | |||
| remark: '备注', | |||
| pleaseEnterRemark: '请输入备注', | |||
| pleaseEnterPositiveIntegerCardsTotalNum: '请输入正整数的卡数!', | |||
| addResSpecificationAndPriceInfo: '新增资源规格和单价信息', | |||
| addResSpecificationBtn: '新增资源规格', | |||
| editResSpecificationAndPriceInfo: '修改资源规格和单价信息', | |||
| resSpecificationAndPriceManagement: '资源规格单价管理', | |||
| sourceSpecCode: '对应资源编码', | |||
| sourceSpecCodeTips: '云脑II需要填写对应的资源编码', | |||
| sourceSpecId: '智算网络资源规格ID', | |||
| cpuNum: 'CPU数', | |||
| gpuMem: '显存', | |||
| mem: '内存', | |||
| shareMem: '共享内存', | |||
| unitPrice: '单价', | |||
| point_hr: '积分/时', | |||
| onShelfConfirm: '请确认是否上架该规格?', | |||
| offShelfConfirm: '请确认是否下架该规格?', | |||
| resSceneManagement: '算力资源应用场景管理', | |||
| addResScene: '新建算力资源应用场景', | |||
| addResSceneBtn: '新增应用场景', | |||
| editResScene: '修改算力资源应用场景', | |||
| resSceneName: '应用场景名称', | |||
| jobType: '任务类型', | |||
| allJobType: '全部任务类型', | |||
| isExclusive: '是否专属', | |||
| allExclusiveAndCommonUse: '全部专属和通用', | |||
| exclusive: '专属', | |||
| commonUse: '通用', | |||
| exclusiveOrg: '专属组织', | |||
| exclusiveOrgTips: '多个组织名之间用英文分号隔开', | |||
| computeCluster: '算力集群', | |||
| resourceSpecification: '资源规格', | |||
| lastUpdateTime: '最后更新时间', | |||
| resSceneDeleteConfirm: '是否确认删除当前应用场景?', | |||
| }, | |||
| } | |||
| export default zh; | |||
| @@ -1,12 +1,13 @@ | |||
| <template> | |||
| <div class="base-dlg"> | |||
| <BaseDialog :visible.sync="dialogShow" :width="`750px`" :title="type === 'add' ? `新建资源池(队列)` : '修改资源池(队列)'" | |||
| <BaseDialog :visible.sync="dialogShow" :width="`750px`" | |||
| :title="type === 'add' ? $t('resourcesManagement.addResQueue') : $t('resourcesManagement.editResQueue')" | |||
| @open="open" @opened="opened" @close="close" @closed="closed"> | |||
| <div class="dlg-content"> | |||
| <div class="form"> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>资源池(队列)名称</span> | |||
| <span>{{ $t('resourcesManagement.resQueueName') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.QueueCode" placeholder="" :disabled="type === 'edit'"></el-input> | |||
| @@ -14,7 +15,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>所属集群</span> | |||
| <span>{{ $t('resourcesManagement.whichCluster') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.Cluster" :disabled="type === 'edit'"> | |||
| @@ -24,7 +25,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>智算中心</span> | |||
| <span>{{ $t('resourcesManagement.aiCenter') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.AiCenterCode" :disabled="type === 'edit'"> | |||
| @@ -34,7 +35,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>计算资源</span> | |||
| <span>{{ $t('resourcesManagement.computeResource') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.ComputeResource" :disabled="type === 'edit'"> | |||
| @@ -44,7 +45,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>卡类型</span> | |||
| <span>{{ $t('resourcesManagement.accCardType') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.AccCardType" :disabled="type === 'edit'"> | |||
| @@ -54,25 +55,25 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>卡数</span> | |||
| <span>{{ $t('resourcesManagement.cardsTotalNum') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.CardsTotalNum" type="number" placeholder=""></el-input> | |||
| </div> | |||
| </div> | |||
| <div class="form-row" style="margin-top: 10px"> | |||
| <div class="title"><span>备注</span></div> | |||
| <div class="title"><span>{{ $t('resourcesManagement.remark') }}</span></div> | |||
| <div class="content" style="width: 400px"> | |||
| <el-input type="textarea" :autosize="{ minRows: 3, maxRows: 4 }" :placeholder="'请输入备注'" | |||
| v-model="dataInfo.Remark"> | |||
| <el-input type="textarea" :autosize="{ minRows: 3, maxRows: 4 }" | |||
| :placeholder="$t('resourcesManagement.pleaseEnterRemark')" v-model="dataInfo.Remark"> | |||
| </el-input> | |||
| </div> | |||
| </div> | |||
| <div class="form-row" style="margin-top: 20px"> | |||
| <div class="title"></div> | |||
| <div class="content"> | |||
| <el-button type="primary" class="btn confirm-btn" @click="confirm">确定</el-button> | |||
| <el-button class="btn" @click="cancel">取消</el-button> | |||
| <el-button type="primary" class="btn confirm-btn" @click="confirm">{{ $t('confirm') }}</el-button> | |||
| <el-button class="btn" @click="cancel">{{ $t('cancel') }}</el-button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -148,14 +149,14 @@ export default { | |||
| if (!this.dataInfo.QueueCode || !this.dataInfo.Cluster || !this.dataInfo.AiCenterCode || !this.dataInfo.ComputeResource || !this.dataInfo.AccCardType || !this.dataInfo.CardsTotalNum) { | |||
| this.$message({ | |||
| type: 'info', | |||
| message: '请先完善信息!' | |||
| message: this.$t('pleaseCompleteTheInformationFirst'), | |||
| }); | |||
| return; | |||
| } | |||
| if (parseInt(this.dataInfo.CardsTotalNum) != Number(this.dataInfo.CardsTotalNum)) { | |||
| this.$message({ | |||
| type: 'info', | |||
| message: '请输入正整数的卡数!' | |||
| message: this.$t('pleaseEnterPositiveIntegerCardsTotalNum') | |||
| }); | |||
| return; | |||
| } | |||
| @@ -165,20 +166,20 @@ export default { | |||
| if (res.Code === 0) { | |||
| this.$message({ | |||
| type: 'success', | |||
| message: '提交成功!' | |||
| message: this.$t('submittedSuccessfully') | |||
| }); | |||
| this.$emit("confirm"); | |||
| } else { | |||
| this.$message({ | |||
| type: 'error', | |||
| message: '提交失败!' | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| } | |||
| }).catch(err => { | |||
| console.log(err); | |||
| this.$message({ | |||
| type: 'error', | |||
| message: '提交失败!' | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| }) | |||
| }, | |||
| @@ -1,61 +1,73 @@ | |||
| <template> | |||
| <div class="base-dlg"> | |||
| <BaseDialog :visible.sync="dialogShow" :width="`750px`" :title="type === 'add' ? `新建算力资源应用场景` : '编辑算力资源应用场景'" | |||
| <BaseDialog :visible.sync="dialogShow" :width="`750px`" | |||
| :title="type === 'add' ? $t('resourcesManagement.addResScene') : $t('resourcesManagement.editResScene')" | |||
| @open="open" @opened="opened" @close="close" @closed="closed"> | |||
| <div class="dlg-content"> | |||
| <div class="form"> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>应用场景名称</span> | |||
| <span>{{ $t('resourcesManagement.resSceneName') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.name" placeholder=""></el-input> | |||
| <el-input v-model="dataInfo.SceneName" placeholder=""></el-input> | |||
| </div> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>任务类型</span> | |||
| <span>{{ $t('resourcesManagement.jobType') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.taskType"> | |||
| <el-select v-model="dataInfo.JobType" :disabled="type === 'edit'"> | |||
| <el-option v-for="item in taskTypeList" :key="item.k" :label="item.v" :value="item.k" /> | |||
| </el-select> | |||
| </div> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>是否专属</span> | |||
| <span>{{ $t('resourcesManagement.isExclusive') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.isExclusive" @change="changeIsExclusive"> | |||
| <el-select v-model="dataInfo.IsExclusive" @change="changeIsExclusive"> | |||
| <el-option v-for="item in isExclusiveList" :key="item.k" :label="item.v" :value="item.k" /> | |||
| </el-select> | |||
| </div> | |||
| </div> | |||
| <div class="form-row" v-if="dataInfo.isExclusive === '1'"> | |||
| <div class="form-row" v-if="dataInfo.IsExclusive === '1'"> | |||
| <div class="title required"> | |||
| <span>专属组织</span> | |||
| <span>{{ $t('resourcesManagement.exclusiveOrg') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.exclusiveOrg" placeholder="多个组织名之间用英文分号隔开"></el-input> | |||
| <el-input v-model="dataInfo.ExclusiveOrg" :placeholder="$t('resourcesManagement.exclusiveOrgTips')"> | |||
| </el-input> | |||
| </div> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>资源池队列</span> | |||
| <span>{{ $t('resourcesManagement.computeCluster') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.queue" @change="changeQueue"> | |||
| <el-select v-model="dataInfo.Cluster" @change="changeCluster" :disabled="type === 'edit'"> | |||
| <el-option v-for="item in clusterList" :key="item.k" :label="item.v" :value="item.k" /> | |||
| </el-select> | |||
| </div> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <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>资源规格</span> | |||
| <span>{{ $t('resourcesManagement.resourceSpecification') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.specs" multiple collapse-tags> | |||
| <el-select v-model="dataInfo.SpecIds" multiple collapse-tags class="specSel"> | |||
| <el-option v-for="item in specsList" :key="item.k" :label="item.v" :value="item.k" /> | |||
| </el-select> | |||
| </div> | |||
| @@ -63,8 +75,8 @@ | |||
| <div class="form-row" style="margin-top: 20px"> | |||
| <div class="title"></div> | |||
| <div class="content"> | |||
| <el-button type="primary" class="btn confirm-btn" @click="confirm">确定</el-button> | |||
| <el-button class="btn" @click="cancel">取消</el-button> | |||
| <el-button type="primary" class="btn confirm-btn" @click="confirm">{{ $t('confirm') }}</el-button> | |||
| <el-button class="btn" @click="cancel">{{ $t('cancel') }}</el-button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -74,7 +86,9 @@ | |||
| </template> | |||
| <script> | |||
| import BaseDialog from '~/components/BaseDialog.vue'; | |||
| import { getQueueList } from '~/apis/modules/resources'; | |||
| import { getResQueueCode, getResSpecificationList, addResScene, updateResScene } from '~/apis/modules/resources'; | |||
| import { JOB_TYPE, CLUSTERS, AI_CENTER, ACC_CARD_TYPE, SPECIFICATION_STATUS } from '~/const'; | |||
| import { getListValueWithKey } from '~/utils'; | |||
| export default { | |||
| name: "SceneDialog", | |||
| @@ -91,10 +105,14 @@ export default { | |||
| return { | |||
| dialogShow: false, | |||
| dataInfo: {}, | |||
| taskTypeList: [{ k: '1', v: '调试任务' }, { k: '2', v: '训练任务' }, { k: '3', v: '评测任务' }, { k: '4', v: '推理任务' }], | |||
| isExclusiveList: [{ k: '', v: '否' }, { k: '1', v: '是' }], | |||
| queueList: [{ k: '1', v: '资源池1' }, { k: '2', v: '资源池2' }], | |||
| specsList: [{ k: '1', v: 'spec1' }, { k: '2', v: 'spec2' }, { k: '3', v: 'spec3' }, { k: '4', v: 'spec4' }, { k: '5', v: 'spec5' }, { k: '6', v: 'spec6' }], | |||
| taskTypeList: [...JOB_TYPE], | |||
| clusterList: [...CLUSTERS], | |||
| aiCenterList: [...AI_CENTER], | |||
| accCardTypeList: [...ACC_CARD_TYPE], | |||
| statusList: [...SPECIFICATION_STATUS], | |||
| isExclusiveList: [{ k: '2', v: this.$t('resourcesManagement.commonUse') }, { k: '1', v: this.$t('resourcesManagement.exclusive') }], | |||
| queueList: [], | |||
| specsList: [], | |||
| }; | |||
| }, | |||
| watch: { | |||
| @@ -105,20 +123,77 @@ export default { | |||
| methods: { | |||
| resetDataInfo() { | |||
| this.dataInfo = { | |||
| id: '', | |||
| name: '', | |||
| taskType: '', | |||
| isExclusive: '', | |||
| exclusiveOrg: '', | |||
| queue: '', | |||
| specs: ['2', '3'], | |||
| SceneName: '', | |||
| JobType: '', | |||
| IsExclusive: '2', | |||
| ExclusiveOrg: '', | |||
| Cluster: '', | |||
| QueueId: '', | |||
| SpecIds: [], | |||
| } | |||
| }, | |||
| getQueueList() { | |||
| 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)} - ${getListValueWithKey(this.aiCenterList, item.AiCenterCode)})`, | |||
| }); | |||
| } | |||
| this.queueList.splice(0, Infinity, ...list); | |||
| if (this.queueList.length === 0) { | |||
| this.changeQueue(); | |||
| } | |||
| } | |||
| }).catch(err => { | |||
| console.log(err); | |||
| }); | |||
| }, | |||
| getResSpecificationList() { | |||
| const params = { | |||
| cluster: this.dataInfo.Cluster, | |||
| queue: this.dataInfo.QueueId, | |||
| status: 2, | |||
| page: 1, | |||
| }; | |||
| getResSpecificationList(params).then(res => { | |||
| res = res.data; | |||
| if (res.Code === 0) { | |||
| const list = res.Data.List; | |||
| const data = list.map((item) => { | |||
| const Queue = item.Queue; | |||
| const Spec = item.Spec; | |||
| const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum === 0 ? '0' : Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`; | |||
| 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')}`, | |||
| } | |||
| }); | |||
| this.specsList.splice(0, Infinity, ...data); | |||
| } | |||
| }).catch(err => { | |||
| console.log(err); | |||
| }); | |||
| }, | |||
| changeIsExclusive() { | |||
| this.dataInfo.exclusiveOrg = ''; | |||
| this.dataInfo.ExclusiveOrg = ''; | |||
| }, | |||
| changeCluster() { | |||
| this.dataInfo.QueueId = ''; | |||
| this.dataInfo.SpecIds = []; | |||
| this.queueList.splice(0, Infinity); | |||
| this.specsList.splice(0, Infinity); | |||
| this.getQueueList(); | |||
| }, | |||
| changeQueue() { | |||
| this.dataInfo.SpecIds = []; | |||
| this.specsList.splice(0, Infinity); | |||
| this.getResSpecificationList(); | |||
| }, | |||
| open() { | |||
| this.resetDataInfo(); | |||
| @@ -126,8 +201,12 @@ export default { | |||
| // | |||
| } else if (this.type === 'edit') { | |||
| this.dataInfo = Object.assign(this.dataInfo, { ...this.data }); | |||
| this.queueList.splice(0, Infinity); | |||
| this.specsList.splice(0, Infinity); | |||
| this.getQueueList().then(() => { | |||
| this.getResSpecificationList(); | |||
| }); | |||
| } | |||
| console.log('open', this.type, this.data); | |||
| this.$emit("open"); | |||
| }, | |||
| opened() { | |||
| @@ -141,7 +220,40 @@ export default { | |||
| this.$emit("update:visible", false); | |||
| }, | |||
| confirm() { | |||
| console.log(this.dataInfo); | |||
| if (!this.dataInfo.SceneName || !this.dataInfo.JobType || !this.dataInfo.QueueId || !this.dataInfo.SpecIds.length || (this.dataInfo.IsExclusive === '1' && !this.dataInfo.ExclusiveOrg)) { | |||
| this.$message({ | |||
| type: 'info', | |||
| message: this.$t('pleaseCompleteTheInformationFirst') | |||
| }); | |||
| return; | |||
| } | |||
| const setApi = this.type === 'add' ? addResScene : updateResScene; | |||
| setApi({ | |||
| ...this.dataInfo, | |||
| action: this.type === 'edit' ? 'edit' : undefined, | |||
| IsExclusive: this.dataInfo.IsExclusive === '1', | |||
| }).then(res => { | |||
| res = res.data; | |||
| if (res.Code === 0) { | |||
| this.$message({ | |||
| type: 'success', | |||
| message: this.$t('submittedSuccessfully') | |||
| }); | |||
| this.$emit("confirm"); | |||
| } else { | |||
| this.$message({ | |||
| type: 'error', | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| } | |||
| }).catch(err => { | |||
| console.log(err); | |||
| this.$message({ | |||
| type: 'error', | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| }) | |||
| }, | |||
| cancel() { | |||
| this.dialogShow = false; | |||
| @@ -201,6 +313,24 @@ export default { | |||
| width: 100%; | |||
| } | |||
| } | |||
| .specSel { | |||
| /deep/ .el-tag.el-tag--info { | |||
| max-width: 81%; | |||
| display: flex; | |||
| align-items: center; | |||
| .el-select__tags-text { | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| } | |||
| .el-tag__close { | |||
| flex-shrink: 0; | |||
| right: -5px; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -216,4 +346,13 @@ export default { | |||
| } | |||
| } | |||
| } | |||
| .el-select-dropdown__item { | |||
| padding-left: 26px !important; | |||
| } | |||
| .el-select-dropdown__item.selected::after { | |||
| right: 0; | |||
| left: 6px; | |||
| } | |||
| </style> | |||
| @@ -1,12 +1,13 @@ | |||
| <template> | |||
| <div class="base-dlg"> | |||
| <BaseDialog :visible.sync="dialogShow" :width="`700px`" :title="type === 'add' ? '新增资源规格和单价信息' : '编辑资源规格和单价信息'" | |||
| <BaseDialog :visible.sync="dialogShow" :width="`700px`" | |||
| :title="type === 'add' ? $t('resourcesManagement.addResSpecificationAndPriceInfo') : $t('resourcesManagement.editResSpecificationAndPriceInfo')" | |||
| @open="open" @opened="opened" @close="close" @closed="closed"> | |||
| <div class="dlg-content"> | |||
| <div class="form"> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>资源池(队列)</span> | |||
| <span>{{ $t('resourcesManagement.resQueue') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.QueueId" :disabled="type === 'edit'"> | |||
| @@ -16,16 +17,17 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title"> | |||
| <span>对应资源编码</span> | |||
| <span>{{ $t('resourcesManagement.sourceSpecCode') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.SourceSpecId" placeholder="云脑II需要填写对应的资源编码" :disabled="type === 'edit'"> | |||
| <el-input v-model="dataInfo.SourceSpecId" :placeholder="$t('resourcesManagement.sourceSpecCodeTips')" | |||
| :disabled="type === 'edit'"> | |||
| </el-input> | |||
| </div> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>卡数</span> | |||
| <span>{{ $t('resourcesManagement.accCardsNum') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.AccCardsNum" type="number" placeholder="" :disabled="type === 'edit'"> | |||
| @@ -34,7 +36,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>CPU数</span> | |||
| <span>{{ $t('resourcesManagement.cpuNum') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.CpuCores" type="number" placeholder="" :disabled="type === 'edit'"></el-input> | |||
| @@ -42,7 +44,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>显存(GB)</span> | |||
| <span>{{ $t('resourcesManagement.gpuMem') }}(GB)</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.GPUMemGiB" type="number" placeholder="" :disabled="type === 'edit'"> | |||
| @@ -51,7 +53,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>内存(GB)</span> | |||
| <span>{{ $t('resourcesManagement.mem') }}(GB)</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.MemGiB" type="number" placeholder="" :disabled="type === 'edit'"></el-input> | |||
| @@ -59,7 +61,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>共享内存(GB)</span> | |||
| <span>{{ $t('resourcesManagement.shareMem') }}(GB)</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.ShareMemGiB" type="number" placeholder="" :disabled="type === 'edit'"> | |||
| @@ -68,7 +70,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>单价(积分/时)</span> | |||
| <span>{{ $t('resourcesManagement.unitPrice') }}({{ $t('resourcesManagement.point_hr') }})</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-input v-model="dataInfo.UnitPrice" type="number" placeholder=""></el-input> | |||
| @@ -76,7 +78,7 @@ | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="title required"> | |||
| <span>状态</span> | |||
| <span>{{ $t('status') }}</span> | |||
| </div> | |||
| <div class="content"> | |||
| <el-select v-model="dataInfo.Status" :disabled="type === 'edit'"> | |||
| @@ -87,8 +89,8 @@ | |||
| <div class="form-row" style="margin-top: 20px"> | |||
| <div class="title"></div> | |||
| <div class="content"> | |||
| <el-button type="primary" class="btn confirm-btn" @click="confirm">确定</el-button> | |||
| <el-button class="btn" @click="cancel">取消</el-button> | |||
| <el-button type="primary" class="btn confirm-btn" @click="confirm">{{ $t('confirm') }}</el-button> | |||
| <el-button class="btn" @click="cancel">{{ $t('cancel') }}</el-button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -186,21 +188,21 @@ export default { | |||
| ) { | |||
| this.$message({ | |||
| type: 'info', | |||
| message: '请先完善信息!' | |||
| message: this.$t('pleaseCompleteTheInformationFirst') | |||
| }); | |||
| return; | |||
| } | |||
| if (parseInt(this.dataInfo.AccCardsNum) != Number(this.dataInfo.AccCardsNum)) { | |||
| this.$message({ | |||
| type: 'info', | |||
| message: '请输入正整数的卡数!' | |||
| message: this.$t('pleaseEnterPositiveIntegerCardsTotalNum') | |||
| }); | |||
| return; | |||
| } | |||
| const setApi = this.type === 'add' ? addResSpecification : updateResSpecification; | |||
| setApi({ | |||
| ...this.dataInfo, | |||
| action: this.type === 'edit' ? 'edit' : undefined, | |||
| action: this.type === 'edit' ? 'on-shelf' : undefined, | |||
| AccCardsNum: Number(this.dataInfo.AccCardsNum), | |||
| CpuCores: Number(this.dataInfo.CpuCores), | |||
| MemGiB: Number(this.dataInfo.MemGiB), | |||
| @@ -213,20 +215,20 @@ export default { | |||
| if (res.Code === 0) { | |||
| this.$message({ | |||
| type: 'success', | |||
| message: '提交成功!' | |||
| message: this.$t('submittedSuccessfully') | |||
| }); | |||
| this.$emit("confirm"); | |||
| } else { | |||
| this.$message({ | |||
| type: 'error', | |||
| message: '提交失败!' | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| } | |||
| }).catch(err => { | |||
| console.log(err); | |||
| this.$message({ | |||
| type: 'error', | |||
| message: '提交失败!' | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| }) | |||
| }, | |||
| @@ -1,6 +1,6 @@ | |||
| <template> | |||
| <div> | |||
| <div class="title"><span>资源池(队列)</span></div> | |||
| <div class="title"><span>{{ $t('resourcesManagement.resQueue') }}</span></div> | |||
| <div class="tools-bar"> | |||
| <div> | |||
| <el-select class="select" size="medium" v-model="selCluster" @change="selectChange"> | |||
| @@ -17,37 +17,48 @@ | |||
| </el-select> | |||
| </div> | |||
| <div> | |||
| <el-button size="medium" icon="el-icon-refresh" @click="syncComputerNetwork">同步智算网络</el-button> | |||
| <el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')">新增资源池</el-button> | |||
| <el-button size="medium" icon="el-icon-refresh" @click="syncComputerNetwork"> | |||
| {{ $t('resourcesManagement.syncAiNetwork') }}</el-button> | |||
| <el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')"> | |||
| {{ $t('resourcesManagement.addResQueueBtn') }}</el-button> | |||
| </div> | |||
| </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="80"></el-table-column> | |||
| <el-table-column prop="QueueCode" label="资源池(队列)名称" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="ClusterName" label="所属集群" align="center" header-align="center"> | |||
| <el-table-column prop="QueueCode" :label="$t('resourcesManagement.resQueueName')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="ClusterName" :label="$t('resourcesManagement.whichCluster')" align="center" | |||
| header-align="center"> | |||
| <template slot-scope="scope"> | |||
| <span :title="scope.row.Cluster">{{ scope.row.ClusterName }}</span> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column prop="AiCenterCode" label="智算中心ID" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="AiCenterName" label="智算中心" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="ComputeResourceName" label="计算资源" align="center" header-align="center"> | |||
| <el-table-column prop="AiCenterCode" :label="$t('resourcesManagement.aiCenterID')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="AiCenterName" :label="$t('resourcesManagement.aiCenter')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="ComputeResourceName" :label="$t('resourcesManagement.computeResource')" align="center" | |||
| header-align="center"> | |||
| </el-table-column> | |||
| <el-table-column prop="AccCardTypeName" label="卡类型" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="CardsTotalNum" label="卡数 " align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="UpdatedTimeStr" label="最后更新时间" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="Remark" label="备注" align="left" header-align="center" min-width="160"> | |||
| <el-table-column prop="AccCardTypeName" :label="$t('resourcesManagement.accCardType')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="CardsTotalNum" :label="$t('resourcesManagement.cardsTotalNum')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="UpdatedTimeStr" :label="$t('resourcesManagement.lastUpdateTime')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="Remark" :label="$t('resourcesManagement.remark')" align="left" header-align="center" | |||
| min-width="160"> | |||
| </el-table-column> | |||
| <el-table-column label="操作" align="center" header-align="center" width="80"> | |||
| <el-table-column :label="$t('operation')" align="center" header-align="center" width="80"> | |||
| <template slot-scope="scope"> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">修改</span> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">{{ $t('edit') }}</span> | |||
| </template> | |||
| </el-table-column> | |||
| <template slot="empty"> | |||
| <span style="font-size: 12px">{{ | |||
| loading ? '加载中...' : '暂无数据' | |||
| loading ? $t('loading') : $t('noData') | |||
| }}</span> | |||
| </template> | |||
| </el-table> | |||
| @@ -79,13 +90,13 @@ export default { | |||
| data() { | |||
| return { | |||
| selCluster: '', | |||
| clusterList: [{ k: '', v: '全部集群' }, ...CLUSTERS], | |||
| clusterList: [{ k: '', v: this.$t('resourcesManagement.allCluster') }, ...CLUSTERS], | |||
| selComputingCenter: '', | |||
| computingCenterList: [{ k: '', v: '全部智算中心' }, ...AI_CENTER], | |||
| computingCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }, ...AI_CENTER], | |||
| selComputingType: '', | |||
| computingTypeList: [{ k: '', v: '全部计算资源' }, ...COMPUTER_RESOURCES], | |||
| computingTypeList: [{ k: '', v: this.$t('resourcesManagement.allComputeResource') }, ...COMPUTER_RESOURCES], | |||
| selCardType: '', | |||
| cardTypeList: [{ k: '', v: '全部卡类型' }, ...ACC_CARD_TYPE], | |||
| cardTypeList: [{ k: '', v: this.$t('resourcesManagement.allAccCardType') }, ...ACC_CARD_TYPE], | |||
| syncLoading: false, | |||
| loading: false, | |||
| tableData: [], | |||
| @@ -1,6 +1,6 @@ | |||
| <template> | |||
| <div> | |||
| <div class="title"><span>算力资源应用场景管理</span></div> | |||
| <div class="title"><span>{{ $t('resourcesManagement.resSceneManagement') }}</span></div> | |||
| <div class="tools-bar"> | |||
| <div> | |||
| <el-select class="select" size="medium" v-model="selTaskType" @change="selectChange"> | |||
| @@ -17,32 +17,52 @@ | |||
| </el-select> | |||
| </div> | |||
| <div> | |||
| <el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')">新增应用场景</el-button> | |||
| <el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')"> | |||
| {{ $t('resourcesManagement.addResSceneBtn') }}</el-button> | |||
| </div> | |||
| </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="100"></el-table-column> | |||
| <el-table-column prop="name" label="应用场景名称" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="taskType" label="任务类型" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="isExclusive" label="是否专属" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="exclusiveOrg" label="专属组织" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="queue" label="资源池(队列)" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="specs" label="资源规格" align="left" header-align="center"> | |||
| <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" | |||
| header-align="center" width="120"> | |||
| </el-table-column> | |||
| <el-table-column prop="IsExclusiveStr" :label="$t('resourcesManagement.isExclusive')" align="center" | |||
| header-align="center" width="120"> | |||
| <template slot-scope="scope"> | |||
| <span :style="{ color: scope.row.IsExclusive ? 'red' : '' }">{{ scope.row.IsExclusiveStr }}</span> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column prop="ExclusiveOrg" :label="$t('resourcesManagement.exclusiveOrg')" align="center" | |||
| header-align="center"> | |||
| <template slot-scope="scope"> | |||
| {{ scope.row.specs }} | |||
| <span>{{ scope.row.IsExclusive ? scope.row.ExclusiveOrg : '--' }}</span> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column label="操作" align="center" header-align="center" width="100"> | |||
| <el-table-column prop="AiCenterStr" :label="$t('resourcesManagement.aiCenter')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="QueueStr" :label="$t('resourcesManagement.resQueue')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="SpecsList" :label="$t('resourcesManagement.resourceSpecification')" align="left" | |||
| header-align="center" min-width="180"> | |||
| <template slot-scope="scope"> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">修改</span> | |||
| <span class="op-btn" style="color:red" @click="deleteRow(scope.row)">删除</span> | |||
| <div v-for="item in scope.row.SpecsList" :key="item.k"> | |||
| <span>{{ item.v }}</span> | |||
| </div> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column :label="$t('operation')" align="center" header-align="center" width="100"> | |||
| <template slot-scope="scope"> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">{{ $t('edit') }}</span> | |||
| <span class="op-btn" style="color:red" @click="deleteRow(scope.row)">{{ $t('delete') }}</span> | |||
| </template> | |||
| </el-table-column> | |||
| <template slot="empty"> | |||
| <span style="font-size: 12px">{{ | |||
| loading ? '加载中...' : '暂无数据' | |||
| loading ? $t('loading') : $t('noData') | |||
| }}</span> | |||
| </template> | |||
| </el-table> | |||
| @@ -65,8 +85,8 @@ | |||
| <script> | |||
| import SceneDialog from '../components/SceneDialog.vue'; | |||
| import { getQueueList, getResQueueCode } from '~/apis/modules/resources'; | |||
| import { CLUSTERS, AI_CENTER, ACC_CARD_TYPE } from '~/const'; | |||
| import { getQueueList, getResQueueCode, getResSceneList, updateResScene } from '~/apis/modules/resources'; | |||
| import { JOB_TYPE, CLUSTERS, AI_CENTER, ACC_CARD_TYPE } from '~/const'; | |||
| import { getListValueWithKey } from '~/utils'; | |||
| import { formatDate } from 'element-ui/lib/utils/date-util'; | |||
| @@ -74,14 +94,15 @@ export default { | |||
| data() { | |||
| return { | |||
| selTaskType: '', | |||
| taskTypeList: [{ k: '', v: '全部任务类型' }, { k: '1', v: '调试任务' }, { k: '2', v: '训练任务' }, { k: '3', v: '评测任务' }, { k: '4', v: '推理任务' }], | |||
| taskTypeList: [{ k: '', v: this.$t('resourcesManagement.allJobType') }, ...JOB_TYPE], | |||
| selIsExclusive: '', | |||
| isExclusiveList: [{ k: '', v: '全部专属和通用' }, { k: '1', v: '专属' }, { k: '2', v: '通用' }], | |||
| 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: '全部资源池队列' }], | |||
| queueList: [{ k: '', v: this.$t('resourcesManagement.allResQueue') }], | |||
| clusterList: [...CLUSTERS], | |||
| selAiCenter: '', | |||
| aiCenterList: [{ k: '', v: '全部智算中心' }, ...AI_CENTER], | |||
| aiCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }, ...AI_CENTER], | |||
| accCardTypeList: [...ACC_CARD_TYPE], | |||
| loading: false, | |||
| tableData: [], | |||
| pageInfo: { | |||
| @@ -118,31 +139,49 @@ export default { | |||
| }, | |||
| getTableData() { | |||
| const params = { | |||
| taskType: this.selTaskType, | |||
| isExclusive: this.selIsExclusive, | |||
| jobType: this.selTaskType, | |||
| IsExclusive: this.selIsExclusive, | |||
| queue: this.selQueue, | |||
| center: this.selAiCenter, | |||
| page: this.pageInfo.curpage, | |||
| pagesize: this.pageInfo.pageSize, | |||
| }; | |||
| console.log('params', params); | |||
| this.loading = true; | |||
| getQueueList(params).then(res => { | |||
| getResSceneList(params).then(res => { | |||
| this.loading = false; | |||
| // const data = res.data. | |||
| const data = new Array(20).fill(0).map((_, index) => { | |||
| return { | |||
| index: index, | |||
| id: `id-${index}-${Math.random().toFixed(2)}`, | |||
| name: `name-${index}-${Math.random().toFixed(2)}`, | |||
| taskType: `taskType-${index}-${Math.random().toFixed(2)}`, | |||
| isExclusive: `isExclusive-${index}-${Math.random().toFixed(2)}`, | |||
| exclusiveOrg: `exclusiveOrg-${index}-${Math.random().toFixed(2)}`, | |||
| queue: `queue-${index}-${Math.random().toFixed(2)}`, | |||
| specs: `spec-${index}-${Math.random().toFixed(2)}`, | |||
| }; | |||
| }); | |||
| this.tableData = data; | |||
| this.pageInfo.total = 99; | |||
| res = res.data; | |||
| if (res.Code === 0) { | |||
| const list = res.Data.List; | |||
| const data = list.map((item) => { | |||
| const Specs = item.Specs; | |||
| const specsList = []; | |||
| for (let i = 0, iLen = Specs.length; i < iLen; i++) { | |||
| const Spec = Specs[i]; | |||
| const NGPU = `${item.ComputeResource}:${Spec.AccCardsNum === 0 ? '0' : Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, item.AccCardType)}`; | |||
| 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')}`, | |||
| }) | |||
| } | |||
| 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, | |||
| AiCenterCode: item.AiCenterCode, | |||
| AiCenterStr: getListValueWithKey(this.aiCenterList, item.AiCenterCode), | |||
| Cluster: item.Cluster, | |||
| QueueId: item.QueueId, | |||
| QueueStr: item.QueueCode ? `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${getListValueWithKey(this.aiCenterList, item.AiCenterCode)})` : '--', | |||
| SpecsList: specsList, | |||
| } | |||
| }); | |||
| this.tableData = data; | |||
| this.pageInfo.total = res.Data.TotalSize; | |||
| } | |||
| }).catch(err => { | |||
| console.log(err); | |||
| this.loading = false; | |||
| @@ -157,26 +196,49 @@ export default { | |||
| this.getTableData(); | |||
| }, | |||
| deleteRow(row) { | |||
| this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', { | |||
| confirmButtonText: '确定', | |||
| cancelButtonText: '取消', | |||
| this.$confirm(this.$t('resourcesManagement.resSceneDeleteConfirm'), this.$t('tips'), { | |||
| confirmButtonText: this.$t('confirm'), | |||
| cancelButtonText: this.$t('cancel'), | |||
| type: 'warning', | |||
| lockScroll: false, | |||
| }).then(() => { | |||
| this.$message({ | |||
| type: 'success', | |||
| message: '删除成功!' | |||
| }); | |||
| }).catch(() => { | |||
| this.$message({ | |||
| type: 'info', | |||
| message: '已取消删除' | |||
| updateResScene({ | |||
| action: 'delete', | |||
| ID: row.ID, | |||
| }).then(res => { | |||
| res = res.data; | |||
| if (res.Code === 0) { | |||
| this.$message({ | |||
| type: 'success', | |||
| message: this.$t('submittedSuccessfully') | |||
| }); | |||
| this.getTableData(); | |||
| } else { | |||
| this.$message({ | |||
| type: 'error', | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| } | |||
| }).catch(err => { | |||
| this.$message({ | |||
| type: 'error', | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| }); | |||
| }); | |||
| }).catch(() => { }); | |||
| }, | |||
| showDialog(type, data) { | |||
| this.sceneDialogType = type; | |||
| this.sceneDialogData = data ? { ...data } : {}; | |||
| this.sceneDialogData = data ? { | |||
| ID: data.ID, | |||
| SceneName: data.SceneName, | |||
| JobType: data.JobType, | |||
| IsExclusive: data.IsExclusive ? '1' : '2', | |||
| ExclusiveOrg: data.ExclusiveOrg, | |||
| Cluster: data.Cluster, | |||
| QueueId: data.QueueId, | |||
| SpecIds: data.SpecsList.map((item) => item.k), | |||
| } : {}; | |||
| this.sceneDialogShow = true; | |||
| }, | |||
| sceneDialogConfirm() { | |||
| @@ -1,6 +1,6 @@ | |||
| <template> | |||
| <div> | |||
| <div class="title"><span>资源规格单价管理</span></div> | |||
| <div class="title"><span>{{ $t('resourcesManagement.resSpecificationAndPriceManagement') }}</span></div> | |||
| <div class="tools-bar"> | |||
| <div> | |||
| <el-select class="select" size="medium" v-model="selQueue" @change="selectChange"> | |||
| @@ -12,55 +12,74 @@ | |||
| </div> | |||
| <div> | |||
| <!-- syncComputerNetwork --> | |||
| <el-button size="medium" icon="el-icon-refresh" @click="confirmOperate">同步智算网络</el-button> | |||
| <el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')">新增资源规格</el-button> | |||
| <el-button size="medium" icon="el-icon-refresh" @click="confirmOperate"> | |||
| {{ $t('resourcesManagement.syncAiNetwork') }}</el-button> | |||
| <el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')"> | |||
| {{ $t('resourcesManagement.addResSpecificationBtn') }}</el-button> | |||
| </div> | |||
| </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-column prop="SpecStr" label="资源规格" align="left" header-align="center" min-width="160"> | |||
| <el-table-column prop="SpecStr" :label="$t('resourcesManagement.resourceSpecification')" align="left" | |||
| header-align="center" min-width="160"> | |||
| </el-table-column> | |||
| <el-table-column prop="QueueInfo" label="资源池(队列)" align="center" header-align="center" min-width="100"> | |||
| <el-table-column prop="QueueInfo" :label="$t('resourcesManagement.resQueue')" align="center" | |||
| header-align="center" min-width="100"> | |||
| </el-table-column> | |||
| <el-table-column prop="SourceSpecId" label="智算网络资源规格ID" align="center" header-align="center"> | |||
| <el-table-column prop="SourceSpecId" :label="$t('resourcesManagement.sourceSpecId')" align="center" | |||
| header-align="center"> | |||
| </el-table-column> | |||
| <el-table-column prop="AccCardsNum" label="卡数 " align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="CpuCores" label="CPU " align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="GPUMemGiB" label="显存(GB)" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="MemGiB" label="内存(GB) " align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="ShareMemGiB" label="共享内存(GB)" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="UpdatedTimeStr" label="最后更新时间" align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="UnitPrice" label="单价(积分/时)" align="center" header-align="center"> | |||
| <el-table-column prop="AccCardsNum" :label="$t('resourcesManagement.accCardsNum')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="CpuCores" :label="$t('resourcesManagement.cpuNum') " align="center" header-align="center"></el-table-column> | |||
| <el-table-column prop="GPUMemGiB" :label="`${$t('resourcesManagement.gpuMem')}(GB)`" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="MemGiB" :label="`${$t('resourcesManagement.mem')}(GB)`" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="ShareMemGiB" :label="`${$t('resourcesManagement.shareMem')}(GB)`" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="UpdatedTimeStr" :label="$t('resourcesManagement.lastUpdateTime')" align="center" | |||
| header-align="center"></el-table-column> | |||
| <el-table-column prop="UnitPrice" | |||
| :label="`${$t('resourcesManagement.unitPrice')}(${$t('resourcesManagement.point_hr')})`" align="center" | |||
| header-align="center"> | |||
| <template slot-scope="scope"> | |||
| <span style="font-weight:600;font-size:14px;">{{ scope.row.UnitPrice }}</span> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column prop="StatusStr" label="状态" align="center" header-align="center" width="100"> | |||
| <el-table-column prop="StatusStr" :label="$t('resourcesManagement.status')" align="center" | |||
| header-align="center" width="100"> | |||
| <template slot-scope="scope"> | |||
| <span :style="{ color: scope.row.Status == '2' ? 'rgb(82, 196, 26)' : 'rgb(245, 34, 45)' }">{{ | |||
| scope.row.StatusStr | |||
| }}</span> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column label="操作" align="center" header-align="center" width="100"> | |||
| <el-table-column :label="$t('operation')" align="center" header-align="center" width="100"> | |||
| <template slot-scope="scope"> | |||
| <span v-if="scope.row.Status == '1'"> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">定价上架</span> | |||
| <span v-if="scope.row.Status == '1' && !scope.row.UnitPrice"> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">{{ | |||
| $t('resourcesManagement.toSetPriceAndOnShelf') | |||
| }}</span> | |||
| </span> | |||
| <span v-if="scope.row.Status == '2'"> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">修改</span> | |||
| <span class="op-btn" @click="onOrOffShelf('off-shelf', scope.row)">下架</span> | |||
| <span class="op-btn" @click="showDialog('edit', scope.row)">{{ $t('edit') }}</span> | |||
| <span class="op-btn" @click="onOrOffShelf('off-shelf', scope.row)">{{ | |||
| $t('resourcesManagement.toOffShelf') | |||
| }}</span> | |||
| </span> | |||
| <span v-if="scope.row.Status == '3'"> | |||
| <span class="op-btn" @click="onOrOffShelf('on-shelf', scope.row)">上架</span> | |||
| <span v-if="scope.row.Status == '3' || scope.row.Status == '1' && scope.row.UnitPrice"> | |||
| <span class="op-btn" @click="onOrOffShelf('on-shelf', scope.row)">{{ | |||
| $t('resourcesManagement.toOnShelf') | |||
| }}</span> | |||
| </span> | |||
| </template> | |||
| </el-table-column> | |||
| <template slot="empty"> | |||
| <span style="font-size: 12px">{{ | |||
| loading ? '加载中...' : '暂无数据' | |||
| loading ? $t('loading') : $t('noData') | |||
| }}</span> | |||
| </template> | |||
| </el-table> | |||
| @@ -92,9 +111,9 @@ export default { | |||
| data() { | |||
| return { | |||
| selQueue: '', | |||
| queueList: [{ k: '', v: '全部资源池' }], | |||
| queueList: [{ k: '', v: this.$t('resourcesManagement.allResQueue') }], | |||
| selStatus: '', | |||
| statusList: [{ k: '', v: '全部状态' }, ...SPECIFICATION_STATUS], | |||
| statusList: [{ k: '', v: this.$t('resourcesManagement.allStatus') }, ...SPECIFICATION_STATUS], | |||
| clusterList: [...CLUSTERS], | |||
| aiCenterList: [...AI_CENTER], | |||
| accCardTypeList: [...ACC_CARD_TYPE], | |||
| @@ -152,7 +171,7 @@ export default { | |||
| const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum === 0 ? '0' : Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`; | |||
| return { | |||
| ...Spec, | |||
| SpecStr: `${NGPU}, CPU:${Spec.CpuCores}, 显存:${Spec.GPUMemGiB}GB, 内存:${Spec.MemGiB}GB, 共享内存:${Spec.ShareMemGiB}GB`, | |||
| 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`, | |||
| QueueId: Queue.ID, | |||
| QueueInfo: `${Queue.QueueCode}(${getListValueWithKey(this.clusterList, Queue.Cluster)} - ${getListValueWithKey(this.aiCenterList, Queue.AiCenterCode)})`, | |||
| UpdatedTimeStr: formatDate(new Date(Spec.UpdatedTime * 1000), 'yyyy-MM-dd HH:mm:ss'), | |||
| @@ -189,9 +208,9 @@ export default { | |||
| this.getTableData(); | |||
| }, | |||
| onOrOffShelf(type, data) { | |||
| this.$confirm(type === 'on-shelf' ? '请确认是否上架该规格?' : '请确认是否下架该规格?', '提示', { | |||
| confirmButtonText: '确定', | |||
| cancelButtonText: '取消', | |||
| this.$confirm(type === 'on-shelf' ? this.$t('resourcesManagement.onShelfConfirm') : this.$t('resourcesManagement.offShelfConfirm'), this.$t('tips'), { | |||
| confirmButtonText: this.$t('confirm'), | |||
| cancelButtonText: this.$t('cancel'), | |||
| type: 'warning', | |||
| lockScroll: false, | |||
| }).then(() => { | |||
| @@ -203,20 +222,20 @@ export default { | |||
| if (res.Code === 0) { | |||
| this.$message({ | |||
| type: 'success', | |||
| message: '操作成功!' | |||
| message: this.$t('submittedSuccessfully') | |||
| }); | |||
| this.getTableData(); | |||
| } else { | |||
| this.$message({ | |||
| type: 'error', | |||
| message: '操作失败!' | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| } | |||
| }).catch(err => { | |||
| console.log(err); | |||
| this.$message({ | |||
| type: 'error', | |||
| message: '操作失败!' | |||
| message: this.$t('submittedFailed') | |||
| }); | |||
| }); | |||
| }).catch(() => { }); | |||