eslint fixed and 页面权限配置 and 默认权限数据加载.
This commit is contained in:
84
src/main/java/com/xuxd/kafka/console/dao/init/DataInit.java
Normal file
84
src/main/java/com/xuxd/kafka/console/dao/init/DataInit.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package com.xuxd.kafka.console.dao.init;
|
||||
|
||||
import com.xuxd.kafka.console.config.AuthConfig;
|
||||
import com.xuxd.kafka.console.dao.SysPermissionMapper;
|
||||
import com.xuxd.kafka.console.dao.SysRoleMapper;
|
||||
import com.xuxd.kafka.console.dao.SysUserMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/17 13:10
|
||||
**/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DataInit implements SmartInitializingSingleton {
|
||||
|
||||
private final AuthConfig authConfig;
|
||||
|
||||
private final SysUserMapper userMapper;
|
||||
|
||||
private final SysRoleMapper roleMapper;
|
||||
|
||||
private final SysPermissionMapper permissionMapper;
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final SqlParse sqlParse;
|
||||
|
||||
|
||||
public DataInit(AuthConfig authConfig,
|
||||
SysUserMapper userMapper,
|
||||
SysRoleMapper roleMapper,
|
||||
SysPermissionMapper permissionMapper,
|
||||
DataSource dataSource) {
|
||||
this.authConfig = authConfig;
|
||||
this.userMapper = userMapper;
|
||||
this.roleMapper = roleMapper;
|
||||
this.permissionMapper = permissionMapper;
|
||||
this.dataSource = dataSource;
|
||||
this.sqlParse = new SqlParse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
if (!authConfig.isEnable()) {
|
||||
log.info("Disable login authentication, no longer try to initialize the data");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Connection connection = dataSource.getConnection();
|
||||
Integer userCount = userMapper.selectCount(null);
|
||||
if (userCount == null || userCount == 0) {
|
||||
initData(connection, SqlParse.USER_TABLE);
|
||||
}
|
||||
|
||||
Integer roleCount = roleMapper.selectCount(null);
|
||||
if (roleCount == null || roleCount == 0) {
|
||||
initData(connection, SqlParse.ROLE_TABLE);
|
||||
}
|
||||
|
||||
Integer permCount = permissionMapper.selectCount(null);
|
||||
if (permCount == null || permCount == 0) {
|
||||
initData(connection, SqlParse.PERM_TABLE);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initData(Connection connection, String table) throws SQLException {
|
||||
log.info("Init default data for {}", table);
|
||||
String sql = sqlParse.getMergeSql(table);
|
||||
PreparedStatement statement = connection.prepareStatement(sql);
|
||||
statement.execute();
|
||||
}
|
||||
}
|
||||
85
src/main/java/com/xuxd/kafka/console/dao/init/SqlParse.java
Normal file
85
src/main/java/com/xuxd/kafka/console/dao/init/SqlParse.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package com.xuxd.kafka.console.dao.init;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import scala.collection.mutable.StringBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author: xuxd
|
||||
* @date: 2023/5/17 21:22
|
||||
**/
|
||||
@Slf4j
|
||||
public class SqlParse {
|
||||
|
||||
private final String FILE = "classpath:db/data-h2.sql";
|
||||
|
||||
private final Map<String, List<String>> sqlMap = new HashMap<>();
|
||||
|
||||
public static final String ROLE_TABLE = "t_sys_role";
|
||||
public static final String USER_TABLE = "t_sys_user";
|
||||
public static final String PERM_TABLE = "t_sys_permission";
|
||||
|
||||
public SqlParse() {
|
||||
sqlMap.put(ROLE_TABLE, new ArrayList<>());
|
||||
sqlMap.put(USER_TABLE, new ArrayList<>());
|
||||
sqlMap.put(PERM_TABLE, new ArrayList<>());
|
||||
|
||||
String table = null;
|
||||
try {
|
||||
File file = ResourceUtils.getFile(FILE);
|
||||
List<String> lines = Files.readLines(file, Charset.forName("UTF-8"));
|
||||
for (String str : lines) {
|
||||
if (StringUtils.isNotEmpty(str)) {
|
||||
if (str.indexOf("start--") > 0) {
|
||||
if (str.indexOf(ROLE_TABLE) > 0) {
|
||||
table = ROLE_TABLE;
|
||||
}
|
||||
if (str.indexOf(USER_TABLE) > 0) {
|
||||
table = USER_TABLE;
|
||||
}
|
||||
if (str.indexOf(PERM_TABLE) > 0) {
|
||||
table = PERM_TABLE;
|
||||
}
|
||||
}
|
||||
if (isSql(str)) {
|
||||
if (table == null) {
|
||||
log.error("Table is null, can not load sql: {}", str);
|
||||
continue;
|
||||
}
|
||||
sqlMap.get(table).add(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getSqlList(String table) {
|
||||
return sqlMap.get(table);
|
||||
}
|
||||
|
||||
public String getMergeSql(String table) {
|
||||
List<String> list = getSqlList(table);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
list.forEach(sql -> sb.append(sql));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private boolean isSql(String str) {
|
||||
return StringUtils.isNotEmpty(str) && str.startsWith("insert");
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,7 @@ public class UserManageServiceImpl implements UserManageService {
|
||||
}
|
||||
userDO.setSalt(UUIDStrUtil.random());
|
||||
userDO.setPassword(UUIDStrUtil.generate(userDTO.getPassword(), userDO.getSalt()));
|
||||
userMapper.insert(userDTO.toDO());
|
||||
userMapper.insert(userDO);
|
||||
} else {
|
||||
SysUserDO userDO = userMapper.selectById(userDTO.getId());
|
||||
if (userDO == null) {
|
||||
|
||||
@@ -50,6 +50,6 @@ cron:
|
||||
|
||||
# 权限认证设置,设置为true,需要先登录才能访问
|
||||
auth:
|
||||
enable: false
|
||||
enable: true
|
||||
# 登录用户token的过期时间,单位:小时
|
||||
expire-hours: 24
|
||||
@@ -1,14 +1,11 @@
|
||||
-- DELETE FROM t_kafka_user;
|
||||
--
|
||||
-- INSERT INTO t_kafka_user (id, username, password) VALUES
|
||||
-- (1, 'Jone', 'p1'),
|
||||
-- (2, 'Jack', 'p2');
|
||||
|
||||
-- 不要随便修改下面的注释,要根据这个注释初始化加载数据
|
||||
-- t_sys_permission start--
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(0,'主页',0,null,'home');
|
||||
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(11,'集群',0,null,'cluster');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(12,'属性配置',1,11,'cluster:property-config');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(13,'日志配置',1,11,'cluster:log-config');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(14,'编辑配置',1,11,'cluster:edit');
|
||||
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(21,'Topic',0,null,'topic');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(22,'刷新',1,21,'topic:load');
|
||||
@@ -49,11 +46,26 @@ insert into t_sys_permission(id, name,type,parent_id,permission) values(83,'客
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(84,'新增配置',1,83,'quota:client:add');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(85,'用户和客户端ID',1,80,'quota:user-client');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(86,'新增配置',1,85,'quota:user-client:add');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(87,'删除',1,80,'quota:del');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(88,'修改',1,80,'quota:edit');
|
||||
|
||||
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(100,'Acl',0,null,'acl');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(101,'资源授权',1,100,'acl:authority');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(102,'新增权限',1,101,'acl:authority:add');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(102,'新增主体权限',1,101,'acl:authority:add-principal');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(103,'权限详情',1,101,'acl:authority:detail');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(104,'管理生产权限',1,101,'acl:authority:producer');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(105,'管理消费权限',1,101,'acl:authority:consumer');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(106,'增加权限',1,101,'acl:authority:add');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(107,'清除权限',1,101,'acl:authority:clean');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(108,'SaslScram用户管理',1,100,'acl:sasl-scram');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(109,'新增/更新用户',1,108,'acl:sasl-scram:add-update');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(110,'详情',1,108,'acl:sasl-scram:detail');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(111,'删除',1,108,'acl:sasl-scram:del');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(112,'管理生产权限',1,108,'acl:sasl-scram:producer');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(113,'管理消费权限',1,108,'acl:sasl-scram:consumer');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(114,'增加权限',1,108,'acl:sasl-scram:add-auth');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(115,'彻底删除',1,108,'acl:sasl-scram:pure');
|
||||
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(140,'用户',0,null,'user-manage');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(141,'用户列表',1,140,'user-manage:user');
|
||||
@@ -78,8 +90,13 @@ insert into t_sys_permission(id, name,type,parent_id,permission) values(167,'解
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(168,'首选副本作leader',1,160,'op:replication-preferred');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(169,'副本变更详情',1,160,'op:replication-update-detail');
|
||||
insert into t_sys_permission(id, name,type,parent_id,permission) values(170,'副本重分配',1,160,'op:replication-reassign');
|
||||
-- t_sys_permission end--
|
||||
|
||||
-- t_sys_role start--
|
||||
insert into t_sys_role(id, role_name, description, permission_ids) VALUES (1,'超级管理员','超级管理员','12,13,14,22,23,24,25,26,27,28,29,30,31,32,33,42,43,44,45,46,47,48,49,50,62,63,64,65,81,82,83,84,85,86,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,141,142,143,144,145,146,147,148,149,150,161,162,163,164,165,166,167,168,169,170');
|
||||
-- insert into t_sys_role(id, role_name, description, permission_ids) VALUES (2,'访客','访客','12,13,22,26,29,32,44,45,50,62,63,81,83,85,141,146,149,150,161,163');
|
||||
-- t_sys_role end--
|
||||
|
||||
insert into t_sys_role(id, role_name, description, permission_ids) VALUES ( 1,'超级管理员','超级管理员','12,13,22,23,24,25,26,27,28,29,30,31,32,33,42,43,44,45,46,47,48,49,50,62,63,64,65,81,82,83,84,85,86,101,102,141,142,143,144,145,146,147,148,149,150,161,162,163,164,165,166,167,168,169,170' );
|
||||
|
||||
insert into t_sys_user(id, username, password, salt, role_ids) VALUES ( 1,'admin','3a3e4d32-5247-321b-9efb-9cbf60b2bf6c','e6973cfc-7583-4baa-8802-65ded1268ab6','1' );
|
||||
-- t_sys_user start--
|
||||
insert into t_sys_user(id, username, password, salt, role_ids) VALUES (1,'admin','3a3e4d32-5247-321b-9efb-9cbf60b2bf6c','e6973cfc-7583-4baa-8802-65ded1268ab6','1' );
|
||||
-- t_sys_user end--
|
||||
@@ -15,8 +15,10 @@
|
||||
><router-link to="/client-quota-page" class="pad-l-r">限流</router-link>
|
||||
<span>|</span
|
||||
><router-link to="/acl-page" class="pad-l-r">Acl</router-link>
|
||||
<span>|</span
|
||||
><router-link to="/user-page" class="pad-l-r">用户</router-link>
|
||||
<span v-show="showUserMenu">|</span
|
||||
><router-link to="/user-page" class="pad-l-r" v-show="showUserMenu"
|
||||
>用户</router-link
|
||||
>
|
||||
<span>|</span
|
||||
><router-link to="/op-page" class="pad-l-r">运维</router-link>
|
||||
<div class="right">
|
||||
@@ -44,7 +46,13 @@
|
||||
import { KafkaClusterApi, AuthApi } from "@/utils/api";
|
||||
import request from "@/utils/request";
|
||||
import { mapMutations, mapState } from "vuex";
|
||||
import {deleteToken, deleteUsername, getClusterInfo, getPermissions, getUsername} from "@/utils/local-cache";
|
||||
import {
|
||||
deleteToken,
|
||||
deleteUsername,
|
||||
getClusterInfo,
|
||||
getPermissions,
|
||||
getUsername,
|
||||
} from "@/utils/local-cache";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import { AUTH, CLUSTER } from "@/store/mutation-types";
|
||||
|
||||
@@ -64,6 +72,7 @@ export default {
|
||||
enableSasl: (state) => state.clusterInfo.enableSasl,
|
||||
showUsername: (state) => state.auth.enable && state.auth.username,
|
||||
username: (state) => state.auth.username,
|
||||
showUserMenu: (state) => state.auth.enable,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -357,4 +357,4 @@ export const AuthApi = {
|
||||
url: "/auth/login",
|
||||
method: "post",
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
16
ui/src/utils/auth.js
Normal file
16
ui/src/utils/auth.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import Store from "@/store";
|
||||
|
||||
export function isUnauthorized(permission) {
|
||||
const enableAuth = Store.state.auth.enable;
|
||||
const permissions = Store.state.auth.permissions;
|
||||
return enableAuth && (!permissions || permissions.indexOf(permission) < 0);
|
||||
}
|
||||
|
||||
export function isAuthorized(permission) {
|
||||
const enableAuth = Store.state.auth.enable;
|
||||
if (!enableAuth) {
|
||||
return true;
|
||||
}
|
||||
const permissions = Store.state.auth.permissions;
|
||||
return permissions && permissions.indexOf(permission) >= 0;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ request.interceptors.request.use((config) => {
|
||||
config.headers["X-Cluster-Info-Id"] = clusterInfo.id;
|
||||
// config.headers["X-Cluster-Info-Name"] = encodeURIComponent(clusterInfo.clusterName);
|
||||
}
|
||||
const token = localStorage.getItem('access_token')
|
||||
const token = localStorage.getItem("access_token");
|
||||
if (token) {
|
||||
config.headers["X-Auth-Token"] = token;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<a-tabs default-active-key="1" size="large" tabPosition="top">
|
||||
<a-tab-pane key="1" tab="资源授权">
|
||||
<a-tab-pane key="1" tab="资源授权" v-if="isAuthorized('acl:authority')">
|
||||
<acl-list></acl-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="SaslScram用户管理">
|
||||
<a-tab-pane
|
||||
key="2"
|
||||
tab="SaslScram用户管理"
|
||||
v-if="isAuthorized('acl:sasl-scram')"
|
||||
>
|
||||
<sasl-scram></sasl-scram>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
@@ -14,9 +18,11 @@
|
||||
<script>
|
||||
import AclList from "@/views/acl/AclList";
|
||||
import SaslScram from "@/views/acl/SaslScram";
|
||||
import { isAuthorized } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
name: "Acl",
|
||||
methods: { isAuthorized },
|
||||
components: {
|
||||
AclList,
|
||||
SaslScram,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
@confirm="onDelete(record)"
|
||||
v-action:acl:authority:clean
|
||||
>
|
||||
<a-button>删除</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
@@ -47,7 +47,10 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="onAddPrincipalAuth"
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="onAddPrincipalAuth"
|
||||
v-action:acl:authority:add-principal
|
||||
>新增主体权限</a-button
|
||||
>
|
||||
<span v-show="hint != ''" class="hint"
|
||||
|
||||
@@ -27,7 +27,12 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="updateUser">新增/更新用户</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="updateUser"
|
||||
v-action:acl:sasl-scram:add-update
|
||||
>新增/更新用户</a-button
|
||||
>
|
||||
<span class="hint" v-show="!enableSasl"
|
||||
>未启用SASL SCRAM认证,不支持相关操作</span
|
||||
>
|
||||
@@ -45,6 +50,7 @@
|
||||
type="dashed"
|
||||
style="float: right"
|
||||
@click="onUserDetail(username)"
|
||||
v-action:acl:sasl-scram:detail
|
||||
>详情</a-button
|
||||
>
|
||||
</div>
|
||||
@@ -58,6 +64,7 @@
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
@confirm="onDeleteUser(record)"
|
||||
v-action:acl:sasl-scram:del
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
>删除</a-button
|
||||
@@ -68,6 +75,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="onManageProducerAuth(record)"
|
||||
v-action:acl:sasl-scram:producer
|
||||
>管理生产权限
|
||||
</a-button>
|
||||
|
||||
@@ -76,6 +84,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="onManageConsumerAuth(record)"
|
||||
v-action:acl:sasl-scram:consumer
|
||||
>管理消费权限
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -83,6 +92,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="onAddAuth(record)"
|
||||
v-action:acl:sasl-scram:add-auth
|
||||
>增加权限
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
@@ -91,7 +101,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="onDeleteUserAndAuth(record)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
v-action:acl:sasl-scram:pure
|
||||
>彻底删除</a-button
|
||||
>
|
||||
</a-popconfirm>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
class="operation-btn"
|
||||
v-show="!record.readOnly"
|
||||
@click="openEditConfigDialog(record)"
|
||||
v-action:cluster:edit
|
||||
>编辑
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
@@ -44,7 +45,11 @@
|
||||
v-show="isDynamic(record.source)"
|
||||
@confirm="deleteBrokerConfig(record)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
v-action:cluster:edit
|
||||
>删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openBrokerConfigDialog(record, true)"
|
||||
v-action:cluster:log-config
|
||||
>日志配置
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="resetTopicOffsetToEndpoint(group, k, 1)"
|
||||
>
|
||||
<a-button size="small" type="danger" style="margin-right: 1%"
|
||||
<a-button
|
||||
size="small"
|
||||
type="danger"
|
||||
style="margin-right: 1%"
|
||||
v-action:group:consumer-detail:min
|
||||
>最小位点
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
@@ -35,7 +39,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="resetTopicOffsetToEndpoint(group, k, 2)"
|
||||
>
|
||||
<a-button size="small" type="danger" style="margin-right: 1%"
|
||||
<a-button
|
||||
size="small"
|
||||
type="danger"
|
||||
style="margin-right: 1%"
|
||||
v-action:group:consumer-detail:last
|
||||
>最新位点
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
@@ -45,6 +53,7 @@
|
||||
type="danger"
|
||||
style="margin-right: 1%"
|
||||
@click="openResetOffsetByTimeDialog(k)"
|
||||
v-action:group:consumer-detail:timestamp
|
||||
>时间戳
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -75,6 +84,7 @@
|
||||
@click="
|
||||
openResetPartitionOffsetDialog(record.topic, record.partition)
|
||||
"
|
||||
v-action:group:consumer-detail:any
|
||||
>重置位点
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
@@ -61,7 +61,10 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="openAddSubscriptionDialog"
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="openAddSubscriptionDialog"
|
||||
v-action:group:add
|
||||
>新增订阅</a-button
|
||||
>
|
||||
</div>
|
||||
@@ -89,7 +92,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="deleteGroup(record.groupId)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
v-action:group:del
|
||||
>删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
@@ -98,6 +105,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openConsumerMemberDialog(record.groupId)"
|
||||
v-action:group:client
|
||||
>消费端
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -105,6 +113,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openConsumerDetailDialog(record.groupId)"
|
||||
v-action:group:consumer-detail
|
||||
>消费详情
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -112,6 +121,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openOffsetPartitionDialog(record.groupId)"
|
||||
v-action:group:offset-partition
|
||||
>位移分区
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
@@ -37,10 +37,10 @@
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {AuthApi} from "@/utils/api";
|
||||
import { AuthApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import {mapMutations} from "vuex";
|
||||
import {AUTH} from "@/store/mutation-types";
|
||||
import { mapMutations } from "vuex";
|
||||
import { AUTH } from "@/store/mutation-types";
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
|
||||
@@ -2,16 +2,25 @@
|
||||
<div class="content">
|
||||
<a-spin :spinning="loading">
|
||||
<a-tabs default-active-key="1" size="large" tabPosition="top">
|
||||
<a-tab-pane key="1" tab="根据时间查询消息">
|
||||
<a-tab-pane
|
||||
v-if="isAuthorized('message:search-time')"
|
||||
key="1"
|
||||
tab="根据时间查询消息"
|
||||
>
|
||||
<SearchByTime :topic-list="topicList"></SearchByTime>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="根据偏移查询消息">
|
||||
<a-tab-pane
|
||||
key="2"
|
||||
v-if="isAuthorized('message:search-offset')"
|
||||
tab="根据偏移查询消息"
|
||||
>
|
||||
<SearchByOffset :topic-list="topicList"></SearchByOffset>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="在线发送">
|
||||
<a-tab-pane key="3" tab="在线发送" v-if="isAuthorized('message:send')">
|
||||
<SendMessage :topic-list="topicList"></SendMessage>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="4" tab="在线删除">
|
||||
|
||||
<a-tab-pane key="4" tab="在线删除" v-if="isAuthorized('message:del')">
|
||||
<DeleteMessage :topic-list="topicList"></DeleteMessage>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
@@ -27,6 +36,7 @@ import { KafkaTopicApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import SendMessage from "@/views/message/SendMessage";
|
||||
import DeleteMessage from "./DeleteMessage";
|
||||
import { isAuthorized, isUnauthorized } from "@/utils/auth";
|
||||
export default {
|
||||
name: "Message",
|
||||
components: { DeleteMessage, SearchByTime, SearchByOffset, SendMessage },
|
||||
@@ -37,6 +47,8 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
isAuthorized,
|
||||
isUnauthorized,
|
||||
getTopicNameList() {
|
||||
request({
|
||||
url: KafkaTopicApi.getTopicNameList.url,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openAddClusterInfoDialog"
|
||||
v-action:op:cluster-switch:add
|
||||
>新增集群
|
||||
</a-button>
|
||||
<br /><br />
|
||||
@@ -38,6 +39,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="switchCluster(record)"
|
||||
v-action:op:cluster-switch:switch
|
||||
>切换
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -45,6 +47,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openUpdateClusterInfoDialog(record)"
|
||||
v-action:op:cluster-switch:edit
|
||||
>编辑
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
@@ -58,6 +61,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
type="danger"
|
||||
v-action:op:cluster-switch:del
|
||||
>删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="content">
|
||||
<div class="content-module">
|
||||
<a-card title="集群管理" style="width: 100%; text-align: left">
|
||||
<p>
|
||||
<p v-action:op:cluster-switch>
|
||||
<a-button type="primary" @click="openClusterInfoDialog">
|
||||
集群切换
|
||||
</a-button>
|
||||
@@ -15,7 +15,7 @@
|
||||
</div>
|
||||
<div class="content-module">
|
||||
<a-card title="Broker管理" style="width: 100%; text-align: left">
|
||||
<p>
|
||||
<p v-action:op:config-throttle>
|
||||
<a-button type="primary" @click="openConfigThrottleDialog">
|
||||
配置限流
|
||||
</a-button>
|
||||
@@ -24,7 +24,7 @@
|
||||
>设置指定broker上的topic的副本之间数据同步占用的带宽,这个设置是broker级别的,但是设置后还要去对应的topic上进行限流配置,指定对这个topic的相关副本进行限制</span
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<p v-action:op:remove-throttle>
|
||||
<a-button type="primary" @click="openRemoveThrottleDialog">
|
||||
解除限流
|
||||
</a-button>
|
||||
@@ -35,21 +35,21 @@
|
||||
</div>
|
||||
<div class="content-module">
|
||||
<a-card title="副本管理" style="width: 100%; text-align: left">
|
||||
<p>
|
||||
<p v-action:op:replication-preferred>
|
||||
<a-button type="primary" @click="openElectPreferredLeaderDialog">
|
||||
首选副本作为leader
|
||||
</a-button>
|
||||
<label>说明:</label>
|
||||
<span>将集群中所有分区leader副本设置为首选副本</span>
|
||||
</p>
|
||||
<p>
|
||||
<p v-action:op:replication-update-detail>
|
||||
<a-button type="primary" @click="openCurrentReassignmentsDialog">
|
||||
副本变更详情
|
||||
</a-button>
|
||||
<label>说明:</label>
|
||||
<span>查看正在进行副本变更/重分配的任务,或者将其取消</span>
|
||||
</p>
|
||||
<p>
|
||||
<p v-action:op:replication-reassign>
|
||||
<a-button type="primary" @click="openReplicaReassignDialog">
|
||||
副本重分配
|
||||
</a-button>
|
||||
|
||||
@@ -1,56 +1,49 @@
|
||||
<script src="../../store/index.js"></script>
|
||||
<template>
|
||||
<a-modal
|
||||
title="新增配置"
|
||||
:visible="show"
|
||||
:width="800"
|
||||
:mask="false"
|
||||
:destroyOnClose="true"
|
||||
:footer="null"
|
||||
:maskClosable="false"
|
||||
@cancel="handleCancel"
|
||||
title="新增配置"
|
||||
:visible="show"
|
||||
:width="800"
|
||||
:mask="false"
|
||||
:destroyOnClose="true"
|
||||
:footer="null"
|
||||
:maskClosable="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<a-form
|
||||
:form="form"
|
||||
:label-col="{ span: 5 }"
|
||||
:wrapper-col="{ span: 12 }"
|
||||
@submit="handleSubmit"
|
||||
:form="form"
|
||||
:label-col="{ span: 5 }"
|
||||
:wrapper-col="{ span: 12 }"
|
||||
@submit="handleSubmit"
|
||||
>
|
||||
<a-form-item label="用户" v-show="showUser">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'user',
|
||||
]"
|
||||
placeholder="输入用户主体标识,比如:用户名,未指定表示用户默认设置"
|
||||
v-decorator="['user']"
|
||||
placeholder="输入用户主体标识,比如:用户名,未指定表示用户默认设置"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="客户端ID" v-show="showClientId">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'client',
|
||||
]"
|
||||
placeholder="输入用户客户端ID,未指定表示默认客户端设置"
|
||||
v-decorator="['client']"
|
||||
placeholder="输入用户客户端ID,未指定表示默认客户端设置"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="IP" v-show="showIP">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'ip',
|
||||
]"
|
||||
placeholder="输入客户端IP"
|
||||
/>
|
||||
<a-input v-decorator="['ip']" placeholder="输入客户端IP" />
|
||||
</a-form-item>
|
||||
<a-form-item label="生产速率">
|
||||
<a-input-number
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'producerRate',
|
||||
]"
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="['producerRate']"
|
||||
/>
|
||||
<a-select default-value="MB" v-model="producerRateUnit" style="width: 100px">
|
||||
<a-select
|
||||
default-value="MB"
|
||||
v-model="producerRateUnit"
|
||||
style="width: 100px"
|
||||
>
|
||||
<a-select-option value="MB"> MB/s</a-select-option>
|
||||
<a-select-option value="KB"> KB/s</a-select-option>
|
||||
<a-select-option value="Byte"> Byte/s</a-select-option>
|
||||
@@ -58,13 +51,15 @@
|
||||
</a-form-item>
|
||||
<a-form-item label="消费速率">
|
||||
<a-input-number
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'consumerRate',
|
||||
]"
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="['consumerRate']"
|
||||
/>
|
||||
<a-select default-value="MB" v-model="consumerRateUnit" style="width: 100px">
|
||||
<a-select
|
||||
default-value="MB"
|
||||
v-model="consumerRateUnit"
|
||||
style="width: 100px"
|
||||
>
|
||||
<a-select-option value="MB"> MB/s</a-select-option>
|
||||
<a-select-option value="KB"> KB/s</a-select-option>
|
||||
<a-select-option value="Byte"> Byte/s</a-select-option>
|
||||
@@ -72,11 +67,9 @@
|
||||
</a-form-item>
|
||||
<a-form-item label="吞吐量">
|
||||
<a-input-number
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'requestPercentage',
|
||||
]"
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="['requestPercentage']"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="{ span: 12, offset: 5 }">
|
||||
@@ -90,7 +83,7 @@
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {KafkaClientQuotaApi} from "@/utils/api";
|
||||
import { KafkaClientQuotaApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/es/notification";
|
||||
|
||||
export default {
|
||||
@@ -122,7 +115,7 @@ export default {
|
||||
show: this.visible,
|
||||
data: [],
|
||||
loading: false,
|
||||
form: this.$form.createForm(this, {name: "coordinated"}),
|
||||
form: this.$form.createForm(this, { name: "coordinated" }),
|
||||
producerRateUnit: "MB",
|
||||
consumerRateUnit: "MB",
|
||||
};
|
||||
@@ -136,13 +129,15 @@ export default {
|
||||
handleSubmit() {
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
const params = Object.assign({type: this.type}, values);
|
||||
const unitMap = {MB: 1024 * 1024, KB: 1024, Byte: 1};
|
||||
const params = Object.assign({ type: this.type }, values);
|
||||
const unitMap = { MB: 1024 * 1024, KB: 1024, Byte: 1 };
|
||||
if (values.consumerRate) {
|
||||
params.consumerRate = params.consumerRate * unitMap[this.consumerRateUnit];
|
||||
params.consumerRate =
|
||||
params.consumerRate * unitMap[this.consumerRateUnit];
|
||||
}
|
||||
if (values.producerRate) {
|
||||
params.producerRate = params.producerRate * unitMap[this.producerRateUnit];
|
||||
params.producerRate =
|
||||
params.producerRate * unitMap[this.producerRateUnit];
|
||||
}
|
||||
params.types = [];
|
||||
params.names = [];
|
||||
@@ -179,7 +174,7 @@ export default {
|
||||
this.loading = false;
|
||||
if (res.code == 0) {
|
||||
this.$message.success(res.msg);
|
||||
this.$emit("closeAddQuotaDialog", {refresh: true});
|
||||
this.$emit("closeAddQuotaDialog", { refresh: true });
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
@@ -192,7 +187,7 @@ export default {
|
||||
},
|
||||
handleCancel() {
|
||||
this.data = [];
|
||||
this.$emit("closeAddQuotaDialog", {refresh: false});
|
||||
this.$emit("closeAddQuotaDialog", { refresh: false });
|
||||
this.producerRateUnit = "MB";
|
||||
this.consumerRateUnit = "MB";
|
||||
},
|
||||
|
||||
@@ -3,18 +3,16 @@
|
||||
<a-spin :spinning="loading">
|
||||
<div id="search-offset-form-advanced-search">
|
||||
<a-form
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="16">
|
||||
<a-form-item label="客户端ID">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'id',
|
||||
]"
|
||||
placeholder="请输入生产者/消费者客户端ID!"
|
||||
v-decorator="['id']"
|
||||
placeholder="请输入生产者/消费者客户端ID!"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -27,26 +25,39 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="openAddQuotaDialog"
|
||||
>新增配置
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="openAddQuotaDialog"
|
||||
v-action:quota:client:add
|
||||
>新增配置
|
||||
</a-button>
|
||||
</div>
|
||||
<QuotaList type="client-id" :columns="columns" :data="data" @refreshQuotaList="refresh"></QuotaList>
|
||||
<AddQuotaConfig type="client-id" :visible="showAddQuotaDialog" :showClientId="true" @closeAddQuotaDialog="closeAddQuotaDialog"></AddQuotaConfig>
|
||||
<QuotaList
|
||||
type="client-id"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
@refreshQuotaList="refresh"
|
||||
></QuotaList>
|
||||
<AddQuotaConfig
|
||||
type="client-id"
|
||||
:visible="showAddQuotaDialog"
|
||||
:showClientId="true"
|
||||
@closeAddQuotaDialog="closeAddQuotaDialog"
|
||||
></AddQuotaConfig>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {KafkaClientQuotaApi} from "@/utils/api";
|
||||
import { KafkaClientQuotaApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import QuotaList from "@/views/quota/QuotaList.vue";
|
||||
import AddQuotaConfig from "@/views/quota/AddQuotaConfig.vue";
|
||||
|
||||
export default {
|
||||
name: "ClientIDQuota",
|
||||
components: {QuotaList, AddQuotaConfig},
|
||||
components: { QuotaList, AddQuotaConfig },
|
||||
props: {
|
||||
topicList: {
|
||||
type: Array,
|
||||
@@ -55,7 +66,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
form: this.$form.createForm(this, {name: "client_id_quota"}),
|
||||
form: this.$form.createForm(this, { name: "client_id_quota" }),
|
||||
data: [],
|
||||
showAlterQuotaDialog: false,
|
||||
showAddQuotaDialog: false,
|
||||
@@ -64,8 +75,8 @@ export default {
|
||||
title: "客户端ID",
|
||||
dataIndex: "client",
|
||||
key: "client",
|
||||
slots: {title: "client"},
|
||||
scopedSlots: {customRender: "client"},
|
||||
slots: { title: "client" },
|
||||
scopedSlots: { customRender: "client" },
|
||||
},
|
||||
{
|
||||
title: "生产速率(带宽/秒)",
|
||||
@@ -90,7 +101,7 @@ export default {
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.loading = true;
|
||||
const params = {types: ["client-id"]};
|
||||
const params = { types: ["client-id"] };
|
||||
if (values.id) {
|
||||
params.names = [values.id.trim()];
|
||||
}
|
||||
|
||||
@@ -5,13 +5,17 @@
|
||||
<a-tab-pane key="1" tab="使用说明">
|
||||
<ClientQuotaIntroduce></ClientQuotaIntroduce>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="用户">
|
||||
<a-tab-pane v-if="isAuthorized('quota:user')" key="2" tab="用户">
|
||||
<UserQuota></UserQuota>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="客户端ID">
|
||||
<a-tab-pane key="3" tab="客户端ID" v-if="isAuthorized('quota:client')">
|
||||
<ClientIDQuota></ClientIDQuota>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="4" tab="用户_客户端ID">
|
||||
<a-tab-pane
|
||||
key="4"
|
||||
tab="用户_客户端ID"
|
||||
v-if="isAuthorized('quota:user-client')"
|
||||
>
|
||||
<UserAndClientIDQuota></UserAndClientIDQuota>
|
||||
</a-tab-pane>
|
||||
<!-- <a-tab-pane key="5" tab="IP">-->
|
||||
@@ -27,10 +31,17 @@ import ClientIDQuota from "@/views/quota/ClientIDQuota.vue";
|
||||
import UserQuota from "@/views/quota/UserQuota.vue";
|
||||
import UserAndClientIDQuota from "@/views/quota/UserAndClientIDQuota.vue";
|
||||
import ClientQuotaIntroduce from "@/views/quota/ClientQuotaIntroduce.vue";
|
||||
import { isAuthorized } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
name: "ClientQuota",
|
||||
components: {ClientIDQuota, UserQuota, UserAndClientIDQuota, ClientQuotaIntroduce},
|
||||
methods: { isAuthorized },
|
||||
components: {
|
||||
ClientIDQuota,
|
||||
UserQuota,
|
||||
UserAndClientIDQuota,
|
||||
ClientQuotaIntroduce,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<h1>客户端限流说明(资源限额)</h1>
|
||||
<hr/>
|
||||
<hr/>
|
||||
<hr />
|
||||
<hr />
|
||||
<h2>支持类型</h2>
|
||||
<ul>
|
||||
<li>基于用户主体标识的配置</li>
|
||||
<li>基于客户端ID的配置</li>
|
||||
<li>基于用户主体+客户端ID的配置</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<hr />
|
||||
<h2>默认配置</h2>
|
||||
<p>比如,基于用户的配置,在新增配置的时候未设置用户名称,则默认应用于所有用户</p>
|
||||
<p>
|
||||
比如,基于用户的配置,在新增配置的时候未设置用户名称,则默认应用于所有用户
|
||||
</p>
|
||||
<p>基于客户端ID的配置,新增的时候,未指定客户端ID,则应用于所有客户端</p>
|
||||
<hr/>
|
||||
<hr />
|
||||
<h2>配置优先级</h2>
|
||||
下面的展示中,数字越小,即越靠上的优先级越高,相同的用户名称或者客户端ID,优先级最高的配置生效,下面的未指定表示 默认配置
|
||||
下面的展示中,数字越小,即越靠上的优先级越高,相同的用户名称或者客户端ID,优先级最高的配置生效,下面的未指定表示
|
||||
默认配置
|
||||
<ol>
|
||||
<li>[用户+客户端ID] 指定用户名称并且指定客户端ID(优先级最高)</li>
|
||||
<li>[用户+客户端ID] 指定用户名称,未指定客户端ID</li>
|
||||
@@ -26,18 +29,17 @@
|
||||
<li>[客户端ID] 指定客户端ID</li>
|
||||
<li>[客户端ID] 未指定客户端ID(优先级最低)</li>
|
||||
</ol>
|
||||
<hr/>
|
||||
<hr />
|
||||
<h2>使用注意</h2>
|
||||
大多数集群一般没有开启认证,所以用户配置可能不支持,限流可以使用基于客户端ID的配置。但是对于优先级最低的:"[客户端ID]
|
||||
未指定客户端ID",默认对于所有客户端生效,万一速率配置过小,可能无意间影响生产业务,所以尽量避免默认配置。
|
||||
<hr/>
|
||||
<hr />
|
||||
<h2>查询</h2>
|
||||
查询默认配置,在查询项的输入框内,输入一个空格即可。
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "ClientQuotaIntroduce",
|
||||
};
|
||||
|
||||
@@ -3,19 +3,14 @@
|
||||
<a-spin :spinning="loading">
|
||||
<div id="search-offset-form-advanced-search">
|
||||
<a-form
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="16">
|
||||
<a-form-item label="IP">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'ip',
|
||||
]"
|
||||
placeholder="请输入ip!"
|
||||
/>
|
||||
<a-input v-decorator="['ip']" placeholder="请输入ip!" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="2" :style="{ textAlign: 'right' }">
|
||||
@@ -28,25 +23,35 @@
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="openAddQuotaDialog"
|
||||
>新增配置
|
||||
>新增配置
|
||||
</a-button>
|
||||
</div>
|
||||
<QuotaList type="ip" :columns="columns" :data="data" @refreshQuotaList="refresh"></QuotaList>
|
||||
<AddQuotaConfig type="ip" :visible="showAddQuotaDialog" :showIP="true" @closeAddQuotaDialog="closeAddQuotaDialog"></AddQuotaConfig>
|
||||
<QuotaList
|
||||
type="ip"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
@refreshQuotaList="refresh"
|
||||
></QuotaList>
|
||||
<AddQuotaConfig
|
||||
type="ip"
|
||||
:visible="showAddQuotaDialog"
|
||||
:showIP="true"
|
||||
@closeAddQuotaDialog="closeAddQuotaDialog"
|
||||
></AddQuotaConfig>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {KafkaClientQuotaApi} from "@/utils/api";
|
||||
import { KafkaClientQuotaApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import QuotaList from "@/views/quota/QuotaList.vue";
|
||||
import AddQuotaConfig from "@/views/quota/AddQuotaConfig.vue";
|
||||
|
||||
export default {
|
||||
name: "IpQuota",
|
||||
components: {QuotaList, AddQuotaConfig},
|
||||
components: { QuotaList, AddQuotaConfig },
|
||||
props: {
|
||||
topicList: {
|
||||
type: Array,
|
||||
@@ -55,7 +60,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
form: this.$form.createForm(this, {name: "ip_quota"}),
|
||||
form: this.$form.createForm(this, { name: "ip_quota" }),
|
||||
data: [],
|
||||
showAlterQuotaDialog: false,
|
||||
showAddQuotaDialog: false,
|
||||
@@ -64,8 +69,8 @@ export default {
|
||||
title: "IP",
|
||||
dataIndex: "ip",
|
||||
key: "ip",
|
||||
slots: {title: "ip"},
|
||||
scopedSlots: {customRender: "ip"},
|
||||
slots: { title: "ip" },
|
||||
scopedSlots: { customRender: "ip" },
|
||||
},
|
||||
{
|
||||
title: "生产速率(带宽/秒)",
|
||||
@@ -90,7 +95,7 @@ export default {
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.loading = true;
|
||||
const params = {types: ["ip"]};
|
||||
const params = { types: ["ip"] };
|
||||
if (values.ip) {
|
||||
params.names = [values.ip.trim()];
|
||||
}
|
||||
|
||||
@@ -2,58 +2,69 @@
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="data"
|
||||
bordered
|
||||
:row-key="
|
||||
(record, index) => {
|
||||
return index;
|
||||
}
|
||||
"
|
||||
@change="handleChange"
|
||||
:columns="columns"
|
||||
:data-source="data"
|
||||
bordered
|
||||
:row-key="
|
||||
(record, index) => {
|
||||
return index;
|
||||
}
|
||||
"
|
||||
@change="handleChange"
|
||||
>
|
||||
<div slot="client" slot-scope="text">
|
||||
<span v-if="text">{{ text }}</span><span v-else style="color: red">默认配置</span>
|
||||
<span v-if="text">{{ text }}</span
|
||||
><span v-else style="color: red">默认配置</span>
|
||||
</div>
|
||||
<div slot="user" slot-scope="text">
|
||||
<span v-if="text">{{ text }}</span><span v-else style="color: red">默认配置</span>
|
||||
<span v-if="text">{{ text }}</span
|
||||
><span v-else style="color: red">默认配置</span>
|
||||
</div>
|
||||
|
||||
<div slot="operation" slot-scope="record">
|
||||
<a-popconfirm
|
||||
:title="'删除当前配置?'"
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
@confirm="deleteConfig(record)"
|
||||
:title="'删除当前配置?'"
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
@confirm="deleteConfig(record)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
>删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openUpdateDialog(record)"
|
||||
>修改
|
||||
v-action:quota:del
|
||||
>删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openUpdateDialog(record)"
|
||||
v-action:quota:edit
|
||||
>修改
|
||||
</a-button>
|
||||
</div>
|
||||
</a-table>
|
||||
<UpdateQuotaConfig :type="type" :record="selectRow" :visible="showUpdateDialog"
|
||||
@closeUpdateQuotaDialog="closeUpdateQuotaDialog"></UpdateQuotaConfig>
|
||||
<UpdateQuotaConfig
|
||||
:type="type"
|
||||
:record="selectRow"
|
||||
:visible="showUpdateDialog"
|
||||
@closeUpdateQuotaDialog="closeUpdateQuotaDialog"
|
||||
></UpdateQuotaConfig>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {KafkaClientQuotaApi} from "@/utils/api";
|
||||
import { KafkaClientQuotaApi } from "@/utils/api";
|
||||
import request from "@/utils/request";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import UpdateQuotaConfig from "@/views/quota/UpdateQuotaConfig.vue";
|
||||
|
||||
export default {
|
||||
name: "QuotaList",
|
||||
components: {UpdateQuotaConfig},
|
||||
components: { UpdateQuotaConfig },
|
||||
props: {
|
||||
columns: {
|
||||
type: Array,
|
||||
@@ -88,7 +99,7 @@ export default {
|
||||
},
|
||||
deleteConfig(record) {
|
||||
this.loading = true;
|
||||
const params = {type: this.type};
|
||||
const params = { type: this.type };
|
||||
params.types = [];
|
||||
params.names = [];
|
||||
if (this.type == "user") {
|
||||
@@ -161,7 +172,7 @@ export default {
|
||||
this.columns.push({
|
||||
title: "操作",
|
||||
key: "operation",
|
||||
scopedSlots: {customRender: "operation"},
|
||||
scopedSlots: { customRender: "operation" },
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,59 +1,58 @@
|
||||
<script src="../../store/index.js"></script>
|
||||
<template>
|
||||
<a-modal
|
||||
title="修改配置"
|
||||
:visible="show"
|
||||
:width="800"
|
||||
:mask="false"
|
||||
:destroyOnClose="true"
|
||||
:footer="null"
|
||||
:maskClosable="false"
|
||||
@cancel="handleCancel"
|
||||
title="修改配置"
|
||||
:visible="show"
|
||||
:width="800"
|
||||
:mask="false"
|
||||
:destroyOnClose="true"
|
||||
:footer="null"
|
||||
:maskClosable="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<a-form
|
||||
:form="form"
|
||||
:label-col="{ span: 5 }"
|
||||
:wrapper-col="{ span: 12 }"
|
||||
@submit="handleSubmit"
|
||||
:form="form"
|
||||
:label-col="{ span: 5 }"
|
||||
:wrapper-col="{ span: 12 }"
|
||||
@submit="handleSubmit"
|
||||
>
|
||||
<a-form-item label="用户" v-show="showUser">
|
||||
<a-input
|
||||
:disabled="true"
|
||||
v-decorator="[
|
||||
'user', { initialValue: record.user }
|
||||
]"
|
||||
placeholder="输入用户主体标识,比如:用户名,未指定表示用户默认设置"
|
||||
:disabled="true"
|
||||
v-decorator="['user', { initialValue: record.user }]"
|
||||
placeholder="输入用户主体标识,比如:用户名,未指定表示用户默认设置"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="客户端ID" v-show="showClientId">
|
||||
<a-input
|
||||
:disabled="true"
|
||||
v-decorator="[
|
||||
'client', { initialValue: record.client }
|
||||
]"
|
||||
placeholder="输入用户客户端ID,未指定表示默认客户端设置"
|
||||
:disabled="true"
|
||||
v-decorator="['client', { initialValue: record.client }]"
|
||||
placeholder="输入用户客户端ID,未指定表示默认客户端设置"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="IP" v-show="showIP">
|
||||
<a-input
|
||||
:disabled="true"
|
||||
v-decorator="[
|
||||
'ip', { initialValue: record.ip }
|
||||
]"
|
||||
placeholder="输入客户端IP"
|
||||
:disabled="true"
|
||||
v-decorator="['ip', { initialValue: record.ip }]"
|
||||
placeholder="输入客户端IP"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="生产速率">
|
||||
<a-input-number
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'producerRate', { initialValue: record.producerRate }
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'producerRate',
|
||||
{ initialValue: record.producerRate },
|
||||
]"
|
||||
/>
|
||||
<a-select default-value="MB" v-model="producerRateUnit" style="width: 100px">
|
||||
<a-select
|
||||
default-value="MB"
|
||||
v-model="producerRateUnit"
|
||||
style="width: 100px"
|
||||
>
|
||||
<a-select-option value="MB"> MB/s</a-select-option>
|
||||
<a-select-option value="KB"> KB/s</a-select-option>
|
||||
<a-select-option value="Byte"> Byte/s</a-select-option>
|
||||
@@ -61,13 +60,18 @@
|
||||
</a-form-item>
|
||||
<a-form-item label="消费速率">
|
||||
<a-input-number
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'consumerRate', { initialValue: record.consumerRate }
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'consumerRate',
|
||||
{ initialValue: record.consumerRate },
|
||||
]"
|
||||
/>
|
||||
<a-select default-value="MB" v-model="consumerRateUnit" style="width: 100px">
|
||||
<a-select
|
||||
default-value="MB"
|
||||
v-model="consumerRateUnit"
|
||||
style="width: 100px"
|
||||
>
|
||||
<a-select-option value="MB"> MB/s</a-select-option>
|
||||
<a-select-option value="KB"> KB/s</a-select-option>
|
||||
<a-select-option value="Byte"> Byte/s</a-select-option>
|
||||
@@ -75,10 +79,11 @@
|
||||
</a-form-item>
|
||||
<a-form-item label="吞吐量">
|
||||
<a-input-number
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'requestPercentage', { initialValue: record.requestPercentage }
|
||||
:min="1"
|
||||
:max="102400000"
|
||||
v-decorator="[
|
||||
'requestPercentage',
|
||||
{ initialValue: record.requestPercentage },
|
||||
]"
|
||||
/>
|
||||
</a-form-item>
|
||||
@@ -93,7 +98,7 @@
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {KafkaClientQuotaApi} from "@/utils/api";
|
||||
import { KafkaClientQuotaApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/es/notification";
|
||||
|
||||
export default {
|
||||
@@ -110,7 +115,7 @@ export default {
|
||||
record: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {}
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -119,7 +124,7 @@ export default {
|
||||
show: this.visible,
|
||||
data: [],
|
||||
loading: false,
|
||||
form: this.$form.createForm(this, {name: "coordinated"}),
|
||||
form: this.$form.createForm(this, { name: "coordinated" }),
|
||||
producerRateUnit: "MB",
|
||||
consumerRateUnit: "MB",
|
||||
showUser: false,
|
||||
@@ -139,16 +144,24 @@ export default {
|
||||
handleSubmit() {
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
const params = {type: this.type, deleteConfigs: []};
|
||||
const unitMap = {MB: 1024 * 1024, KB: 1024, Byte: 1};
|
||||
const params = { type: this.type, deleteConfigs: [] };
|
||||
const unitMap = { MB: 1024 * 1024, KB: 1024, Byte: 1 };
|
||||
if (values.consumerRate) {
|
||||
const num = typeof (values.consumerRate) == "string" && values.consumerRate.indexOf(" ") > 0 ? values.consumerRate.split(" ")[0] : values.consumerRate;
|
||||
const num =
|
||||
typeof values.consumerRate == "string" &&
|
||||
values.consumerRate.indexOf(" ") > 0
|
||||
? values.consumerRate.split(" ")[0]
|
||||
: values.consumerRate;
|
||||
params.consumerRate = num * unitMap[this.consumerRateUnit];
|
||||
} else {
|
||||
params.deleteConfigs.push("consumerRate");
|
||||
}
|
||||
if (values.producerRate) {
|
||||
const num = typeof (values.producerRate) == "string" && values.producerRate.indexOf(" ") > 0 ? values.producerRate.split(" ")[0] : values.producerRate;
|
||||
const num =
|
||||
typeof values.producerRate == "string" &&
|
||||
values.producerRate.indexOf(" ") > 0
|
||||
? values.producerRate.split(" ")[0]
|
||||
: values.producerRate;
|
||||
params.producerRate = num * unitMap[this.producerRateUnit];
|
||||
} else {
|
||||
params.deleteConfigs.push("producerRate");
|
||||
@@ -207,7 +220,7 @@ export default {
|
||||
this.loading = false;
|
||||
if (res.code == 0) {
|
||||
this.$message.success(res.msg);
|
||||
this.$emit("closeUpdateQuotaDialog", {refresh: true});
|
||||
this.$emit("closeUpdateQuotaDialog", { refresh: true });
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
@@ -220,7 +233,7 @@ export default {
|
||||
},
|
||||
handleCancel() {
|
||||
this.data = [];
|
||||
this.$emit("closeUpdateQuotaDialog", {refresh: false});
|
||||
this.$emit("closeUpdateQuotaDialog", { refresh: false });
|
||||
},
|
||||
init() {
|
||||
this.producerRateUnit = "MB";
|
||||
@@ -243,9 +256,7 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
created() {},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,28 +3,24 @@
|
||||
<a-spin :spinning="loading">
|
||||
<div id="search-offset-form-advanced-search">
|
||||
<a-form
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="10">
|
||||
<a-form-item label="用户标识">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'user',
|
||||
]"
|
||||
placeholder="请输入用户标识,如:用户名!"
|
||||
v-decorator="['user']"
|
||||
placeholder="请输入用户标识,如:用户名!"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-form-item label="客户端ID">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'client',
|
||||
]"
|
||||
placeholder="请输入客户端ID!"
|
||||
v-decorator="['client']"
|
||||
placeholder="请输入客户端ID!"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -37,27 +33,40 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="openAddQuotaDialog"
|
||||
>新增配置
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="openAddQuotaDialog"
|
||||
v-action:quota:user-client:add
|
||||
>新增配置
|
||||
</a-button>
|
||||
</div>
|
||||
<QuotaList type="user&client-id" :columns="columns" :data="data" @refreshQuotaList="refresh"></QuotaList>
|
||||
<AddQuotaConfig type="user&client-id" :visible="showAddQuotaDialog" :showUser="true" :showClientId="true"
|
||||
@closeAddQuotaDialog="closeAddQuotaDialog"></AddQuotaConfig>
|
||||
<QuotaList
|
||||
type="user&client-id"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
@refreshQuotaList="refresh"
|
||||
></QuotaList>
|
||||
<AddQuotaConfig
|
||||
type="user&client-id"
|
||||
:visible="showAddQuotaDialog"
|
||||
:showUser="true"
|
||||
:showClientId="true"
|
||||
@closeAddQuotaDialog="closeAddQuotaDialog"
|
||||
></AddQuotaConfig>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {KafkaClientQuotaApi} from "@/utils/api";
|
||||
import { KafkaClientQuotaApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import QuotaList from "@/views/quota/QuotaList.vue";
|
||||
import AddQuotaConfig from "@/views/quota/AddQuotaConfig.vue";
|
||||
|
||||
export default {
|
||||
name: "UserAndClientIDQuota",
|
||||
components: {QuotaList, AddQuotaConfig},
|
||||
components: { QuotaList, AddQuotaConfig },
|
||||
props: {
|
||||
topicList: {
|
||||
type: Array,
|
||||
@@ -66,7 +75,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
form: this.$form.createForm(this, {name: "user_client_id_quota"}),
|
||||
form: this.$form.createForm(this, { name: "user_client_id_quota" }),
|
||||
data: [],
|
||||
showAlterQuotaDialog: false,
|
||||
showAddQuotaDialog: false,
|
||||
@@ -75,15 +84,15 @@ export default {
|
||||
title: "用户标识",
|
||||
dataIndex: "user",
|
||||
key: "user",
|
||||
slots: {title: "user"},
|
||||
scopedSlots: {customRender: "user"},
|
||||
slots: { title: "user" },
|
||||
scopedSlots: { customRender: "user" },
|
||||
},
|
||||
{
|
||||
title: "客户端ID",
|
||||
dataIndex: "client",
|
||||
key: "client",
|
||||
slots: {title: "client"},
|
||||
scopedSlots: {customRender: "client"},
|
||||
slots: { title: "client" },
|
||||
scopedSlots: { customRender: "client" },
|
||||
},
|
||||
{
|
||||
title: "生产速率(带宽/秒)",
|
||||
@@ -108,7 +117,7 @@ export default {
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.loading = true;
|
||||
const params = {types: ["user", "client-id"], names: []};
|
||||
const params = { types: ["user", "client-id"], names: [] };
|
||||
if (values.user) {
|
||||
params.names.push(values.user.trim());
|
||||
}
|
||||
|
||||
@@ -3,18 +3,16 @@
|
||||
<a-spin :spinning="loading">
|
||||
<div id="search-offset-form-advanced-search">
|
||||
<a-form
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
class="ant-advanced-search-form"
|
||||
:form="form"
|
||||
@submit="handleSearch"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="16">
|
||||
<a-form-item label="用户标识">
|
||||
<a-input
|
||||
v-decorator="[
|
||||
'user',
|
||||
]"
|
||||
placeholder="请输入用户标识,如:用户名!"
|
||||
v-decorator="['user']"
|
||||
placeholder="请输入用户标识,如:用户名!"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -27,26 +25,39 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="openAddQuotaDialog"
|
||||
>新增配置
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="openAddQuotaDialog"
|
||||
v-action:quota:user:add
|
||||
>新增配置
|
||||
</a-button>
|
||||
</div>
|
||||
<QuotaList type="user" :columns="columns" :data="data" @refreshQuotaList="refresh"></QuotaList>
|
||||
<AddQuotaConfig type="user" :visible="showAddQuotaDialog" :showUser="true" @closeAddQuotaDialog="closeAddQuotaDialog"></AddQuotaConfig>
|
||||
<QuotaList
|
||||
type="user"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
@refreshQuotaList="refresh"
|
||||
></QuotaList>
|
||||
<AddQuotaConfig
|
||||
type="user"
|
||||
:visible="showAddQuotaDialog"
|
||||
:showUser="true"
|
||||
@closeAddQuotaDialog="closeAddQuotaDialog"
|
||||
></AddQuotaConfig>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {KafkaClientQuotaApi} from "@/utils/api";
|
||||
import { KafkaClientQuotaApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import QuotaList from "@/views/quota/QuotaList.vue";
|
||||
import AddQuotaConfig from "@/views/quota/AddQuotaConfig.vue";
|
||||
|
||||
export default {
|
||||
name: "UserQuota",
|
||||
components: {QuotaList, AddQuotaConfig},
|
||||
components: { QuotaList, AddQuotaConfig },
|
||||
props: {
|
||||
topicList: {
|
||||
type: Array,
|
||||
@@ -55,7 +66,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
form: this.$form.createForm(this, {name: "user_quota"}),
|
||||
form: this.$form.createForm(this, { name: "user_quota" }),
|
||||
data: [],
|
||||
showAlterQuotaDialog: false,
|
||||
showAddQuotaDialog: false,
|
||||
@@ -65,8 +76,8 @@ export default {
|
||||
dataIndex: "user",
|
||||
key: "user",
|
||||
width: 300,
|
||||
slots: {title: "user"},
|
||||
scopedSlots: {customRender: "user"},
|
||||
slots: { title: "user" },
|
||||
scopedSlots: { customRender: "user" },
|
||||
},
|
||||
{
|
||||
title: "生产速率(带宽/秒)",
|
||||
@@ -91,7 +102,7 @@ export default {
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.loading = true;
|
||||
const params = {types: ["user"]};
|
||||
const params = { types: ["user"] };
|
||||
if (values.user) {
|
||||
params.names = [values.user.trim()];
|
||||
}
|
||||
|
||||
@@ -44,7 +44,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="electPreferredLeader(record)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
v-action:topic:partition-detail:preferred
|
||||
>首选副本作为leader
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
@@ -36,7 +36,13 @@
|
||||
|
||||
<a-col :span="8" :style="{ textAlign: 'right' }">
|
||||
<a-form-item>
|
||||
<a-button type="primary" html-type="submit"> 刷新</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
html-type="submit"
|
||||
v-action:topic:load
|
||||
>
|
||||
刷新</a-button
|
||||
>
|
||||
<!-- <a-button :style="{ marginLeft: '8px' }" @click="handleReset">-->
|
||||
<!-- 重置-->
|
||||
<!-- </a-button>-->
|
||||
@@ -46,7 +52,10 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="openCreateTopicDialog" v-action:action
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="openCreateTopicDialog"
|
||||
v-action:topic:add
|
||||
>新增</a-button
|
||||
>
|
||||
<a-popconfirm
|
||||
@@ -60,7 +69,7 @@
|
||||
class="btn-left"
|
||||
:disabled="!hasSelected"
|
||||
:loading="loading"
|
||||
v-action:action
|
||||
v-action:topic:batch-del
|
||||
>
|
||||
批量删除
|
||||
</a-button>
|
||||
@@ -98,7 +107,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="deleteTopic(record.name)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
v-action:topic:del
|
||||
>删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
@@ -107,6 +120,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openPartitionInfoDialog(record.name)"
|
||||
v-action:topic:partition-detail
|
||||
>分区详情
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -114,6 +128,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openAddPartitionDialog(record.name)"
|
||||
v-action:topic:partition-add
|
||||
>增加分区
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -121,6 +136,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openConsumedDetailDialog(record.name)"
|
||||
v-action:topic:consumer-detail
|
||||
>消费详情
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -128,6 +144,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openTopicConfigDialog(record.name)"
|
||||
v-action:topic:property-config
|
||||
>属性配置
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -135,6 +152,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openUpdateReplicaDialog(record.name)"
|
||||
v-action:topic:replication-modify
|
||||
>变更副本
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -142,6 +160,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openMessageStatsDialog(record.name)"
|
||||
v-action:topic:send-count
|
||||
>发送统计
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -149,6 +168,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openThrottleDialog(record.name)"
|
||||
v-action:topic:replication-sync-throttle
|
||||
>限流
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
@@ -98,7 +98,10 @@ export default {
|
||||
this.loading = false;
|
||||
if (res.code == 0) {
|
||||
this.$message.success(res.msg);
|
||||
this.$emit("closeCreateUserDialog", { refresh: true, data: res.data });
|
||||
this.$emit("closeCreateUserDialog", {
|
||||
refresh: true,
|
||||
data: res.data,
|
||||
});
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
|
||||
@@ -31,24 +31,9 @@ const columns = [
|
||||
width: "12%",
|
||||
slots: { title: "type" },
|
||||
scopedSlots: { customRender: "type" },
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
console.log(
|
||||
`selectedRowKeys: ${selectedRowKeys}`,
|
||||
"selectedRows: ",
|
||||
selectedRows
|
||||
);
|
||||
},
|
||||
onSelect: (record, selected, selectedRows) => {
|
||||
console.log(record, selected, selectedRows);
|
||||
},
|
||||
onSelectAll: (selected, selectedRows, changeRows) => {
|
||||
console.log(selected, selectedRows, changeRows);
|
||||
},
|
||||
};
|
||||
import { UserManageApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
|
||||
@@ -60,7 +45,6 @@ export default {
|
||||
loading: false,
|
||||
data: [],
|
||||
columns,
|
||||
rowSelection,
|
||||
expandedRowKeys: [],
|
||||
};
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
cancel-text="取消"
|
||||
@confirm="deleteRole(item)"
|
||||
>
|
||||
<a :style="{ display: 'flex' }">
|
||||
<a :style="{ display: 'flex' }" v-action:user-manage:role:del>
|
||||
<a-icon type="delete" />
|
||||
</a>
|
||||
</a-popconfirm>
|
||||
@@ -35,7 +35,9 @@
|
||||
<span
|
||||
:style="{ margin: '25px', fontSize: '15px', display: 'block' }"
|
||||
>
|
||||
<a @click="addRole()"><a-icon type="plus" /> 新增角色</a>
|
||||
<a @click="addRole()" v-action:user-manage:role:save
|
||||
><a-icon type="plus" /> 新增角色</a
|
||||
>
|
||||
</span>
|
||||
</a-col>
|
||||
<a-col :md="20">
|
||||
@@ -116,7 +118,11 @@
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button type="primary" :loading="loading" @click="onSave()"
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="onSave()"
|
||||
v-action:user-manage:role:save
|
||||
>保存</a-button
|
||||
>
|
||||
</a-form-item>
|
||||
@@ -212,8 +218,8 @@ export default {
|
||||
const btnArr = [self];
|
||||
btn.children = btnArr;
|
||||
const selected = btn.children
|
||||
.map((bc) => bc.id)
|
||||
.filter((id) => idSet.has(id));
|
||||
.map((bc) => bc.id)
|
||||
.filter((id) => idSet.has(id));
|
||||
btn.selected = selected || [];
|
||||
btn.selectAll = btn.selected.length == btn.children.length;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,10 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="operation-row-button">
|
||||
<a-button type="primary" @click="openCreateUserDialog()"
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="openCreateUserDialog()"
|
||||
v-action:user-manage:user:add
|
||||
>新增用户</a-button
|
||||
>
|
||||
</div>
|
||||
@@ -49,7 +52,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="deleteUser(record)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
v-action:user-manage:user:del
|
||||
>删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
@@ -59,7 +66,11 @@
|
||||
cancel-text="取消"
|
||||
@confirm="resetPassword(record)"
|
||||
>
|
||||
<a-button size="small" href="javascript:;" class="operation-btn"
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
v-action:user-manage:user:reset-pass
|
||||
>重置密码
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
@@ -68,6 +79,7 @@
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openUpdateUserRoleDialog(record)"
|
||||
v-action:user-manage:user:change-role
|
||||
>分配角色
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
@@ -2,16 +2,32 @@
|
||||
<div class="content">
|
||||
<a-spin :spinning="loading">
|
||||
<a-tabs default-active-key="1" size="large" tabPosition="top">
|
||||
<a-tab-pane key="1" tab="用户列表">
|
||||
<a-tab-pane
|
||||
key="1"
|
||||
tab="用户列表"
|
||||
v-if="isAuthorized('user-manage:user')"
|
||||
>
|
||||
<User></User>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="角色列表">
|
||||
<a-tab-pane
|
||||
key="2"
|
||||
tab="角色列表"
|
||||
v-if="isAuthorized('user-manage:role')"
|
||||
>
|
||||
<Role></Role>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="权限列表">
|
||||
<a-tab-pane
|
||||
key="3"
|
||||
tab="权限列表"
|
||||
v-if="isAuthorized('user-manage:permission')"
|
||||
>
|
||||
<Permission></Permission>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="4" tab="个人设置">
|
||||
<a-tab-pane
|
||||
key="4"
|
||||
tab="个人设置"
|
||||
v-if="isAuthorized('user-manage:setting')"
|
||||
>
|
||||
<UserSetting></UserSetting>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
@@ -24,6 +40,7 @@ import Permission from "@/views/user/Permission.vue";
|
||||
import Role from "@/views/user/Role.vue";
|
||||
import User from "@/views/user/User.vue";
|
||||
import UserSetting from "@/views/user/UserSetting.vue";
|
||||
import { isAuthorized } from "@/utils/auth";
|
||||
export default {
|
||||
name: "UserManage",
|
||||
components: { Permission, Role, User, UserSetting },
|
||||
@@ -33,7 +50,7 @@ export default {
|
||||
topicList: [],
|
||||
};
|
||||
},
|
||||
methods: {},
|
||||
methods: { isAuthorized },
|
||||
created() {},
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user