Compare commits
2 Commits
master
...
x-20250106
Author | SHA1 | Date |
---|---|---|
|
0aca3945e8 | |
|
94b3ccffeb |
53
.eslintrc.js
53
.eslintrc.js
|
@ -1,29 +1,24 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
extends: ['plugin:vue/essential', '@vue/standard', '@vue/typescript'],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-unused-vars': [
|
||||
0,
|
||||
{
|
||||
vars: 'all',
|
||||
args: 'none'
|
||||
}
|
||||
],
|
||||
semi: 0,
|
||||
eqeqeq: 0,
|
||||
'one-var': 0,
|
||||
camelcase: 0,
|
||||
'no-case-declarations': 0,
|
||||
'space-before-function-paren': 0,
|
||||
'vue/no-parsing-error': [2, { "x-invalid-end-tag": false }],
|
||||
'@typescript-eslint/indent': ['error', 2]
|
||||
},
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
}
|
||||
};
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: ['plugin:vue/essential', '@vue/standard', '@vue/typescript'],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-unused-vars': [0, { vars: 'all', args: 'none' }],
|
||||
semi: 0,
|
||||
eqeqeq: 0,
|
||||
'one-var': 0,
|
||||
camelcase: 0,
|
||||
'no-case-declarations': 0,
|
||||
'space-before-function-paren': 0,
|
||||
'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }],
|
||||
'@typescript-eslint/indent': ['error', 2],
|
||||
'comma-dangle': ['error', 2],
|
||||
},
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
; Force npm to always require authentication when accessing the registry, even for GET requests.
|
||||
; always-auth = false
|
||||
|
||||
; The location of npm's cache directory. See npm-cache (https://docs.npmjs.com/cli/cache)
|
||||
; Default: Windows: %AppData%\npm-cache, Posix: ~/.npm
|
||||
; cache =
|
||||
|
||||
; What level of logs to report. On failure, all logs are written to npm-debug.log in the current working directory.
|
||||
; Any logs of a higher level than the setting are shown. The default is "warn", which shows warn and error output.
|
||||
; Default: "warn"
|
||||
; Values: "silent", "error", "warn", "http", "info", "verbose", "silly"
|
||||
; loglevel =
|
||||
|
||||
; The config file to read for global config options.
|
||||
; Default: {prefix}/etc/npmrc
|
||||
; globalconfig =
|
||||
|
||||
; The location to install global items. If set on the command line, then it forces non-global commands to run in the specified folder.
|
||||
; Default: see npm-folders (https://docs.npmjs.com/files/folders)
|
||||
; prefix =
|
||||
|
||||
; The base URL of the npm package registry.
|
||||
; Default: https://registry.npmjs.org/
|
||||
registry = http://58.210.154.140:13011/repository/bocloud-npm/
|
||||
auto-install-peers = true
|
||||
strict-peer-dependencies = false
|
||||
shamefully-hoist = true
|
||||
always-auth = true
|
||||
_auth = Ym9jbG91ZDpjbXBAdjU4Nw==
|
||||
|
||||
; If set to false, then ignore npm-shrinkwrap.json files when installing.
|
||||
; Default: true
|
||||
; shrinkwrap =
|
|
@ -1,10 +1,9 @@
|
|||
@media screen and(-ms-high-contrast:active),
|
||||
(-ms-high-contrast:none) {
|
||||
.el-table__header,
|
||||
.el-table__body {
|
||||
width: 100% !important;
|
||||
}
|
||||
/* .basic-form-item{
|
||||
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||
.el-table__header,
|
||||
.el-table__body {
|
||||
width: 100% !important;
|
||||
}
|
||||
/* .basic-form-item{
|
||||
height: 32.76px;
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
// 正反编译
|
||||
export function booleanFilter(value) {
|
||||
const obj = {
|
||||
|
@ -6,7 +8,7 @@ export function booleanFilter(value) {
|
|||
1: '是',
|
||||
0: '否',
|
||||
YES: '是',
|
||||
NO: '否'
|
||||
NO: '否',
|
||||
}
|
||||
return obj[value] || value
|
||||
}
|
||||
|
@ -29,7 +31,10 @@ export function vmStatusFilter(status) {
|
|||
UNKNOWN: '已断开',
|
||||
UNKNOWNON: '已断开',
|
||||
UNKNOWNOFF: '已断开',
|
||||
UNKNOWNSUSPEND: '已断开'
|
||||
UNKNOWNSUSPEND: '已断开',
|
||||
RECYCLING: '回收中',
|
||||
MIGRATING: '迁移中',
|
||||
FAULT_RESUMING: '故障恢复中',
|
||||
}
|
||||
return statusMap[status] || '未知'
|
||||
}
|
||||
|
@ -95,7 +100,10 @@ export function vmStatusColorFilter(status) {
|
|||
DISABLED: 'danger',
|
||||
DEALLOCATEING: 'warning',
|
||||
PROTECTING: 'warning',
|
||||
DOWN: 'info'
|
||||
DOWN: 'info',
|
||||
RECYCLING: 'warning',
|
||||
MIGRATING: 'warning',
|
||||
FAULT_RESUMING: 'warning',
|
||||
}
|
||||
return statusMap[status] || 'danger'
|
||||
}
|
||||
|
@ -104,12 +112,12 @@ export function taskStatusFilter(value, type) {
|
|||
const statusMap = {
|
||||
DEVELOPING: '开发中',
|
||||
APPROVING: '发布中',
|
||||
APPROVED: ' 已发布'
|
||||
APPROVED: ' 已发布',
|
||||
}
|
||||
const colorMap = {
|
||||
DEVELOPING: 'normal',
|
||||
APPROVING: 'warning',
|
||||
APPROVED: 'success'
|
||||
APPROVED: 'success',
|
||||
}
|
||||
return type === 'color' ? colorMap[value] : statusMap[value]
|
||||
}
|
||||
|
@ -123,7 +131,7 @@ export function taskTypeFilter(value) {
|
|||
RECOVERY: '文件恢复',
|
||||
HTTP: 'HTTP请求',
|
||||
DATABASE: '数据库',
|
||||
POINT: '聚合节点'
|
||||
POINT: '聚合节点',
|
||||
}
|
||||
return obj[value]
|
||||
}
|
||||
|
@ -140,20 +148,20 @@ export function applyStatusFilter(value, type) {
|
|||
// },
|
||||
APPROVED: {
|
||||
name: '已发布',
|
||||
color: 'success'
|
||||
color: 'success',
|
||||
},
|
||||
DEVELOPING: {
|
||||
name: '开发中',
|
||||
color: 'normal'
|
||||
color: 'normal',
|
||||
},
|
||||
UNAPPLY: {
|
||||
name: '未发布',
|
||||
color: 'primary'
|
||||
color: 'primary',
|
||||
},
|
||||
CREATED: {
|
||||
name: '新创建',
|
||||
color: 'normal'
|
||||
}
|
||||
color: 'normal',
|
||||
},
|
||||
}
|
||||
return obj[value] && obj[value][type]
|
||||
}
|
||||
|
@ -162,48 +170,62 @@ export function taskExeStatusFilter(value, type = 'name') {
|
|||
const obj = {
|
||||
CREATED: {
|
||||
name: '未执行',
|
||||
color: 'normal'
|
||||
color: 'normal',
|
||||
},
|
||||
NOREADY: {
|
||||
name: '已跳过',
|
||||
color: 'warning'
|
||||
color: 'warning',
|
||||
},
|
||||
READY: {
|
||||
name: '准备中',
|
||||
color: 'normal'
|
||||
color: 'normal',
|
||||
},
|
||||
WAITTING: {
|
||||
name: '等待执行',
|
||||
color: 'primary'
|
||||
color: 'primary',
|
||||
},
|
||||
CANCELING: {
|
||||
name: '取消中',
|
||||
color: 'primary'
|
||||
color: 'primary',
|
||||
},
|
||||
RUNNING: {
|
||||
name: '正在执行',
|
||||
color: 'normal'
|
||||
color: 'normal',
|
||||
},
|
||||
SUCCESS: {
|
||||
name: '执行成功',
|
||||
color: 'success'
|
||||
color: 'success',
|
||||
},
|
||||
SUSPENDED: {
|
||||
name: '已暂停',
|
||||
color: 'warning'
|
||||
color: 'warning',
|
||||
},
|
||||
FAILED: {
|
||||
name: '执行失败',
|
||||
color: 'danger'
|
||||
color: 'danger',
|
||||
},
|
||||
CANCELED: {
|
||||
name: '手动结束',
|
||||
color: 'warning'
|
||||
color: 'warning',
|
||||
},
|
||||
EXCEPTION: {
|
||||
name: '执行异常',
|
||||
color: 'danger'
|
||||
}
|
||||
color: 'danger',
|
||||
},
|
||||
}
|
||||
return obj[value] && obj[value][type] // 容错处理(初始化值不存在)
|
||||
}
|
||||
const filters = {
|
||||
booleanFilter,
|
||||
vmStatusFilter,
|
||||
vmStatusColorFilter,
|
||||
taskStatusFilter,
|
||||
taskTypeFilter,
|
||||
applyStatusFilter,
|
||||
taskExeStatusFilter,
|
||||
}
|
||||
|
||||
// 注册全局过滤器
|
||||
Object.keys(filters).forEach((key) => {
|
||||
Vue.filter(key, filters[key])
|
||||
})
|
||||
|
|
21
src/main.ts
21
src/main.ts
|
@ -21,21 +21,22 @@ import './icons'
|
|||
import VueCompositionAPI from '@vue/composition-api'
|
||||
import rules from '@/validate/index'
|
||||
import actions from './shared/action'
|
||||
import './filters'
|
||||
|
||||
Vue.use(ElementUI, { size: 'small' });
|
||||
Vue.use(ElementUI, { size: 'small' })
|
||||
Vue.use(VueCompositionAPI)
|
||||
Vue.use(CmpElement, { rules })
|
||||
Vue.use(CmpEcharts)
|
||||
Vue.config.productionTip = false
|
||||
|
||||
let instance: any = null
|
||||
function render(props:any) {
|
||||
const { appPath = '', container } = props;
|
||||
function render(props: any) {
|
||||
const { appPath = '', container } = props
|
||||
instance = new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount(container ? container.querySelector('#app') : '#app');
|
||||
render: (h) => h(App),
|
||||
}).$mount(container ? container.querySelector('#app') : '#app')
|
||||
store.commit('SET_APP_PATH', appPath)
|
||||
}
|
||||
if (!(window as any).__POWERED_BY_QIANKUN__) {
|
||||
|
@ -48,8 +49,8 @@ export async function bootstrap() {
|
|||
}
|
||||
|
||||
export async function mount(props: any) {
|
||||
console.log('cop app mounted');
|
||||
const getStyle = window.getComputedStyle;
|
||||
console.log('cop app mounted')
|
||||
const getStyle = window.getComputedStyle
|
||||
// @ts-ignore
|
||||
// window.getComputedStyle = (element, property) => {
|
||||
// if (!element || element.nodeType === 9) return {};
|
||||
|
@ -57,10 +58,10 @@ export async function mount(props: any) {
|
|||
// };
|
||||
render(props)
|
||||
actions.init(props, (state: any) => {
|
||||
const { permissions, userData } = state;
|
||||
userData && store.commit('SET_USERDATA', userData);
|
||||
const { permissions, userData } = state
|
||||
userData && store.commit('SET_USERDATA', userData)
|
||||
if (!store.getters.addRoutes && permissions) {
|
||||
store.dispatch('permission/GenerateRoutes');
|
||||
store.dispatch('permission/GenerateRoutes')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -83,9 +83,7 @@
|
|||
</template>
|
||||
<el-table-column label="状态">
|
||||
<template slot-scope="scope">
|
||||
<status-icon :type="vmStatusColorFilter(scope.row.status)">
|
||||
{{ vmStatusFilter(scope.row.status) }}
|
||||
</status-icon>
|
||||
<status-icon :type="scope.row.status | vmStatusColorFilter"> {{ scope.row.status | vmStatusFilter }} </status-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="平台名称" prop="vendorName"></el-table-column>
|
||||
|
@ -110,36 +108,34 @@ export default {
|
|||
mixins: [show],
|
||||
props: {
|
||||
itemData: {
|
||||
type: Object
|
||||
type: Object,
|
||||
},
|
||||
osCategory: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
hasResource: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
vmStatusFilter,
|
||||
vmStatusColorFilter,
|
||||
list: null,
|
||||
total: null,
|
||||
listQuery: {
|
||||
name: '',
|
||||
privateIps: ''
|
||||
privateIps: '',
|
||||
},
|
||||
params: {
|
||||
page: 1,
|
||||
rows: 10
|
||||
rows: 10,
|
||||
},
|
||||
dialogServerVisible: false,
|
||||
vendorOptions: '',
|
||||
selectList: [],
|
||||
idList: [],
|
||||
http: getResource
|
||||
http: getResource,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -148,12 +144,12 @@ export default {
|
|||
computed: {
|
||||
path() {
|
||||
return this.$route.path
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
path(val) {
|
||||
this.http = val.includes('PatchDeploy') ? getHosts : getResource
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clearCustomParams() {
|
||||
|
@ -183,7 +179,7 @@ export default {
|
|||
this.listQuery = {
|
||||
name: '',
|
||||
privateIps: '',
|
||||
vendorId: ''
|
||||
vendorId: '',
|
||||
}
|
||||
this.params.page = 1
|
||||
this.selectList = []
|
||||
|
@ -196,7 +192,7 @@ export default {
|
|||
host: data.host,
|
||||
username: data.user,
|
||||
password: data.pasd,
|
||||
osCategory: data.category
|
||||
osCategory: data.category,
|
||||
})
|
||||
})
|
||||
this.dialogServerVisible = true
|
||||
|
@ -206,7 +202,7 @@ export default {
|
|||
this.$confirm('您确定要清空所选主机吗?', '提示', {
|
||||
confirmButtonText: '清空',
|
||||
confirmButtonClass: 'el-button--danger',
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
this.clearCustomParams()
|
||||
this.itemData.hostList = []
|
||||
|
@ -223,7 +219,7 @@ export default {
|
|||
},
|
||||
getVendor() {
|
||||
getCloudVendor({
|
||||
simple: true
|
||||
simple: true,
|
||||
}).then((data) => {
|
||||
if (data.success) {
|
||||
this.vendorOptions = data.data.rows
|
||||
|
@ -305,7 +301,7 @@ export default {
|
|||
category: this.path.includes('PatchDeploy') ? '' : 'Computer',
|
||||
catalog: this.path.includes('PatchDeploy') ? 'Computer' : '',
|
||||
osCategory: this.osCategory,
|
||||
vendorId: this.listQuery.vendorId
|
||||
vendorId: this.listQuery.vendorId,
|
||||
})
|
||||
this.getList()
|
||||
},
|
||||
|
@ -326,7 +322,7 @@ export default {
|
|||
pasd: data.password || getPassword(data),
|
||||
port: data.osCategory.toUpperCase() === 'WINDOWS' ? 5986 : 22,
|
||||
category: data.osCategory,
|
||||
privateIps: this.path.includes('PatchDeploy') ? '' : data.privateIps
|
||||
privateIps: this.path.includes('PatchDeploy') ? '' : data.privateIps,
|
||||
}
|
||||
if (data.paramsList) {
|
||||
tmp.paramsList = data.paramsList
|
||||
|
@ -339,13 +335,13 @@ export default {
|
|||
this.itemData.resourceList = this.itemData.hostList.slice()
|
||||
this.itemData.resourceList.unshift({
|
||||
id: 0,
|
||||
rawName: '选择全部'
|
||||
rawName: '选择全部',
|
||||
})
|
||||
}
|
||||
this.clearCustomParams()
|
||||
this.dialogServerVisible = false
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
|
|
|
@ -15,32 +15,24 @@
|
|||
<el-col :span="24">
|
||||
<el-form-item label="">
|
||||
<smart-table :data="itemData.targets" class="target-table">
|
||||
<el-table-column label="主机名称" prop="name" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column label="主机名称" prop="name" show-overflow-tooltip> </el-table-column>
|
||||
<el-table-column label="IP">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.host" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="(item, index) in scope.row.privateIps"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="item">
|
||||
</el-option>
|
||||
<el-option v-for="(item, index) in scope.row.privateIps" :key="index" :label="item" :value="item"> </el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="端口">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.port'"
|
||||
:rules="{required: true, message: '请填写端口号'}">
|
||||
<el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.port'" :rules="{ required: true, message: '请填写端口号' }">
|
||||
<el-input v-model="scope.row.port" type="number"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="用户名">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.user'"
|
||||
:rules="{required: true, message: '请填写用户名'}">
|
||||
<el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.user'" :rules="{ required: true, message: '请填写用户名' }">
|
||||
<el-input v-model="scope.row.user"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
@ -61,47 +53,37 @@
|
|||
</smart-table>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible"
|
||||
append-to-body>
|
||||
<el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" append-to-body>
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-select clearable v-model="listQuery.vendorId" placeholder="所属平台">
|
||||
<el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
<el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id"> </el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="IP地址" v-model="listQuery.ip">
|
||||
</el-input>
|
||||
<el-input placeholder="IP地址" v-model="listQuery.ip"> </el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="主机名" v-model="listQuery.name">
|
||||
</el-input>
|
||||
<el-input placeholder="主机名" v-model="listQuery.name"> </el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="ghost" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<basic-table :data="list" :params="params" :get-list="getList" :total="total" ref="serverTable1"
|
||||
@select="handleSelectItem" @select-all="handleSelectAll">
|
||||
<el-table-column type="selection" :selectable="selectAble" width="60">
|
||||
</el-table-column>
|
||||
<el-table-column label="主机名" prop="name">
|
||||
</el-table-column>
|
||||
<basic-table :data="list" :params="params" :get-list="getList" :total="total" ref="serverTable1" @select="handleSelectItem" @select-all="handleSelectAll">
|
||||
<el-table-column type="selection" :selectable="selectAble" width="60"> </el-table-column>
|
||||
<el-table-column label="主机名" prop="name"> </el-table-column>
|
||||
<el-table-column label="IP">
|
||||
<template slot-scope="scope">
|
||||
<div v-for="(item, index) in scope.row.privateIps" :key="index">{{item}}</div>
|
||||
<div v-for="(item, index) in scope.row.privateIps" :key="index">{{ item }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态">
|
||||
<template slot-scope="scope">
|
||||
<status-icon :type="vmStatusColorFilter(scope.row.status)">
|
||||
{{vmStatusFilter(scope.row.status)}}
|
||||
</status-icon>
|
||||
<status-icon :type="scope.row.status | vmStatusColorFilter"> {{ scope.row.status | vmStatusFilter }} </status-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="平台名称" prop="vendorName">
|
||||
</el-table-column>
|
||||
<el-table-column label="平台名称" prop="vendorName"> </el-table-column>
|
||||
</basic-table>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="ghost" @click.native="dialogServerVisible = false">取消</el-button>
|
||||
|
@ -118,47 +100,42 @@ import { vmStatusFilter, vmStatusColorFilter } from '@/filters/index'
|
|||
export default {
|
||||
props: {
|
||||
itemData: {
|
||||
type: Object
|
||||
}
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
vmStatusFilter,
|
||||
vmStatusColorFilter,
|
||||
list: null,
|
||||
total: null,
|
||||
listQuery: {
|
||||
name: '',
|
||||
privateIps: '',
|
||||
catalog: ''
|
||||
catalog: '',
|
||||
},
|
||||
params: {
|
||||
page: 1,
|
||||
rows: 10
|
||||
rows: 10,
|
||||
},
|
||||
dialogServerVisible: false,
|
||||
vendorOptions: '',
|
||||
selectList: [],
|
||||
idList: []
|
||||
idList: [],
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
selectAble (row) {
|
||||
selectAble(row) {
|
||||
if (row.osCategory && row.osCategory.toLowerCase() == 'linux' && row.status && row.status.toLowerCase() == 'running') {
|
||||
if (row.catalog.toLowerCase() == 'physical') {
|
||||
const server = JSON.parse(row.inventory)
|
||||
if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) ||
|
||||
(server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if (server.powerState.toLowerCase() == 'running') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else if (row.catalog.toLowerCase() == 'logical') {
|
||||
const cloud_server = JSON.parse(row.inventory)
|
||||
if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) ||
|
||||
(cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if (cloud_server.status.toLowerCase() == 'running') {
|
||||
return true
|
||||
}
|
||||
|
@ -167,41 +144,41 @@ export default {
|
|||
}
|
||||
return false
|
||||
},
|
||||
selectServer () {
|
||||
selectServer() {
|
||||
this.getVendor()
|
||||
// 初始化数据
|
||||
this.listQuery = {
|
||||
name: '',
|
||||
privateIps: '',
|
||||
catalog: '',
|
||||
vendorId: ''
|
||||
vendorId: '',
|
||||
}
|
||||
this.params.page = 1
|
||||
this.selectList = []
|
||||
// 对数据进行格式化以适应后端的传参需求
|
||||
this.itemData.targets.forEach(data => {
|
||||
this.itemData.targets.forEach((data) => {
|
||||
this.selectList.push({
|
||||
id: data.resourceId,
|
||||
name: data.name,
|
||||
host: data.host,
|
||||
username: data.user,
|
||||
password: data.pasd ? crypto.encrypt(data.pasd) : data.pasd,
|
||||
osCategory: data.category
|
||||
osCategory: data.category,
|
||||
})
|
||||
})
|
||||
this.dialogServerVisible = true
|
||||
this.handleSearch()
|
||||
},
|
||||
clearServer () {
|
||||
clearServer() {
|
||||
this.$confirm('您确定要清空所选主机吗?', '提示', {
|
||||
confirmButtonText: '清空',
|
||||
confirmButtonClass: 'el-button--danger',
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
this.itemData.targets = []
|
||||
})
|
||||
},
|
||||
delServer (id) {
|
||||
delServer(id) {
|
||||
for (let i = 0, len = this.itemData.targets.length; i < len; i++) {
|
||||
if (this.itemData.targets[i].id === id) {
|
||||
this.itemData.targets.splice(i, 1)
|
||||
|
@ -209,16 +186,16 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
getVendor () {
|
||||
getVendor() {
|
||||
getCloudVendor({
|
||||
simple: true
|
||||
}).then(data => {
|
||||
simple: true,
|
||||
}).then((data) => {
|
||||
if (data.success) {
|
||||
this.vendorOptions = data.data.rows
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSelectItem (selection, row) {
|
||||
handleSelectItem(selection, row) {
|
||||
this.refreshId()
|
||||
if (this.idList.indexOf(row.id) > -1) {
|
||||
for (let j = 0; j < this.selectList.length; j++) {
|
||||
|
@ -232,16 +209,18 @@ export default {
|
|||
this.selectList.push(row)
|
||||
}
|
||||
},
|
||||
handleSelectAll (selection) {
|
||||
handleSelectAll(selection) {
|
||||
this.refreshId()
|
||||
if (selection.length) { // 全选情况下
|
||||
this.list.forEach(item => {
|
||||
if (selection.length) {
|
||||
// 全选情况下
|
||||
this.list.forEach((item) => {
|
||||
if (this.idList.indexOf(item.id) == -1 && item.privateIps.length && item.status != 'STOPPED') {
|
||||
this.selectList.push(item)
|
||||
}
|
||||
})
|
||||
} else { // 全不选情况下
|
||||
this.list.forEach(item => {
|
||||
} else {
|
||||
// 全不选情况下
|
||||
this.list.forEach((item) => {
|
||||
if (this.idList.indexOf(item.id) > -1) {
|
||||
for (let j = 0; j < this.selectList.length; j++) {
|
||||
const row = this.selectList[j]
|
||||
|
@ -254,13 +233,13 @@ export default {
|
|||
})
|
||||
}
|
||||
},
|
||||
refreshId () {
|
||||
refreshId() {
|
||||
this.idList = []
|
||||
this.selectList.forEach(item => {
|
||||
this.selectList.forEach((item) => {
|
||||
this.idList.push(item.id)
|
||||
})
|
||||
},
|
||||
getList () {
|
||||
getList() {
|
||||
const self = this
|
||||
this.refreshId()
|
||||
const handleData = function (data) {
|
||||
|
@ -271,7 +250,7 @@ export default {
|
|||
})
|
||||
})
|
||||
}
|
||||
getResource(this.params).then(data => {
|
||||
getResource(this.params).then((data) => {
|
||||
if (data.success) {
|
||||
this.list = data.data.rows
|
||||
this.total = data.data.total
|
||||
|
@ -279,20 +258,20 @@ export default {
|
|||
}
|
||||
})
|
||||
},
|
||||
handleSearch () {
|
||||
handleSearch() {
|
||||
this.params.page = 1
|
||||
this.params.params = this.$tools.handleSearchParam({
|
||||
vendorId: this.listQuery.vendorId,
|
||||
category: 'Computer',
|
||||
catalog: this.listQuery.catalog,
|
||||
'name:LK': this.listQuery.name,
|
||||
'privateIps:LK': this.listQuery.ip
|
||||
'privateIps:LK': this.listQuery.ip,
|
||||
})
|
||||
this.getList()
|
||||
},
|
||||
ok () {
|
||||
ok() {
|
||||
this.itemData.targets = []
|
||||
this.selectList.forEach(data => {
|
||||
this.selectList.forEach((data) => {
|
||||
this.itemData.targets.push({
|
||||
resourceId: data.id,
|
||||
name: data.name,
|
||||
|
@ -302,17 +281,16 @@ export default {
|
|||
pasd: data.password ? crypto.decrypt(data.password) : data.password,
|
||||
category: data.osCategory,
|
||||
sudo: true,
|
||||
privateIps: data.privateIps
|
||||
privateIps: data.privateIps,
|
||||
})
|
||||
})
|
||||
this.dialogServerVisible = false
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.target-table .el-form-item.is-error {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.target-table .el-form-item.is-error {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,32 +11,24 @@
|
|||
<el-col :span="24">
|
||||
<el-form-item label="">
|
||||
<smart-table :data="itemData.targets" class="target-table">
|
||||
<el-table-column label="主机名称" prop="name" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column label="主机名称" prop="name" show-overflow-tooltip> </el-table-column>
|
||||
<el-table-column label="IP">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.host" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="(item, index) in scope.row.privateIps"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="item">
|
||||
</el-option>
|
||||
<el-option v-for="(item, index) in scope.row.privateIps" :key="index" :label="item" :value="item"> </el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="端口">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.port'"
|
||||
:rules="{required: true, message: '请填写端口号'}">
|
||||
<el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.port'" :rules="{ required: true, message: '请填写端口号' }">
|
||||
<el-input v-model="scope.row.port" type="number"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="用户名">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.user'"
|
||||
:rules="{required: true, message: '请填写用户名'}">
|
||||
<el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.user'" :rules="{ required: true, message: '请填写用户名' }">
|
||||
<el-input v-model="scope.row.user"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
@ -57,22 +49,18 @@
|
|||
</smart-table>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible"
|
||||
append-to-body>
|
||||
<el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" append-to-body>
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-select clearable v-model="listQuery.vendorId" placeholder="所属平台">
|
||||
<el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
<el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id"> </el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="IP地址" v-model="listQuery.ip">
|
||||
</el-input>
|
||||
<el-input placeholder="IP地址" v-model="listQuery.ip"> </el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="主机名" v-model="listQuery.name">
|
||||
</el-input>
|
||||
<el-input placeholder="主机名" v-model="listQuery.name"> </el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="ghost" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
||||
|
@ -82,24 +70,21 @@
|
|||
<el-table-column label="主机名称">
|
||||
<template slot-scope="scope">
|
||||
<el-radio :label="scope.row.id" v-model="targetId" :disabled="selectAble(scope.row)" @change.native="getCurrentRow(scope.row)">
|
||||
<span style="font-size: 12px;">{{scope.row.name}}</span>
|
||||
<span style="font-size: 12px">{{ scope.row.name }}</span>
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="IP">
|
||||
<template slot-scope="scope">
|
||||
<div v-for="(item, index) in scope.row.privateIps" :key="index">{{item}}</div>
|
||||
<div v-for="(item, index) in scope.row.privateIps" :key="index">{{ item }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态">
|
||||
<template slot-scope="scope">
|
||||
<status-icon :type="vmStatusColorFilter(scope.row.status)">
|
||||
{{vmStatusFilter(scope.row.status)}}
|
||||
</status-icon>
|
||||
<status-icon :type="scope.row.status | vmStatusColorFilter"> {{ scope.row.status | vmStatusFilter }} </status-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="平台名称" prop="vendorName">
|
||||
</el-table-column>
|
||||
<el-table-column label="平台名称" prop="vendorName"> </el-table-column>
|
||||
</basic-table>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="ghost" @click.native="dialogServerVisible = false">取消</el-button>
|
||||
|
@ -116,48 +101,43 @@ import crypto from 'utils/crypto.js'
|
|||
export default {
|
||||
props: {
|
||||
itemData: {
|
||||
type: Object
|
||||
}
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
vmStatusFilter,
|
||||
vmStatusColorFilter,
|
||||
list: null,
|
||||
total: null,
|
||||
listQuery: {
|
||||
name: '',
|
||||
privateIps: ''
|
||||
privateIps: '',
|
||||
},
|
||||
params: {
|
||||
page: 1,
|
||||
rows: 10
|
||||
rows: 10,
|
||||
},
|
||||
dialogServerVisible: false,
|
||||
groupOptions: '',
|
||||
vendorOptions: '',
|
||||
selectList: [],
|
||||
idList: [],
|
||||
targetId: null
|
||||
targetId: null,
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
selectAble (row) {
|
||||
selectAble(row) {
|
||||
if (row.osCategory && row.osCategory.toLowerCase() == 'linux' && row.status.toLowerCase() == 'running') {
|
||||
if (row.catalog.toLowerCase() == 'physical') {
|
||||
const server = JSON.parse(row.inventory)
|
||||
if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) ||
|
||||
(server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if (server.powerState.toLowerCase() == 'running') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else if (row.catalog.toLowerCase() == 'logical') {
|
||||
const cloud_server = JSON.parse(row.inventory)
|
||||
if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) ||
|
||||
(cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
|
||||
if (cloud_server.status.toLowerCase() == 'running') {
|
||||
return false
|
||||
}
|
||||
|
@ -166,51 +146,51 @@ export default {
|
|||
}
|
||||
return true
|
||||
},
|
||||
selectServer () {
|
||||
selectServer() {
|
||||
this.getVendor()
|
||||
// 初始化数据
|
||||
this.listQuery = {
|
||||
name: '',
|
||||
privateIps: '',
|
||||
vendorId: ''
|
||||
vendorId: '',
|
||||
}
|
||||
this.params.page = 1
|
||||
this.selectList = []
|
||||
// 对数据进行格式化以适应后端的传参需求
|
||||
this.itemData.targets.forEach(data => {
|
||||
this.itemData.targets.forEach((data) => {
|
||||
this.selectList.push({
|
||||
id: data.resourceId,
|
||||
name: data.name,
|
||||
host: data.host,
|
||||
username: data.user,
|
||||
password: data.pasd ? crypto.encrypt(data.pasd) : data.pasd,
|
||||
osCategory: data.category
|
||||
osCategory: data.category,
|
||||
})
|
||||
})
|
||||
this.dialogServerVisible = true
|
||||
this.handleSearch()
|
||||
},
|
||||
delServer () {
|
||||
this.selectList = [];
|
||||
this.itemData.targets = [];
|
||||
this.targetId = null;
|
||||
delServer() {
|
||||
this.selectList = []
|
||||
this.itemData.targets = []
|
||||
this.targetId = null
|
||||
},
|
||||
getVendor () {
|
||||
getVendor() {
|
||||
getCloudVendor({
|
||||
simple: true
|
||||
}).then(data => {
|
||||
simple: true,
|
||||
}).then((data) => {
|
||||
if (data.success) {
|
||||
this.vendorOptions = data.data.rows
|
||||
}
|
||||
})
|
||||
},
|
||||
refreshId () {
|
||||
refreshId() {
|
||||
this.idList = []
|
||||
this.selectList.forEach(item => {
|
||||
this.selectList.forEach((item) => {
|
||||
this.idList.push(item.id)
|
||||
})
|
||||
},
|
||||
getList () {
|
||||
getList() {
|
||||
const self = this
|
||||
this.refreshId()
|
||||
const handleData = function (data) {
|
||||
|
@ -218,7 +198,7 @@ export default {
|
|||
item.privateIps = JSON.parse(item.privateIps)
|
||||
})
|
||||
}
|
||||
getResource(this.params).then(data => {
|
||||
getResource(this.params).then((data) => {
|
||||
if (data.success) {
|
||||
this.list = data.data.rows
|
||||
this.total = data.data.total
|
||||
|
@ -226,22 +206,22 @@ export default {
|
|||
}
|
||||
})
|
||||
},
|
||||
handleSearch () {
|
||||
handleSearch() {
|
||||
this.params.page = 1
|
||||
this.params.params = this.$tools.handleSearchParam({
|
||||
vendorId: this.listQuery.vendorId,
|
||||
category: 'Computer',
|
||||
'name:LK': this.listQuery.name,
|
||||
'privateIps:LK': this.listQuery.ip
|
||||
'privateIps:LK': this.listQuery.ip,
|
||||
})
|
||||
this.getList()
|
||||
},
|
||||
getCurrentRow (data) {
|
||||
this.selectList = [data];
|
||||
getCurrentRow(data) {
|
||||
this.selectList = [data]
|
||||
},
|
||||
ok () {
|
||||
ok() {
|
||||
this.itemData.targets = []
|
||||
this.selectList.forEach(data => {
|
||||
this.selectList.forEach((data) => {
|
||||
this.itemData.targets.push({
|
||||
resourceId: data.id,
|
||||
name: data.name,
|
||||
|
@ -251,17 +231,16 @@ export default {
|
|||
pasd: data.password ? crypto.decrypt(data.password) : data.password,
|
||||
category: data.osCategory,
|
||||
sudo: true,
|
||||
privateIps: data.privateIps
|
||||
privateIps: data.privateIps,
|
||||
})
|
||||
})
|
||||
this.dialogServerVisible = false
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.target-table .el-form-item.is-error {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.target-table .el-form-item.is-error {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/**
|
||||
* Created by HaijunZhang on 2019/4/28.
|
||||
*/
|
||||
<template>
|
||||
<common-wrapper code="storage" :add-data="addData" ref="common" :elements="elements" :get-params="getParams" :item-data="retention" :disabled="disabled" v-if="isLoadData">
|
||||
<basic-form :model="addData.configs" ref="addForm" label-position="left">
|
||||
<el-divider></el-divider>
|
||||
<h5>配置信息</h5>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<basic-form-item label="磁盘类别:" prop="diskType" validate = "required">
|
||||
<el-select v-model="addData.configs.diskType" placeholder="请先选择磁盘类别" @change="sizeChange">
|
||||
<el-option v-for="item in categoryData" :label="item.name" :value="item.value" :key="item.value"></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<basic-form-item label="大小:" >
|
||||
<el-input-number :min="minSize" :max="maxSize" v-model="currentElement.insAmount" placeholder="请输入大小"></el-input-number>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10" v-if="addData.configs.diskType == 'io1'">
|
||||
<basic-form-item label="IOPS:" prop="iops" validate="required">
|
||||
<el-input-number size="medium" v-model="addData.configs.iops" :min="100" :max="64000"> </el-input-number>
|
||||
<span class="info">IOPS和磁盘最大比率为 50:1</span>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider></el-divider>
|
||||
<h5>云配置信息</h5>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<basic-form-item label="名称:" validate="required" prop="name">
|
||||
<el-input v-model="addData.configs.name" placeholder="请输入名称"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<basic-form-item label="描述:" prop="remark">
|
||||
<el-input type="textarea" v-model="addData.configs.remark" placeholder="请输入描述"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</basic-form>
|
||||
<div slot="preview-card">
|
||||
<basic-form-item label="磁盘容量:">{{currentElement.insAmount}}GB</basic-form-item>
|
||||
</div>
|
||||
</common-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonWrapper from 'views/resource-apply/components/PublicCommonWrapper.vue';
|
||||
import { add, element } from '../data/publicInit'
|
||||
import { getSystemConfigs } from 'services/system/index'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { getShoppingCartDetail } from 'services/system/shop_cart'
|
||||
export default {
|
||||
components: { CommonWrapper },
|
||||
props: {
|
||||
type: {
|
||||
type: String
|
||||
},
|
||||
itemData: {
|
||||
type: [Object, Boolean]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
elements: [{
|
||||
...element,
|
||||
name: '云硬盘',
|
||||
serviceCode: 'bingocloudos.standard.volume',
|
||||
insAmount: 20,
|
||||
main: true
|
||||
}
|
||||
],
|
||||
addData: {
|
||||
...add,
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type,
|
||||
diskCategory: ''
|
||||
},
|
||||
service: 'bingocloudos.standard.volume',
|
||||
configs: {
|
||||
diskType: 'gp2',
|
||||
iops: 100
|
||||
}
|
||||
},
|
||||
categoryData: [
|
||||
{ name: '通用型 SSD', value: 'gp2', size: 1 },
|
||||
{ name: '预配置 IOPS SSD', value: 'io1', size: 4 },
|
||||
{ name: 'Cold HDD', value: 'sc1', size: 125 },
|
||||
{ name: '吞吐优化 HDD', value: 'st1', size: 125 },
|
||||
{ name: '磁介质', value: 'standard', size: 1 }
|
||||
],
|
||||
minSize: 20,
|
||||
maxSize: 100000,
|
||||
serverList: [],
|
||||
retention: false,
|
||||
isLoadData: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentElement () {
|
||||
return this.elements[0]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
getSystemConfigs({ codes: 'DefaultDiskSize' }).then(data => {
|
||||
if (data.success) {
|
||||
this.maxSize = Number(data.data.DefaultDiskSize)
|
||||
}
|
||||
})
|
||||
if (this.itemData) {
|
||||
this.retention = this.itemData
|
||||
this.addData = cloneDeep(this.retention)
|
||||
this.handleShowData()
|
||||
} else if (this.$route.query.id) {
|
||||
getShoppingCartDetail(this.$route.query.id).then(data => {
|
||||
if (data.success) {
|
||||
this.retention = JSON.parse(data.data.inventory)
|
||||
this.addData = cloneDeep(this.retention)
|
||||
this.handleShowData()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.addData = {
|
||||
...add,
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type,
|
||||
diskCategory: ''
|
||||
},
|
||||
service: 'bingocloudos.standard.volume',
|
||||
configs: {
|
||||
diskType: 'gp2',
|
||||
iops: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
this.isLoadData = true
|
||||
},
|
||||
watch: {
|
||||
'addData.location.vendorType' () {
|
||||
this.$emit('type', this.addData.location.vendorType)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sizeChange() {
|
||||
const obj = this.categoryData.find(item => item.value == this.addData.configs.diskType)
|
||||
this.minSize = obj.size
|
||||
this.currentElement.insAmount = obj.size
|
||||
if (this.addData.configs.diskType == 'io1') {
|
||||
this.addData.configs.iops = 100
|
||||
}
|
||||
},
|
||||
getPostData () {
|
||||
let data = false
|
||||
data = this.$refs.common.handlePostData()
|
||||
return data
|
||||
},
|
||||
// 数据回现展示
|
||||
handleShowData() {
|
||||
const { elements } = this.retention
|
||||
const [first, ...others] = elements
|
||||
this.elements = [
|
||||
{
|
||||
...element,
|
||||
...first,
|
||||
insAmount: this.addData.configs.size
|
||||
}
|
||||
]
|
||||
},
|
||||
getParams () {
|
||||
let data = false;
|
||||
this.$refs.addForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.addData.configs.size = this.currentElement.insAmount
|
||||
data = true
|
||||
}
|
||||
})
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
|
@ -9,6 +9,7 @@
|
|||
<tce :type="type" v-if="type == 'TCE'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></tce>
|
||||
<ali :type="type" v-if="type == 'ALIYUN'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></ali>
|
||||
<aws :type="type" v-if="type == 'AWS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></aws>
|
||||
<bingoCloudOS :type="type" v-if="type == 'BINGOCLOUDOS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></bingoCloudOS>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -19,6 +20,7 @@ import tencent from './tencent.vue'
|
|||
import tce from './tce.vue'
|
||||
import op from './op.vue'
|
||||
import aws from './aws.vue'
|
||||
import bingoCloudOS from './bingoCloudOS.vue'
|
||||
export default {
|
||||
props: {
|
||||
itemData: {
|
||||
|
@ -28,7 +30,7 @@ export default {
|
|||
type: Boolean
|
||||
}
|
||||
},
|
||||
components: { ali, op, huawei, tencent, aws, tce },
|
||||
components: { ali, op, huawei, tencent, aws, bingoCloudOS, tce },
|
||||
data () {
|
||||
return {
|
||||
type: ''
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :title="addData.title" :visible.sync="addData.dialog" width="50%" v-if="addData.dialog" append-to-body>
|
||||
<div>
|
||||
<el-form ref="data" :model="addData.data" :status-icon="true" label-width="120px">
|
||||
<basic-form-item label="卷类型" prop="catalog" validate="required">
|
||||
<el-select v-model="addData.data.catalog" @change="setCatelog" :disabled="addData.title === '编辑磁盘' && addData.data.catalog === 'root'">
|
||||
<el-option label="根" value="root" v-if="addData.title === '编辑磁盘'"></el-option>
|
||||
<el-option label="EBS" value="EBS"></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
<basic-form-item label="设备:" prop="device" validate="required">
|
||||
<el-select v-model="addData.data.device" :disabled="addData.title === '编辑磁盘' && addData.data.catalog === 'root'">
|
||||
<el-option label="/dev/xvda" value="/dev/xvda" v-if="addData.data.catalog === 'root'"></el-option>
|
||||
<template v-if="addData.data.catalog === 'EBS'">
|
||||
<!--<el-option label="/dev/sdb" value="/dev/sdb"></el-option>
|
||||
<el-option label="/dev/sdc" value="/dev/sdc"></el-option>
|
||||
<el-option label="/dev/sdd" value="/dev/sdd"></el-option>
|
||||
<el-option label="/dev/sde" value="/dev/sde"></el-option>
|
||||
<el-option label="/dev/sdf" value="/dev/sdf"></el-option>
|
||||
<el-option label="/dev/sdg" value="/dev/sdg"></el-option>
|
||||
<el-option label="/dev/sdh" value="/dev/sdh"></el-option>
|
||||
<el-option label="/dev/sdi" value="/dev/sdi"></el-option>
|
||||
<el-option label="/dev/sdj" value="/dev/sdj"></el-option>
|
||||
<el-option label="/dev/sdk" value="/dev/sdk"></el-option>
|
||||
<el-option label="/dev/sdl" value="/dev/sdl"></el-option>-->
|
||||
<el-option v-for="(item, index) in addData.deviceList" :key="`device-${index}`" :label="item.name" :value="item.value"> </el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
<basic-form-item label="类别:" prop="category" validate="required">
|
||||
<el-select v-model="addData.data.category" placeholder="请先选择磁盘类别" @change="sizeChange">
|
||||
<template v-if="addData.data.catalog === 'root'">
|
||||
<el-option v-for="item in categoryData" :label="item.name" :value="item.value" :key="item.value"></el-option>
|
||||
</template>
|
||||
<template v-if="addData.data.catalog === 'EBS'">
|
||||
<el-option v-for="item in categoryDatas" :label="item.name" :value="item.value" :key="item.value"></el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
<basic-form-item label="大小(GB):" prop="size" validate="required">
|
||||
<el-input-number size="medium" v-model="addData.data.size" :min="addData.data.size" :max="32768" v-if="addData.data.catalog === 'root'"> </el-input-number>
|
||||
<el-input-number size="medium" v-model="addData.data.size" :min="0" :max="32768" v-if="addData.data.catalog === 'EBS'"> </el-input-number>
|
||||
</basic-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="ghost" @click="back">取 消</el-button>
|
||||
<el-button type="primary" @click="ok">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
addData: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {
|
||||
data: {
|
||||
labelIds: []
|
||||
},
|
||||
dialog: false
|
||||
}
|
||||
}
|
||||
},
|
||||
networkList: {
|
||||
type: Array
|
||||
},
|
||||
xvda: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
categoryDatas: [
|
||||
{
|
||||
name: '通用型 SSD',
|
||||
value: 'gp2',
|
||||
size: 1
|
||||
},
|
||||
{
|
||||
name: '预配置 IOPS SSD',
|
||||
value: 'io1',
|
||||
size: 4
|
||||
},
|
||||
{
|
||||
name: 'Cold HDD',
|
||||
value: 'sc1',
|
||||
size: 500
|
||||
},
|
||||
{
|
||||
name: '吞吐优化 HDD',
|
||||
value: 'st1',
|
||||
size: 500
|
||||
},
|
||||
{
|
||||
name: '磁介质',
|
||||
value: 'standard',
|
||||
size: 1
|
||||
}
|
||||
],
|
||||
categoryData: [
|
||||
{
|
||||
name: '通用型 SSD',
|
||||
value: 'gp2',
|
||||
size: 1
|
||||
},
|
||||
{
|
||||
name: '预配置 IOPS SSD',
|
||||
value: 'io1',
|
||||
size: 4
|
||||
},
|
||||
{
|
||||
name: '磁介质',
|
||||
value: 'standard',
|
||||
size: 1
|
||||
}
|
||||
],
|
||||
sizeData: {
|
||||
gp2: 20,
|
||||
io1: 40,
|
||||
sc1: 500,
|
||||
st1: 500,
|
||||
standard: 1
|
||||
},
|
||||
regionList: [],
|
||||
minSize: 20
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setCatelog() {},
|
||||
back() {
|
||||
if (this.addData.title == '编辑磁盘' && this.xvda) this.$emit('back')
|
||||
this.addData.dialog = false
|
||||
},
|
||||
sizeChange() {
|
||||
this.minSize = this.sizeData[this.addData.data.category]
|
||||
this.addData.data.size = this.sizeData[this.addData.data.category]
|
||||
},
|
||||
ok() {
|
||||
this.$refs.data.validate(valid => {
|
||||
if (valid) {
|
||||
this.$emit('ok', this.addData)
|
||||
this.addData.dialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mine-text {
|
||||
font-size: 10px;
|
||||
color: #b4b4b4;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,273 @@
|
|||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<template v-for="(item, index) in tagList">
|
||||
<el-tag class="m-l-xs" :key="index" v-if="item.catalog === 'root'" :disable-transitions="false" @click.stop="modify(item, index)" @close.stop="handleClose(item, index)">
|
||||
{{ item.device }}
|
||||
</el-tag>
|
||||
<el-tag class="m-l-xs" :key="index" v-else closable :disable-transitions="false" @click.stop="modify(item, index)" @close.stop="handleClose(item, index)">
|
||||
{{ item.device }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<el-button size="mini" @click="add" type="primary" class="m-l-md">添加</el-button>
|
||||
<span class="mine-text m-l-md" v-if="!tagList.length">默认第一块为系统盘,其余为数据盘</span>
|
||||
</div>
|
||||
<add :add-data="addData" v-if="addData.dialog" @ok="addOk" :now-list="tagList"></add>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import add from './add.vue'
|
||||
export default {
|
||||
components: {
|
||||
add
|
||||
},
|
||||
props: {
|
||||
networkList: {
|
||||
type: Array
|
||||
},
|
||||
diskId: {
|
||||
type: [String, Number]
|
||||
},
|
||||
type: {
|
||||
type: String
|
||||
},
|
||||
imageData: {
|
||||
type: Array
|
||||
},
|
||||
source: {
|
||||
type: String
|
||||
},
|
||||
parentData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
diskId: {
|
||||
handler(newVal, oldVal) {
|
||||
this.tagList = []
|
||||
const result = this.imageData.filter((item) => Number(item.id) === Number(newVal))
|
||||
if (result.length !== 0) {
|
||||
const rows = result[0]
|
||||
if (rows.blockDeviceMappings) {
|
||||
JSON.parse(rows.blockDeviceMappings).forEach((item, index) => {
|
||||
const newItem = {
|
||||
device: item.deviceName
|
||||
}
|
||||
if (item.ebs) {
|
||||
newItem.size = item.ebs.volumeSize ? item.ebs.volumeSize : 40
|
||||
newItem.category = item.ebs.volumeTypeAsString
|
||||
}
|
||||
if (item.deviceName === rows.rootDeviceName) {
|
||||
newItem.catalog = 'root'
|
||||
} else {
|
||||
newItem.catalog = 'EBS'
|
||||
}
|
||||
this.tagList.push(newItem)
|
||||
if (rows.osCategory === 'windows') {
|
||||
this.deviceList = this.deviceListWin
|
||||
} else {
|
||||
this.deviceList = this.deviceListLinux
|
||||
}
|
||||
})
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.parentData && this.parentData.diskDevices) {
|
||||
this.tagList = this.parentData.diskDevices
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tagList: [],
|
||||
deviceList: [],
|
||||
deviceListLinux: [
|
||||
{
|
||||
name: '/dev/sdb',
|
||||
value: '/dev/sdb'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdc',
|
||||
value: '/dev/sdc'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdd',
|
||||
value: '/dev/sdd'
|
||||
},
|
||||
{
|
||||
name: '/dev/sde',
|
||||
value: '/dev/sde'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdf',
|
||||
value: '/dev/sdf'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdg',
|
||||
value: '/dev/sdg'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdh',
|
||||
value: '/dev/sdh'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdi',
|
||||
value: '/dev/sdi'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdj',
|
||||
value: '/dev/sdj'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdk',
|
||||
value: '/dev/sdk'
|
||||
},
|
||||
{
|
||||
name: '/dev/sdl',
|
||||
value: '/dev/sdl'
|
||||
}
|
||||
],
|
||||
deviceListWin: [
|
||||
{
|
||||
name: 'xvdb',
|
||||
value: 'xvdb'
|
||||
},
|
||||
{
|
||||
name: 'xvdc',
|
||||
value: 'xvdc'
|
||||
},
|
||||
{
|
||||
name: 'xvdd',
|
||||
value: 'xvdd'
|
||||
},
|
||||
{
|
||||
name: 'xvde',
|
||||
value: 'xvde'
|
||||
},
|
||||
{
|
||||
name: 'xvdf',
|
||||
value: 'xvdf'
|
||||
},
|
||||
{
|
||||
name: 'xvdg',
|
||||
value: 'xvdg'
|
||||
},
|
||||
{
|
||||
name: 'xvdh',
|
||||
value: 'xvdh'
|
||||
},
|
||||
{
|
||||
name: 'xvdi',
|
||||
value: 'xvdi'
|
||||
},
|
||||
{
|
||||
name: 'xvdj',
|
||||
value: 'xvdj'
|
||||
},
|
||||
{
|
||||
name: 'xvdk',
|
||||
value: 'xvdk'
|
||||
},
|
||||
{
|
||||
name: 'xvdl',
|
||||
value: 'xvdl'
|
||||
}
|
||||
],
|
||||
devices: [],
|
||||
addData: {
|
||||
dialog: false,
|
||||
data: {}
|
||||
},
|
||||
modifyData: {
|
||||
dialog: false,
|
||||
data: {}
|
||||
},
|
||||
nowList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose(data, index) {
|
||||
this.tagList.splice(index, 1)
|
||||
},
|
||||
getDevices() {
|
||||
let list = this.deviceList
|
||||
if (this.tagList.length == 0) {
|
||||
this.$message.error('请先选择系统盘!')
|
||||
return []
|
||||
}
|
||||
if (this.tagList.length > 1) {
|
||||
this.tagList.forEach((item, index) => {
|
||||
if (item.catalog === 'EBS') {
|
||||
list = list.filter((row) => row.value !== item.device)
|
||||
}
|
||||
})
|
||||
return list
|
||||
} else {
|
||||
if (this.tagList[0].catalog === 'root') {
|
||||
return list
|
||||
}
|
||||
}
|
||||
},
|
||||
add() {
|
||||
const list = this.getDevices()
|
||||
if (list.length) {
|
||||
this.addData = {
|
||||
dialog: true,
|
||||
title: '新增磁盘',
|
||||
deviceList: list,
|
||||
data: {
|
||||
device: '',
|
||||
size: 0,
|
||||
catalog: 'EBS',
|
||||
category: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
modify(data, index) {
|
||||
const list = this.getDevices()
|
||||
const arr = [
|
||||
{
|
||||
name: data.device,
|
||||
value: data.device
|
||||
}
|
||||
]
|
||||
const ss = data.catalog === 'EBS' ? list.concat(arr) : []
|
||||
this.addData = {
|
||||
dialog: true,
|
||||
index: index,
|
||||
title: '编辑磁盘',
|
||||
deviceList: ss,
|
||||
data: {
|
||||
catalog: data.catalog,
|
||||
device: data.device,
|
||||
size: data.size,
|
||||
category: data.category ? data.category : 'gp2',
|
||||
deleteWithInstance: data.deleteWithInstance
|
||||
}
|
||||
}
|
||||
},
|
||||
addOk(data) {
|
||||
if (data.index >= 0) {
|
||||
this.tagList[data.index] = data.data
|
||||
} else {
|
||||
this.tagList.push(data.data)
|
||||
}
|
||||
},
|
||||
ok() {
|
||||
return this.tagList
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mine-text {
|
||||
font-size: 10px;
|
||||
color: #b4b4b4;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,84 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :title="addData.title" :visible.sync="addData.dialog" width="40%" v-if="addData.dialog" append-to-body>
|
||||
<div>
|
||||
<el-form ref="data" :model="addData.data" :status-icon="true" label-width="120px">
|
||||
<!-- <basic-form-item label="deviceIndex:" prop="deviceIndex" validate = "required">
|
||||
<el-input v-model="addData.data.deviceIndex"></el-input>
|
||||
</basic-form-item> -->
|
||||
<basic-form-item label="网络接口:" prop="networkInterfaceUuid" validate="required">
|
||||
<el-select v-model="addData.data.networkInterfaceUuid">
|
||||
<el-option v-for="item in list" :disabled="nowList.indexOf(item.networkInterfaceUuid) > -1" :label="item.name + '(类型:' + item.interfaceType + ')'" :value="item.networkInterfaceUuid" :key="item.value"></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="ghost" @click="addData.dialog = false">取 消</el-button>
|
||||
<el-button type="primary" @click="ok">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* global $ */
|
||||
import { getNics } from 'services/platform/bingoCloudOS'
|
||||
export default {
|
||||
props: {
|
||||
addData: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {
|
||||
data: {
|
||||
labelIds: []
|
||||
},
|
||||
dialog: false
|
||||
}
|
||||
}
|
||||
},
|
||||
subnetId: {
|
||||
type: [String, Number]
|
||||
},
|
||||
vendorId: {
|
||||
type: [String, Number]
|
||||
},
|
||||
nowList: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getNics() {
|
||||
getNics({
|
||||
simple: true,
|
||||
params: JSON.stringify([{ param: { vendorId: this.vendorId, subnetId: this.subnetId, deviceIndex: -1 }, sign: 'EQ' }])
|
||||
}).then(data => {
|
||||
if (data.success) {
|
||||
this.list = data.data.rows
|
||||
}
|
||||
})
|
||||
},
|
||||
ok() {
|
||||
this.$refs.data.validate(valid => {
|
||||
if (valid) {
|
||||
this.list.forEach(item => {
|
||||
if (item.networkInterfaceUuid == this.addData.data.networkInterfaceUuid) this.addData.data.name = item.name
|
||||
})
|
||||
this.$emit('ok', this.addData)
|
||||
this.addData.dialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getNics()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
|
@ -0,0 +1,86 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="addData.subnetId">
|
||||
<el-tag class="m-l-xs" :key="index" v-for="(item, index) in tagList" closable :disable-transitions="false" @click.stop="modify(item, index)" @close.stop="handleClose(index)">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
<el-button size="mini" @click="add" type="primary" class="m-l-md">添加</el-button>
|
||||
</div>
|
||||
<div v-else>暂无子网</div>
|
||||
<add :add-data="addObj" v-if="addObj.dialog" @ok="addOk" :subnet-id="addData.subnetId" :vendor-id="addData.vendorId" :now-list="nowList"></add>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import add from './add.vue'
|
||||
export default {
|
||||
components: { add },
|
||||
props: {
|
||||
addData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tagList: [],
|
||||
addObj: {
|
||||
dialog: false,
|
||||
data: {}
|
||||
},
|
||||
modifyData: {
|
||||
dialog: false,
|
||||
data: {}
|
||||
},
|
||||
nowList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose(index) {
|
||||
this.nowList.splice(index, 1)
|
||||
this.tagList.splice(index, 1)
|
||||
},
|
||||
add() {
|
||||
this.addObj = {
|
||||
dialog: true,
|
||||
title: '新增网络接口',
|
||||
data: {
|
||||
deviceIndex: this.tagList.length
|
||||
}
|
||||
}
|
||||
},
|
||||
modify(data, index) {
|
||||
this.addObj = {
|
||||
dialog: true,
|
||||
index: index,
|
||||
title: '编辑网络接口',
|
||||
data: {
|
||||
deviceIndex: data.deviceIndex,
|
||||
networkInterfaceUuid: data.networkInterfaceUuid
|
||||
}
|
||||
}
|
||||
},
|
||||
addOk(data) {
|
||||
if (data.index >= 0) {
|
||||
this.tagList[data.index] = data.data
|
||||
this.nowList[data.index].networkInterfaceUuid = data.data.networkInterfaceUuid
|
||||
} else {
|
||||
this.tagList.push(data.data)
|
||||
this.nowList.push(data.data.networkInterfaceUuid)
|
||||
}
|
||||
},
|
||||
ok() {
|
||||
return this.tagList
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
subnetId: {
|
||||
handler(newVal) {
|
||||
this.tagList = []
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -0,0 +1,110 @@
|
|||
<template>
|
||||
<div>
|
||||
<basic-form-item label="系统规格:" validate="required">
|
||||
<div v-if="addData.configs.flavorId">
|
||||
已选规格:{{addData.configs.cpu}}C/{{addData.configs.memory}}G
|
||||
</div>
|
||||
<el-form :inline="true" class="m-t-xs">
|
||||
<el-form-item>
|
||||
<el-input placeholder="名称" v-model="searchData.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearchSpec">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="list" highlight-current-row tooltip-effect="dark" stripe border fit>
|
||||
<el-table-column label="名称">
|
||||
<template slot-scope="scope">
|
||||
<el-radio :label="scope.row.id" v-model="addData.configs.flavorId" @change="checkConfig">
|
||||
{{ scope.row.name }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格uuid" prop="flavorUuid"> </el-table-column>
|
||||
<el-table-column label="cpu" prop="cpu"> </el-table-column>
|
||||
<el-table-column label="内存(GB)" prop="memory"> </el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-container">
|
||||
<el-pagination @size-change="handleSizeChange1" @current-change="getList" :current-page.sync="params.page" :page-sizes="[5, 10, 20, 30, 50]" :page-size="params.rows" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination>
|
||||
</div>
|
||||
</basic-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* global $ */
|
||||
import { getFlavor } from 'services/platform/index'
|
||||
export default {
|
||||
props: {
|
||||
addData: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {
|
||||
data: {
|
||||
},
|
||||
dialog: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
searchData: {
|
||||
name: ''
|
||||
},
|
||||
params: {
|
||||
page: 1,
|
||||
rows: 5
|
||||
},
|
||||
list: [],
|
||||
total: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkConfig (id) {
|
||||
const obj = this.list.find(item => item.id == id)
|
||||
this.$set(this.addData.configs, 'cpu', obj.cpu)
|
||||
this.$set(this.addData.configs, 'memory', obj.memory)
|
||||
},
|
||||
handleSizeChange1(val) {
|
||||
this.params.rows = val
|
||||
this.getList()
|
||||
},
|
||||
// 获取规格列表
|
||||
getList() {
|
||||
getFlavor(this.params).then((data) => {
|
||||
if (data.success) {
|
||||
this.list = data.data.rows
|
||||
this.total = data.data.total
|
||||
if (!this.addData.configs.flavorId && this.list.length) {
|
||||
this.$set(this.addData.configs, 'flavorId', this.list[0].id)
|
||||
this.checkConfig(this.addData.configs.flavorId)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 搜索功能
|
||||
handleSearchSpec() {
|
||||
this.params.page = 1
|
||||
this.params.params = this.$tools.handleSearchParam({
|
||||
vendorId: this.addData.location.vendorId,
|
||||
regionId: this.addData.location.region,
|
||||
'name:LK': this.searchData.name
|
||||
})
|
||||
this.getList()
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'addData.location.region' () {
|
||||
this.handleSearchSpec()
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.handleSearchSpec()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,190 @@
|
|||
<template>
|
||||
<el-col :span="24">
|
||||
<basic-form-item label="镜像:" validate="required">
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-input v-model="searchData.name" placeholder="名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchData.type">
|
||||
<el-option v-for="(item, index) in typeList" :key="index" :label="item.name" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchData.osType" clearable>
|
||||
<el-option v-for="(item, index) in osTypeList" :key="index" :label="item.name" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchData.architecture" clearable>
|
||||
<el-option v-for="(item, index) in architectureList" :key="index" :label="item.name" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="hendleSearch">搜索</el-button>
|
||||
</el-form-item>
|
||||
<el-table :data="imageList" highlight-current-row tooltip-effect="dark" stripe border fit>
|
||||
<template slot="empty">
|
||||
请选择地域
|
||||
</template>
|
||||
<el-table-column label="镜像名称">
|
||||
<template slot-scope="scope">
|
||||
<el-radio :label="scope.row.id" v-model="addData.imageId">
|
||||
{{ scope.row.name }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="镜像ID" prop="imageUuid" show-overflow-tooltip> </el-table-column>
|
||||
<el-table-column prop="status" label="状态" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<status-icon :type="scope.row.status | vmStatusColor">{{ scope.row.status | openstackServer }}</status-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="regionName" label="可用域" show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-container">
|
||||
<el-pagination @size-change="handleChange" @current-change="getImageData" :current-page.sync="params.page" :page-sizes="[5, 10, 20, 30, 50]" :page-size="params.rows" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination>
|
||||
</div>
|
||||
</el-form>
|
||||
</basic-form-item>
|
||||
<basic-form-item label="虚拟磁盘:">
|
||||
<DataDisk ref="disk" :image-data="imageList" :disk-id="addData.imageId" :parent-data="addData"></DataDisk>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getImage } from 'services/platform/index'
|
||||
import DataDisk from './addDisk/index.vue'
|
||||
export default {
|
||||
components: { DataDisk },
|
||||
props: {
|
||||
addData: {
|
||||
type: Object
|
||||
},
|
||||
imageData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
rows: []
|
||||
}
|
||||
}
|
||||
},
|
||||
location: {
|
||||
type: Object
|
||||
},
|
||||
itemData: {
|
||||
type: [Object, Boolean]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.hendleSearch()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchData: {
|
||||
type: 'PUBLIC',
|
||||
osType: '',
|
||||
architecture: ''
|
||||
},
|
||||
typeList: [
|
||||
{
|
||||
name: '公共镜像',
|
||||
value: 'PUBLIC'
|
||||
},
|
||||
{
|
||||
name: '私有镜像',
|
||||
value: 'PRIVATE'
|
||||
}
|
||||
],
|
||||
architectureList: [
|
||||
{
|
||||
name: 'i386',
|
||||
value: 'i386'
|
||||
},
|
||||
{
|
||||
name: 'x86_64',
|
||||
value: 'x86_64'
|
||||
}
|
||||
],
|
||||
osTypeList: [
|
||||
{
|
||||
name: 'kernel',
|
||||
value: 'kernel'
|
||||
},
|
||||
{
|
||||
name: 'machine',
|
||||
value: 'machine '
|
||||
}
|
||||
],
|
||||
imageList: [],
|
||||
params: {
|
||||
page: 1,
|
||||
rows: 5
|
||||
},
|
||||
total: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange(val) {
|
||||
this.params.rows = val
|
||||
this.getImageData()
|
||||
},
|
||||
hendleSearch() {
|
||||
if (!this.location.region) return this.$message.error('请选择地域')
|
||||
this.params.params = this.$tools.handleSearchParam({
|
||||
vendorId: this.location.vendorId,
|
||||
imageType: this.searchData.type,
|
||||
regionId: this.location.region,
|
||||
architecture: this.searchData.architecture,
|
||||
osType: this.searchData.osType,
|
||||
status: 'ACTIVE',
|
||||
applyList: true,
|
||||
'name:lk': this.searchData.name
|
||||
})
|
||||
this.getImageData()
|
||||
},
|
||||
getImageData() {
|
||||
getImage(this.params).then(data => {
|
||||
if (data.success) {
|
||||
this.imageList = data.data.rows
|
||||
this.total = data.data.total
|
||||
this.$set(this.imageData, 'rows', data.data.rows)
|
||||
if (this.itemData && (this.itemData.location.vendorId != this.location.vendorId)) {
|
||||
this.$set(this.addData, 'imageId', '')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'location.vendorId': {
|
||||
handler(newVal) {
|
||||
this.hendleSearch()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.powerLine {
|
||||
background-color: #d4d4d4;
|
||||
padding: 5px;
|
||||
margin-bottom: 10px;
|
||||
border-color: #cbcbcb;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.powerLine .powerLineLeft {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.powerLine .powerLineRight {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,382 @@
|
|||
/**
|
||||
* Created by HaijunZhang on 2019/4/28.
|
||||
*/
|
||||
<template>
|
||||
<common-wrapper code="compute" :show-count="!vmData.hasEip" :add-data="addData" @vendorId="getList" @backZone="getSubnet" ref="common" :elements="elements" :get-params="getParams" :modify-element="modifyElement" :item-data="retention" :disabled="disabled">
|
||||
<el-divider></el-divider>
|
||||
<h5>配置信息</h5>
|
||||
<el-col :span="15" v-if="addData.location.region">
|
||||
<flavor :add-data="addData"></flavor>
|
||||
</el-col>
|
||||
<images v-if="addData.location.vendorId" :add-data="addData.configs" :vendor-id="addData.location.vendorId" :location="addData.location" vendorType="bingoCloudOS" :item-data="retention" ref="image"></images>
|
||||
<div style="clear:both"></div>
|
||||
<basic-form :model="vmData" ref="addForm" label-position="left" :disabled="disabled">
|
||||
<el-divider></el-divider>
|
||||
<h5>网络信息</h5>
|
||||
<el-col :span="4">
|
||||
<basic-form-item prop="terminationProtected" label="启动终止保护:">
|
||||
<el-checkbox v-model="vmData.terminationProtected"></el-checkbox>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<basic-form-item prop="hasIpv6" label="设置IPV6:">
|
||||
<el-checkbox v-model="vmData.hasIpv6" @change="changeHasIpv6"></el-checkbox>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<basic-form-item prop="hasEip" label="设置EIP:">
|
||||
<el-checkbox v-model="vmData.hasEip" @change="changeHasEip"></el-checkbox>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" v-if="vmData.hasEip">
|
||||
<basic-form-item label="弹性IP:" prop="eipId" validate="required">
|
||||
<el-select v-model="vmData.eipId" filterable clearable @change="changeE">
|
||||
<el-option v-for="(item, index) in eipList" :key="index" :label="item.name" :value="item.id"> {{ item.name }}({{ item.publicIp }}) </el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="所属网络:" prop="networkId" validate="required" required-message="请选择所属网络">
|
||||
<el-select v-model="vmData.networkId" @change="changeVPC">
|
||||
<el-option v-for="item in vpcData" :label="`${item.name}(${item.vpcId})`" :value="item.id" :key="item.vpcId"></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="所属子网:" prop="subnetId" validate="required" required-message="请选择子网">
|
||||
<el-select v-model="vmData.subnetId" filterable placeholder="请先选择交换机">
|
||||
<el-option v-for="(item, index) in subnets" :label="item.name" :value="item.id" :key="index">{{ item.name }}({{ item.subnetId }} - {{ item.cidr }})</el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" v-if="addData.emption.count == 1">
|
||||
<el-col :span="24">
|
||||
<el-col :span="6">
|
||||
<basic-form-item label="手动指定IP: ">
|
||||
<el-checkbox v-model="vmData.manualIp"></el-checkbox>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="18" v-if="vmData.manualIp">
|
||||
<basic-form-item label="IP:" prop="managerIp" validate="required,ip" required-message="请指定ip">
|
||||
<el-input v-model="vmData.managerIp" placeholder="请输入192.168.1.1类型格式"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="安全组:" prop="groups" :rules="[{ required: true, message: '请选择安全组', trigger: 'blur' }]">
|
||||
<el-select v-model="vmData.groups" multiple>
|
||||
<el-option v-for="(item, index) in groupsData" :key="index" :label="`${item.name}(${item.value})`" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<div style="clear:both"></div>
|
||||
<el-divider></el-divider>
|
||||
<h5>云主机信息</h5>
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="虚机名称:" validate="required" prop="name">
|
||||
<el-input v-model="vmData.name" placeholder="请输入虚拟机名"></el-input>
|
||||
<div class="tip">设置虚拟机名称前缀</div>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="密钥:" prop="keypairId" validate="required" required-message="该字段为必填字段">
|
||||
<el-select v-model="vmData.keypairId">
|
||||
<el-option v-for="item in keypairList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</basic-form>
|
||||
</common-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonWrapper from 'views/resource-apply/components/PublicCommonWrapper.vue';
|
||||
import { add } from '../../data/publicInit'
|
||||
import { getKey, getGroup, getVpc, getSubnet, getListEip } from 'services/platform/index'
|
||||
import images from './image.vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { getShoppingCartDetail } from 'services/system/shop_cart'
|
||||
import flavor from './flavor.vue'
|
||||
export default {
|
||||
components: { CommonWrapper, images, flavor },
|
||||
props: {
|
||||
type: {
|
||||
type: String
|
||||
},
|
||||
itemData: {
|
||||
type: [Object, Boolean]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
elements: [{
|
||||
name: '云主机',
|
||||
serviceCode: 'bingocloudos.standard.server',
|
||||
main: true,
|
||||
cpu: 0,
|
||||
memory: 0
|
||||
}
|
||||
],
|
||||
addData: {
|
||||
...cloneDeep(add),
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type,
|
||||
diskCategory: ''
|
||||
},
|
||||
service: 'bingocloudos.standard.server',
|
||||
configs: {
|
||||
resourceLabel: [],
|
||||
imageId: '',
|
||||
imageType: 'PUBLIC',
|
||||
imageName: ''
|
||||
}
|
||||
},
|
||||
vmData: {
|
||||
networkId: '',
|
||||
subnetId: '',
|
||||
groups: [],
|
||||
terminationProtected: false,
|
||||
hasIpv6: false,
|
||||
hasEip: false,
|
||||
keypairId: ''
|
||||
},
|
||||
vpcData: [],
|
||||
subnets: [],
|
||||
groupsData: [],
|
||||
eipList: [],
|
||||
keypairList: [],
|
||||
retention: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentElement () {
|
||||
return this.elements[0]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.itemData) {
|
||||
this.retention = this.itemData
|
||||
this.handleShowData()
|
||||
} else if (this.$route.query.id) {
|
||||
getShoppingCartDetail(this.$route.query.id).then(data => {
|
||||
if (data.success) {
|
||||
this.retention = JSON.parse(data.data.inventory)
|
||||
this.handleShowData()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.addData = {
|
||||
...add,
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type,
|
||||
diskCategory: ''
|
||||
},
|
||||
service: 'bingocloudos.standard.server',
|
||||
configs: {
|
||||
resourceLabel: [],
|
||||
imageId: '',
|
||||
imageType: 'PUBLIC',
|
||||
imageName: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleShowData () {
|
||||
this.addData = cloneDeep(this.retention)
|
||||
const { name, hasIpv6, networkId, subnetId, groups, manualIp, managerIp, terminationProtected, hasEip, keypairId, eipId } = this.addData.configs
|
||||
this.vmData = {
|
||||
name: name,
|
||||
networkId: networkId,
|
||||
subnetId: subnetId,
|
||||
groups: groups,
|
||||
manualIp: manualIp,
|
||||
managerIp: managerIp,
|
||||
terminationProtected: terminationProtected,
|
||||
hasIpv6: hasIpv6,
|
||||
hasEip: hasEip,
|
||||
keypairId: keypairId,
|
||||
eipId
|
||||
}
|
||||
this.getVPCList()
|
||||
if (hasEip) this.getListEips()
|
||||
},
|
||||
changeHasIpv6(val) {
|
||||
this.getVPCList()
|
||||
if (val) {
|
||||
this.vmData.networkId = ''
|
||||
this.vmData.subnetId = ''
|
||||
}
|
||||
},
|
||||
changeHasEip(val) {
|
||||
this.getVPCList()
|
||||
if (val) {
|
||||
this.vmData.networkId = ''
|
||||
this.vmData.subnetId = ''
|
||||
this.getListEips()
|
||||
}
|
||||
},
|
||||
getListEips() {
|
||||
getListEip({
|
||||
vendorId: this.addData.location.vendorId,
|
||||
regionId: this.addData.location.region
|
||||
}).then((data) => {
|
||||
if (data.success) {
|
||||
this.eipList = data.data
|
||||
}
|
||||
})
|
||||
},
|
||||
getPostData () {
|
||||
let data = false
|
||||
data = this.$refs.common.handlePostData()
|
||||
return data
|
||||
},
|
||||
getVPCList() {
|
||||
if (this.retention && this.retention.location.region == this.addData.location.region) {
|
||||
this.subnets = []
|
||||
this.groupsData = []
|
||||
} else {
|
||||
this.$set(this.vmData, 'networkId', '')
|
||||
this.$set(this.vmData, 'subnetId', '')
|
||||
this.$set(this.vmData, 'groups', [])
|
||||
this.subnets = []
|
||||
this.groupsData = []
|
||||
}
|
||||
this.groupsData = []
|
||||
const params = {
|
||||
page: 1,
|
||||
rows: 9999
|
||||
}
|
||||
params.params = this.$tools.handleSearchParam({
|
||||
vendorId: this.addData.location.vendorId,
|
||||
regionId: this.addData.location.region,
|
||||
hasIpv6: this.vmData.hasIpv6
|
||||
})
|
||||
getVpc(params).then((data) => {
|
||||
if (data.success) {
|
||||
this.vpcData = data.data.rows
|
||||
if (this.vmData.networkId) {
|
||||
this.changeVPC()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
changeVPC() {
|
||||
this.getSubnet()
|
||||
this.getGroupData()
|
||||
},
|
||||
// 获取子网
|
||||
getSubnet() {
|
||||
const params = JSON.stringify([
|
||||
{
|
||||
param: {
|
||||
networkId: this.vmData.networkId,
|
||||
zone: this.addData.location.az,
|
||||
vendorId: this.addData.location.vendorId,
|
||||
regionId: this.addData.location.region,
|
||||
hasIpv6: this.vmData.hasIpv6
|
||||
},
|
||||
sign: 'EQ'
|
||||
}
|
||||
])
|
||||
getSubnet({
|
||||
page: 1,
|
||||
rows: 999999,
|
||||
params
|
||||
}).then((data) => {
|
||||
if (data.success) {
|
||||
this.subnets = data.data.rows
|
||||
}
|
||||
})
|
||||
},
|
||||
getGroupData() {
|
||||
getGroup({
|
||||
simple: true,
|
||||
params: JSON.stringify([
|
||||
{
|
||||
param: {
|
||||
vendorId: this.addData.location.vendorId,
|
||||
vpcId: this.vmData.networkId
|
||||
},
|
||||
sign: 'EQ'
|
||||
}
|
||||
])
|
||||
}).then((data) => {
|
||||
if (data.success) {
|
||||
this.groupsData = data.data.rows
|
||||
}
|
||||
})
|
||||
},
|
||||
getList () {
|
||||
this.getVPCList(true)
|
||||
this.getKeypair()
|
||||
},
|
||||
getKeypair() {
|
||||
getKey({
|
||||
simple: true,
|
||||
params: JSON.stringify([{ param: { vendorId: this.addData.location.vendorId, regionId: this.addData.location.region }, sign: 'EQ' }])
|
||||
}).then(data => {
|
||||
if (data.success) {
|
||||
this.keypairList = data.data.rows
|
||||
}
|
||||
})
|
||||
},
|
||||
getParams () {
|
||||
let data = false;
|
||||
this.$refs.addForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.vmData.diskDevices = this.$refs.image.$refs.disk.ok()
|
||||
let flag = false
|
||||
this.vmData.diskDevices.forEach((item, index) => {
|
||||
if (index == 0) item.deleteWithInstance = 'true'
|
||||
else item.deleteWithInstance = 'false'
|
||||
if (!item.size) flag = true
|
||||
})
|
||||
if (this.vmData.diskDevices.length == 0) return this.$message.error('请添加磁盘')
|
||||
if (flag) return this.$message.error('磁盘数据不完善')
|
||||
const { ...other } = this.vmData;
|
||||
const result = {
|
||||
...other,
|
||||
regionId: this.addData.location.region,
|
||||
zoneId: this.addData.location.az
|
||||
};
|
||||
if (this.vmData.hasEip) this.addData.emption.count = 1
|
||||
data = result;
|
||||
}
|
||||
});
|
||||
return data;
|
||||
},
|
||||
modifyElement () {
|
||||
this.currentElement.cpu = this.addData.configs.cpu
|
||||
this.currentElement.memory = this.addData.configs.memory
|
||||
this.vmData.diskDevices.forEach(item => {
|
||||
this.elements.push({
|
||||
serviceCode: 'bingocloudos.standard.volume',
|
||||
insAmount: item.size
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'addData.location.vendorType' () {
|
||||
this.$emit('type', this.addData.location.vendorType)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '../../index.scss';
|
||||
.remark_title{
|
||||
font-size: 12px;
|
||||
color: #979797;
|
||||
}
|
||||
</style>
|
|
@ -6,6 +6,7 @@
|
|||
<vc :type="type" v-if="type == 'VMWARE'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></vc>
|
||||
<op :type="type" v-else-if="type == 'OPENSTACK'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></op>
|
||||
<aws :type="type" v-else-if="type == 'AWS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></aws>
|
||||
<bingoCloudOS :type="type" v-else-if="type == 'BINGOCLOUDOS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></bingoCloudOS>
|
||||
<ali :type="type" v-else-if="type == 'ALIYUN'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></ali>
|
||||
<huawei :type="type" v-else-if="type == 'HUAWEI'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></huawei>
|
||||
<tencent :type="type" v-else-if="type == 'TENCENT'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></tencent>
|
||||
|
@ -21,6 +22,7 @@ import huawei from './huawei/index.vue'
|
|||
import tencent from './tencent/index.vue'
|
||||
import tce from './tce/index.vue'
|
||||
import aws from './aws/index.vue'
|
||||
import bingoCloudOS from './bingoCloudOS/index.vue'
|
||||
export default {
|
||||
props: {
|
||||
itemData: {
|
||||
|
@ -30,7 +32,7 @@ export default {
|
|||
type: Boolean
|
||||
}
|
||||
},
|
||||
components: { vc, ali, op, huawei, tencent, aws, tce },
|
||||
components: { vc, ali, op, huawei, tencent, aws, bingoCloudOS, tce },
|
||||
data () {
|
||||
return {
|
||||
type: ''
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* Created by HaijunZhang on 2019/4/28.
|
||||
*/
|
||||
<template>
|
||||
<common-wrapper code="network" :add-data="addData" ref="common" :elements="elements" :get-params="getParams" :item-data="retention" :disabled="disabled" v-if="isLoadData">
|
||||
<basic-form :model="addData.configs" ref="addForm" label-position="left">
|
||||
<h5>云配置信息</h5>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<basic-form-item label="名称:" validate="required" prop="name">
|
||||
<el-input v-model="addData.configs.name" placeholder="请输入名称"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<basic-form-item label=" ">
|
||||
<p style="font-size:12px">
|
||||
通过选择从其中分配公有 IP 地址的公有 IPv4 地址池来分配弹性 IP 地址。您可以为运行中的实例免费关联一个弹性 IP (EIP)地址。如果将更多 EIP 与该实例关联,则将按比例向与该实例相关联的每个额外 EIP 收费。额外 EIP 只能在 Amazon VPC 中使用。为确保有效使用弹性 IP 地址,当这些 IP
|
||||
地址未与运行中的实例相关联或者关联到已停止的实例或未连接的网络接口时,我们会按小时收取少量费用。
|
||||
</p>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</basic-form>
|
||||
</common-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonWrapper from 'views/resource-apply/components/PublicCommonWrapper.vue';
|
||||
import { add, element } from '../data/publicInit'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { getShoppingCartDetail } from 'services/system/shop_cart'
|
||||
|
||||
export default {
|
||||
components: { CommonWrapper },
|
||||
props: {
|
||||
type: {
|
||||
type: String
|
||||
},
|
||||
itemData: {
|
||||
type: [Object, Boolean]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
elements: [{
|
||||
...element,
|
||||
name: 'EIP',
|
||||
serviceCode: 'network.bingoCloudOS.eip',
|
||||
main: true
|
||||
}
|
||||
],
|
||||
addData: {
|
||||
...cloneDeep(add),
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type
|
||||
},
|
||||
service: 'network.bingoCloudOS.eip',
|
||||
configs: {
|
||||
bandwidth: 1
|
||||
}
|
||||
},
|
||||
retention: false,
|
||||
isLoadData: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentElement () {
|
||||
return this.elements[0]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.itemData) {
|
||||
this.retention = this.itemData
|
||||
this.addData = cloneDeep(this.retention)
|
||||
const { elements } = this.retention
|
||||
const [first, ...others] = elements
|
||||
this.elements = [
|
||||
{
|
||||
...element,
|
||||
...first
|
||||
}
|
||||
]
|
||||
} else if (this.$route.query.id) {
|
||||
getShoppingCartDetail(this.$route.query.id).then(data => {
|
||||
if (data.success) {
|
||||
this.retention = JSON.parse(data.data.inventory)
|
||||
this.addData = cloneDeep(this.retention)
|
||||
const { elements } = this.retention
|
||||
const [first, ...others] = elements
|
||||
this.elements = [
|
||||
{
|
||||
...element,
|
||||
...first
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.addData = {
|
||||
...add,
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type
|
||||
},
|
||||
service: 'network.bingoCloudOS.eip',
|
||||
configs: {
|
||||
bandwidth: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
this.isLoadData = true
|
||||
},
|
||||
methods: {
|
||||
getPostData () {
|
||||
let data = false
|
||||
data = this.$refs.common.handlePostData()
|
||||
return data
|
||||
},
|
||||
getParams () {
|
||||
let data = false;
|
||||
this.$refs.addForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.addData.configs.regionId = this.addData.location.region
|
||||
data = true
|
||||
}
|
||||
})
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
|
@ -5,6 +5,7 @@
|
|||
<div>
|
||||
<ali :type="type" v-if="type == 'ALIYUN'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></ali>
|
||||
<huawei :type="type" v-else-if="type == 'HUAWEI'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></huawei>
|
||||
<bingoCloudOS :type="type" v-else-if="type == 'BINGOCLOUDOS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></bingoCloudOS>
|
||||
<aws :type="type" v-else-if="type == 'AWS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></aws>
|
||||
<tencent :type="type" v-else-if="type == 'TENCENT'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></tencent>
|
||||
<tce :type="type" v-else-if="type == 'TCE'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></tce>
|
||||
|
@ -19,6 +20,7 @@ import huawei from './huawei.vue'
|
|||
import tencent from './tencent.vue'
|
||||
import tce from './tce.vue'
|
||||
import aws from './aws.vue'
|
||||
import bingoCloudOS from './bingoCloudOS.vue'
|
||||
export default {
|
||||
props: {
|
||||
itemData: {
|
||||
|
@ -28,7 +30,7 @@ export default {
|
|||
type: Boolean
|
||||
}
|
||||
},
|
||||
components: { ali, op, huawei, tencent, aws, tce },
|
||||
components: { ali, op, huawei, tencent, aws, bingoCloudOS, tce },
|
||||
data () {
|
||||
return {
|
||||
type: ''
|
||||
|
|
|
@ -0,0 +1,806 @@
|
|||
/**
|
||||
* Created by HaijunZhang on 2019/4/28.
|
||||
*/
|
||||
<template>
|
||||
<common-wrapper code="network" :add-data="addData" ref="common" @vendorId="handleSearch" :elements="elements" :get-params="getParams" :item-data="retention" :disabled="disabled">
|
||||
<basic-form :model="addData.configs" ref="addForm" label-position="left">
|
||||
<el-divider></el-divider>
|
||||
<h5>配置信息</h5>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<basic-form-item validate="required" label="负载均衡器类型:">
|
||||
<el-radio-group v-model="addData.configs.loadBalancerType" @change="selectType">
|
||||
<el-radio label="application">应用程序负载均衡器</el-radio>
|
||||
<el-radio label="network">网络负载均衡器</el-radio>
|
||||
</el-radio-group>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="名称:" prop="name" validate="required,awsName" require-message="仅允许a-z、A-Z、0-9和连字符">
|
||||
<el-input v-model="addData.configs.name" placeholder="仅允许a-z、A-Z、0-9和连字符"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<basic-form-item validate="required" label="模式:">
|
||||
<el-radio-group v-model="addData.configs.scheme" @change="changeClassification">
|
||||
<el-radio label="internet-facing">面向Internet</el-radio>
|
||||
<el-radio label="internal">内部</el-radio>
|
||||
</el-radio-group>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="IP地址类型:" validate="required" require-message="请选择IP地址类型">
|
||||
<el-select v-model="addData.configs.ipAddressType" @change="changeIpAddressType" v-if="addData.configs.scheme === 'internet-facing'" placeholder="请选择IP地址类型">
|
||||
<el-option value="ipv4" label="ipv4"></el-option>
|
||||
<el-option value="dualstack" label="dualstack"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="addData.configs.ipAddressType" v-if="addData.configs.scheme === 'internal'" disabled>
|
||||
<el-option value="ipv4" label="ipv4" disabled></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 20px">
|
||||
<el-col :span="24">
|
||||
<basic-form-item label="侦听器: " validate="required">
|
||||
<basic-table :data="dataList2" v-if="addData.configs.loadBalancerType === 'application'">
|
||||
<el-table-column label="负载均衡器协议" prop="protocol">
|
||||
<template slot-scope="scope">
|
||||
<el-select style="width: 50%" v-model="scope.row.protocol" @change="changeData1(scope.row.protocol, scope.$index)">
|
||||
<el-option value="HTTP" label="HTTP"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="负载均衡器端口" prop="port">
|
||||
<template slot-scope="scope">
|
||||
<el-input style="width: 50%" v-model="scope.row.port"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="200" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.native.prevent="deleteRow(scope.$index, dataList2)"><i class="el-icon-delete"></i> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<div slot="pagination"></div>
|
||||
</basic-table>
|
||||
<basic-table :data="dataList" v-if="addData.configs.loadBalancerType === 'network'">
|
||||
<el-table-column label="负载均衡器协议" prop="protocol">
|
||||
<template slot-scope="scope">
|
||||
<el-select style="width: 50%" v-model="scope.row.protocol" @change="changeData2(scope.row.protocol, scope.$index)">
|
||||
<el-option value="TCP" label="TCP"></el-option>
|
||||
<el-option value="TCP_UDP" label="TCP_UDP"></el-option>
|
||||
<el-option value="UDP" label="UDP"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="负载均衡器端口" prop="port">
|
||||
<template slot-scope="scope">
|
||||
<el-input style="width: 50%" v-model="scope.row.port"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="200" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.native.prevent="deleteRow(scope.$index, dataList)"><i class="el-icon-delete"></i> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<div slot="pagination"></div>
|
||||
</basic-table>
|
||||
<el-button style="margin-top: 10px" type="primary" @click="addRow">添加侦听器</el-button>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="VPC:" validate="required">
|
||||
<el-select @change="handleSubNets" v-model="vpcModel" value-key="vpcId" clearable>
|
||||
<el-option v-for="(item, index) in vpcList" :key="index" :label="item.vpcValue" :value="item"></el-option>
|
||||
</el-select>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 10px">
|
||||
<el-col :span="24">
|
||||
<basic-form-item label="可用区:" validate="required">
|
||||
<el-row v-if="showNorth1a">
|
||||
<el-col :span="3">
|
||||
<el-checkbox v-model="northA_checked">cn-north-1a</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
<el-row>
|
||||
<el-select v-model="subNetValueA" style="width: 50%" @change="changePrivateAddressA" value-key="id" :disabled="!northA_checked">
|
||||
<el-option v-for="(item, index) in cnNorth1AList" :key="index" :label="item.subNetValueA" :value="item"> </el-option>
|
||||
</el-select>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-row v-if="northA_checked" style="margin-top: 20px">
|
||||
<el-col :span="2">IPv4地址</el-col>
|
||||
<el-col :span="1">
|
||||
<el-tooltip class="item" effect="dark" content="Virtual Private Cloud (VPC) 是品高云内您自己的逻辑隔离区域中的虚拟网络。请选择您为目标实例选择的同一 VPC。" placement="top">
|
||||
<i class="el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="addData.configs.scheme === 'internet-facing' && addData.configs.loadBalancerType === 'network'">
|
||||
<el-select v-model="Ipv4_addressA" @change="hanldeElastic">
|
||||
<el-option label="由AWS分配" value="BINGOCLOUDOS"></el-option>
|
||||
<el-option label="选择弹性IP" value="IP"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="Ipv4_Elastic_Val_A" v-if="Ipv4_addressA == 'IP'" style="margin-top: 10px">
|
||||
<el-option v-for="(item, index) in elasticList" :key="index" :label="item.publicIp + '(' + item.elasticIpUuid + ')'" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="addData.configs.scheme === 'internet-facing' && addData.configs.loadBalancerType === 'application'">
|
||||
<el-row>
|
||||
<span>由AWS分配</span>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="addData.configs.scheme === 'internal' && addData.configs.loadBalancerType === 'network'">
|
||||
<el-row>
|
||||
<span>从CIDR分配{{ cidr }}</span>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col v-if="addData.configs.scheme === 'internal' && addData.configs.loadBalancerType === 'application'" :span="21"> 从CIDR分配{{ cidr }} </el-col>
|
||||
<el-col v-if="showIpv6 && addData.configs.loadBalancerType === 'application' && addData.configs.scheme === 'internet-facing' && addData.configs.ipAddressType == 'dualstack'">
|
||||
<el-col :span="2">IPv6地址</el-col>
|
||||
<el-col :span="1" style="margin-left: -40px">
|
||||
<el-tooltip class="item" effect="dark" content="节点的 IPv6 地址从子网 CIDR 分配。" placement="top">
|
||||
<i class="el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col v-if="ipv6_cidr && addData.configs.loadBalancerType === 'application'" :span="8">{{ ipv6_cidr }}</el-col>
|
||||
<el-col v-else :span="8">无</el-col>
|
||||
</el-col>
|
||||
<el-col v-if="showIpv6 && addData.configs.loadBalancerType === 'network' && addData.configs.scheme === 'internet-facing' && addData.configs.ipAddressType == 'dualstack'">
|
||||
<el-col :span="2">IPv6地址</el-col>
|
||||
<el-col :span="1" style="margin-left: -40px">
|
||||
<el-tooltip class="item" effect="dark" content="节点的 IPv6 地址从子网 CIDR 分配。" placement="top">
|
||||
<i class="el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col v-if="ipv6_cidr" :span="8">
|
||||
<el-select v-model="north1A_CIDR_value">
|
||||
<el-option :label="'从CIDR分配' + ipv6_cidr" value="assign"></el-option>
|
||||
<el-option :label="'从CIDR输入 IP' + ipv6_cidr" value="input"></el-option>
|
||||
</el-select>
|
||||
<basic-form-item v-if="addData.configs.ipAddressType == 'dualstack' && north1A_CIDR_value == 'input'" maxlength="64">
|
||||
<el-input v-model="private_Ipv6_input_A" placeholder="IPv6地址"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="ipv6_cidr && addData.configs.loadBalancerType === 'application'" :span="8">{{ ipv6_cidr }}</el-col>
|
||||
<el-col v-if="!ipv6_cidr" :span="8">无</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="classificationStatus && northA_checked && addData.configs.loadBalancerType === 'network'" style="margin: 10px 0 0 -28px">
|
||||
<el-col :span="3">私有IPv4地址</el-col>
|
||||
<el-col :span="8" style="margin-left: -40px">
|
||||
<el-select v-model="north1A_CIDR_value">
|
||||
<el-option :label="'从CIDR分配' + cidr" value="assign"></el-option>
|
||||
<el-option :label="'从CIDR输入' + cidr" value="input"></el-option>
|
||||
</el-select>
|
||||
<basic-form-item v-if="addData.configs.ipAddressType == 'ipv4' && north1A_CIDR_value == 'input'" maxlength="64">
|
||||
<el-input v-model="private_Ipv4_input_A" placeholder="私有IPv4地址"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="showNorth1B" :style="showNorth1a ? 'margin-top: 20px;' : ''">
|
||||
<el-col :span="3">
|
||||
<el-checkbox v-model="northB_checked">cn-north-1b</el-checkbox>
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
<el-row>
|
||||
<el-select v-model="subNetValueB" style="width: 50%" @change="changePrivateAddressB" value-key="id" :disabled="!northB_checked">
|
||||
<el-option v-for="(item, index) in cnNorth1BList" :key="index" :label="item.subNetValueB" :value="item"></el-option>
|
||||
</el-select>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-row v-if="northB_checked" style="margin-top: 20px">
|
||||
<el-col :span="2">IPv4地址</el-col>
|
||||
<el-col :span="1">
|
||||
<el-tooltip class="item" effect="dark" content="对于面向 Internet 的负载均衡器,节点的 IPv4 地址由 品高云 分配,您也可以选择您的其中一个弹性 IP 地址。对于内部负载均衡器,IPv4 地址从子网 CIDR 分配。" placement="top">
|
||||
<i class="el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="addData.configs.scheme === 'internet-facing' && addData.configs.loadBalancerType === 'network'">
|
||||
<el-select v-model="Ipv4_addressB" @change="hanldeElastic">
|
||||
<el-option label="由品高云分配" value="BINGOCLOUDOS"></el-option>
|
||||
<el-option label="选择弹性IP" value="IP"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="Ipv4_Elastic_Val_B" v-if="Ipv4_addressB == 'IP'" style="margin-top: 10px">
|
||||
<el-option v-for="(item, index) in elasticList" :key="index" :label="item.publicIp + '(' + item.elasticIpUuid + ')'" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="addData.configs.scheme === 'internet-facing' && addData.configs.loadBalancerType === 'application'">
|
||||
<el-row>
|
||||
<span>由AWS分配</span>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="addData.configs.scheme === 'internal' && addData.configs.loadBalancerType === 'network'">
|
||||
<el-row>
|
||||
<span>从CIDR分配{{ cidrB }}</span>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col v-if="addData.configs.scheme === 'internal' && addData.configs.loadBalancerType === 'application'" :span="21"> 从CIDR分配{{ cidrB }} </el-col>
|
||||
<el-col v-if="showIpv6 && addData.configs.scheme === 'internet-facing' && addData.configs.ipAddressType == 'dualstack'">
|
||||
<el-col :span="2">IPv6地址</el-col>
|
||||
<el-col :span="1" style="margin-left: -40px">
|
||||
<el-tooltip class="item" effect="dark" content="节点的 IPv6 地址从子网 CIDR 分配。" placement="top">
|
||||
<i class="el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col v-if="ipv6_cidrB && addData.configs.loadBalancerType === 'network'" :span="8">
|
||||
<el-select v-model="north1B_CIDR_value">
|
||||
<el-option :label="'从CIDR分配' + ipv6_cidrB" value="assign"></el-option>
|
||||
<el-option :label="'从CIDR输入 IP' + ipv6_cidrB" value="input"></el-option>
|
||||
</el-select>
|
||||
<basic-form-item v-if="addData.configs.ipAddressType == 'dualstack' && north1B_CIDR_value == 'input'" maxlength="64">
|
||||
<el-input v-model="private_Ipv6_input_B" placeholder="IPv6地址"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="ipv6_cidrB && addData.configs.loadBalancerType === 'application'" :span="8">{{ ipv6_cidrB }}</el-col>
|
||||
<el-col v-if="!ipv6_cidrB" :span="8">无</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="classificationStatus && northB_checked && addData.configs.loadBalancerType === 'network'" style="margin: 10px 0 0 -28px">
|
||||
<el-col :span="3">私有IPv4地址</el-col>
|
||||
<el-col :span="8" style="margin-left: -40px">
|
||||
<el-select v-model="north1B_CIDR_value">
|
||||
<el-option :label="'从CIDR分配' + cidrB" value="assign"></el-option>
|
||||
<el-option :label="'从CIDR输入' + cidrB" value="input"></el-option>
|
||||
</el-select>
|
||||
<basic-form-item v-if="addData.configs.ipAddressType == 'ipv4' && north1B_CIDR_value == 'input'" maxlength="64">
|
||||
<el-input v-model="private_Ipv4_input_B" placeholder="私有IPv4地址"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row class="top_margin_border">
|
||||
<!-- <el-form :inline="true" v-if="addData.configs.loadBalancerType === 'application'">
|
||||
<el-form-item label="筛选条件:">
|
||||
<el-select v-model="safeOptions" @change="changeSafeGroup">
|
||||
<el-option label="VPC 安全组" value="vpc"></el-option>
|
||||
<el-option label="EC2 安全组" value="ec2"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form> -->
|
||||
</el-row>
|
||||
<basic-form-item label-width="140px" label="安全组: " validate="required" v-if="addData.configs.loadBalancerType === 'application'">
|
||||
<basic-table :data="safeTableData" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55"></el-table-column>
|
||||
<el-table-column prop="groupUuid" label="安全组ID"></el-table-column>
|
||||
<el-table-column prop="name" label="名称"></el-table-column>
|
||||
<el-table-column prop="remark" label="描述"></el-table-column>
|
||||
<div slot="pagination"></div>
|
||||
</basic-table>
|
||||
</basic-form-item>
|
||||
</basic-form>
|
||||
</common-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonWrapper from 'views/resource-apply/components/PublicCommonWrapper.vue';
|
||||
import { add, element } from '../data/publicInit'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { getShoppingCartDetail } from 'services/system/shop_cart'
|
||||
import { getTargetgroups, getTargets, getVpcData, getSubNetsList, getSafeTableData, getElasticIp } from 'services/platform/bingoCloudOS'
|
||||
|
||||
export default {
|
||||
components: { CommonWrapper },
|
||||
props: {
|
||||
type: {
|
||||
type: String
|
||||
},
|
||||
itemData: {
|
||||
type: [Object, Boolean]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
elements: [{
|
||||
...element,
|
||||
name: '负载均衡',
|
||||
serviceCode: 'network.bingoCloudOS.slb',
|
||||
main: true
|
||||
}
|
||||
],
|
||||
addData: {
|
||||
...cloneDeep(add),
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type
|
||||
},
|
||||
service: 'network.bingoCloudOS.slb',
|
||||
configs: {
|
||||
name: '',
|
||||
loadBalancerType: 'network',
|
||||
scheme: 'internet-facing',
|
||||
ipAddressType: 'ipv4',
|
||||
availabilityZones: []
|
||||
}
|
||||
},
|
||||
retention: false,
|
||||
// 订购所需
|
||||
detailTableData: [],
|
||||
tableData: [],
|
||||
params: {
|
||||
page: 1,
|
||||
rows: 9999
|
||||
},
|
||||
paramd: {
|
||||
page: 1,
|
||||
rows: 9999
|
||||
},
|
||||
publicParams: {
|
||||
page: 1,
|
||||
rows: 9999
|
||||
},
|
||||
safeTableParams: {
|
||||
page: 1,
|
||||
rows: 10
|
||||
},
|
||||
private_Ipv4_input_A: '',
|
||||
private_Ipv4_input_B: '',
|
||||
private_Ipv6_input_A: '',
|
||||
private_Ipv6_input_B: '',
|
||||
regionId: 'cn-north-1',
|
||||
tempStore: '',
|
||||
listeners: [],
|
||||
CheckPort: '',
|
||||
runStatePath: '/',
|
||||
runStateProtocol: 'HTTP',
|
||||
aimClassification: 'instance',
|
||||
aimGroupName: '',
|
||||
protocolVersion: 'HTTP1',
|
||||
aimPort: 80,
|
||||
aimProtocol: 'HTTP',
|
||||
protocol: '',
|
||||
classificationSelection: '',
|
||||
safeOptions: '',
|
||||
regionList: '',
|
||||
north1A_CIDR_value: 'assign',
|
||||
north1B_CIDR_value: 'assign',
|
||||
vpcList: [],
|
||||
vpcValue: '',
|
||||
vpcId: '',
|
||||
assignSafeRadio: 3, // 分配安全组单选
|
||||
input: '',
|
||||
classification: '',
|
||||
classificationStatus: false,
|
||||
dataList: [{ protocol: 'TCP', port: 80 }],
|
||||
dataList2: [{ protocol: 'HTTP', port: 80 }],
|
||||
northA_checked: false, // 控制cn-north-1a的选择框
|
||||
northB_checked: false, // 控制cn-north-1b的选择框
|
||||
showNorth1a: true,
|
||||
showNorth1B: true, // 是否显示cn-north-1b
|
||||
cnNorth1AList: [],
|
||||
cnNorth1BList: [],
|
||||
subNetValueA: '',
|
||||
subNetValueB: '',
|
||||
Ipv4_addressA: 'BINGOCLOUDOS',
|
||||
Ipv4_addressB: 'BINGOCLOUDOS',
|
||||
elasticList: [],
|
||||
Ipv4_Elastic_Val_A: '',
|
||||
Ipv4_Elastic_Val_B: '',
|
||||
zone: '',
|
||||
north1A_CIDR: '',
|
||||
north1B_CIDR: '',
|
||||
subNetList: [],
|
||||
cidr: '',
|
||||
cidrB: '',
|
||||
showIpv6: false,
|
||||
ipv6_cidr: '',
|
||||
ipv6_cidrB: '',
|
||||
safeTableData: [], // 安全组表格
|
||||
vpcModel: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentElement () {
|
||||
return this.elements[0]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.itemData) {
|
||||
this.retention = this.itemData
|
||||
this.addData = cloneDeep(this.retention)
|
||||
const { elements } = this.retention
|
||||
const [first, ...others] = elements
|
||||
this.elements = [
|
||||
{
|
||||
...element,
|
||||
...first
|
||||
}
|
||||
]
|
||||
} else if (this.$route.query.id) {
|
||||
getShoppingCartDetail(this.$route.query.id).then(data => {
|
||||
if (data.success) {
|
||||
this.retention = JSON.parse(data.data.inventory)
|
||||
this.addData = cloneDeep(this.retention)
|
||||
const { elements } = this.retention
|
||||
const [first, ...others] = elements
|
||||
this.elements = [
|
||||
{
|
||||
...element,
|
||||
...first
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'addData.location.vendorType' () {
|
||||
this.$emit('type', this.addData.location.vendorType)
|
||||
},
|
||||
northB_checked(newVal, oldVal) {
|
||||
if (this.cnNorth1BList.length && newVal) {
|
||||
this.addData.configs.availabilityZones[1] = { sId: this.cnNorth1BList[0].id }
|
||||
} else {
|
||||
this.addData.configs.availabilityZones.pop()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getPostData () {
|
||||
let data = false
|
||||
data = this.$refs.common.handlePostData()
|
||||
return data
|
||||
},
|
||||
getParams () {
|
||||
let data = false;
|
||||
this.$refs.addForm.validate(valid => {
|
||||
if (valid) {
|
||||
if (this.dataList.length) {
|
||||
for (let i = 0; i < this.dataList.length; i++) {
|
||||
if (this.dataList[i].protocol == '选择协议' || this.dataList[i].port == '') {
|
||||
return this.$message.error('请填写侦听器相关信息')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return this.$message.error('至少添加一个侦听器')
|
||||
}
|
||||
if (this.addData.configs.availabilityZones.length <= 1 || this.northA_checked == false || this.northB_checked == false) {
|
||||
return this.$message.error('当前vpc不可用,必须指定至少两个子网')
|
||||
}
|
||||
if (this.Ipv4_addressA == 'IP' && this.Ipv4_addressB == 'IP' && this.Ipv4_Elastic_Val_A == this.Ipv4_Elastic_Val_B) return this.$message.error('弹性IP地址不可相同')
|
||||
if (this.addData.configs.loadBalancerType === 'network') {
|
||||
this.addData.configs.availabilityZones[0].loadBalancerAddresses = []
|
||||
this.addData.configs.availabilityZones[1].loadBalancerAddresses = []
|
||||
if (this.addData.configs.scheme === 'internet-facing' || (this.addData.configs.scheme === 'internal' && this.north1A_CIDR_value != 'input' && this.north1B_CIDR_value != 'input')) {
|
||||
this.addData.configs.availabilityZones[0].loadBalancerAddresses[0] = { eipId: this.Ipv4_Elastic_Val_A }
|
||||
this.addData.configs.availabilityZones[1].loadBalancerAddresses[0] = { eipId: this.Ipv4_Elastic_Val_B }
|
||||
}
|
||||
if (this.north1A_CIDR_value == 'input' && this.north1B_CIDR_value == 'input') {
|
||||
this.addData.configs.availabilityZones[0].loadBalancerAddresses[0] = { privateIPv4Address: this.private_Ipv4_input_A }
|
||||
this.addData.configs.availabilityZones[1].loadBalancerAddresses[0] = { privateIPv4Address: this.private_Ipv4_input_B }
|
||||
if (this.private_Ipv4_input_A && this.private_Ipv4_input_B && this.private_Ipv4_input_A == this.private_Ipv4_input_B) {
|
||||
return this.$message.error('输入的私有IPv4地址不能相同')
|
||||
}
|
||||
}
|
||||
if ((this.north1A_CIDR_value == 'input' && this.north1B_CIDR_value != 'input') || (this.north1A_CIDR_value != 'input' && this.north1B_CIDR_value == 'input')) {
|
||||
return this.$message.error('输入的私有Ipv4或Ipv6地址需同时存在')
|
||||
}
|
||||
if (this.addData.configs.ipAddressType == 'dualstack') {
|
||||
if (this.ipv6_cidr == null) {
|
||||
return this.$message.error('所选的子网必须具有IP地址类型所需的CIDR块')
|
||||
}
|
||||
if (this.north1A_CIDR_value == 'input' && this.north1B_CIDR_value == 'input') {
|
||||
this.addData.configs.availabilityZones[0].loadBalancerAddresses[0] = { iPv6Address: this.private_Ipv6_input_A }
|
||||
this.addData.configs.availabilityZones[1].loadBalancerAddresses[0] = { iPv6Address: this.private_Ipv6_input_B }
|
||||
}
|
||||
}
|
||||
this.dataList.forEach((item, index) => {
|
||||
if (index + 1 < this.dataList.length) {
|
||||
if (item.port == this.dataList[index + 1].port) return this.$message.error('端口号不能相同')
|
||||
}
|
||||
})
|
||||
data = {
|
||||
balancer: this.addData.configs,
|
||||
listeners: this.dataList,
|
||||
targetGroup: { id: this.tempStore }
|
||||
}
|
||||
} else {
|
||||
const safeGroup = []
|
||||
this.securityGroups.forEach(item => {
|
||||
safeGroup.push({ id: item.id })
|
||||
})
|
||||
if (safeGroup.length == 0) {
|
||||
return this.$message.error('至少选择一个安全组')
|
||||
}
|
||||
const newBalancer = JSON.parse(JSON.stringify(this.addData.configs))
|
||||
newBalancer.securityGroups = safeGroup
|
||||
data = {
|
||||
balancer: newBalancer,
|
||||
listeners: this.dataList2,
|
||||
targetGroup: { id: this.tempStore }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return data;
|
||||
},
|
||||
selectType() {
|
||||
if (this.addData.configs.loadBalancerType === 'application') {
|
||||
this.listeners = this.dataList
|
||||
}
|
||||
if (this.addData.configs.loadBalancerType === 'network') {
|
||||
this.listeners = this.dataList
|
||||
}
|
||||
this.getData()
|
||||
},
|
||||
handleDetailSearch() {
|
||||
const params = [{ param: { tgId: this.tempStore[0] }, sign: 'EQ' }]
|
||||
this.paramd.params = JSON.stringify(params)
|
||||
this.getDetailData()
|
||||
},
|
||||
getDetailData() {
|
||||
getTargets(this.paramd).then(data => {
|
||||
if (data.success) {
|
||||
this.detailTableData = data.data.rows
|
||||
this.totald = data.data.total
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSearch() {
|
||||
this.getData()
|
||||
this.getVpcList()
|
||||
this.hanldeElastic()
|
||||
this.params.params = this.$tools.handleSearchParam({
|
||||
vendorId: this.addData.location.vendorId,
|
||||
regionId: this.addData.location.region
|
||||
})
|
||||
},
|
||||
getData() {
|
||||
const targetGroupsParams = JSON.parse(JSON.stringify(this.publicParams))
|
||||
if (this.addData.configs.loadBalancerType === 'application') {
|
||||
targetGroupsParams.params = JSON.stringify([
|
||||
{
|
||||
param: {
|
||||
vendorId: this.addData.location.vendorId,
|
||||
loadBalancerUuids: '[]',
|
||||
vpcUuid: this.vpcId,
|
||||
regionId: this.addData.location.region
|
||||
},
|
||||
sign: 'EQ'
|
||||
},
|
||||
{
|
||||
param: {
|
||||
protocol: '"HTTP"'
|
||||
},
|
||||
sign: 'IN'
|
||||
}
|
||||
])
|
||||
} else {
|
||||
const protocolData = JSON.parse(JSON.stringify(this.dataList))
|
||||
const isTCP = protocolData.every(item => {
|
||||
return item.protocol == 'TCP'
|
||||
})
|
||||
const isUDP = protocolData.every(item => {
|
||||
return item.protocol == 'UDP'
|
||||
})
|
||||
for (let i = 0; i < protocolData.length; i++) {
|
||||
if (isTCP) {
|
||||
this.protocol = '"TCP"'
|
||||
} else {
|
||||
this.protocol = '"TCP_UDP"'
|
||||
}
|
||||
if (isUDP) {
|
||||
this.protocol = '"UDP"'
|
||||
}
|
||||
}
|
||||
targetGroupsParams.params = JSON.stringify([
|
||||
{
|
||||
param: {
|
||||
vendorId: this.addData.location.vendorId,
|
||||
loadBalancerUuids: '[]',
|
||||
vpcUuid: this.vpcId,
|
||||
regionId: this.addData.location.region
|
||||
},
|
||||
sign: 'EQ'
|
||||
},
|
||||
{
|
||||
param: {
|
||||
protocol: this.protocol
|
||||
},
|
||||
sign: 'IN'
|
||||
}
|
||||
])
|
||||
}
|
||||
getTargetgroups(targetGroupsParams).then(data => {
|
||||
if (data.success) {
|
||||
this.tableData = data.data.rows
|
||||
if (this.tableData.length) {
|
||||
this.tempStore = this.tableData[0].id
|
||||
} else {
|
||||
this.tempStore = ''
|
||||
}
|
||||
this.total = data.data.total
|
||||
}
|
||||
})
|
||||
},
|
||||
changeData1(name, index) {
|
||||
switch (name) {
|
||||
case 'HTTP':
|
||||
this.dataList2[index].port = 80
|
||||
break
|
||||
// case 'HTTPS':
|
||||
// this.dataList2[index].port = 443
|
||||
// break
|
||||
}
|
||||
},
|
||||
changeData2(name, index) {
|
||||
switch (name) {
|
||||
case 'TCP':
|
||||
this.dataList[index].port = 80
|
||||
break
|
||||
case 'TCP_UDP':
|
||||
this.dataList[index].port = 53
|
||||
break
|
||||
case 'UDP':
|
||||
this.dataList[index].port = 53
|
||||
}
|
||||
this.getData()
|
||||
},
|
||||
deleteRow(index, rows) {
|
||||
rows.splice(index, 1)
|
||||
this.getData()
|
||||
},
|
||||
addRow() {
|
||||
if (this.addData.configs.loadBalancerType === 'network') {
|
||||
this.dataList.push({ protocol: '选择协议', port: '' })
|
||||
}
|
||||
if (this.addData.configs.loadBalancerType === 'application') {
|
||||
this.dataList2.push({ protocol: 'HTTP', port: 80 })
|
||||
}
|
||||
},
|
||||
changeClassification() {
|
||||
if (this.addData.configs.scheme === 'internal') {
|
||||
this.addData.configs.ipAddressType = 'ipv4'
|
||||
this.classificationStatus = true
|
||||
} else {
|
||||
this.addData.configs.ipAddressType = 'ipv4'
|
||||
this.classificationStatus = false
|
||||
}
|
||||
},
|
||||
goBack() {
|
||||
sessionStorage.setItem('platformId', this.serverId)
|
||||
this.$router.back(-1)
|
||||
},
|
||||
getVpcList() {
|
||||
const params = JSON.stringify([{ param: { regionId: this.addData.location.region, vendorId: this.addData.location.vendorId }, sign: 'EQ' }])
|
||||
const vpcParams = JSON.parse(JSON.stringify(this.publicParams))
|
||||
vpcParams.params = params
|
||||
getVpcData(vpcParams).then(data => {
|
||||
this.vpcList = data.data.rows
|
||||
this.vpcList.forEach((item, index) => {
|
||||
item.vpcValue = `${item.vpcId} (${item.cidr}) | ${item.name}`
|
||||
})
|
||||
this.vpcModel = this.vpcList[0]
|
||||
if (this.vpcList.length > 0) {
|
||||
this.handleSubNets()
|
||||
this.getSafeTableList()
|
||||
this.getData()
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSubNets() {
|
||||
this.vpcId = this.vpcModel.vpcId
|
||||
this.Ipv4_addressA = 'BINGOCLOUDOS'
|
||||
this.Ipv4_addressB = 'BINGOCLOUDOS'
|
||||
this.getData()
|
||||
this.northA_checked = this.northB_checked = false
|
||||
const params = JSON.stringify([{ param: { networkId: this.vpcModel.id, vendorId: this.addData.location.vendorId }, sign: 'EQ' }])
|
||||
const subNetsParams = JSON.parse(JSON.stringify(this.publicParams))
|
||||
subNetsParams.params = params
|
||||
getSubNetsList(subNetsParams).then(data => {
|
||||
this.subNetList = data.data.rows
|
||||
if (this.addData.location.region == 'cn-north-1') {
|
||||
this.cnNorth1AList = this.subNetList.filter(item => item.zone == 'cn-north-1a')
|
||||
} else {
|
||||
this.cnNorth1AList = this.subNetList.filter(item => item.zone == 'cn-northwest-1a')
|
||||
}
|
||||
if (this.cnNorth1AList.length) {
|
||||
this.addData.configs.availabilityZones[0] = { sId: this.cnNorth1AList[0].id }
|
||||
this.cidr = this.cnNorth1AList[0].cidr
|
||||
this.ipv6_cidr = this.cnNorth1AList[0].ipv6Cidr
|
||||
this.showNorth1a = true
|
||||
} else {
|
||||
this.showNorth1a = false
|
||||
}
|
||||
this.cnNorth1BList = this.subNetList.filter(item1 => item1.zone == 'cn-north-1b')
|
||||
if (this.cnNorth1BList.length) {
|
||||
this.ipv6_cidrB = this.cnNorth1BList[0].ipv6Cidr
|
||||
this.cidrB = this.cnNorth1BList[0].cidr
|
||||
this.showNorth1B = true
|
||||
} else {
|
||||
this.showNorth1B = false
|
||||
}
|
||||
this.subNetList.forEach((item, index) => {
|
||||
this.zone = item.zone
|
||||
if ((item.zone == 'cn-north-1a' || item.zone == 'cn-northwest-1a') && (this.addData.configs.scheme === 'internet-facing' || this.addData.configs.scheme === 'internal')) {
|
||||
item.subNetValueA = `${item.subnetUuid} (${item.name})`
|
||||
this.subNetValueA = this.cnNorth1AList[0]
|
||||
} else {
|
||||
item.subNetValueB = `${item.subnetUuid} (${item.name})`
|
||||
this.subNetValueB = this.cnNorth1BList[0]
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
// cn-north-1a下拉框触发事件
|
||||
changePrivateAddressA(e) {
|
||||
this.addData.configs.availabilityZones[0] = { sId: e.id }
|
||||
this.ipv6_cidr = e.ipv6Cidr
|
||||
this.cidr = e.cidr
|
||||
},
|
||||
// cn-north-1b下拉框触发事件
|
||||
changePrivateAddressB(e) {
|
||||
this.addData.configs.availabilityZones[1] = { sId: e.id }
|
||||
this.ipv6_cidrB = e.ipv6Cidr
|
||||
this.cidrB = e.cidr
|
||||
},
|
||||
changeIpAddressType(e) {
|
||||
if (e === 'ipv4') {
|
||||
this.showIpv6 = false
|
||||
} else {
|
||||
this.showIpv6 = true
|
||||
}
|
||||
},
|
||||
getSafeTableList() {
|
||||
this.safeTableParams.params = JSON.stringify([{ param: { vpcId: this.vpcModel.id, vendorId: this.addData.location.vendorId }, sign: 'EQ' }])
|
||||
getSafeTableData(this.safeTableParams).then(data => {
|
||||
this.safeTableData = data.data.rows
|
||||
})
|
||||
},
|
||||
handleSelectionChange(row) {
|
||||
this.securityGroups = row
|
||||
},
|
||||
// 选择弹性ip时获取
|
||||
hanldeElastic() {
|
||||
if (this.Ipv4_addressA == 'IP' || this.Ipv4_addressB == 'IP') {
|
||||
const params = JSON.stringify([
|
||||
{ param: { regionId: this.addData.location.region, vendorId: this.addData.location.vendorId }, sign: 'EQ' },
|
||||
{
|
||||
param: {
|
||||
associationId: ''
|
||||
},
|
||||
sign: 'NUL'
|
||||
}
|
||||
])
|
||||
const subNetsParams = JSON.parse(JSON.stringify(this.publicParams))
|
||||
subNetsParams.params = params
|
||||
getElasticIp(subNetsParams).then(data => {
|
||||
this.elasticList = data.data.rows
|
||||
if (this.elasticList.length && this.Ipv4_addressA == 'IP') {
|
||||
this.Ipv4_Elastic_Val_A = this.elasticList[0].id
|
||||
}
|
||||
if (this.elasticList.length && this.Ipv4_addressB == 'IP') {
|
||||
this.Ipv4_Elastic_Val_B = this.elasticList[0].id
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.elasticList = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
|
@ -5,12 +5,14 @@
|
|||
<div>
|
||||
<ali :type="type" v-if="type == 'ALIYUN'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></ali>
|
||||
<aws :type="type" v-else-if="type == 'AWS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></aws>
|
||||
<bingoCloudOS :type="type" v-else-if="type == 'BINGOCLOUDOS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></bingoCloudOS>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ali from './ali.vue'
|
||||
import aws from './aws.vue'
|
||||
import bingoCloudOS from './bingoCloudOS.vue'
|
||||
export default {
|
||||
props: {
|
||||
itemData: {
|
||||
|
@ -20,7 +22,7 @@ export default {
|
|||
type: Boolean
|
||||
}
|
||||
},
|
||||
components: { ali, aws },
|
||||
components: { ali, aws, bingoCloudOS },
|
||||
data () {
|
||||
return {
|
||||
type: ''
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* Created by HaijunZhang on 2019/4/28.
|
||||
*/
|
||||
<template>
|
||||
<common-wrapper code="network" :add-data="addData" ref="common" :elements="elements" :get-params="getParams" :item-data="retention" :disabled="disabled" v-if="isLoadData">
|
||||
<basic-form :model="addData.configs" ref="addForm" label-position="left">
|
||||
<el-divider></el-divider>
|
||||
<h5>配置信息</h5>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<basic-form-item label="cidr: " prop="cidr" validate="required,cidr">
|
||||
<el-input v-model="addData.configs.cidr"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
<el-col :span="13">
|
||||
<basic-form-item label="IPV6 CIDR:" prop="providedIpv6Cidr" validate="required" label-width="120px">
|
||||
<el-radio-group v-model="addData.configs.providedIpv6Cidr">
|
||||
<el-radio label="0">无IPV6 CIDR</el-radio>
|
||||
<el-radio label="1">Amazon</el-radio>
|
||||
</el-radio-group>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider></el-divider>
|
||||
<h5>云配置信息</h5>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10">
|
||||
<basic-form-item label="名称:" validate="required" prop="name">
|
||||
<el-input v-model="addData.configs.name" placeholder="请输入名称"></el-input>
|
||||
</basic-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</basic-form>
|
||||
</common-wrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonWrapper from 'views/resource-apply/components/PublicCommonWrapper.vue';
|
||||
import { add, element } from '../data/publicInit'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { getShoppingCartDetail } from 'services/system/shop_cart'
|
||||
|
||||
export default {
|
||||
components: { CommonWrapper },
|
||||
props: {
|
||||
type: {
|
||||
type: String
|
||||
},
|
||||
itemData: {
|
||||
type: [Object, Boolean]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
elements: [{
|
||||
...element,
|
||||
name: 'VPC',
|
||||
serviceCode: 'bingocloudos.standard.vpc',
|
||||
main: true
|
||||
}
|
||||
],
|
||||
addData: {
|
||||
...cloneDeep(add),
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type
|
||||
},
|
||||
service: 'bingocloudos.standard.vpc',
|
||||
configs: {
|
||||
providedIpv6Cidr: '0',
|
||||
cidr: ''
|
||||
}
|
||||
},
|
||||
retention: false,
|
||||
isLoadData: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentElement () {
|
||||
return this.elements[0]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.itemData) {
|
||||
this.retention = this.itemData
|
||||
this.addData = cloneDeep(this.retention)
|
||||
const { elements } = this.retention
|
||||
const [first, ...others] = elements
|
||||
this.elements = [
|
||||
{
|
||||
...element,
|
||||
...first
|
||||
}
|
||||
]
|
||||
} else if (this.$route.query.id) {
|
||||
getShoppingCartDetail(this.$route.query.id).then(data => {
|
||||
if (data.success) {
|
||||
this.retention = JSON.parse(data.data.inventory)
|
||||
this.addData = cloneDeep(this.retention)
|
||||
const { elements } = this.retention
|
||||
const [first, ...others] = elements
|
||||
this.elements = [
|
||||
{
|
||||
...element,
|
||||
...first
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.addData = {
|
||||
...add,
|
||||
location: {
|
||||
...add.location,
|
||||
vendorType: this.type
|
||||
},
|
||||
service: 'bingocloudos.standard.vpc',
|
||||
configs: {
|
||||
providedIpv6Cidr: '0',
|
||||
cidr: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
this.isLoadData = true
|
||||
},
|
||||
watch: {
|
||||
'addData.location.vendorType' () {
|
||||
this.$emit('type', this.addData.location.vendorType)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getPostData () {
|
||||
let data = false
|
||||
data = this.$refs.common.handlePostData()
|
||||
return data
|
||||
},
|
||||
getParams () {
|
||||
let data = false;
|
||||
this.$refs.addForm.validate(valid => {
|
||||
if (valid) {
|
||||
data = true
|
||||
}
|
||||
})
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
|
@ -5,6 +5,7 @@
|
|||
<div>
|
||||
<op :type="type" v-if="type == 'OPENSTACK'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></op>
|
||||
<aws :type="type" v-if="type == 'AWS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></aws>
|
||||
<bingoCloudOS :type="type" v-if="type == 'AWS'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></bingoCloudOS>
|
||||
<ali :type="type" v-if="type == 'ALIYUN'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></ali>
|
||||
<huawei :type="type" v-if="type == 'HUAWEI'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></huawei>
|
||||
<tencent :type="type" v-if="type == 'TENCENT'" @type="setType" :item-data="itemData" :disabled="disabled" ref="node"></tencent>
|
||||
|
@ -19,6 +20,7 @@ import op from './op.vue'
|
|||
import tencent from './tencent.vue'
|
||||
import tce from './tce.vue'
|
||||
import aws from './aws.vue'
|
||||
import bingoCloudOS from './bingoCloudOS.vue'
|
||||
export default {
|
||||
props: {
|
||||
itemData: {
|
||||
|
@ -28,7 +30,7 @@ export default {
|
|||
type: Boolean
|
||||
}
|
||||
},
|
||||
components: { ali, op, huawei, tencent, aws, tce },
|
||||
components: { ali, op, huawei, tencent, aws, bingoCloudOS, tce },
|
||||
data () {
|
||||
return {
|
||||
type: ''
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
<div>
|
||||
<AdvanceTable :title="`${title}主机列表`" :data="tableData" :searchConfigs="searchConfigs" :params="params" :total="total" :columns="columns" :get-list="getData" :loading="loading" :key="path">
|
||||
<template v-slot:action>
|
||||
<el-button type="primary" @click="handleCreate(null, 1)" icon="el-icon-plus">
|
||||
新增
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleCreate(null, 1)" icon="el-icon-plus"> 新增 </el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh" @click="handleSynchro(type)">同步</el-button>
|
||||
<!-- <el-button type="primary" icon="el-icon-refresh" @click="handleSynchro('RIS')">同步RIS</el-button> -->
|
||||
<el-button icon="el-icon-upload2" @click="importData"> 导入 </el-button>
|
||||
|
@ -127,7 +125,7 @@ export default {
|
|||
} else {
|
||||
callback(new Error('请输入正确的IP地址'))
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
columns,
|
||||
vmSearchConfigs,
|
||||
|
@ -138,11 +136,11 @@ export default {
|
|||
params: {
|
||||
page: 1,
|
||||
rows: 20,
|
||||
sorter: JSON.stringify({ gmtCreate: '1' })
|
||||
sorter: JSON.stringify({ gmtCreate: '1' }),
|
||||
},
|
||||
setData: {
|
||||
dialog: false,
|
||||
data: {}
|
||||
data: {},
|
||||
},
|
||||
type: 'VM',
|
||||
searchConfigs: vmSearchConfigs,
|
||||
|
@ -151,7 +149,7 @@ export default {
|
|||
// 新增编辑
|
||||
textMap2: {
|
||||
update: '主机修改',
|
||||
create: '新增主机'
|
||||
create: '新增主机',
|
||||
},
|
||||
addHostVisible: false,
|
||||
addHostData: {
|
||||
|
@ -164,7 +162,7 @@ export default {
|
|||
ips: [],
|
||||
// ip: '',
|
||||
username: '',
|
||||
password: ''
|
||||
password: '',
|
||||
},
|
||||
typeName: 'ansible',
|
||||
statusList: [
|
||||
|
@ -174,54 +172,29 @@ export default {
|
|||
{ id: 'PAUSED', name: '已停止' },
|
||||
{ id: 'UNKNOWN', name: '已断开' },
|
||||
{ id: 'EXCEPTION', name: '异常' },
|
||||
{ id: 'UNKNOWSTATUS', name: '未知' }
|
||||
{ id: 'UNKNOWSTATUS', name: '未知' },
|
||||
],
|
||||
segmentIdList: [],
|
||||
flag: true,
|
||||
detail: {},
|
||||
importDialog: {
|
||||
visible: false
|
||||
visible: false,
|
||||
},
|
||||
idx: '',
|
||||
userConfig: {
|
||||
visible: false
|
||||
}
|
||||
visible: false,
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
path() {
|
||||
return this.$route.path
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
path(val) {
|
||||
this.judgeType(val)
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
vmStatusFilter(val) {
|
||||
const statusMap = {
|
||||
RUNNING: '运行中',
|
||||
STOPPED: '已关机',
|
||||
SUSPENDED: '已挂起',
|
||||
PAUSED: '已停止',
|
||||
UNKNOWN: '已断开',
|
||||
EXCEPTION: '异常',
|
||||
UNKNOWSTATUS: '未知'
|
||||
}
|
||||
return statusMap[val] || '未知'
|
||||
},
|
||||
vmStatusColorFilter(val) {
|
||||
const statusMap = {
|
||||
RUNNING: 'success',
|
||||
STOPPED: 'danger',
|
||||
SUSPENDED: 'danger',
|
||||
PAUSED: 'danger',
|
||||
EXCEPTION: 'warning',
|
||||
UNKNOWN: 'warning'
|
||||
}
|
||||
return statusMap[val] || 'warning'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.judgeType(this.path)
|
||||
|
@ -241,7 +214,7 @@ export default {
|
|||
// 导入任务
|
||||
importData() {
|
||||
this.importDialog = {
|
||||
visible: true
|
||||
visible: true,
|
||||
}
|
||||
},
|
||||
async getsegmentIdList() {
|
||||
|
@ -256,7 +229,7 @@ export default {
|
|||
addIp() {
|
||||
this.addHostData.ipList.push({
|
||||
value: '',
|
||||
key: Date.now()
|
||||
key: Date.now(),
|
||||
})
|
||||
this.$forceUpdate()
|
||||
},
|
||||
|
@ -286,14 +259,14 @@ export default {
|
|||
category: this.type == 'VM' ? 'LOGICAL' : 'PHYSICAL',
|
||||
ipList: [
|
||||
{
|
||||
value: ''
|
||||
}
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
ips: [],
|
||||
// ip: '',
|
||||
username: '',
|
||||
password: '',
|
||||
updateMode: 'MANUAL'
|
||||
updateMode: 'MANUAL',
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
|
@ -308,7 +281,7 @@ export default {
|
|||
ips.split(' ').forEach((item) => {
|
||||
this.addHostData.ipList.push({
|
||||
value: item,
|
||||
key: Date.now()
|
||||
key: Date.now(),
|
||||
})
|
||||
})
|
||||
break
|
||||
|
@ -340,7 +313,7 @@ export default {
|
|||
if (data.success) {
|
||||
this.$message({
|
||||
message: data.message,
|
||||
type: 'success'
|
||||
type: 'success',
|
||||
})
|
||||
that.addHostVisible = false
|
||||
that.getData()
|
||||
|
@ -354,13 +327,13 @@ export default {
|
|||
dialog: true,
|
||||
data: {
|
||||
...row,
|
||||
ips: row.ips.includes('[') ? JSON.parse(row.ips).join('') : row.ips
|
||||
}
|
||||
ips: row.ips.includes('[') ? JSON.parse(row.ips).join('') : row.ips,
|
||||
},
|
||||
}
|
||||
},
|
||||
handleSynchro(category) {
|
||||
this.$confirm('执行同步操作前,请先在【分组管理—>网段管理】页面创建网段数据,以免影响正常使用,您确定要同步?', '提示', {
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
syncHost(this.type == 'VM' ? 'LOGICAL' : 'PHYSICAL').then((res) => {
|
||||
const type = res.success ? 'success' : 'error'
|
||||
|
@ -371,7 +344,7 @@ export default {
|
|||
},
|
||||
settingAllow(row) {
|
||||
this.$confirm('您确定要设置HostsAllow配置嘛?', '提示', {
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
HostsAllow(row.id).then((res) => {
|
||||
const type = res.success ? 'success' : 'error'
|
||||
|
@ -382,7 +355,7 @@ export default {
|
|||
},
|
||||
handleDelete(row) {
|
||||
this.$confirm('您确定要删除该主机吗嘛?', '提示', {
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
deleteBsmHost(row.id).then((res) => {
|
||||
const type = res.success ? 'success' : 'error'
|
||||
|
@ -402,7 +375,7 @@ export default {
|
|||
if (document.querySelector('#inspect')) document.querySelector('#inspect').checked = true
|
||||
this.$confirm(`<div>您确定要对主机[${row.ip}]进行纳管巡检吗?<div> <div><input type="checkbox" id="inspect" autocomplete="off" checked>是否更新密码再进行纳管巡检</div>`, '提示', {
|
||||
type: 'warning',
|
||||
dangerouslyUseHTMLString: true
|
||||
dangerouslyUseHTMLString: true,
|
||||
}).then(() => {
|
||||
this.submitInspect({ id: row.id, force: document.querySelector('#inspect').checked })
|
||||
})
|
||||
|
@ -425,7 +398,7 @@ export default {
|
|||
OC = osCategory.toLocaleUpperCase()
|
||||
}
|
||||
this.$router.push({ name: 'serverConfig', params: { type: 'pm', osCategory: OC, host: data.ip, segmentId: data.segmentId } })
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<el-dialog title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" append-to-body width="1200px">
|
||||
<AdvanceTable :data="list" :card-border="false" row-key="id" :searchConfigs="searchConfigs" :params="params" :total="total" :columns="columns" :get-list="getList" :loading="loading" ref="tableRef" @select="handleSelectItem" @select-all="handleSelectAll">
|
||||
<template #status="status">
|
||||
<status-icon :type="vmStatusColorFilter(status, 'color')">{{ vmStatusFilter(status) }}</status-icon>
|
||||
<status-icon :type="status | vmStatusColorFilter">{{ status | vmStatusFilter }}</status-icon>
|
||||
</template>
|
||||
</AdvanceTable>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
|
@ -69,24 +69,24 @@ import { vmStatusFilter, vmStatusColorFilter } from '@/filters/index'
|
|||
import { ref, nextTick, unref, computed, reactive, watch, defineComponent, Ref } from '@vue/composition-api'
|
||||
import { Message, MessageBox } from 'element-ui'
|
||||
interface IHost {
|
||||
id: number,
|
||||
name: string,
|
||||
ip: string,
|
||||
port: number,
|
||||
segmentId: number,
|
||||
osCategory: string,
|
||||
username: string,
|
||||
pasd: string,
|
||||
id: number
|
||||
name: string
|
||||
ip: string
|
||||
port: number
|
||||
segmentId: number
|
||||
osCategory: string
|
||||
username: string
|
||||
pasd: string
|
||||
password: string
|
||||
}
|
||||
interface ITargetHost {
|
||||
id: number,
|
||||
rawName: string,
|
||||
host: string,
|
||||
port: number,
|
||||
segmentId: number,
|
||||
category: string,
|
||||
user: string,
|
||||
id: number
|
||||
rawName: string
|
||||
host: string
|
||||
port: number
|
||||
segmentId: number
|
||||
category: string
|
||||
user: string
|
||||
pasd: string
|
||||
}
|
||||
function formatHostData(list: IHost[]) {
|
||||
|
@ -100,23 +100,24 @@ function formatHostData(list: IHost[]) {
|
|||
segmentId,
|
||||
category,
|
||||
user,
|
||||
pasd: pasd && encrypt(pasd)
|
||||
pasd: pasd && encrypt(pasd),
|
||||
}
|
||||
})
|
||||
}
|
||||
export default defineComponent({
|
||||
props: {
|
||||
itemData: {
|
||||
type: Object
|
||||
type: Object,
|
||||
},
|
||||
osCategory: { // 通过osCategory过滤linux/windows机器
|
||||
osCategory: {
|
||||
// 通过osCategory过滤linux/windows机器
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
const hostData = reactive({
|
||||
|
@ -131,14 +132,17 @@ export default defineComponent({
|
|||
username,
|
||||
pasd: password,
|
||||
password,
|
||||
osCategory
|
||||
osCategory,
|
||||
}
|
||||
})
|
||||
}),
|
||||
})
|
||||
// 对主机数据监听,实时返回主机数据
|
||||
watch(() => hostData.list, () => {
|
||||
context.emit('host-change', formatHostData(hostData.list))
|
||||
});
|
||||
watch(
|
||||
() => hostData.list,
|
||||
() => {
|
||||
context.emit('host-change', formatHostData(hostData.list))
|
||||
}
|
||||
)
|
||||
const { list, total, params, loading, getList } = useTable({
|
||||
getService: getHosts,
|
||||
async afterGetList() {
|
||||
|
@ -148,7 +152,7 @@ export default defineComponent({
|
|||
unref(tableRef).toggleRowSelection(item, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
const selectList: Ref<IHost[]> = ref([])
|
||||
function handleSelectItem(selection: IHost[], row: IHost) {
|
||||
|
@ -188,7 +192,7 @@ export default defineComponent({
|
|||
...others,
|
||||
osCategory,
|
||||
pasd: pasd || (password && decrypt(password)),
|
||||
port: port || (osCategory.toUpperCase() === 'WINDOWS' ? 5986 : 22)
|
||||
port: port || (osCategory.toUpperCase() === 'WINDOWS' ? 5986 : 22),
|
||||
}
|
||||
})
|
||||
dialogServerVisible.value = false
|
||||
|
@ -211,7 +215,7 @@ export default defineComponent({
|
|||
MessageBox.confirm('您确定要清空所选主机吗?', '提示', {
|
||||
confirmButtonText: '清空',
|
||||
confirmButtonClass: 'el-button--danger',
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
hostData.list = []
|
||||
})
|
||||
|
@ -220,7 +224,7 @@ export default defineComponent({
|
|||
MessageBox.confirm(`您确定要删除主机【${name}】吗?`, '提示', {
|
||||
confirmButtonText: '清空',
|
||||
confirmButtonClass: 'el-button--danger',
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
const index = hostData.list.findIndex((item: IHost) => item.id === id)
|
||||
hostData.list.splice(index, 1)
|
||||
|
@ -246,8 +250,6 @@ export default defineComponent({
|
|||
total,
|
||||
params,
|
||||
loading,
|
||||
vmStatusFilter,
|
||||
vmStatusColorFilter,
|
||||
getList,
|
||||
handleSelectItem,
|
||||
handleSelectAll,
|
||||
|
@ -259,9 +261,9 @@ export default defineComponent({
|
|||
selectServer,
|
||||
clearServer,
|
||||
delServer,
|
||||
getPostData
|
||||
getPostData,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
"types": ["webpack-env"],
|
||||
"outDir": "dist",
|
||||
// "typeRoots": ["./node_modules/@types/", "./types"],
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
|
|
Loading…
Reference in New Issue