更新vue版本,添加端口映射配置

This commit is contained in:
az
2023-12-06 22:18:09 +08:00
parent 781b14861c
commit 6cbf2ecac4
12 changed files with 292 additions and 70 deletions
+1 -1
View File
@@ -23,7 +23,7 @@
"codemirror": "5.32.0",
"dropzone": "5.2.0",
"echarts": "3.8.5",
"element-ui": "2.0.8",
"element-ui": "^2.15.14",
"file-saver": "1.3.3",
"font-awesome": "4.7.0",
"js-cookie": "2.2.0",
@@ -44,3 +44,22 @@ export function updateEnableStatus(id, enable) {
}
})
}
export function portMappingBindSecurityGroup(id, securityGroupId) {
return request({
url: '/port-mapping/bind/security-group',
method: 'post',
data: {
id: id,
securityGroupId: securityGroupId
}
})
}
export function portMappingUnbindSecurityGroup(id) {
return request({
url: `/port-mapping/unbind/security-group?id=${id}`,
method: 'post'
})
}
@@ -0,0 +1,83 @@
<template>
<el-popover
placement="top"
:width="width"
v-model="visible">
<p class="popper-p-css"><i class="el-icon-warning" style="color: #e6a23c"/>{{title}}</p>
<div style="text-align: center; margin: 0">
<el-button size="mini" @click="handleCancelClick">{{cancelText}}</el-button>
<el-button type="primary" size="mini" @click="handleCommitClick">{{okText}}</el-button>
</div>
<el-link slot="reference" :underline="false" :type="type" :size="size" :icon="icon" :disabled="disabled" style="width: 100%;text-align: left;">{{buttonText}}</el-link>
</el-popover>
</template>
<script>
export default {
name: 'deleteLink',
props: {
width: {
type: Number,
default: 160
},
buttonText: {
type: String,
default: '删除'
},
type: {
type: String,
default: 'danger'
},
size: {
type: String,
default: 'mini'
},
icon: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
title: {
type: String,
default: '确定删除吗?'
},
okText: {
type: String,
default: '确定'
},
cancelText: {
type: String,
default: '取消'
}
},
data() {
return {
visible: false
}
},
methods: {
handleCancelClick() {
this.visible = false
this.$emit('handleCancelClick')
},
handleCommitClick() {
this.visible = false
this.$emit('handleCommitClick')
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.popper-p-css{
margin-top: 0px !important;
margin-bottom: 5px !important;
.el-icon-warning{
margin-right: 5px;
}
}
</style>
+4 -2
View File
@@ -173,6 +173,7 @@ export default {
protocalName: '协议',
supportStatus: '支持状态',
domainName: '域名',
securityGroup: '安全组',
defaultPassType: '默认放行类型',
ruleName: '规则名称',
rule: '规则内容',
@@ -180,9 +181,10 @@ export default {
priority: '优先级',
ruleConfig: '规则配置',
portMappingBindSecurityGroup: '绑定安全组',
securityGroupBindPortMapping: '绑定端口映射',
securityGroupBindPortMapping: '端口映射绑定',
bind: '绑定',
unbind: '解绑'
unbind: '解绑',
bindOtherSecurityGroup: '已绑定其他安全组'
},
button: {
lookOver: '查看'
@@ -176,6 +176,12 @@
<template slot="append">毫秒</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('table.securityGroup')" prop="securityGroup">
<el-select style="width: 280px;" class="filter-item" v-model="temp.securityGroupId" clearable >
<el-option v-for="item in securityGroupList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('描述')" prop="description">
<el-input v-model="temp.description"></el-input>
</el-form-item>
@@ -204,6 +210,7 @@
<script>
import { fetchList, createUserPortMapping, updateUserPortMapping, updateEnableStatus, deletePortMapping } from '@/api/portMapping'
import { fetchGroupList } from '@/api/securityGroup'
import { availablePortList, portAvailable } from '@/api/portPool'
import { licenseList, licenseAuthList } from '@/api/license'
import { protocalList } from '@/api/protocal'
@@ -325,6 +332,7 @@ export default {
licenseId:null,
},
more: true,
securityGroupList: []
}
},
filters: {
@@ -359,6 +367,7 @@ export default {
this.getLicenseList()
this.getLicenseAuthList()
this.getProtocalList()
this.fetchSecurityGroupList()
},
methods: {
getList() {
@@ -380,6 +389,13 @@ export default {
this.getList()
})
},
fetchSecurityGroupList () {
fetchGroupList().then(res => {
if(res.data.code == 0) {
this.securityGroupList = res.data.data
}
})
},
getDomainNameBindInfo() {
domainNameBindInfo().then(response => {
this.domainName = response.data.data
@@ -37,27 +37,39 @@
<span>{{scope.row.updateTime}}</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" :label="$t('table.enableStatus')" width="150">
<el-table-column class-name="status-col" :label="$t('table.enableStatus')">
<template slot-scope="scope">
<el-tag :type="scope.row.enable" v-if="scope.row.enable == '启用'">{{scope.row.enable}}</el-tag>
<el-tag :type="scope.row.disable" v-if="scope.row.enable == '禁用'">{{scope.row.enable}}</el-tag>
<el-tag type="success" v-if="scope.row.enable == '启用'">{{scope.row.enable}}</el-tag>
<el-tag type="danger" v-if="scope.row.enable == '禁用'">{{scope.row.enable}}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.actions')" width="400" class-name="small-padding fixed-width">
<el-table-column align="center" :label="$t('table.actions')" class-name="small-padding fixed-width" style="display:flex;justify-content:center">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">{{$t('table.edit')}}</el-button>
<el-button v-if="scope.row.enable =='启用'" size="mini" type="warning" @click="handleDisableStatus(scope.row)">{{$t('table.disable')}}</el-button>
<el-button v-if="scope.row.enable =='用'" size="mini" type="success" @click="handleEnableStatus(scope.row)">{{$t('table.enable')}}</el-button>
<!-- <el-button v-if="scope.row.status!='deleted'" size="mini" type="danger" @click="handleDelete(scope.row,'deleted')">{{$t('table.delete')}}</el-button>-->
<ButtonPopover @handleCommitClick="handleDelete(scope.row)" style="margin-left: 10px"/>
<el-button type="primary" size="mini" @click="handleGoRulePage(scope.row)">{{$t('table.ruleConfig')}}</el-button>
<el-button type="primary" size="mini" @click="handlePortMapping(scope.row)">{{$t('table.securityGroupBindPortMapping')}}</el-button>
<div>
<el-link :underline="false" type="primary" size="mini" @click="handleUpdate(scope.row)">{{$t('table.edit')}}</el-link>
<el-link :underline="false" v-if="scope.row.enable =='用'" size="mini" type="warning" @click="handleDisableStatus(scope.row)">{{$t('table.disable')}}</el-link>
<el-link :underline="false" v-if="scope.row.enable =='禁用'" size="mini" type="success" @click="handleEnableStatus(scope.row)">{{$t('table.enable')}}</el-link>
<el-link :underline="false" type="primary" size="mini" @click="handleGoRulePage(scope.row)">{{$t('table.ruleConfig')}}</el-link>
</div>
<el-dropdown>
<span class="el-dropdown-link">
更多操作<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>
<LinkPopover @handleCommitClick="handleDelete(scope.row)" style="width: 100%"/>
</el-dropdown-item>
<el-dropdown-item>
<el-link :underline="false" type="primary" size="mini" @click="handlePortMapping(scope.row)">{{$t('table.securityGroupBindPortMapping')}}</el-link>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :rules="rules" ref="dataForm" :model="temp" label-position="right" label-width="200px" style='width: 500px; margin-left:50px;'>
<el-form :rules="rules" ref="dataForm" :model="temp" label-position="right" label-width="120px" style='width: 500px; margin-left:10px;'>
<el-form-item :label="$t('table.name')" prop="name">
<el-input :placeholder="$t('table.name')" v-model="temp.name"></el-input>
</el-form-item>
@@ -67,7 +79,7 @@
</el-form-item>
<el-form-item :label="$t('table.defaultPassType')" prop="defaultPassType">
<el-select style="width: 300px" class="filter-item" v-model="temp.defaultPassType">
<el-select style="width: 380px" class="filter-item" v-model="temp.defaultPassType">
<el-option v-for="item in passTypeList" :key="item.key" :label="item.key" :value="item.value">
</el-option>
</el-select>
@@ -91,36 +103,64 @@
</span>
</el-dialog>
<el-dialog :title="$t('table.securityGroupBindPortMapping')" :visible.sync="dialogBindPortMappingVisible">
<el-table :key='tableKey' :data="list" v-loading="listLoading" element-loading-text="给我一点时间" border fit highlight-current-row
style="width: 100%">
<el-table-column align="center" :label="$t('table.id')" width="60">
<el-dialog :title="$t('table.securityGroupBindPortMapping')+'---'+forBindProtMappingSecurityGroup.name+'安全组'" :visible.sync="dialogBindPortMappingVisible" width="90%">
<el-table :key='tableKey' :data="portMappingList" v-loading="listLoading" element-loading-text="给我一点时间" border fit align="center" width="100%"
highlight-current-row style="width: 100%">
<el-table-column align="center" :label="$t('table.id')" width="50">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
<span>{{ scope.row.id }}</span>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.name')">
<el-table-column align="center" :label="$t('table.licenseName')" width="130">
<template slot-scope="scope">
<span>{{scope.row.name}}</span>
<span>{{ scope.row.licenseName }}</span>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.desc')">
<el-table-column align="center" :label="$t('table.protocalName')" width="100">
<template slot-scope="scope">
<span>{{scope.row.description}}</span>
<span>{{ scope.row.protocal }}</span>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.defaultPassType')">
<el-table-column align="center" :label="$t('table.domainName')" width="200">
<template slot-scope="scope">
<span>{{scope.row.defaultPassType}}</span>
<span>{{ scope.row.domain }}</span>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.actions')" width="200" class-name="small-padding fixed-width">
<el-table-column align="center" :label="$t('table.serverPort')" width="80">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleBind(scope.row)">{{$t('table.bind')}}</el-button>
<el-button type="danger" size="mini" @click="handleUnbind(scope.row)">{{$t('table.unbind')}}</el-button>
<span>{{ scope.row.serverPort }}</span>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.proxyClient')" width="120">
<template slot-scope="scope">
<span>{{ scope.row.clientIp }}:{{ scope.row.clientPort }}</span>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.desc')" width="120">
<template slot-scope="scope">
<span>{{ scope.row.description }}</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" :label="$t('table.enableStatus')" width="100">
<template slot-scope="scope">
<el-tag :type="scope.row.enable | statusFilter">{{ scope.row.enable | statusName }}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.actions')" width="120" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="primary" size="mini" v-if="!scope.row.securityGroupId" @click="handleBind(scope.row)">{{$t('table.bind')}}</el-button>
<el-button type="danger" size="mini" v-if="scope.row.securityGroupId && scope.row.securityGroupId == forBindProtMappingSecurityGroup.id" @click="handleUnbind(scope.row)">{{$t('table.unbind')}}</el-button>
<span v-if="scope.row.securityGroupId && scope.row.securityGroupId != forBindProtMappingSecurityGroup.id" style="font-size: 12px;">{{$t('table.bindOtherSecurityGroup')}}</span>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination background @size-change="handlePortMappingSizeChange" @current-change="handlePortMappingCurrentChange"
:current-pageInfo.sync="portMappingListQuery.current" :pageInfo-sizes="[10, 20, 30, 50]" :pageInfo-size="portMappingListQuery.size"
layout="total, sizes, prev, pager, next, jumper" :total="portMappingTotal">
</el-pagination>
</div>
</el-dialog>
</div>
@@ -128,9 +168,10 @@
<script>
import {fetchGroupList, createGroup, updateGroup, deleteGroup, enableGroup, disableGroup} from '@/api/securityGroup'
import { fetchList as fetchPortMappingList, portMappingBindSecurityGroup, portMappingUnbindSecurityGroup} from '@/api/portMapping'
import waves from '@/directive/waves' // 水波纹指令
import { parseTime } from '@/utils'
import ButtonPopover from '../../components/Button/buttonPopover'
import LinkPopover from '../../components/Link/linkPopover'
export default {
name: 'complexTable',
@@ -138,7 +179,7 @@ import ButtonPopover from '../../components/Button/buttonPopover'
waves
},
components: {
ButtonPopover
LinkPopover
},
data() {
return {
@@ -167,7 +208,23 @@ import ButtonPopover from '../../components/Button/buttonPopover'
downloadLoading: false,
checkBoxData:[], //表单勾选的行
dialogBindPortMappingVisible: false,
bindProtMappingSecurityGroup: {}
forBindProtMappingSecurityGroup: {},
portMappingList: [],
portMappingTotal: null,
portMappingListLoading: false,
portMappingListQuery: {
current: 1,
size: 10,
importance: undefined,
title: undefined,
type: undefined,
userId: undefined,
license: undefined,
port: undefined,
isOnline: undefined,
enable: undefined,
description: undefined
},
}
},
filters: {
@@ -192,6 +249,7 @@ import ButtonPopover from '../../components/Button/buttonPopover'
created() {
// eslint-disable-next-line no-sequences
this.getList()
this.getPortMappingList()
},
methods: {
getList() {
@@ -201,6 +259,15 @@ import ButtonPopover from '../../components/Button/buttonPopover'
this.listLoading = false
})
},
getPortMappingList() {
this.portMappingListLoading = true
fetchPortMappingList(this.portMappingListQuery).then(response => {
this.portMappingList = response.data.data.records
this.portMappingTotal = response.data.data.total
this.portMappingListQuery.current = response.data.data.current
this.portMappingListLoading = false
})
},
handleEnableStatus(row) {
enableGroup(row.id).then(response => {
if (response.data.code === 0) {
@@ -303,7 +370,41 @@ import ButtonPopover from '../../components/Button/buttonPopover'
},
handlePortMapping(row) {
this.dialogBindPortMappingVisible = true
this.bindProtMappingSecurityGroup = row
this.forBindProtMappingSecurityGroup = row
},
handlePortMappingSizeChange(val) {
this.portMappingListQuery.size = val
this.getPortMappingList()
},
handlePortMappingCurrentChange(val) {
this.portMappingListQuery.current = val
this.getPortMappingList()
},
handleBind(portMapping) {
portMappingBindSecurityGroup(portMapping.id, this.forBindProtMappingSecurityGroup.id).then(response => {
if (response.data.code === 0) {
this.$notify({
title: '成功',
message: '绑定成功',
type: 'success',
duration: 2000
})
this.getPortMappingList()
}
})
},
handleUnbind(portMapping) {
portMappingUnbindSecurityGroup(portMapping.id).then(response => {
if (response.data.code === 0) {
this.$notify({
title: '成功',
message: '解绑成功',
type: 'success',
duration: 2000
})
this.getPortMappingList()
}
})
}
}
}
@@ -66,7 +66,7 @@ public class PortMappingController {
@Post
@Mapping("/update")
public PortMappingUpdateRes update(PortMappingUpdateReq req) {
public void update(PortMappingUpdateReq req) {
ParamCheckUtil.checkNotNull(req, "req");
ParamCheckUtil.checkNotNull(req.getLicenseId(), "licenseId");
ParamCheckUtil.checkNotNull(req.getServerPort(), "serverPort");
@@ -91,7 +91,7 @@ public class PortMappingController {
req.setProxyTimeoutMs(0L);
}
return portMappingService.update(req);
portMappingService.update(req);
}
@Get
@@ -124,23 +124,22 @@ public class PortMappingController {
/**
* 绑定安全组
* @param portMappingId 端口映射Id
* @param securityGroupId 安全组Id
* @param req portMappingId和securityGroupId
*/
@Post
@Mapping("/bind/security-group")
public void bindSecurityGroup(Integer portMappingId, Integer securityGroupId) {
portMappingService.portBindSecurityGroup(portMappingId, securityGroupId);
public void bindSecurityGroup(PortMappingBindSecurityGroupReq req) {
portMappingService.portBindSecurityGroup(req.getId(), req.getSecurityGroupId());
}
/**
* 安全组解绑
* @param portMappingId 端口映射Id
* @param id 端口映射Id
*/
@Post
@Mapping("/unbind/security-group")
public void unbindSecurityGroup(Integer portMappingId) {
portMappingService.portUnbindSecurityGroup(portMappingId);
public void unbindSecurityGroup(Integer id) {
portMappingService.portUnbindSecurityGroup(id);
}
@@ -0,0 +1,12 @@
package org.dromara.neutrinoproxy.server.controller.req.proxy;
import lombok.Data;
@Data
public class PortMappingBindSecurityGroupReq {
private Integer id;
private Integer securityGroupId;
}
@@ -66,6 +66,12 @@ public class PortMappingUpdateReq {
* 代理超时时间
*/
private Long proxyTimeoutMs;
/**
* 安全组Id
*/
private Integer securityGroupId;
/**
* 描述
*/
@@ -101,6 +101,12 @@ public class PortMappingListRes {
* 描述
*/
private String description;
/**
* 安全组Id
*/
private Integer securityGroupId;
/**
* 创建时间
*/
@@ -21,6 +21,7 @@
*/
package org.dromara.neutrinoproxy.server.dal.entity;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -107,23 +108,9 @@ public class PortMappingDO {
*/
private Date updateTime;
public PortMappingListRes toRes() {
PortMappingListRes res = new PortMappingListRes();
res.setId(id);
res.setLicenseId(licenseId);
res.setProtocal(protocal);
res.setSubdomain(subdomain);
res.setServerPort(serverPort);
res.setClientIp(clientIp);
res.setClientPort(clientPort);
res.setDescription(description);
res.setIsOnline(isOnline);
res.setProxyResponses(proxyResponses);
res.setProxyTimeoutMs(proxyTimeoutMs);
res.setEnable(enable);
res.setCreateTime(createTime);
res.setUpdateTime(updateTime);
BeanUtil.copyProperties(this, res);
return res;
}
}
@@ -1,5 +1,6 @@
package org.dromara.neutrinoproxy.server.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -168,7 +169,7 @@ public class PortMappingService implements LifecycleBean {
return new PortMappingCreateRes();
}
public PortMappingUpdateRes update(PortMappingUpdateReq req) {
public void update(PortMappingUpdateReq req) {
LicenseDO licenseDO = licenseMapper.findById(req.getLicenseId());
ParamCheckUtil.checkNotNull(licenseDO, ExceptionConstant.LICENSE_NOT_EXIST);
if (!SystemContextHolder.isAdmin()) {
@@ -185,16 +186,7 @@ public class PortMappingService implements LifecycleBean {
ParamCheckUtil.checkNotNull(oldPortMappingDO, ExceptionConstant.PORT_MAPPING_NOT_EXIST);
PortMappingDO portMappingDO = new PortMappingDO();
portMappingDO.setId(req.getId());
portMappingDO.setProtocal(req.getProtocal());
portMappingDO.setSubdomain(req.getSubdomain());
portMappingDO.setLicenseId(req.getLicenseId());
portMappingDO.setServerPort(req.getServerPort());
portMappingDO.setClientIp(req.getClientIp());
portMappingDO.setClientPort(req.getClientPort());
portMappingDO.setProxyResponses(req.getProxyResponses());
portMappingDO.setProxyTimeoutMs(req.getProxyTimeoutMs());
portMappingDO.setDescription(req.getDescription());
BeanUtil.copyProperties(req, portMappingDO);
portMappingDO.setUpdateTime(new Date());
portMappingDO.setEnable(EnableStatusEnum.ENABLE.getStatus());
portMappingMapper.updateById(portMappingDO);
@@ -208,7 +200,6 @@ public class PortMappingService implements LifecycleBean {
if (NetworkProtocolEnum.isHttp(portMappingDO.getProtocal()) && StrUtil.isNotBlank(proxyConfig.getServer().getTcp().getDomainName()) && StrUtil.isNotBlank(portMappingDO.getSubdomain())) {
ProxyUtil.setSubdomainToServerPort(portMappingDO.getSubdomain(), portMappingDO.getServerPort());
}
return new PortMappingUpdateRes();
}
public PortMappingDetailRes detail(Integer id) {