cmc-web/webs/cmp-web/src/views/resource/ctstack/page/securityGroup.vue

625 lines
18 KiB
Vue

<template>
<div>
<cb-detail v-if="detailFlag" :title="detail.name" :data="detail" @goBack="goBack">
<template v-slot:item_container>
<cb-detail-item label="名称">{{ detail.name }}</cb-detail-item>
<cb-detail-item label="所属平台">{{ detail.vendorName }}</cb-detail-item>
<cb-detail-item label="描述">{{ detail.remark }}</cb-detail-item>
<cb-detail-item label="所属地域">{{ detail.regionName }}</cb-detail-item>
<!-- <cb-detail-item label="所属租户">{{ detail.tenantName }}</cb-detail-item> -->
</template>
<el-tabs value="second">
<el-tab-pane label="规则列表" name="second">
<cb-advance-table :data="ruleDetailData" :params="paramd" :columns="columns_detail" :get-list="getDetailHost" :total="ruleDetailTotal" :loading="loading">
<template #protocol="val, record">
{{ record.protocol | secruityProtocol }}
</template>
<template #direction="val, record">
{{ record.direction | securityGroupFilter }}
</template>
<template #tenantName="val, record">
{{ record.etherType | etherType }}
</template>
<template #remoteIpPrefix="val, record">
{{ record.destinationAddressPrefix || (record.etherType == 'IPv6' ? '::/0' : '0.0.0.0/0') }}
</template>
<template #operate="val, record">
<el-button type="text" icon="el-icon-delete" @click="ruleRemove(record)" :disabled="record.disabled">删除 </el-button>
</template>
</cb-advance-table>
</el-tab-pane>
</el-tabs>
</cb-detail>
<el-dialog :title="titleName" :visible.sync="addFlag" v-if="addFlag" width="50%" :before-close="handleClose">
<security-item ref="securityItem" :vendorId="platformObject.vendorId" :addData="addData"></security-item>
<span slot="footer" class="dialog-footer">
<el-button @click="addFlag = false"> </el-button>
<el-button type="primary" @click="dialogOk(1, 'addData')"> </el-button>
</span>
</el-dialog>
<el-dialog title="添加规则" :visible.sync="ruleFlag" width="50%">
<span>
<security-rule ref="securityRule" :addData="ruleData" v-if="ruleFlag"></security-rule>
</span>
<span slot="footer" class="dialog-footer">
<el-button type="ghost" @click="ruleFlag = false"> </el-button>
<el-button type="primary" @click="dialogOk(2, 'ruleData')"> </el-button>
</span>
</el-dialog>
<el-card class="wrapper" v-if="!detailFlag">
<cb-advance-table title="安全组列表" :search-configs="searchConfigs" :data="tableData" :params="params" :columns="columns" :get-list="getData" :total="total" :loading="loading" @selection-change="selectChange">
<template #name="val, record">
<span class="detail-href" @click="getDetail(record.id)">{{ val }}</span>
</template>
<template v-slot:action>
<el-button type="primary" @click="dialog('addFlag', 1)"> <i class="el-icon-plus" /> 新增 </el-button>
</template>
<template #operate="val, record">
<el-button :disabled="record.disabled" type="text" @click="dropdownClick({ id: record.id, index: 2 })"> <i class="el-icon-delete"></i> 删除 </el-button>
<div class="action-divider"></div>
<el-button :disabled="record.disabled" type="text" @click="dropdownClick({ id: record.id, index: 3 })"> 添加规则 </el-button>
</template>
</cb-advance-table>
</el-card>
</div>
</template>
<script>
import securityItem from './components/securityItem.vue'
import securityRule from './components/securityRule.vue'
import { getRegion } from 'services/platform/index'
import { removeGroups, removeGroupRules, getGroup, removeGroup, modifyGroup, createGroup, detailGroup, getGroupRule, createGroupRule, removeGroupRule, detailGroupRule } from 'views/resource/ctstack/services/group'
const detailSetting = {
type: 'safe_group',
columns: [
[
{ name: '名称', value: 'name' },
{ name: '所属平台', value: 'vendorName' },
{ name: '描述', value: 'remark' }
],
[
{ name: '所属地域', value: 'regionName' }
// { name: '所属租户', value: 'tenantName' }
]
]
}
export default {
components: {
securityItem,
securityRule
},
props: {
platformObject: {
type: Object,
default: function () {
return {
vendorId: -1,
operate: -1
}
}
}
},
data() {
return {
ruleDetailData: [],
ruleDetailTotal: 0,
detailSetting,
paramd: {
page: 1,
rows: 10
},
detail: '',
detailFlag: false,
params: {
page: 1,
rows: 10
},
searchData: {
name: '',
regionId: ''
},
regionList: [],
tableData: [],
total: 0,
titleName: '新增',
addFlag: false,
addData: {},
ruleData: {
remoteIpPrefix: '',
portMin: '',
portMax: '',
direction: 'ingress',
protocol: 'TCP'
},
ruleFlag: false,
id: '',
idList: [],
selectList: [],
ruleIdList: [],
ruleSelectList: [],
columns: [
{
label: '名称',
prop: 'name',
scopedSlots: { customRender: 'name' }
},
{
label: '所属VPC',
prop: 'vpcName'
},
{
label: '描述',
prop: 'remark'
},
{
label: '所属地域',
prop: 'regionName'
},
{
label: '所属平台',
prop: 'vendorName'
},
{
label: '操作',
disabled: true,
width: '190px',
scopedSlots: { customRender: 'operate' }
}
],
searchConfigs: [
{ label: '名称', value: 'name', type: 'Input' },
{
value: 'regionId',
type: 'Select',
data: [],
label: '所属地域',
props: { value: 'regionId' }
},
{ type: 'Const', value: 'vendorId', initValue: this.platformObject.vendorId }
],
loading: false,
columns_detail: [
{
label: 'IP协议',
prop: 'protocol',
scopedSlots: { customRender: 'protocol' }
},
{
label: '方向',
prop: 'direction',
scopedSlots: { customRender: 'direction' }
},
{
label: '以太网类型',
prop: 'etherType',
scopedSlots: { customRender: 'etherType' }
},
{
label: '端口范围',
prop: 'destinationPortRange'
},
{
label: '远端地址',
prop: 'destinationAddressPrefix',
scopedSlots: { customRender: 'remoteIpPrefix' }
},
{
label: '操作',
disabled: true,
width: '220px',
scopedSlots: { customRender: 'operate' }
}
],
isCreate: false
}
},
methods: {
selectChange(val) {
this.selectList = val
},
ruleRefreshId() {
this.ruleIdList = []
this.ruleSelectList.forEach(item => {
this.ruleIdList.push(item.id)
})
},
// 单选
ruleHandleSelectItem(selection, row) {
this.ruleRefreshId()
if (this.ruleIdList.indexOf(row.id) > -1) {
for (let j = 0; j < this.ruleSelectList.length; j++) {
const item = this.ruleSelectList[j]
if (item.id == row.id) {
this.ruleSelectList.splice(j, 1)
break
}
}
} else {
this.ruleSelectList.push(row)
}
},
// 全选
ruleHandleSelectAll(selection) {
this.ruleRefreshId()
if (selection.length) {
// 全选情况下
this.ruleDetailData.forEach(item => {
if (this.idList.indexOf(item.id) == -1) {
this.ruleSelectList.push(item)
}
})
} else {
// 全不选情况下
this.ruleDetailData.forEach(item => {
if (this.idList.indexOf(item.id) > -1) {
for (let j = 0; j < this.ruleSelectList.length; j++) {
const row = this.ruleSelectList[j]
if (item.id == row.id) {
this.ruleSelectList.splice(j, 1)
break
}
}
}
})
}
},
refreshId() {
this.idList = []
this.selectList.forEach(item => {
this.idList.push(item.id)
})
},
// 单选
handleSelectItem(selection, row) {
this.refreshId()
if (this.idList.indexOf(row.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const item = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
} else {
this.selectList.push(row)
}
},
// 全选
handleSelectAll(selection) {
this.refreshId()
if (selection.length) {
// 全选情况下
selection.forEach(item => {
if (this.idList.indexOf(item.id) == -1) {
this.selectList.push(item)
}
})
} else {
// 全不选情况下
this.tableData.forEach(item => {
if (this.idList.indexOf(item.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const row = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
}
})
}
},
ruleHandleDelete() {
this.ruleRefreshId()
const list = this.ruleIdList
this.$confirm('此操作将删除所选规则, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
removeGroupRules(list).then(data => {
if (data.success) {
this.$message({
type: 'success',
message: data.message
})
this.getData()
this.ruleSelectList = []
}
})
})
},
// 删除规则
ruleRemove(data) {
this.$confirm('此操作将永久删除该规则, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
removeGroupRule(data.id).then(data => {
if (data.success) {
this.$message({
type: 'success',
message: data.message
})
this.getDetailHost(1)
}
})
})
},
// 详情
getDetail(id) {
this.id = id
detailGroup(id).then(data => {
if (data.success) {
this.detail = data.data
this.detailFlag = true
this.getDetailHost(1)
}
})
},
goBack() {
this.ruleSelectList = []
this.getData()
this.detailFlag = false
},
getDetailHost(page) {
this.ruleRefreshId()
this.paramd.page = page || this.paramd.page
this.paramd.params = JSON.stringify([
{
param: {
groupId: this.id,
vendorId: this.platformObject.vendorId
},
sign: 'EQ'
}
])
getGroupRule(this.paramd).then(data => {
if (data.success) {
this.ruleDetailData = data.data.rows
this.ruleDetailTotal = data.data.total
this.ruleDetailData.forEach(data => {
if ((data.projectVisibility && data.projectVisibility != 'GLOBAL_PROJECT') || data.tenantId || data.tenantIds || data.tenantName) {
data.disabled = true
}
const self = this
setTimeout(function () {
if (self.ruleIdList.indexOf(data.id) > -1) self.$refs.ruleMultipleTable.$refs.basicTable.toggleRowSelection(data, true)
})
})
}
})
},
getData() {
this.loading = true
getGroup(this.params)
.then(data => {
if (data.success) {
this.tableData = data.data.rows
this.total = data.data.total
this.selectList = []
this.refreshId()
this.tableData.forEach(data => {
if ((data.projectVisibility && data.projectVisibility != 'GLOBAL_PROJECT') || data.tenantId || data.tenantIds || data.tenantName) {
data.disabled = true
}
const self = this
setTimeout(function () {
if (self.idList.indexOf(data.id) > -1) self.$refs.multipleTable.$refs.basicTable.toggleRowSelection(data, true)
})
})
}
})
.finally(() => {
this.loading = false
})
},
handleSizeChange(val) {
this.params.rows = val
this.getData()
},
handleDelete() {
this.refreshId()
const list = this.idList
this.$confirm('此操作将删除所选安全组, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
removeGroups(list).then(data => {
if (data.success) {
this.$message({
type: 'success',
message: data.message
})
this.getData()
this.selectList = []
}
})
})
},
// 删除
remove(id) {
this.$confirm('此操作将永久删除该安全组, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
removeGroup(id).then(data => {
if (data.success) {
this.$message({
type: 'success',
message: data.message
})
this.getData()
}
})
})
},
// 下拉框点击事件
dropdownClick(command) {
switch (command.index) {
case 1:
this.dialog('addFlag', 1, command.id)
break
case 2:
this.remove(command.id)
break
case 3:
this.dialog('ruleFlag', 2, command.id)
break
}
},
// 模态框开启前执行事件
dialog(flag, index, id) {
this[flag] = true
switch (index) {
case 1:
this.titleName = '新增安全组'
this.addData = {}
if (id) {
this.titleName = '编辑安全组'
detailGroup(id).then(data => {
if (data.success) {
const { id, name, remark } = data.data
this.addData = {
id,
name,
remark
}
}
})
}
break
case 2:
this.ruleData = {
vendorId: this.platformObject.vendorId,
groupId: id,
destinationAddressPrefix: '0.0.0.0/0',
direction: 'ingress',
protocol: 'TCP',
ethertype: 'IPv4',
priority: 1,
action: 'accept',
portMin: '',
portMax: ''
}
break
}
},
// 模态框确认
dialogOk(index) {
switch (index) {
case 1:
if (!this.isCreate) {
const data = this.$refs.securityItem.getPostData()
if (!data) return
data.vendorId = this.platformObject.vendorId
this.isCreate = true
createGroup(data).then(data => {
if (data.success) {
this.$message({
type: 'success',
message: data.message
})
this.addFlag = false
this.getData()
}
this.isCreate = false
})
}
break
case 2:
const data1 = this.$refs.securityRule.getPostData()
if (!data1) return
if (data1.portMax < data1.portMin) {
this.$message('结束端口不能小于起始端口')
return
}
createGroupRule(data1).then(data => {
if (data.success) {
this.$message({
type: 'success',
message: data.message
})
this.getData()
this.ruleFlag = false
this.ruleData = {
remoteIpPrefix: '',
portMin: '',
portMax: '',
direction: 'ingress',
protocol: 'TCP'
}
}
})
break
}
},
// 模态框退出及取消触发事件
cancel(formName, flag) {
this[flag] = false
this.$refs[formName].resetFields()
},
// 模态框ESE事件
handleClose(done) {
const list = ['addFlag', 'ruleFlag']
for (let i = 0; i < list.length; i++) {
if (this[list[i]]) {
switch (list[i]) {
case 'addFlag':
this.cancel('addData', 'addFlag')
break
case 'ruleFlag':
this.cancel('ruleData', 'addFlag')
break
}
}
}
},
// 获取域
getRegion() {
getRegion({ vendorId: this.platformObject.vendorId }).then(data => {
if (data.success) {
this.regionList = data.data
this.searchConfigs[1].data = data.data
}
})
}
},
mounted() {
this.getRegion()
},
watch: {
platformObject: {
handler(newVal, oldVal) {
this.searchConfigs = [
{ label: '名称', value: 'name', type: 'Input' },
{
value: 'regionId',
type: 'Select',
data: [],
label: '所属地域'
},
{ type: 'Const', value: 'vendorId', initValue: newVal.vendorId }
]
this.getDetailHost()
this.getRegion()
},
deep: true
}
}
}
</script>
<style scoped>
.no-searchBox {
padding: 10px;
}
.table-container {
border: none !important;
}
</style>