Browse Source

Merge remote-tracking branch 'origin/res-manage' into res-manage

pull/2765/head
chenyifan01 2 years ago
parent
commit
461ebb8efe
10 changed files with 182 additions and 59 deletions
  1. +30
    -0
      web_src/vuepages/apis/modules/resources.js
  2. +3
    -3
      web_src/vuepages/const/index.js
  3. +1
    -1
      web_src/vuepages/langs/config/en-US.js
  4. +1
    -1
      web_src/vuepages/langs/config/zh-CN.js
  5. +2
    -2
      web_src/vuepages/pages/resources/components/QueueDialog.vue
  6. +5
    -4
      web_src/vuepages/pages/resources/components/SceneDialog.vue
  7. +28
    -8
      web_src/vuepages/pages/resources/components/SpecificationDialog.vue
  8. +52
    -6
      web_src/vuepages/pages/resources/queue/index.vue
  9. +22
    -4
      web_src/vuepages/pages/resources/scene/index.vue
  10. +38
    -30
      web_src/vuepages/pages/resources/specification/index.vue

+ 30
- 0
web_src/vuepages/apis/modules/resources.js View File

@@ -1,5 +1,15 @@
import service from '../service';

// 查询智算列表
export const getAiCenterList = () => {
return service({
url: '/admin/resources/queue/centers',
method: 'get',
params: {},
data: {},
});
}

// 查询资源队列列表
// page 当前页数,从1开始
// cluster 所属集群 :OpenI 启智集群,C2Net 智算集群
@@ -44,6 +54,16 @@ export const getResQueueCode = (params) => { // cluster
});
}

// 同步智算网络资源池(队列)
export const syncResQueue = () => {
return service({
url: '/admin/resources/queue/grampus/sync',
method: 'post',
params: {},
data: {},
});
}

// 新增资源规格
export const addResSpecification = (data) => {
return service({
@@ -80,6 +100,16 @@ export const getResSpecificationList = (params) => {
});
}

// 同步智算网络资源池(队列)
export const syncResSpecification = () => {
return service({
url: '/admin/resources/specification/grampus/sync',
method: 'post',
params: {},
data: {},
});
}

// 新增资源应用场景
/*
{


+ 3
- 3
web_src/vuepages/const/index.js View File

@@ -11,6 +11,6 @@ export const JOB_TYPE = [{ k: 'DEBUG', v: i18n.t('debugTask') }, { k: 'TRAIN', 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: i18n.t('resourcesManagement.toOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }];
export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'MLU', v: 'MLU' }];
export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'RTX3080', v: 'RTX3080' }];
export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }];

+ 1
- 1
web_src/vuepages/langs/config/en-US.js View File

@@ -85,7 +85,7 @@ const en = {
pclcci: 'PCL Cloud Computer Institute',
hefeiCenter: 'HeFei AI Center',
xuchangCenter: 'XuChang AI Center',
toOnShelf: 'To Be On Shelf',
willOnShelf: 'To Be On Shelf',
onShelf: 'On Shelf',
offShelf: 'Off Shelf',
toOnShelf: 'To On Shelf',


+ 1
- 1
web_src/vuepages/langs/config/zh-CN.js View File

@@ -85,7 +85,7 @@ const zh = {
pclcci: '鹏城云计算所',
hefeiCenter: '合肥类脑类脑智能开放平台',
xuchangCenter: '中原人工智能计算中心',
toOnShelf: '待上架',
willOnShelf: '待上架',
onShelf: '已上架',
offShelf: '已下架',
toOnShelf: '上架',


+ 2
- 2
web_src/vuepages/pages/resources/components/QueueDialog.vue View File

@@ -100,8 +100,8 @@ export default {
data() {
return {
dialogShow: false,
clusterList: [...CLUSTERS],
computingCenterList: [...AI_CENTER],
clusterList: [CLUSTERS[0]],
computingCenterList: [AI_CENTER[0], AI_CENTER[1]],
computingTypeList: [...COMPUTER_RESOURCES],
cardTypeList: [...ACC_CARD_TYPE],



+ 5
- 4
web_src/vuepages/pages/resources/components/SceneDialog.vue View File

@@ -53,7 +53,7 @@
</div>
</div>
<div class="form-row">
<div class="title required">
<div class="title">
<span>{{ $t('resourcesManagement.resQueue') }}</span>
</div>
<div class="content">
@@ -107,7 +107,6 @@ export default {
dataInfo: {},
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') }],
@@ -131,6 +130,8 @@ export default {
QueueId: '',
SpecIds: [],
}
this.queueList = [];
this.specsList = [];
},
getQueueList() {
return getResQueueCode({ cluster: this.dataInfo.Cluster }).then(res => {
@@ -142,7 +143,7 @@ export default {
const item = data[i];
list.push({
k: item.ID,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${getListValueWithKey(this.aiCenterList, item.AiCenterCode)})`,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${item.AiCenterName})`,
});
}
this.queueList.splice(0, Infinity, ...list);
@@ -220,7 +221,7 @@ export default {
this.$emit("update:visible", false);
},
confirm() {
if (!this.dataInfo.SceneName || !this.dataInfo.JobType || !this.dataInfo.QueueId || !this.dataInfo.SpecIds.length || (this.dataInfo.IsExclusive === '1' && !this.dataInfo.ExclusiveOrg)) {
if (!this.dataInfo.SceneName || !this.dataInfo.JobType || !this.dataInfo.SpecIds.length || (this.dataInfo.IsExclusive === '1' && !this.dataInfo.ExclusiveOrg)) {
this.$message({
type: 'info',
message: this.$t('pleaseCompleteTheInformationFirst')


+ 28
- 8
web_src/vuepages/pages/resources/components/SpecificationDialog.vue View File

@@ -100,8 +100,8 @@
</template>
<script>
import BaseDialog from '~/components/BaseDialog.vue';
import { getResQueueCode, addResSpecification, updateResSpecification } from '~/apis/modules/resources';
import { SPECIFICATION_STATUS, CLUSTERS, AI_CENTER } from '~/const';
import { getResQueueCode, addResSpecification, updateResSpecification, getAiCenterList } from '~/apis/modules/resources';
import { SPECIFICATION_STATUS, CLUSTERS } from '~/const';
import { getListValueWithKey } from '~/utils';

export default {
@@ -110,6 +110,7 @@ export default {
visible: { type: Boolean, default: false },
title: { type: String, default: '' },
type: { type: String, defalut: 'add' },
editOr: { type: Boolean, defalut: false },
data: { type: Object, default: () => ({}) },
},
components: {
@@ -122,7 +123,7 @@ export default {
queueList: [],
statusList: [...SPECIFICATION_STATUS],
clusterList: [...CLUSTERS],
aiCenterList: [...AI_CENTER],
aiCenterList: [],
};
},
watch: {
@@ -143,8 +144,25 @@ export default {
Status: '1',
}
},
getAiCenterList() {
getAiCenterList().then(res => {
res = res.data;
if (res.Code === 0) {
const list = res.Data;
const data = list.map(item => {
return {
k: item.AiCenterCode,
v: item.AiCenterName
};
});
this.aiCenterList.splice(0, Infinity, ...data);
}
}).catch(err => {
console.log(err);
});
},
getQueueList() {
getResQueueCode().then(res => {
getResQueueCode({ cluster: this.type === 'add' ? 'OpenI' : undefined }).then(res => {
res = res.data;
if (res.Code === 0) {
const data = res.Data;
@@ -153,7 +171,7 @@ export default {
const item = data[i];
list.push({
k: item.ID,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${getListValueWithKey(this.aiCenterList, item.AiCenterCode)})`,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${item.AiCenterName})`,
});
}
this.queueList.splice(0, Infinity, ...list);
@@ -162,9 +180,11 @@ export default {
console.log(err);
});
},

open() {
this.resetDataInfo();
this.getQueueList();
this.getAiCenterList();
if (this.type === 'add') {
//
} else if (this.type === 'edit') {
@@ -183,8 +203,8 @@ export default {
this.$emit("update:visible", false);
},
confirm() {
if (!this.dataInfo.QueueId || !this.dataInfo.AccCardsNum || !this.dataInfo.CpuCores || !this.dataInfo.MemGiB || !this.dataInfo.ShareMemGiB || !this.dataInfo.GPUMemGiB
|| !this.dataInfo.UnitPrice || !this.dataInfo.Status
if (this.dataInfo.AccCardsNum === '' || this.dataInfo.CpuCores === '' || this.dataInfo.MemGiB === '' || this.dataInfo.ShareMemGiB === '' || this.dataInfo.GPUMemGiB === ''
|| this.dataInfo.UnitPrice === '' || !this.dataInfo.Status
) {
this.$message({
type: 'info',
@@ -202,7 +222,7 @@ export default {
const setApi = this.type === 'add' ? addResSpecification : updateResSpecification;
setApi({
...this.dataInfo,
action: this.type === 'edit' ? 'on-shelf' : undefined,
action: this.editOr ? 'edit' : this.type === 'edit' ? 'on-shelf' : undefined,
AccCardsNum: Number(this.dataInfo.AccCardsNum),
CpuCores: Number(this.dataInfo.CpuCores),
MemGiB: Number(this.dataInfo.MemGiB),


+ 52
- 6
web_src/vuepages/pages/resources/queue/index.vue View File

@@ -17,7 +17,7 @@
</el-select>
</div>
<div>
<el-button size="medium" icon="el-icon-refresh" @click="syncComputerNetwork">
<el-button size="medium" icon="el-icon-refresh" @click="syncComputerNetwork" v-loading="syncLoading">
{{ $t('resourcesManagement.syncAiNetwork') }}</el-button>
<el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')">
{{ $t('resourcesManagement.addResQueueBtn') }}</el-button>
@@ -56,6 +56,9 @@
<span v-if="scope.row.Cluster !== 'C2Net'" class="op-btn" @click="showDialog('edit', scope.row)">{{
$t('edit')
}}</span>
<span v-else class="op-btn" style="color:rgb(187, 187, 187);cursor:not-allowed">{{
$t('edit')
}}</span>
</template>
</el-table-column>
<template slot="empty">
@@ -83,8 +86,8 @@

<script>
import QueueDialog from '../components/QueueDialog.vue';
import { getResQueueList, addResQueue, updateResQueue } from '~/apis/modules/resources';
import { CLUSTERS, AI_CENTER, COMPUTER_RESOURCES, ACC_CARD_TYPE } from '~/const';
import { getAiCenterList, getResQueueList, addResQueue, updateResQueue, syncResQueue } from '~/apis/modules/resources';
import { CLUSTERS, COMPUTER_RESOURCES, ACC_CARD_TYPE } from '~/const';
import { getListValueWithKey } from '~/utils';
import { formatDate } from 'element-ui/lib/utils/date-util';

@@ -94,7 +97,7 @@ export default {
selCluster: '',
clusterList: [{ k: '', v: this.$t('resourcesManagement.allCluster') }, ...CLUSTERS],
selComputingCenter: '',
computingCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }, ...AI_CENTER],
computingCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }],
selComputingType: '',
computingTypeList: [{ k: '', v: this.$t('resourcesManagement.allComputeResource') }, ...COMPUTER_RESOURCES],
selCardType: '',
@@ -115,6 +118,23 @@ export default {
},
components: { QueueDialog },
methods: {
getAiCenterList() {
getAiCenterList().then(res => {
res = res.data;
if (res.Code === 0) {
const list = res.Data;
const data = list.map(item => {
return {
k: item.AiCenterCode,
v: item.AiCenterName
};
});
this.computingCenterList.splice(1, Infinity, ...data);
}
}).catch(err => {
console.log(err);
});
},
getTableData() {
const params = {
cluster: this.selCluster,
@@ -133,8 +153,8 @@ export default {
const data = list.map((item) => {
return {
...item,
QueueCode: item.QueueCode || '--',
ClusterName: getListValueWithKey(this.clusterList, item.Cluster),
AiCenterName: getListValueWithKey(this.computingCenterList, item.AiCenterCode),
ComputeResourceName: getListValueWithKey(this.computingTypeList, item.ComputeResource),
AccCardTypeName: getListValueWithKey(this.cardTypeList, item.AccCardType),
UpdatedTimeStr: formatDate(new Date(item.UpdatedTime * 1000), 'yyyy-MM-dd HH:mm:ss'),
@@ -149,7 +169,31 @@ export default {
});
},
syncComputerNetwork() {
//
this.syncLoading = true;
syncResQueue().then(res => {
this.syncLoading = false;
res = res.data;
if (res.Code === 0) {
this.$message({
type: 'success',
message: this.$t('submittedSuccessfully')
});
this.getAiCenterList();
this.getTableData();
} else {
this.$message({
type: 'error',
message: this.$t('submittedFailed')
});
}
}).catch(err => {
console.log(err);
this.syncLoading = false;
this.$message({
type: 'error',
message: this.$t('submittedFailed')
});
});
},
selectChange() {
this.pageInfo.curpage = 1;
@@ -166,10 +210,12 @@ export default {
},
queueDialogConfirm() {
this.queueDialogShow = false;
this.getAiCenterList();
this.getTableData();
}
},
mounted() {
this.getAiCenterList();
this.getTableData();
},
beforeDestroy() {


+ 22
- 4
web_src/vuepages/pages/resources/scene/index.vue View File

@@ -85,8 +85,8 @@

<script>
import SceneDialog from '../components/SceneDialog.vue';
import { getQueueList, getResQueueCode, getResSceneList, updateResScene } from '~/apis/modules/resources';
import { JOB_TYPE, CLUSTERS, AI_CENTER, ACC_CARD_TYPE } from '~/const';
import { getQueueList, getResQueueCode, getResSceneList, updateResScene, getAiCenterList } from '~/apis/modules/resources';
import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE } from '~/const';
import { getListValueWithKey } from '~/utils';
import { formatDate } from 'element-ui/lib/utils/date-util';

@@ -101,7 +101,7 @@ export default {
queueList: [{ k: '', v: this.$t('resourcesManagement.allResQueue') }],
clusterList: [...CLUSTERS],
selAiCenter: '',
aiCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }, ...AI_CENTER],
aiCenterList: [{ k: '', v: this.$t('resourcesManagement.allAiCenter') }],
accCardTypeList: [...ACC_CARD_TYPE],
loading: false,
tableData: [],
@@ -118,6 +118,23 @@ export default {
},
components: { SceneDialog },
methods: {
getAiCenterList() {
getAiCenterList().then(res => {
res = res.data;
if (res.Code === 0) {
const list = res.Data;
const data = list.map(item => {
return {
k: item.AiCenterCode,
v: item.AiCenterName
};
});
this.aiCenterList.splice(1, Infinity, ...data);
}
}).catch(err => {
console.log(err);
});
},
getQueueList() {
getResQueueCode().then(res => {
res = res.data;
@@ -128,7 +145,7 @@ export default {
const item = data[i];
list.push({
k: item.ID,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${getListValueWithKey(this.aiCenterList, item.AiCenterCode)})`,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${item.AiCenterName})`,
});
}
this.queueList.push(...list);
@@ -247,6 +264,7 @@ export default {
}
},
mounted() {
this.getAiCenterList();
this.getQueueList();
this.getTableData();
},


+ 38
- 30
web_src/vuepages/pages/resources/specification/index.vue View File

@@ -11,8 +11,7 @@
</el-select>
</div>
<div>
<!-- syncComputerNetwork -->
<el-button size="medium" icon="el-icon-refresh" @click="confirmOperate">
<el-button size="medium" icon="el-icon-refresh" @click="syncComputerNetwork" v-loading="syncLoading">
{{ $t('resourcesManagement.syncAiNetwork') }}</el-button>
<el-button type="primary" icon="el-icon-plus" size="medium" @click="showDialog('add')">
{{ $t('resourcesManagement.addResSpecificationBtn') }}</el-button>
@@ -33,7 +32,8 @@
</el-table-column>
<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="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"
@@ -65,7 +65,7 @@
}}</span>
</span>
<span v-if="scope.row.Status == '2'">
<span class="op-btn" @click="showDialog('edit', scope.row)">{{ $t('edit') }}</span>
<span class="op-btn" @click="showDialog('edit', scope.row, true)">{{ $t('edit') }}</span>
<span class="op-btn" @click="onOrOffShelf('off-shelf', scope.row)">{{
$t('resourcesManagement.toOffShelf')
}}</span>
@@ -96,14 +96,15 @@
</div>
</div>
<SpecificationDialog :visible.sync="specificationDialogShow" :type="specificationDialogType"
:data="specificationDialogData" @confirm="specificationDialogConfirm"></SpecificationDialog>
:editOr="specificationDialogEditOr" :data="specificationDialogData" @confirm="specificationDialogConfirm">
</SpecificationDialog>
</div>
</template>

<script>
import SpecificationDialog from '../components/SpecificationDialog.vue';
import { getResQueueCode, getResSpecificationList, updateResSpecification } from '~/apis/modules/resources';
import { SPECIFICATION_STATUS, CLUSTERS, AI_CENTER, ACC_CARD_TYPE } from '~/const';
import { getResQueueCode, getResSpecificationList, updateResSpecification, syncResSpecification } from '~/apis/modules/resources';
import { SPECIFICATION_STATUS, CLUSTERS, ACC_CARD_TYPE } from '~/const';
import { getListValueWithKey } from '~/utils';
import { formatDate } from 'element-ui/lib/utils/date-util';

@@ -115,7 +116,6 @@ export default {
selStatus: '',
statusList: [{ k: '', v: this.$t('resourcesManagement.allStatus') }, ...SPECIFICATION_STATUS],
clusterList: [...CLUSTERS],
aiCenterList: [...AI_CENTER],
accCardTypeList: [...ACC_CARD_TYPE],
syncLoading: false,
loading: false,
@@ -128,6 +128,7 @@ export default {
},
specificationDialogShow: false,
specificationDialogType: 'add',
specificationDialogEditOr: false,
specificationDialogData: {},
};
},
@@ -143,7 +144,7 @@ export default {
const item = data[i];
list.push({
k: item.ID,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${getListValueWithKey(this.aiCenterList, item.AiCenterCode)})`,
v: `${item.QueueCode}(${getListValueWithKey(this.clusterList, item.Cluster)} - ${item.AiCenterName})`,
});
}
this.queueList.push(...list);
@@ -171,9 +172,10 @@ export default {
const NGPU = `${Queue.ComputeResource}:${Spec.AccCardsNum === 0 ? '0' : Spec.AccCardsNum + '*' + getListValueWithKey(this.accCardTypeList, Queue.AccCardType)}`;
return {
...Spec,
SourceSpecId: Spec.SourceSpecId || '--',
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)})`,
QueueInfo: `${Queue.QueueCode}(${getListValueWithKey(this.clusterList, Queue.Cluster)} - ${Queue.AiCenterName})`,
UpdatedTimeStr: formatDate(new Date(Spec.UpdatedTime * 1000), 'yyyy-MM-dd HH:mm:ss'),
Status: Spec.Status.toString(),
StatusStr: getListValueWithKey(this.statusList, Spec.Status.toString()),
@@ -188,7 +190,30 @@ export default {
});
},
syncComputerNetwork() {
//
this.syncLoading = true;
syncResSpecification().then(res => {
this.syncLoading = false;
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 => {
console.log(err);
this.syncLoading = false;
this.$message({
type: 'error',
message: this.$t('submittedFailed')
});
});
},
selectChange() {
this.pageInfo.curpage = 1;
@@ -198,8 +223,9 @@ export default {
this.pageInfo.curpage = val;
this.getTableData();
},
showDialog(type, data) {
showDialog(type, data, editOr) {
this.specificationDialogType = type;
this.specificationDialogEditOr = !!editOr;
this.specificationDialogData = data ? { ...data } : {};
this.specificationDialogShow = true;
},
@@ -239,24 +265,6 @@ export default {
});
});
}).catch(() => { });
},
confirmOperate() {
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
lockScroll: false,
}).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
},
mounted: function () {


Loading…
Cancel
Save