feat: 数据库对接(待调试)

develop
时启龙 2024-09-05 21:18:23 +08:00
parent 768259ff5f
commit 01406890f5
5 changed files with 5279 additions and 462 deletions

View File

@ -995,5 +995,17 @@ export default {
callback()
},
trigger: trigger
},
ctstackDatabaseName: {
validator: (rule, value, callback) => {
// 长度在 4 到 64个字符必须以字母开头不区分大小写可以包含字母、数字、中划线或下划线不能包含其他特殊字符
const reg = /^[a-zA-Z][a-zA-Z0-9_-]{3,63}$/
if (reg.test(value)) {
callback()
} else {
callback(new Error('长度在 4 到 64个字符必须以字母开头不区分大小写可以包含字母、数字、中划线或下划线不能包含其他特殊字符'))
}
},
trigger: trigger
}
}

View File

@ -1,113 +1,117 @@
<template>
<el-dialog v-if="addData.dialog" title="新增RDS" :visible.sync="addData.dialog" width="950px">
<el-dialog title="新增数据库" :visible.sync="addData.dialog" top="5vh" width="800px" :close-on-click-modal="false">
<el-steps :active="active" finish-status="success">
<el-step title="基础资源"></el-step>
<el-step title="实例配置"></el-step>
</el-steps>
<el-row class="box" v-show="active === 0">
<cb-form ref="basicData" :model="addData.data" label-width="120px">
<cb-form-item label="计费方式: " prop="payType" :rules="[required]">
<el-radio-group v-model="addData.data.payType" @change="getFlavorList">
<el-radio-button label="Postpaid">后付费按量付费</el-radio-button>
<el-radio-button disabled label="Prepaid">预付费包年包月</el-radio-button>
<cb-form ref="basicData" :model="formData" label-width="120px">
<cb-form-item label="计费方式: " prop="billMode" :rules="[required]">
<el-radio-group v-model="formData.billMode" @change="getFlavorList">
<el-radio-button label="2">后付费按量付费</el-radio-button>
<el-radio-button label="1">预付费包年包月</el-radio-button>
</el-radio-group>
</cb-form-item>
<region-item :add-data="addData.data"></region-item>
<cb-form-item
label="实例名称:"
prop="name"
:rules="[{ pattern: /^[a-zA-Z\u4e00-\u9fa5?!((https?:)\/\/)][a-zA-Z0-9:_-]([a-zA-Z0-9:_-]{1,62})?$/, message: '由字母、数字、中文、下划线_、中划线-)冒号(:组成以字母或中文开头不能以http://或https://开头长度限制在2-64个字符。', trigger: null }]"
validate="required"
>
<el-input v-model="addData.data.name" placeholder="请输入实例名称" class="basic-cmp"></el-input>
</cb-form-item>
<!-- <el-col :span="12"> -->
<cb-form-item label="类型: " prop="dataStoreType" :rules="[required]">
<el-select v-model="addData.data.dataStoreType" clearable placeholder="请选择类型" @change="changeType">
<el-option v-for="(item, key) in typeList" :key="key" :value="key" :label="key"></el-option>
<cb-form-item label="地域: " prop="regionId" :rules="[required]">
<el-select v-model="formData.regionId" clearable placeholder="请选择地域" @change="changeRegion">
<el-option v-for="item in regionData" :key="item.code" :value="item.code" :label="item.name"></el-option>
</el-select>
</cb-form-item>
<!-- </el-col> -->
<!-- <el-col :span="12"> -->
<cb-form-item label="版本: " prop="dataStoreVersion" :rules="[required]">
<el-select v-model="addData.data.dataStoreVersion" clearable placeholder="请选择版本" @change="changeVersion">
<el-option v-for="item in versionList" :key="item.value" :value="item.value" :label="item.name"></el-option>
<cb-form-item label="企业项目: " prop="projectId" :rules="[required]">
<el-select v-model="formData.projectId" clearable placeholder="请选择企业项目" @change="changeProject">
<el-option v-for="item in projectList" :key="item.projectSetId" :value="item.projectSetId" :label="item.projectSetName"></el-option>
</el-select>
</cb-form-item>
<!-- </el-col> -->
<cb-form-item label="系列: " prop="series" :rules="[required]">
<el-select v-model="addData.data.series" clearable placeholder="请选择系列" @change="changeCategory">
<el-option v-for="(item, index) in categoryList" :key="index" :value="item.value" :label="item.name"></el-option>
<cb-form-item label="数据库类型: " prop="type" :rules="[required]">
<el-select v-model="formData.type" clearable placeholder="请选择类型">
<el-option v-for="(item, key) in sqlTypeMap" :key="key" :value="key" :label="key"></el-option>
</el-select>
</cb-form-item>
<cb-form-item label="存储类型: " prop="volType" :rules="[required]">
<el-select v-model="addData.data.volType" clearable placeholder="请选择类型" @change="getFlavorList">
<el-option v-for="(item, index) in volTypeList" :key="index" :value="item.value" :label="item.name"></el-option>
</el-select>
<cb-form-item label="数据库版本: " prop="prodVersion" :rules="[required]">
<el-radio-group v-model="formData.prodVersion" clearable placeholder="请选择版本" @change="changeVersion">
<el-radio v-for="item in versionList" :key="item.value" :value="item.value" :label="item.name"></el-radio>
</el-radio-group>
</cb-form-item>
<cb-form-item label="实例类型: " prop="prodSpecName" :rules="[required]">
<el-radio-group v-model="formData.prodSpecName" clearable placeholder="请选择实例类型" @change="changeCategory">
<el-radio v-for="item in prodSpecNameList" :key="item" :value="item" :label="item"></el-radio>
</el-radio-group>
</cb-form-item>
<cb-form-item label="主节点可用区: " prop="mysqlNodeInfoList.0.availabilityZoneInfo.0.availabilityZoneName" :rules="[required]">
<el-radio-group v-model="formData.mysqlNodeInfoList[0].availabilityZoneInfo[0].availabilityZoneName" clearable placeholder="请选择类型" @change="changeZone">
<el-radio v-for="item in zoneList" :key="item.availabilityZoneId" :label="item.availabilityZoneId">{{ item.displayName }}</el-radio>
</el-radio-group>
</cb-form-item>
<cb-form-item label="备节点可用区1: " prop="mysqlNodeInfoList.0.availabilityZoneInfo.1.availabilityZoneName" :rules="[required]" v-if="formData.prodSpecName === '一主一备'">
<el-radio-group v-model="formData.mysqlNodeInfoList[0].availabilityZoneInfo[1].availabilityZoneName" clearable placeholder="请选择可用区">
<el-radio v-for="item in zoneList" :key="item.availabilityZoneId" :label="item.availabilityZoneId">{{ item.displayName }}</el-radio>
</el-radio-group>
</cb-form-item>
<cb-form-item label="备节点可用区2: " prop="mysqlNodeInfoList.0.availabilityZoneInfo.2.availabilityZoneName" :rules="[required]" v-if="formData.prodSpecName === '一主两备'">
<el-radio-group v-model="formData.mysqlNodeInfoList[0].availabilityZoneInfo[2].availabilityZoneName" clearable placeholder="请选择可用区">
<el-radio v-for="item in zoneList" :key="item.availabilityZoneId" :label="item.availabilityZoneId">{{ item.displayName }}</el-radio>
</el-radio-group>
</cb-form-item>
<cb-form-item label="性能类型: " prop="mysqlNodeInfoList.0.instSpec" :rules="[required]">
<el-radio-group v-model="formData.mysqlNodeInfoList[0].instSpec" clearable placeholder="请选择性能类型" @change="changeInstSpec">
<el-radio v-for="item in instSpecList" :key="item.value" :label="item.value">{{ item.name }}</el-radio>
</el-radio-group>
</cb-form-item>
<cb-form-item label="实例规格: " prop="flavorId" :rules="[required]" required-message="">
<cb-smart-table :data="specList" stripe>
<el-table-column show-overflow-tooltip label="规格代码" prop="flavorUuid">
<cb-smart-table :data="flavorList" stripe max-height="300px" :rows="99999">
<el-table-column show-overflow-tooltip label="规格代码" prop="specName">
<template v-slot="scope">
<el-radio v-model="addData.data.flavorId" :label="scope.row.id">{{ scope.row.flavorUuid }}</el-radio>
<el-radio v-model="formData.flavorId" :label="scope.row.specName" @input="changeFlavorId">{{ scope.row.specName }}</el-radio>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="实例规格族" prop="typeLabel"></el-table-column>
<el-table-column show-overflow-tooltip label="CPU" prop="cpu"></el-table-column>
<el-table-column show-overflow-tooltip label="内存GB" prop="memory"></el-table-column>
<el-table-column show-overflow-tooltip label="最大连接数(个)" prop="maxConnections"></el-table-column>
<el-table-column show-overflow-tooltip label="最大IOPS次/秒)" prop="maxIops"></el-table-column>
<el-table-column show-overflow-tooltip label="最大IO带宽Mbps" prop="maxIombps" v-if="addData.data.volType !== 'local_ssd'"></el-table-column>
<el-table-column show-overflow-tooltip label="CPU/内存" prop="prodPerformanceSpec"></el-table-column>
<span slot="pagination"></span>
</cb-smart-table>
</cb-form-item>
<cb-form-item label="存储空间(GB): " prop="volSize" :rules="[required]">
<cb-form-item label="存储类型: " prop="mysqlNodeInfoList.0.storageType" :rules="[required]">
<el-select v-model="formData.mysqlNodeInfoList[0].storageType" clearable placeholder="请选择类型">
<el-option v-for="(item, index) in storageTypeList" :key="index" :value="item.value" :label="item.name"></el-option>
</el-select>
</cb-form-item>
<cb-form-item label="存储空间(GB): " prop="mysqlNodeInfoList.0.storageSpace" :rules="[required]">
<div style="padding: 0 10px">
<el-slider v-model="addData.data.volSize" :marks="marks" show-input :min="20" :max="6000"> </el-slider>
<el-slider v-model="formData.mysqlNodeInfoList[0].storageSpace" show-input :min="100" :max="32768"> </el-slider>
</div>
</cb-form-item>
<cb-form-item v-if="formData.billMode == '1'" label="购买时长:" prop="period" :rules="[required]">
<el-select v-model="formData.period" clearable filterable>
<el-option v-for="(item, index) in periodList" :key="index" :value="item.value" :label="item.name"></el-option>
</el-select>
</cb-form-item>
</cb-form>
</el-row>
<cb-form v-show="active === 1" :model="addData.data" ref="data" label-width="120px">
<!-- <cb-form :model="formData" ref="data" label-width="120px"> -->
<cb-form v-show="active === 1" :model="formData" ref="data" label-width="120px">
<el-row>
<cb-form-item label="网络类型: " prop="instanceNetworkType" :rules="[required]">
<el-radio-group v-model="addData.data.instanceNetworkType" @change="changeNetworkType">
<el-radio-button label="Classic">经典网络</el-radio-button>
<el-radio-button label="VPC">专有网络</el-radio-button>
</el-radio-group>
</cb-form-item>
<div v-if="addData.data.instanceNetworkType == 'VPC'">
<cb-form-item label="VPC: " prop="vpcId" :rules="[required]">
<el-select v-model="addData.data.vpcId" clearable placeholder="请选择VPC" @change="changeVpc">
<cb-form-item label="虚拟私有云: " prop="vpcId" :rules="[required]">
<el-select v-model="formData.vpcId" clearable placeholder="请选择虚拟私有云" @change="changeVpc">
<el-option v-for="(item, index) in vpcList" :key="index" :value="item.value" :label="item.name"></el-option>
</el-select>
</cb-form-item>
<cb-form-item label="主节点交换机: " prop="vswitchId" :rules="[required]">
<el-select v-model="addData.data.vswitchId" clearable placeholder="请选择主节点交换机">
<el-option v-for="(item, index) in vswitchList" :key="index" :value="item.value" :label="item.name"></el-option>
<cb-form-item label="子网: " prop="subnetId" :rules="[required]">
<el-select v-model="formData.subnetId" clearable placeholder="请选择子网">
<el-option v-for="(item, index) in subnetList" :key="index" :value="item.value" :label="item.name"></el-option>
</el-select>
</cb-form-item>
</div>
<!-- <cb-form-item label="参数模板: " prop="paramGroupId" :rules="[required]">
<el-select v-model="addData.data.paramGroupId" clearable placeholder="请选择参数模板">
<el-option v-for="(item, index) in templateList" :key="index" :value="item.id" :label="item.name"></el-option>
</el-select>
</cb-form-item> -->
<cb-form-item label="时区: " prop="timeZone" :rules="[required]">
<el-select filterable v-model="addData.data.timeZone" clearable placeholder="请选择时区">
<el-option v-for="(item, index) in timeList" :key="index" :value="item.value" :label="item.name"></el-option>
<cb-form-item label="安全组: " prop="securityGroupId">
<el-select v-model="formData.securityGroupId" clearable filterable>
<el-option v-for="(item, index) in sgroupList" :key="index" :value="item.value" :label="item.name"></el-option>
</el-select>
</cb-form-item>
<cb-form-item label="表名大小写: " prop="IgnoreCase" :rules="[required]">
<el-radio-group v-model="addData.data.IgnoreCase">
<el-radio label="1">不区分大小写默认</el-radio>
<el-radio label="0">区分大小写</el-radio>
</el-radio-group>
<cb-form-item label="实例名称:" prop="name" :rules="[required, ctstackDatabaseName]">
<el-input v-model="formData.name" placeholder="请输入实例名称" class="basic-cmp"></el-input>
</cb-form-item>
<cb-form-item label="登录密码:" prop="password" :rules="[required, ctstackBMSPassword]">
<el-input type="password" v-model="formData.password" @blur="PswBlur" show-password></el-input>
</cb-form-item>
<cb-form-item label="确认密码:" prop="endPassword" :rules="[required, ctstackBMSPassword]">
<el-input type="password" v-model="formData.endPassword" @blur="PswBlur"></el-input>
</cb-form-item>
<!-- <cb-form-item label="资源组: " prop="resourceId">
<el-select v-model="addData.data.resourceId" clearable filterable>
<el-option v-for="(item, index) in rgroupList" :key="index" :value="item.resourceGroupUuid" :label="item.displayName"></el-option>
</el-select>
</cb-form-item> -->
</el-row>
</cb-form>
<div slot="footer">
@ -120,13 +124,24 @@
</template>
<script>
import validate from '@/validate'
import { getRegion } from 'services/platform/index'
import { getSubnet } from 'views/resource/ctstack/services/subnet.js'
import { getRegion, getFlavor, getParamGroup, createRds, getFlavorSpec } from 'views/resource/ctstack/services/database/rds.js'
import { getGroup } from 'views/resource/ctstack/services/group.js'
import { getFlavor, createRds, getRdsProject, getRdsZone } from 'views/resource/ctstack/services/database/rds.js'
import { getVpc } from 'views/resource/ctstack/services/vpcs.js'
import RegionItem from './RegionItem.vue'
import { handleSearchParam } from '@cmp/cmp-element'
import { encrypt, handleSearchParam } from '@cmp/cmp-element'
import { uniqBy, cloneDeep } from 'lodash-es'
const instSpecMap = {
通用型: '1',
计算增强型: '2',
内存优化型: '3'
}
const instSpecMapRevers = {
1: '通用型',
2: '计算增强型',
3: '内存优化型'
}
export default {
components: { RegionItem },
props: {
addData: {
type: Object
@ -135,304 +150,271 @@ export default {
data() {
return {
required: validate.required,
ctstackDatabaseName: validate.ctstackDatabaseName,
ctstackBMSPassword: validate.ctstackBMSPassword,
active: 0,
regions: [],
typeList: {
MySQL: ['5.5', '5.6', '5.7', '8.0']
// SQLServer: ['2008r2', '08r2_ent_ha', '2012', '2012_ent_ha', '2012_std_ha', '2012_web', '2014_std_ha', '2016_ent_ha', '2016_std_ha', '2016_web', '2017_std_ha', '2017_ent', '2019_std_ha', '2019_ent'],
// PostgreSQL: ['9.4', '10.0', '11.0', '12.0', '13.0'],
// MariaDB: ['10.3']
formData: {
vendorId: this.addData.vendorId,
type: this.addData.type,
flavorId: '',
billMode: '2', // 12
regionId: '',
prodVersion: '', // 12.16
prodSpecName: '', //
mysqlNodeInfoList: [
{
nodeType: 'master', //
instSpec: '1', // 1=2=3=4=
storageType: 'SATA', // : SSD=IOSATA=IOSAS=IOSSD-genric=SSDFAST-SSD=SSD
storageSpace: 100, // (:G100,32768)
prodPerformanceSpec: '', // (: 4C8G)
disks: 1, //
availabilityZoneInfo: [
{
availabilityZoneName: '',
availabilityZoneCount: 1,
nodeType: 'master' // AZmaster/slave/readNode
},
{
availabilityZoneName: '',
availabilityZoneCount: 1,
nodeType: 'slave'
},
{
availabilityZoneName: '',
availabilityZoneCount: 1,
nodeType: 'slave'
}
]
}
],
vpcId: '',
subnetId: '',
securityGroupId: '',
name: '',
password: '',
endPassword: '',
period: '1', // 1-36
count: 1,
autoRenewStatus: 0, // 0-,1-
prodId: '', // id
projectId: '',
projectName: '',
hostType: '' // host type: S6 or S7
},
projectList: [],
regionData: [],
sqlTypeMap: {
MySQL: ['5.7', '8.0']
},
prodSpecNameList: [],
storageTypeList: [
{
name: '极速型SSD',
value: 'FAST-SSD'
},
{
name: '通用型SSD',
value: 'SSD-genric'
},
{
name: '高IO',
value: 'SAS'
},
{
name: '普通IO',
value: 'SATA'
},
{
name: '超高IO',
value: 'SSD'
}
],
periodList: [
{ name: '1个月', value: '1' },
{ name: '2个月', value: '2' },
{ name: '3个月', value: '3' },
{ name: '4个月', value: '4' },
{ name: '5个月', value: '5' },
{ name: '6个月', value: '6' },
{ name: '7个月', value: '7' },
{ name: '8个月', value: '8' },
{ name: '9个月', value: '9' },
{ name: '12个月', value: '12' },
{ name: '24个月', value: '24' },
{ name: '36个月', value: '36' }
],
allFlavorList: [],
flavorList: [],
versionList: [],
categoryList: [],
categoryMap: {
5.5: [
{
name: '高可用版',
value: 'HighAvailability',
volType: [
{
name: '本地SSD云盘',
value: 'local_ssd'
}
]
}
],
5.6: [
{
name: '高可用版',
value: 'HighAvailability',
volType: [
{
name: '本地SSD云盘',
value: 'local_ssd'
}
]
},
{ name: '基础版', value: 'Basic', volType: [] }
],
5.7: [
{
name: '高可用版',
value: 'HighAvailability',
volType: [
{
name: '本地SSD云盘',
value: 'local_ssd'
},
{
name: 'ESSD PL1云盘',
value: 'cloud_essd'
},
{
name: 'ESSD PL2云盘',
value: 'cloud_essd2'
},
{
name: 'ESSD PL3云盘',
value: 'cloud_essd3'
},
{
name: 'SSD云盘',
value: 'cloud_ssd'
}
]
},
{
name: '基础版',
value: 'Basic',
volType: [
{
name: 'ESSD PL1云盘',
value: 'cloud_essd'
},
{
name: 'SSD云盘',
value: 'cloud_ssd'
}
]
},
{
name: '三节点企业版',
value: 'Finance',
volType: [
{
name: '本地SSD云盘',
value: 'local_ssd'
}
]
}
],
'8.0': [
{
name: '高可用版',
value: 'HighAvailability',
volType: [
{
name: '本地SSD云盘',
value: 'local_ssd'
},
{
name: 'ESSD PL1云盘',
value: 'cloud_essd'
},
{
name: 'ESSD PL2云盘',
value: 'cloud_essd2'
},
{
name: 'ESSD PL3云盘',
value: 'cloud_essd3'
},
{
name: 'SSD云盘',
value: 'cloud_ssd'
}
]
},
{
name: '基础版',
value: 'Basic',
volType: [
{
name: 'ESSD PL1云盘',
value: 'cloud_essd'
},
{
name: 'SSD云盘',
value: 'cloud_ssd'
}
]
},
{
name: '三节点企业版',
value: 'Finance',
volType: [
{
name: '本地SSD云盘',
value: 'local_ssd'
}
]
}
]
},
volTypeList: [],
specList: [],
zoneList: [],
instSpecList: [],
vpcList: [],
vswitchList: [],
templateList: [],
timeList: [
{ name: 'UTC-12:00', value: '-12:00' },
{ name: 'UTC-11:00', value: '-11:00' },
{ name: 'UTC-10:00', value: '-10:00' },
{ name: 'UTC-09:00', value: '-9:00' },
{ name: 'UTC-08:00', value: '-8:00' },
{ name: 'UTC-07:00', value: '-7:00' },
{ name: 'UTC-06:00', value: '-6:00' },
{ name: 'UTC-05:00', value: '-5:00' },
{ name: 'UTC-04:00', value: '-4:00' },
{ name: 'UTC-03:00', value: '-3:00' },
{ name: 'UTC-02:00', value: '-2:00' },
{ name: 'UTC-01:00', value: '-1:00' },
{ name: 'UTC+00:00', value: '+0:00' },
{ name: 'UTC+01:00', value: '+1:00' },
{ name: 'UTC+02:00', value: '+2:00' },
{ name: 'UTC+03:00', value: '+3:00' },
{ name: 'UTC+04:00', value: '+4:00' },
{ name: 'UTC+05:00', value: '+5:00' },
{ name: 'UTC+05:30', value: '+5:30' },
{ name: 'UTC+06:00', value: '+6:00' },
{ name: 'UTC+07:00', value: '+7:00' },
{ name: 'UTC+08:00', value: '+8:00' },
{ name: 'UTC+09:00', value: '+9:00' },
{ name: 'UTC+10:00', value: '+10:00' },
{ name: 'UTC+11:00', value: '+11:00' },
{ name: 'UTC+12:00', value: '+12:00' },
{ name: 'UTC+13:00', value: '+13:00' }
],
rgroupList: [],
marks: {
20: '20GB',
1500: '1500GB',
3000: '3000GB'
}
subnetList: [],
sgroupList: []
}
},
created() {
this.changeType(this.addData.data.dataStoreType)
this.getVendorDetail()
this.getRegionList()
},
mounted() {},
computed: {
regionId() {
return this.addData.data.regionId
}
},
watch: {
regionId(newVal) {
this.versionList = []
this.addData.data.dataStoreVersion = ''
this.getVersions()
}
},
methods: {
getVendorDetail() {
// detailCloudVendor(this.addData.data.vendorId).then(data => {
// if (data.success) {
// const authentication = data.data.authentication ? JSON.parse(data.data.authentication) : {}
// this.regions = authentication.regions || []
// }
// })
},
getFlavorList() {
const { dataStoreType, dataStoreVersion, series, vendorId, regionId, volType, zone } = this.addData.data
if (dataStoreType && dataStoreVersion && series && regionId && volType && zone) {
getFlavor({
series: series,
getRegionList() {
const { vendorId, type } = this.formData
if (type) {
getRegion({
vendorId: vendorId,
regionId: regionId,
zone: zone,
engine: dataStoreType.toLowerCase(),
version: dataStoreVersion,
storageType: volType
type: type
}).then(data => {
if (data.success) {
this.specList = data.data
this.addData.data.flavorId = this.specList.length ? this.specList[0].id : ''
this.regionData = data.data
this.formData.regionId = this.regionData.length ? this.regionData[0].code : ''
this.changeRegion()
}
})
}
},
getVersions() {
const { vendorId, regionId } = this.addData.data
const params = {
type: 'version',
vendorId,
regionId,
engine: 'MySQL'
}
// const res = await getFlavorSpec(params)
// if (res) {
// this.versionList = res.data
// }
this.versionList = [
{ name: '8.0', value: '8.0' },
{ name: '5.7', value: '5.7' }
]
},
async getSeries(version) {
const { vendorId, regionId } = this.addData.data
const params = {
type: 'series',
vendorId,
regionId,
version,
engine: 'MySQL'
}
const res = await getFlavorSpec(params)
if (res) {
this.categoryList = res.data
}
},
async getStorageType(series) {
const { vendorId, regionId } = this.addData.data
const params = {
type: 'storageType',
vendorId,
regionId,
series,
engine: 'MySQL'
}
const res = await getFlavorSpec(params)
if (res) {
this.volTypeList = res.data
}
},
changeVersion(value) {
this.categoryList = []
this.$set(this.addData.data, 'series', '')
this.volTypeList = []
this.addData.data.volType = ''
this.specList = []
this.getSeries(value)
},
changeCategory(value) {
this.volTypeList = []
this.addData.data.volType = ''
this.specList = []
this.getStorageType(value)
},
changeNetworkType(value) {
if (value == 'VPC') {
changeRegion() {
this.getVpcList()
this.getProject()
},
getProject() {
getRdsProject({
regionId: this.formData.regionId,
vendorId: this.formData.vendorId,
type: this.formData.type
}).then(res => {
if (res.success) {
this.projectList = res.data
this.formData.projectId = this.projectList.length ? this.projectList[0].projectSetId : ''
this.changeProject()
}
})
},
async changeProject() {
if (!this.formData.projectId) return
this.formData.projectName = this.projectList.find(item => item.projectSetId === this.formData.projectId)?.projectSetName
await this.getZone()
this.getFlavorList()
},
async getZone() {
await getRdsZone({
regionId: this.formData.regionId,
vendorId: this.formData.vendorId,
projectId: this.formData.projectId
}).then(data => {
if (data.success) {
this.zoneList = data.data
}
})
},
getFlavorList() {
const { type, vendorId, regionId, projectId } = this.formData
if ((type, vendorId, regionId, projectId)) {
getFlavor({
type,
vendorId,
regionId,
projectId
}).then(data => {
if (data.success) {
this.allFlavorList = Object.freeze(data.data)
this.getVersionList()
}
})
}
},
getVersionList() {
const list = this.allFlavorList.map(({ prodVersion }) => ({ name: prodVersion, value: prodVersion }))
this.versionList = uniqBy(list, 'value')
this.formData.prodVersion = this.versionList.length ? this.versionList[0].value : ''
this.changeVersion()
},
changeVersion() {
this.getCategoryList()
},
getCategoryList() {
const { prodVersion } = this.formData
if (!prodVersion) return
const list = this.allFlavorList.filter(item => item.prodVersion === prodVersion).map(({ prodSpecName }) => prodSpecName)
this.prodSpecNameList = list
this.formData.prodSpecName = this.prodSpecNameList.length ? this.prodSpecNameList[0] : ''
this.changeCategory()
},
changeCategory() {
this.resetZone()
},
resetZone() {
const [first = '', second = '', third = ''] = this.zoneList.map(item => item.availabilityZoneId)
switch (this.formData.prodSpecName) {
case '单机版':
case '只读实例':
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[0].availabilityZoneName = first
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[1].availabilityZoneName = ''
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[2].availabilityZoneName = ''
break
case '一主一备':
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[0].availabilityZoneName = first
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[1].availabilityZoneName = second
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[2].availabilityZoneName = ''
break
case '一主两备':
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[0].availabilityZoneName = first
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[1].availabilityZoneName = second
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[2].availabilityZoneName = third
break
default:
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[0].availabilityZoneName = first
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[1].availabilityZoneName = ''
this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[2].availabilityZoneName = ''
break
}
this.changeZone()
},
changeZone() {
this.getInstSpecList()
},
getInstSpecList() {
const { prodVersion, prodSpecName } = this.formData
if (!prodVersion || !prodSpecName) return
const instSpecMap = {
通用型: '1',
计算增强型: '2',
内存优化型: '3'
}
this.instSpecList = this.allFlavorList.filter(item => item.prodVersion === prodVersion && item.prodSpecName === prodSpecName).map(({ instanceType }) => ({ name: instanceType, value: instSpecMap[instanceType] }))
this.formData.mysqlNodeInfoList[0].instSpec = this.instSpecList.length ? this.instSpecList[0].value : ''
this.changeInstSpec()
},
changeInstSpec() {
this._getFlavor()
},
_getFlavor() {
const { prodVersion, prodSpecName, mysqlNodeInfoList } = this.formData
if (!prodVersion || !prodSpecName || !mysqlNodeInfoList[0].instSpec) return
//
const find = this.allFlavorList.find(item => item.prodVersion === prodVersion && item.prodSpecName === prodSpecName && item.instanceType === instSpecMapRevers[mysqlNodeInfoList[0].instSpec])
if (!find) return console.log('未找到规格', prodVersion, prodSpecName, instSpecMapRevers[mysqlNodeInfoList[0].instSpec])
//
this.flavorList = find.instSpecInfoList.filter(item => item.azList.includes(this.formData.mysqlNodeInfoList[0].availabilityZoneInfo[0].availabilityZoneName)).sort((a, b) => a.prodPerformanceSpec?.split(/[A-Z]/)[0] - b.prodPerformanceSpec?.split(/[A-Z]/)[0])
this.formData.flavorId = this.flavorList.length ? this.flavorList[0].specName : ''
this.changeFlavorId()
},
changeFlavorId() {
const { prodVersion, prodSpecName, mysqlNodeInfoList } = this.formData
const group = this.allFlavorList.find(item => item.prodVersion === prodVersion && item.prodSpecName === prodSpecName && item.instanceType === instSpecMapRevers[mysqlNodeInfoList[0].instSpec]) || {}
this.formData.prodId = group.prodId || ''
const find = this.flavorList.find(item => item.specName === this.formData.flavorId) || {}
this.formData.hostType = find.generation || ''
this.formData.mysqlNodeInfoList[0].prodPerformanceSpec = find.prodPerformanceSpec || ''
},
getVpcList() {
getVpc({
simple: true,
params: handleSearchParam({
vendorId: this.addData.data.vendorId,
regionId: this.addData.data.regionId
vendorId: this.formData.vendorId,
regionId: this.formData.regionId
})
}).then(data => {
this.loading = false
@ -442,63 +424,41 @@ export default {
})
},
changeVpc(value) {
let networkId = ''
this.vswitchList = []
this.addData.data.vswitchId = ''
this.vpcList.forEach(item => {
if (value == item.value) {
networkId = item.id
this.getSwitchList(networkId)
}
})
this.subnetList = []
this.formData.subnetId = ''
this.getSubnetList()
this.getRgroup()
},
getSwitchList(networkId) {
getSubnetList() {
getSubnet({
simple: true,
params: handleSearchParam({
networkId: networkId,
vendorId: this.addData.data.vendorId,
zone: this.addData.data.zone
vpcUuid: this.formData.vpcId,
vendorId: this.formData.vendorId
})
}).then(data => {
if (data.success) {
this.vswitchList = data.data.rows
}
})
},
getTemplateList() {
getParamGroup({
regionId: this.addData.data.regionId,
vendorId: this.addData.data.vendorId,
engine: this.addData.data.dataStoreType.toLowerCase(),
version: this.addData.data.dataStoreVersion
}).then(data => {
if (data.success) {
this.templateList = data.data
this.subnetList = data.data.rows
this.formData.subnetId = this.subnetList.length ? this.subnetList[0].value : ''
}
})
},
getRgroup() {
// getResource({
// page: 1,
// rows: 99999,
// params: handleSearchParam({
// vendorId: this.addData.data.vendorId,
// 'status:ueq': 'PendingDelete'
// })
// }).then(data => {
// if (data.success) {
// this.rgroupList = data.data.rows
// }
// })
getGroup({
simple: true,
params: JSON.stringify([{ param: { vendorId: this.formData.vendorId, regionId: this.formData.regionId, tenantId: 0, vpcUuid: this.formData.vpcId }, sign: 'EQ' }])
}).then(data => {
if (data.success) {
this.sgroupList = data.data.rows
this.formData.securityGroupId = this.sgroupList.length ? this.sgroupList[0].value : ''
}
})
},
next(num) {
if (num === 0) {
this.$refs.basicData.validate(valid => {
if (valid) {
this.active = 1
this.getRgroup()
this.getTemplateList()
}
})
}
@ -509,7 +469,19 @@ export default {
if (!valid) {
return false
}
createRds(this.addData.data).then(data => {
const params = cloneDeep(this.formData)
//
params.mysqlNodeInfoList[0].availabilityZoneInfo = params.mysqlNodeInfoList[0].availabilityZoneInfo.filter(item => item.availabilityZoneName)
if (params.password !== params.endPassword) {
this.$notify({
title: '提示',
message: '两次密码输入不一致'
})
return
}
if (params.password) params.password = encrypt(params.password)
if (params.endPassword) params.endPassword = encrypt(params.endPassword)
createRds(params).then(data => {
const type = data.success ? 'success' : 'error'
this.$message[type](data.message)
if (data.success) {
@ -519,7 +491,13 @@ export default {
}
})
})
},
PswBlur(e) {
const value = e.target.value
}
}
}
</script>
//

View File

@ -12,9 +12,6 @@
<template #type="type">
{{ filter[type] }}
</template>
<template #instanceNetworkType="instanceNetworkType">
{{ filter[instanceNetworkType] }}
</template>
<template #payType="payType">
{{ filter[payType] }}
</template>
@ -24,7 +21,7 @@
<template #operate="val, record">
<el-button type="text" @click="patch(record)" :disabled="record.status !== 'Running'"> 重启 </el-button>
<div class="action-divider"></div>
<el-button type="text" @click="removeAliRds(record)" :disabled="record.status !== 'Running'"> 释放实例 </el-button>
<el-button type="text" @click="removeRds(record)" :disabled="record.status !== 'Running'"> 释放实例 </el-button>
</template>
</cb-advance-table>
<add :add-data="addData" v-if="addData.dialog" @back="getData"></add>
@ -35,7 +32,6 @@
<cb-detail-item label="版本">{{ detailData.dataStoreVersion }}</cb-detail-item>
<cb-detail-item label="实例类型">{{ filter[detailData.type] }}</cb-detail-item>
<cb-detail-item label="数据库类型">{{ detailData.dataStoreType }}</cb-detail-item>
<cb-detail-item label="网络类型">{{ filter[detailData.instanceNetworkType] }}</cb-detail-item>
<cb-detail-item label="付费类型">{{ filter[detailData.payType] }}</cb-detail-item>
<cb-detail-item label="规格">{{ detailData.flavorId }}</cb-detail-item>
<cb-detail-item label="可用区">{{ detailData.region }}</cb-detail-item>
@ -266,7 +262,7 @@
<script>
import validate from '@/validate'
import { getAliRds, detailAliRds, getRdsCos, patchAliRds, removeAliRds, getRdsUsers, createRdsUsers, removeRdsUsers, resetRdsUserPasd, resetRdsUser, authRdsUser, getRdsDbs, createRdsDbs, removeRdsDbs } from 'views/resource/ctstack/services/database/rds.js'
import { getRds, detailRds, getRdsCos, patchRds, removeRds, getRdsUsers, createRdsUsers, removeRdsUsers, resetRdsUserPasd, resetRdsUser, authRdsUser, getRdsDbs, createRdsDbs, removeRdsDbs } from 'views/resource/ctstack/services/database/rds.js'
import add from './add.vue'
import ModifyRole from './ModifyRole.vue'
import { keywords } from './validate'
@ -377,7 +373,8 @@ export default {
rdsDBPassword: { pattern: '^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,32}$', message: '必须包含三种及以上类型大小写字母、数字、特殊符号。长度为8-32位特殊字符包括! @ # $ % ^ & * () _ + - =', trigger: null },
searchConfigs: [
{ type: 'Input', label: '名称', value: 'name' },
{ type: 'Const', value: 'vendorId', initValue: this.platformObject.vendorId }
{ type: 'Const', value: 'vendorId', initValue: this.platformObject.vendorId },
{ type: 'Const', value: 'dbType', initValue: 'MYSQL' }
],
columns,
loading: false,
@ -524,7 +521,7 @@ export default {
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
patchAliRds(data.id).then(data => {
patchRds(data.id).then(data => {
if (data.success) {
this.$message({
type: 'success',
@ -535,13 +532,13 @@ export default {
})
})
},
removeAliRds(data) {
removeRds(data) {
this.$confirm('确定释放该实例吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
removeAliRds(data.id).then(data => {
removeRds(data.id).then(data => {
if (data.success) {
this.$message({
type: 'success',
@ -554,7 +551,7 @@ export default {
},
getData() {
this.loading = true
getAliRds(this.params).then(data => {
getRds(this.params).then(data => {
this.loading = false
if (data.success) {
this.tableData = data.data.rows
@ -562,42 +559,16 @@ export default {
}
})
},
handleSearch() {
this.params.page = 1
this.params.params = handleSearchParam({
vendorId: this.platformObject.vendorId,
regionId: this.searchData.regionId,
zone: this.searchData.zone,
'name:lk': this.searchData.name
})
this.getData()
},
handleCreate() {
this.addData = {
dialog: true,
data: {
vendorId: this.platformObject.vendorId,
payType: 'Postpaid',
regionId: '',
type: 'MySQL',
dataStoreVersion: '',
category: '',
volType: '',
availZone: '',
flavorId: '',
volSize: 20,
instanceNetworkType: 'Classic',
vpcId: '',
vswitchId: '',
paramGroupId: '',
timeZone: '+8:00',
IgnoreCase: '1'
}
type: 'MySQL'
}
},
getDetail(id) {
this.Super = false
detailAliRds(id).then(data => {
detailRds(id).then(data => {
if (data.success) {
this.detailData = data.data
this.detailFlag = true

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +1,94 @@
import { request } from '@cmp/cmp-element'
import { wrapperParams, downloadFile } from 'utils'
const url = '/cmp/plugins/ctstack/v1/rds'
import { projectList, zoneList, flavorList } from './mockData'
const url = '/cmp/plugins/ctstack/v1/cloudrds'
// 是否开发环境
const isDev = process.env.NODE_ENV === 'development'
const mockRequest = data =>
new Promise(resolve =>
resolve({
success: true,
data
})
)
export function getRegion(params) {
return request.get(`${url}/mysql/regions`, { params })
return request.get(`${url}/regions`, { params })
}
export function getRdsProject(params) {
if (isDev) return mockRequest(projectList)
return request.get(`${url}/projects`, { params })
}
export function getRdsZone(params) {
if (isDev) return mockRequest(zoneList)
return request.get(`${url}/zones`, { params })
}
export function getFlavor(params) {
return request.get(`${url}/mysql/flavors`, { params })
if (isDev) return mockRequest(flavorList)
return request.get(`${url}/flavors`, { params })
}
export function getParamGroup(params) {
return request.get(`${url}/mysql/param/groups`, { params })
return request.get(`${url}/param/groups`, { params })
}
export function createRds(params) {
return request.post(`${url}/mysql`, params)
return request.post(`${url}`, params)
}
export function getRdsDbs(id, params) {
return request.get(`${url}/mysql/${id}/dbs`, { params })
return request.get(`${url}/${id}/dbs`, { params })
}
export function getRdsCos(id, params) {
return request.get(`${url}/mysql/${id}/nets`, { params })
return request.get(`${url}/${id}/nets`, { params })
}
export function getAliRds(params) {
return request.get(`${url}/mysql`, { params })
export function getRds(params) {
return request.get(`${url}`, { params })
}
export function detailAliRds(id) {
return request.get(`${url}/mysql/${id}`)
export function detailRds(id) {
return request.get(`${url}/${id}`)
}
export function patchAliRds(id) {
return request.patch(`${url}/mysql/${id}`)
export function patchRds(id) {
return request.patch(`${url}/${id}`)
}
export function removeAliRds(id) {
return request.delete(`${url}/mysql/${id}`)
export function removeRds(id) {
return request.delete(`${url}/${id}`)
}
export function getRdsUsers(id, params) {
return request.get(`${url}/mysql/${id}/users`, { params })
return request.get(`${url}/${id}/users`, { params })
}
export function createRdsUsers(id, params) {
return request.post(`${url}/mysql/${id}/users`, params)
return request.post(`${url}/${id}/users`, params)
}
export function removeRdsUsers(params) {
return request.delete(`${url}/mysql/${params.rdsId}/users/${params.userId}`)
return request.delete(`${url}/${params.rdsId}/users/${params.userId}`)
}
export function resetRdsUserPasd(params) {
return request.put(`${url}/mysql/${params.rdsId}/users/${params.userId}/resetpassword`, wrapperParams(params))
return request.put(`${url}/${params.rdsId}/users/${params.userId}/resetpassword`, wrapperParams(params))
}
export function resetRdsUser(params) {
return request.put(`${url}/mysql/${params.rdsId}/users/${params.userId}/resetaccount`, wrapperParams(params))
return request.put(`${url}/${params.rdsId}/users/${params.userId}/resetaccount`, wrapperParams(params))
}
export function authRdsUser(params) {
return request.put(`${url}/mysql/${params.rdsId}/users/${params.userId}/dbs`, wrapperParams(params))
return request.put(`${url}/${params.rdsId}/users/${params.userId}/dbs`, wrapperParams(params))
}
export function createRdsDbs(id, params) {
return request.post(`${url}/mysql/${id}/dbs`, params)
return request.post(`${url}/${id}/dbs`, params)
}
export function removeRdsDbs(params) {
return request.delete(`${url}/mysql/${params.rdsId}/dbs/${params.dbId}`)
}
export function getFlavorSpec(params) {
return request.get(`${url}/mysql/flavors/spec`, { params })
return request.delete(`${url}/${params.rdsId}/dbs/${params.dbId}`)
}