cos-web/src/views/resource-apply/ecs/EFCVmList.vue

764 lines
29 KiB
Vue
Raw Normal View History

2024-05-28 07:53:11 +00:00
<template>
<basic-form :model="formData" ref="addForm" label-width="0" :disabled="disabled">
<basic-table :data="showParamList" ref="addTable">
<el-table-column label="序号" show-overflow-tooltip width="60px">
<template slot-scope="{ $index }">
<basic-form-item label="">
{{ $index + 1 }}
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="命名规则" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" :prop="`showParamList.${$index}.configs.nameRuleId`">
<el-select v-model="row.configs.nameRuleId" placeholder="请选择命名规则" clearable filterable>
<el-option v-for="(item, index) in nameruleList" :key="index" :label="item.name" :value="item.id"> </el-option>
</el-select>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="主机名" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required,vmHostName" :prop="`showParamList.${$index}.configs.vmHostName`">
<el-input v-model="row.configs.vmHostName"> </el-input>
</basic-form-item>
</template>
</el-table-column>
<!-- <el-table-column label="云平台类型" show-overflow-tooltip>
<template slot-scope="{ row,$index }">
<basic-form-item label="">
<el-select v-model="row.subLocation.vendorType">
<el-option :label="item | vendorName" :value="item" v-for="item in vendorTypelist" :key="item"></el-option>
</el-select>
</basic-form-item>
</template>
</el-table-column> -->
<el-table-column label="区域" show-overflow-tooltip width="180px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.subLocation.region`">
<el-select v-model="row.subLocation.region" @change="changeRegion(row, true)">
<el-option :label="item.regionName" :value="item.region" v-for="item in regionList" :key="item.region"></el-option>
</el-select>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="可用区" show-overflow-tooltip width="180px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.subLocation.az`">
<el-select v-model="row.subLocation.az" @change="changeAz(row, true)">
<el-option :label="item.azName" :value="item.availablitiyZone" v-for="item in getZoneListByRegion(row)" :key="item.availablitiyZone"></el-option>
</el-select>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="镜像类型" show-overflow-tooltip width="180px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.configs.osCategory`">
<el-select v-model="row.configs.osCategory" placeholder="请选择" @change="getVersionList(row, true)">
<el-option v-for="(item, index) in row.osList" :key="index" :label="item" :value="item"> </el-option>
</el-select>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="镜像版本" show-overflow-tooltip width="180px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.configs.osVersion`">
<el-select v-model="row.configs.osVersion" placeholder="请选择" @change="getImage(row, true)">
<el-option v-for="(item, index) in row.versionList" :key="index" :label="item" :value="item"> </el-option>
</el-select>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="CPU" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.configs.cpu`">
<el-input-number :min="1" :max="500" v-model="row.configs.cpu" @change="(val) => changeCpu(val, row)"> </el-input-number>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="内存GB" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.configs.memory`">
<el-input-number :min="row.configs.templateRam" :max="500" v-model="row.configs.memory" @change="(val) => changeMemory(val, row)"> </el-input-number>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="磁盘GB" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.configs.sysDisk.disk`">
<span class="detail-href" @click="handleOpenDiskDialog(row, $index)">
<template v-if="getDiskTotalSize(row) > 0">{{ getDiskTotalSize(row) }}</template>
<template v-else></template>
</span>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="网络" show-overflow-tooltip width="180px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" :prop="`showParamList.${$index}`" :rules="rules.networkCardConfigsRule">
<span class="detail-href" @click="handleOpenNetworkDialog(row, $index)">
<template v-if="!row.configs.networkCardConfigs.length || row.configs.networkCardConfigs[0].ipPoolId">
<div v-for="(item, index) in row.configs.networkCardConfigs" :key="index">
{{ item.ipPoolName }} <span v-if="item.address.length">-{{ item.address.join('') }}</span>
</div>
</template>
<template v-else></template>
</span>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="密码" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required,vmPassword" :prop="`showParamList.${$index}.configs.password`">
<el-input v-model="row.configs.password" placeholder="请输入密码" show-password></el-input>
</basic-form-item>
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.configs.confirm_password`">
<el-input v-model="row.configs.confirm_password" placeholder="请再次输入密码" show-password></el-input>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="用途" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.subLocation.purpose`">
<el-input v-model="row.subLocation.purpose"> </el-input>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="软件配置" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="">
<span class="detail-href" @click="openGraph(row, $index)"> {{ getGraphConfigLabel(row) }} </span>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="数量" show-overflow-tooltip width="160px">
<template slot-scope="{ row, $index }">
<basic-form-item label="" validate="required" :prop="`showParamList.${$index}.emption.count`">
<el-input-number v-model="row.emption.count"> </el-input-number>
</basic-form-item>
</template>
</el-table-column>
<el-table-column label="操作" width="160px" fixed="right">
<template slot-scope="{ row, $index }">
<basic-form-item label="">
<el-button type="text" @click="handleClone(row)"></el-button>
<el-button type="text" @click="handleSub($index)"></el-button>
</basic-form-item>
</template>
</el-table-column>
<span slot="pagination"></span>
</basic-table>
<DataDisk v-if="addDiskDialog.visible" :dialog="addDiskDialog" @success="changeDisk"></DataDisk>
<Ippool v-if="addNetworkDialog.visible" :dialog="addNetworkDialog" :disabled="disabled"></Ippool>
<el-dialog :visible.sync="graphDialog.visible" title="作业编排" width="1200px" append-to-body top="5vh" :closeOnClickModal="false">
<Graph v-if="graphDialog.visible" :addData="addData" :graphDialog="graphDialog" @back="graphDialog.visible = false" :disabled="disabled"></Graph>
</el-dialog>
</basic-form>
</template>
<script>
import { conditionService, conditionImage, getNameRule } from 'services/platform/index'
import { generateSpec, getSpecValue } from 'views/resource-apply/utils/index'
import { getPoolCondition } from 'services/platform/pool'
import { uniqBy, cloneDeep } from 'lodash-es'
import { transformNetworkConfig } from './ImageItem'
import { subApplicationParam, GEN_UUID, ServiceCodeMap, defaultTask } from '../data/EFCInit'
import Ippool, { CECSTACK_DEFAULT_CONFIG, CLOUDTOWER_DEFAULT_CONFIG } from './EFCIppool'
import DataDisk from './EFCDataDisk'
import sku from '../mixins/EFCsku'
import Graph from '../graph/graph.vue'
import { getVolumeTpl } from 'services/platform/smart.js'
export default {
name: 'VmList',
mixins: [sku],
components: {
Ippool,
DataDisk,
Graph
},
props: {
itemData: {
type: [Object, Boolean]
},
showParamList: {
type: Array,
required: true,
default: () => []
},
addData: {
type: Object,
required: true,
default: () => {}
},
disabled: {
type: Boolean
}
},
provide() {
// 使用函数的形式,可以访问到 `this`
return {
getSubApplicationParamsForTaskServer: () => this.addData.subApplicationParams.filter((item) => item.taskGroupUuid === this.graphDialog.task.taskGroupUuid)
}
},
computed: {
formData() {
return { showParamList: this.showParamList }
},
regionList() {
return this.allPoolList.reduce((pre, cur) => {
if (!pre.find((item) => item.region == cur.region)) {
pre.push({
regionName: cur.regionName,
region: cur.region
})
}
return pre
}, [])
}
},
data() {
return {
nameruleList: [],
vendorTypelist: [],
allPoolList: [],
addDiskDialog: {
visible: false,
index: '',
row: {}
},
addNetworkDialog: {
visible: false,
row: {},
cb: () => {}
},
rules: {
networkCardConfigsRule: [
{
required: true,
validator: (rule, value, callback) => {
const validateNetworkCard = this.validateNetworkCard(value)
if (validateNetworkCard.valid) {
callback()
} else {
callback(new Error(validateNetworkCard.message))
}
},
trigger: null
}
]
},
graphDialog: {
visible: false,
task: {},
cb: () => {}
},
CTDataDisktemplateData: []
}
},
created() {
getNameRule({
page: 1,
rows: 9999
}).then((data) => {
if (data.success) {
this.nameruleList = data.data.rows
}
})
this.getAllPool()
// 获取云平台类型
conditionService('server').then((data) => {
if (data.success) {
this.vendorTypelist = data.data
}
})
},
methods: {
getGraphConfigLabel(row) {
const task = this.addData.tasks.find(({ taskGroupUuid }) => taskGroupUuid === row.taskGroupUuid)
if (!task) return '配置'
return `${task.taskName}`
},
openGraph(row) {
if (!this.addData.location.name) return this.$message.error('请填写业务信息')
if (!row.configs.vmHostName) return this.$message.error('请填写主机名')
if (!row.configs.password) return this.$message.error('请填写密码')
this.$emit('handleUpdateParamList')
this.graphDialog.visible = true
this.graphDialog.task = cloneDeep(
this.addData.tasks.find((item) => item.taskGroupUuid === row.taskGroupUuid) || {
...defaultTask,
taskGroupUuid: row.taskGroupUuid
}
)
this.graphDialog.cb = () => {
this.graphDialog.task.taskName = `${this.addData.location.name}_${this.graphDialog.task.name}`
const findIndex = this.addData.tasks.findIndex((item) => item.taskGroupUuid === row.taskGroupUuid)
if (findIndex > -1) {
this.addData.tasks[findIndex] = this.graphDialog.task
} else {
this.addData.tasks.push(this.graphDialog.task)
}
}
},
changeCpu(val, row) {
row.elements[0].specs[0].cpu = val
},
changeMemory(val, row) {
row.elements[0].specs[1].memory = val
},
// 将磁盘配置保存到 elements 中
async changeDisk(index = -1, row) {
row = index > -1 ? this.showParamList[index] : row
// 系统盘
row.elements[1].specs = [{ disk: row.configs.sysDisk.disk }]
row.configs.sysDisk.categoryId = row.elements[1].categoryId
// 数据盘
row.elements.splice(2)
if (row.configs.addDiskList.length) {
const dataDiskElementClone = cloneDeep(row.elements[1])
row.configs.addDiskList.map((item) => {
row.elements.push({ ...dataDiskElementClone, specs: [{ disk: item.disk }] })
})
}
// 设置各个云平台的默认磁盘配置
const vendorType = row.subLocation.vendorType
const vendorId = row.subLocation.vendorId
switch (vendorType) {
case 'VMWARE':
row.configs.sysDisk.diskType = 'thin'
// 设置磁盘默认数据
row.configs.addDiskList.forEach((item) => {
item.createLvm = false
item.diskType = 'thin'
item.fileSystem = 'ext3'
item.forceMount = false
})
break
case 'INSPURRAIL':
row.configs.sysDisk.diskType = 'thin'
// 设置磁盘默认数据
row.configs.addDiskList.forEach((item) => {
item.createLvm = false
item.diskType = 'thin'
item.fileSystem = 'ext3'
item.forceMount = false
})
break
case 'CLOUDTOWER':
const busData = [
{ name: 'VIRTIO', value: 'VIRTIO' },
{ name: 'SCSI', value: 'SCSI' },
{ name: 'IDE', value: 'IDE' }
]
// 设置磁盘默认数据
if (!this.CTDataDisktemplateData.length || this.CTDataDisktemplateData[0].vendorId !== vendorId) {
await getVolumeTpl({
simple: true,
params: this.$tools.handleSearchParam({ vendorId })
}).then((data) => {
if (data.success) {
if (!data.data.rows.length) {
row.configs.addDiskList = []
return this.$message.error('获取CLOUDTOWER存储策略数据为空,请联系管理员')
}
this.CTDataDisktemplateData = data.data.rows
}
})
}
row.configs.addDiskList.forEach((item) => {
item.type = 'newDisk'
item.bus = busData[0].value
item.volumeTemplateId = this.CTDataDisktemplateData[0].id // 存储策略
item.volumeTemplateName = this.CTDataDisktemplateData[0].name
})
break
case 'CECSTACK':
row.configs.addDiskList.forEach((item) => {
item.deleteWithInstance = true
item.bootVolume = false
// item.size = ''
// item.volumeType = ''
item.volumeUnit = 'GiB'
// item.bootIndex = ''
})
break
default:
break
}
},
handleClone(row = subApplicationParam) {
const cloneData = cloneDeep(row)
cloneData.taskGroupUuid = GEN_UUID()
cloneData.taskTargetUuid = GEN_UUID()
cloneData.configs.name = ''
this.showParamList.push(cloneData)
},
handleSub(index) {
this.showParamList.splice(index, 1)
},
handleOpenNetworkDialog(row, index) {
this.addNetworkDialog.visible = true
this.addNetworkDialog.row = row
this.addNetworkDialog.cb = () => {
this.$refs.addForm && this.$refs.addForm.$refs.formRef.validateField(`showParamList.${index}`)
}
},
getDiskTotalSize(row) {
return row.configs.sysDisk.disk + row.configs.addDiskList.reduce((pre, cur) => pre + cur.disk, 0)
},
handleOpenDiskDialog(row, index) {
this.addDiskDialog.visible = true
this.addDiskDialog.row = row
this.addDiskDialog.index = index
},
getOsList(row) {
if (!row.subLocation.vendorId) return
let params
if (row.subLocation.vendorType === 'CECSTACK') {
params = {
condition: 'listByImageType',
vendorId: row.subLocation.vendorId,
status: 'ACTIVE',
tenantId: 0,
regionId: row.subLocation.region,
imageType: 'PUBLIC'
}
} else {
params = {
condition: 'listTenantImages',
vendorId: row.subLocation.vendorId
}
if (row.subLocation.vendorType === 'SANGFOR') {
if (!row.subLocation.azUuid) return
params.azUuid = row.subLocation.azUuid
}
}
conditionImage(params).then((data) => {
if (data.success) {
row.imageData = data.data
this.$set(row, 'osList', Object.keys(row.imageData))
if (!this.itemData) {
row.configs.osCategory = row.osList[0]
row.configs.osVersion = ''
}
this.$set(row, 'versionList', [])
this.getVersionList(row, !row.configs.osVersion)
}
})
return row.osList
},
getVersionList(row, flag) {
if (row.subLocation.vendorType === 'CECSTACK') {
row.versionList = row.imageData[row.configs.osCategory].map(({ name }) => name)
} else {
row.versionList = Object.keys(row.imageData[row.configs.osCategory])
}
if (flag) {
row.configs.osVersion = row.versionList[0]
this.getImage(row, true)
} else {
this.getImage(row, false)
}
},
getImage(row, flag) {
let obj
if (row.subLocation.vendorType === 'CECSTACK') {
obj = row.imageData[row.configs.osCategory].find(({ name }) => row.configs.osVersion === name)
} else {
obj = row.imageData[row.configs.osCategory][row.configs.osVersion]?.[0]
}
if (!obj) return
if (flag) {
row.configs.imageId = obj.id
// 电子云为 minDisk
// cloudtower 镜像中可能没系统盘大小
row.configs.templateDisk = obj.templateDisk || obj.minDisk || 50
row.configs.templateRam = obj.minRam / 1024 || 1
if (row.configs.memory < row.configs.templateRam) row.configs.memory = row.configs.templateRam
row.configs.sysDisk.disk = row.configs.templateDisk
}
if (row.subLocation.vendorType == 'CECSTACK') {
if (flag) {
this.$set(row.configs, 'networkCardConfigs', [
{
networkId: obj.networkId,
ipPolicy: 'Auto',
ipPoolId: '',
ipPoolName: '',
address: [],
portGroupId: '',
loading: false,
// 电子云特殊参数
...CECSTACK_DEFAULT_CONFIG
}
])
}
} else if (row.subLocation.vendorType == 'SANGFOR') {
row.configs.vmUuid = obj.imageUuid
if (flag && row.configs.networkCardConfigs.length == 0) {
const hardware_status = JSON.parse(obj.detail || '{}')?.hardware_status
if (!hardware_status) return this.$message.error('镜像缺少网卡,请检查镜像是否正确')
const configs = transformNetworkConfig(hardware_status).map((item) => ({
ipPolicy: 'Auto',
ipPoolId: '',
ipPoolName: '',
address: [],
portGroupId: '',
loading: false
}))
this.$set(row.configs, 'networkCardConfigs', configs)
}
} else if (row.subLocation.vendorType == 'VMWARE') {
if (flag && (row.configs.networkCardConfigs.length == 0 || row.configs.networkCardConfigs[0].networkCardId != obj.networkCards?.[0]?.id)) {
if (!obj.networkCards?.length) this.$message.error('镜像缺少网卡,请检查镜像是否正确')
this.$set(
row.configs,
'networkCardConfigs',
obj.networkCards.map((item) => {
return {
networkCardId: item.id,
ipPolicy: 'Auto',
ipPoolId: '',
ipPoolName: '',
address: [],
portGroupId: '',
loading: false
}
})
)
}
} else if (row.subLocation.vendorType == 'INSPURRAIL') {
if (flag) {
if (row.configs.networkCardConfigs.length == 0 || row.configs.networkCardConfigs[0].networkCardId != obj.networkCards?.[0]?.id) {
if (!obj.networkCards?.length) this.$message.error('镜像缺少网卡,请检查镜像是否正确')
this.$set(
row.configs,
'networkCardConfigs',
obj.networkCards.map((item) => {
return {
networkCardId: item.id,
ipPolicy: 'Auto',
ipPoolId: '',
ipPoolName: '',
address: [],
portGroupId: '',
loading: false
}
})
)
}
// 模板里面的磁盘配置
const volumes = obj.volumes || []
volumes.map(({ bootVolume, size }) => {
if (bootVolume) {
row.configs.templateDisk = size
row.configs.sysDisk.disk = size
} else {
row.configs.addDiskList.push({ disk: size, templateDisk: size })
}
})
}
} else if (row.subLocation.vendorType == 'CLOUDTOWER') {
if (flag) {
this.$set(row.configs, 'networkCardConfigs', [
{
networkId: obj.networkId,
ipPolicy: 'Auto',
ipPoolId: '',
ipPoolName: '',
address: [],
portGroupId: '',
loading: false,
// CLOUDTOWER特殊参数
...CLOUDTOWER_DEFAULT_CONFIG
}
])
}
} else if (row.subLocation.vendorType === 'CNWARE') {
const res = JSON.parse(obj.configuration).devices.map((d) => {
if (d.capacity) {
const size = Number(d.capacity) / 1024 / 1024 / 1024
// 系统盘大小
row.configs.templateDisk = size
}
return {
...d
}
})
if (flag) {
row.configs.sysDiskList = res.flat()
}
}
// 设置硬盘参数
if (flag) this.changeDisk(-1, row)
},
setVendor(row, manual = true) {
const findVendorList = this.getVendorListByRegionZone(row)
const pool = findVendorList.filter((item) => item.vendorId == row.subLocation.vendorId)[0]
if (!pool) return this.$message.error('当前可用区下不存在资源池')
console.log('当前资源池:', pool.vendorType, pool.name)
const { vendorType, id, azUuid } = pool
row.subLocation.poolGroupId = id
row.subLocation.azUuid = azUuid
row.subLocation.vendorType = vendorType
row.networkRelations = pool.networkRelations || []
row.service = ServiceCodeMap.server[vendorType]
row.elements.map((item, index) => {
item.serviceCode = index === 0 ? ServiceCodeMap.server[vendorType] : ServiceCodeMap.disk[vendorType]
})
switch (vendorType) {
case 'VMWARE':
row.configs.isAddShterm = false
break
case 'INSPURRAIL':
row.configs.isAddShterm = false
break
case 'CLOUDTOWER':
row.configs.serverId = 0
row.configs.ha = true
row.configs.firmware = 'BIOS'
row.configs.status = 'running'
row.configs.fullClone = false
break
default:
break
}
// 根据云平台类型设置默认磁盘配置
this.changeDisk(-1, row)
this.getData(row, manual)
},
getData(row, manual = true) {
// 加载服务目录
if (!this.itemData || !this.disabled) this.loadSku(row)
this.getOsList(row)
},
getZoneListByRegion(row) {
const filterPools = this.allPoolList.filter((item) => item.region == row.subLocation.region)
if (!filterPools.length) return []
// 同一地域下可能会存在重复可用区,去重处理
if (filterPools[0].vendorType === 'CECSTACK') {
const formatPools = []
// 将多个可用区扁平化放在资源池中
filterPools.map((pool) => {
pool.regionRelations.map((zone) => {
formatPools.push({ ...pool, availablitiyZone: zone.zoneId, azName: zone.zoneName })
})
})
return uniqBy(formatPools, 'availablitiyZone')
} else {
return uniqBy(filterPools, 'availablitiyZone')
}
},
getVendorListByRegionZone(row) {
const zoneList = this.getZoneListByRegion(row)
return zoneList.filter((item) => item.availablitiyZone == row.subLocation.az)
},
// 地域变化
// manual 手动切换
changeRegion(row, manual = true) {
this.setZone(row, manual)
},
// 设置可用区
setZone(row, manual = true) {
const zoneList = this.getZoneListByRegion(row)
// 手动切换才需要置空
if (manual && !zoneList.length) return (row.subLocation.az = '')
if (!zoneList.find((item) => item.availablitiyZone === row.subLocation.az)) {
row.subLocation.az = zoneList[0].availablitiyZone
}
this.changeAz(row, manual)
},
// 可用区改变
changeAz(row, manual = true) {
const findVendorList = this.getVendorListByRegionZone(row)
if (manual && !findVendorList.length) return (row.subLocation.vendorId = '')
if (!findVendorList.find((item) => item.vendorId === row.subLocation.vendorId)) {
row.subLocation.vendorId = findVendorList[0].vendorId
}
this.setVendor(row, manual)
},
// 所有资源池
async getAllPool() {
const res = await getPoolCondition({
condition: 'listPoolGroups',
tenantId: this.addData.location.tenantId
})
if (!res.success) return
this.allPoolList = res.data
if (!this.regionList.length) return
const [{ region }] = this.regionList
if (!this.showParamList[0].subLocation.region) {
this.showParamList[0].subLocation.region = region
}
this.changeRegion(this.showParamList[0], false)
},
validateNetworkCard(param) {
const res = {
valid: true,
message: ''
}
let flag = false
let addressLenFlag = false
let cecstackFlag = false
param.configs.networkCardConfigs.forEach((item) => {
if (!item.ipPoolId || (item.ipPolicy == 'Manual' && item.address.length == 0) || (item.checkIpv6 && (!item.ipv6PoolId || (item.ipv6Policy == 'Manual' && item.ipv6Address.length == 0)))) flag = true
if (item.ipPolicy == 'Manual' && item.address.length !== param.emption.count) {
addressLenFlag = true
}
if (param.subLocation.vendorType === 'CECSTACK' && !(item.vpcUuid || item.subnetUuid)) {
cecstackFlag = true
}
})
if (flag) {
res.valid = false
res.message = '网卡信息配置不完善'
return res
}
if (addressLenFlag) {
res.valid = false
res.message = 'IP数量与云主机订购数量不一致'
return res
}
if (cecstackFlag) {
res.valid = false
res.message = '缺少 VPC 和子网信息'
}
return res
},
getParams() {
let data = false
this.$refs.addForm.validate((valid) => {
if (valid) {
const result = []
this.showParamList.forEach((param) => {
const validateNetworkCard = this.validateNetworkCard(param)
if (!validateNetworkCard.valid) {
data = false
return
}
const { password, confirm_password, ...other } = param.configs
if (password !== confirm_password) {
data = false
this.$message.error('两次密码输入不一致')
return
}
result.push({
...other,
categoryId: param.elements[0].categoryId
})
})
if (result.length === this.showParamList.length) data = result
} else {
this.$message.error('虚拟机信息未填写完整')
}
})
return data
}
}
}
</script>
<style scoped lang="scss"></style>