mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
Merge branch 'master' into registry-nacos
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-registry-api</artifactId>
|
||||
<version>1.12.4-SNAPSHOT</version>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easyopen starter -->
|
||||
|
@@ -0,0 +1,98 @@
|
||||
package com.gitee.sop.adminserver.api.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.easyopen.annotation.Api;
|
||||
import com.gitee.easyopen.annotation.ApiService;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDoc;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
|
||||
import com.gitee.easyopen.util.CopyUtil;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.fastmybatis.core.query.Sort;
|
||||
import com.gitee.fastmybatis.core.support.PageEasyui;
|
||||
import com.gitee.fastmybatis.core.util.MapperUtil;
|
||||
import com.gitee.sop.adminserver.api.service.param.ConfigIpBlackForm;
|
||||
import com.gitee.sop.adminserver.api.service.param.ConfigIpBlacklistPageParam;
|
||||
import com.gitee.sop.adminserver.api.service.result.ConfigIpBlacklistVO;
|
||||
import com.gitee.sop.adminserver.bean.ChannelMsg;
|
||||
import com.gitee.sop.adminserver.bean.ConfigLimitDto;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import com.gitee.sop.adminserver.common.BizException;
|
||||
import com.gitee.sop.adminserver.entity.ConfigIpBlacklist;
|
||||
import com.gitee.sop.adminserver.mapper.ConfigIpBlacklistMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@ApiService
|
||||
@ApiDoc("IP黑名单管理")
|
||||
@Slf4j
|
||||
public class IPBlacklistApi {
|
||||
|
||||
@Autowired
|
||||
ConfigIpBlacklistMapper configIpBlacklistMapper;
|
||||
|
||||
@ApiDocMethod(description = "获取IP黑名单,分页")
|
||||
@Api(name = "ip.blacklist.page")
|
||||
PageEasyui<ConfigIpBlacklistVO> page(ConfigIpBlacklistPageParam form) {
|
||||
Query query = Query.build(form);
|
||||
query.orderby("id", Sort.DESC);
|
||||
return MapperUtil.queryForEasyuiDatagrid(configIpBlacklistMapper, query, ConfigIpBlacklistVO.class);
|
||||
}
|
||||
|
||||
@ApiDocMethod(description = "IP黑名单--新增")
|
||||
@Api(name = "ip.blacklist.add")
|
||||
void add(ConfigIpBlackForm form) {
|
||||
ConfigIpBlacklist rec = configIpBlacklistMapper.getByColumn("ip", form.getIp());
|
||||
if (rec != null) {
|
||||
throw new BizException("IP已添加");
|
||||
}
|
||||
rec = new ConfigIpBlacklist();
|
||||
CopyUtil.copyPropertiesIgnoreNull(form, rec);
|
||||
configIpBlacklistMapper.saveIgnoreNull(rec);
|
||||
try {
|
||||
this.sendIpBlacklistMsg(rec, BlacklistMsgType.ADD);
|
||||
} catch (Exception e) {
|
||||
log.error("推送IP黑名单失败, rec:{}",rec, e);
|
||||
throw new BizException("推送IP黑名单失败");
|
||||
}
|
||||
}
|
||||
|
||||
@ApiDocMethod(description = "IP黑名单--修改")
|
||||
@Api(name = "ip.blacklist.update")
|
||||
void update(ConfigIpBlackForm form) {
|
||||
ConfigIpBlacklist rec = configIpBlacklistMapper.getById(form.getId());
|
||||
CopyUtil.copyPropertiesIgnoreNull(form, rec);
|
||||
configIpBlacklistMapper.updateIgnoreNull(rec);
|
||||
}
|
||||
|
||||
@ApiDocMethod(description = "IP黑名单--删除")
|
||||
@Api(name = "ip.blacklist.del")
|
||||
void del(long id) {
|
||||
ConfigIpBlacklist rec = configIpBlacklistMapper.getById(id);
|
||||
if (rec == null) {
|
||||
return;
|
||||
}
|
||||
configIpBlacklistMapper.deleteById(id);
|
||||
try {
|
||||
this.sendIpBlacklistMsg(rec, BlacklistMsgType.DELETE);
|
||||
} catch (Exception e) {
|
||||
log.error("推送IP黑名单失败, rec:{}",rec, e);
|
||||
throw new BizException("推送IP黑名单失败");
|
||||
}
|
||||
}
|
||||
|
||||
public void sendIpBlacklistMsg(ConfigIpBlacklist configIpBlacklist, BlacklistMsgType blacklistMsgType) throws Exception {
|
||||
String configData = JSON.toJSONString(configIpBlacklist);
|
||||
ChannelMsg channelMsg = new ChannelMsg(blacklistMsgType.name().toLowerCase(), configData);
|
||||
String jsonData = JSON.toJSONString(channelMsg);
|
||||
String path = ZookeeperContext.getIpBlacklistChannelPath();
|
||||
log.info("消息推送--IP黑名单设置({}), path:{}, data:{}",blacklistMsgType.name(), path, jsonData);
|
||||
ZookeeperContext.createOrUpdateData(path, jsonData);
|
||||
}
|
||||
|
||||
enum BlacklistMsgType {
|
||||
ADD, DELETE
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package com.gitee.sop.adminserver.api.service.param;
|
||||
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:config_ip_black
|
||||
* 备注:IP黑名单
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class ConfigIpBlackForm {
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** ip, 数据库字段:ip */
|
||||
@NotBlank(message = "不能为空")
|
||||
@Length(max = 30, message = "ip长度太长")
|
||||
private String ip;
|
||||
|
||||
/** 备注, 数据库字段:remark */
|
||||
@Length(max = 100, message = "备注长度太长")
|
||||
private String remark;
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.gitee.sop.adminserver.api.service.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import com.gitee.fastmybatis.core.query.Operator;
|
||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||
import com.gitee.fastmybatis.core.query.param.PageParam;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ConfigIpBlacklistPageParam extends PageParam {
|
||||
@ApiDocField(description = "IP")
|
||||
@Condition(operator = Operator.like)
|
||||
private String ip;
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package com.gitee.sop.adminserver.api.service.result;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:config_ip_black
|
||||
* 备注:IP黑名单
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class ConfigIpBlacklistVO {
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** ip, 数据库字段:ip */
|
||||
private String ip;
|
||||
|
||||
/** 备注, 数据库字段:remark */
|
||||
private String remark;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -104,6 +104,10 @@ public class ZookeeperContext {
|
||||
return SOP_MSG_CHANNEL_PATH + "/limit-conf";
|
||||
}
|
||||
|
||||
public static String getIpBlacklistChannelPath() {
|
||||
return SOP_MSG_CHANNEL_PATH + "/ipblacklist-conf";
|
||||
}
|
||||
|
||||
public static CuratorFramework getClient() {
|
||||
return client;
|
||||
}
|
||||
|
@@ -0,0 +1,39 @@
|
||||
package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:config_ip_blacklist
|
||||
* 备注:IP黑名单
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "config_ip_blacklist")
|
||||
@Data
|
||||
public class ConfigIpBlacklist {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** ip, 数据库字段:ip */
|
||||
private String ip;
|
||||
|
||||
/** 备注, 数据库字段:remark */
|
||||
private String remark;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.gitee.sop.adminserver.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
|
||||
import com.gitee.sop.adminserver.entity.ConfigIpBlacklist;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface ConfigIpBlacklistMapper extends CrudMapper<ConfigIpBlacklist, Long> {
|
||||
}
|
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,o=t[0],i=t[1],f=t[2],l=0,d=[];l<o.length;l++)c=o[l],u[c]&&d.push(u[c][0]),u[c]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);h&&h(t);while(d.length)d.shift()();return a.push.apply(a,f||[]),n()}function n(){for(var e,t=0;t<a.length;t++){for(var n=a[t],r=!0,c=1;c<n.length;c++){var o=n[c];0!==u[o]&&(r=!1)}r&&(a.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},c={runtime:0},u={runtime:0},a=[];function o(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-009073d4":"28312808","chunk-238a81e9":"5955f13d","chunk-25908fca":"ca176fa6","chunk-29e7142c":"994a3ac0","chunk-2d2085ef":"a63a74dc","chunk-2d22c2e3":"4a098244","chunk-37401378":"4e39ec9b","chunk-4a59cbe4":"a6360c68","chunk-6a68a33e":"b6685cb9","chunk-73b2dcec":"14f248eb"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-009073d4":1,"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-29e7142c":1,"chunk-37401378":1,"chunk-6a68a33e":1,"chunk-73b2dcec":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise(function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-009073d4":"0af16c7e","chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-29e7142c":"d10599db","chunk-2d2085ef":"31d6cfe0","chunk-2d22c2e3":"31d6cfe0","chunk-37401378":"a43114f3","chunk-4a59cbe4":"31d6cfe0","chunk-6a68a33e":"3b12267b","chunk-73b2dcec":"99cf6327"}[e]+".css",u=i.p+r,a=document.getElementsByTagName("link"),o=0;o<a.length;o++){var f=a[o],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===u))return t()}var d=document.getElementsByTagName("style");for(o=0;o<d.length;o++){f=d[o],l=f.getAttribute("data-href");if(l===r||l===u)return t()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=t,h.onerror=function(t){var r=t&&t.target&&t.target.src||u,a=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");a.code="CSS_CHUNK_LOAD_FAILED",a.request=r,delete c[e],h.parentNode.removeChild(h),n(a)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var a=new Promise(function(t,n){r=u[e]=[t,n]});t.push(r[2]=a);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=o(e),f=function(t){l.onerror=l.onload=null,clearTimeout(d);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src,a=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");a.type=r,a.request=c,n[1](a)}u[e]=void 0}};var d=setTimeout(function(){f({type:"timeout",target:l})},12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var d=0;d<f.length;d++)t(f[d]);var h=l;n()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.095e8b9c.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function n(n){for(var r,c,a=n[0],f=n[1],i=n[2],l=0,d=[];l<a.length;l++)c=a[l],u[c]&&d.push(u[c][0]),u[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);h&&h(n);while(d.length)d.shift()();return o.push.apply(o,i||[]),t()}function t(){for(var e,n=0;n<o.length;n++){for(var t=o[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(o.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-238a81e9":"5955f13d","chunk-25908fca":"ca176fa6","chunk-29e7142c":"994a3ac0","chunk-2d2085ef":"7c741493","chunk-2d208c3a":"93f165b2","chunk-2d221c34":"8f017357","chunk-34c76be7":"98e1e7e5","chunk-37401378":"4e39ec9b","chunk-6f78c9fe":"f1ed64fa","chunk-73b2dcec":"14f248eb","chunk-9b31c83a":"2758df30"}[e]+".js"}function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[],t={"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-29e7142c":1,"chunk-34c76be7":1,"chunk-37401378":1,"chunk-73b2dcec":1,"chunk-9b31c83a":1};c[e]?n.push(c[e]):0!==c[e]&&t[e]&&n.push(c[e]=new Promise(function(n,t){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-29e7142c":"d10599db","chunk-2d2085ef":"31d6cfe0","chunk-2d208c3a":"31d6cfe0","chunk-2d221c34":"31d6cfe0","chunk-34c76be7":"f531fb07","chunk-37401378":"a43114f3","chunk-6f78c9fe":"31d6cfe0","chunk-73b2dcec":"99cf6327","chunk-9b31c83a":"3b12267b"}[e]+".css",u=f.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var i=o[a],l=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(l===r||l===u))return n()}var d=document.getElementsByTagName("style");for(a=0;a<d.length;a++){i=d[a],l=i.getAttribute("data-href");if(l===r||l===u)return n()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=n,h.onerror=function(n){var r=n&&n.target&&n.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],h.parentNode.removeChild(h),t(o)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(function(n,t){r=u[e]=[n,t]});n.push(r[2]=o);var i,l=document.createElement("script");l.charset="utf-8",l.timeout=120,f.nc&&l.setAttribute("nonce",f.nc),l.src=a(e),i=function(n){l.onerror=l.onload=null,clearTimeout(d);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,t[1](o)}u[e]=void 0}};var d=setTimeout(function(){i({type:"timeout",target:l})},12e4);l.onerror=l.onload=i,document.head.appendChild(l)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],l=i.push.bind(i);i.push=n,i=i.slice();for(var d=0;d<i.length;d++)n(i[d]);var h=l;t()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.4a507d5e.js></script></body></html>
|
@@ -1 +1 @@
|
||||
.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-b81bfbde]{cursor:pointer;margin-left:10px}
|
||||
.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-51d6f4a2]{cursor:pointer;margin-left:10px}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22c2e3"],{f1ac:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"app-container"},[n("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[n("el-form-item",{attrs:{label:"serviceId"}},[n("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"serviceId"},model:{value:t.searchFormData.serviceId,callback:function(e){t.$set(t.searchFormData,"serviceId",e)},expression:"searchFormData.serviceId"}})],1),t._v(" "),n("el-form-item",[n("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:t.onSearchTable}},[t._v("查询")])],1)],1),t._v(" "),n("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","row-key":"id"}},[n("el-table-column",{attrs:{prop:"serviceId",label:"服务名称",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",{domProps:{innerHTML:t._s(t.renderServiceName(e.row))}})]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"ipPort",label:"IP端口",width:"250"}}),t._v(" "),n("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-tag",{attrs:{type:"success"}},[t._v("已上线")]):t._e(),t._v(" "),e.row.parentId>0&&"STARTING"===e.row.status?n("el-tag",{attrs:{type:"info"}},[t._v("正在启动")]):t._e(),t._v(" "),e.row.parentId>0&&"UNKNOWN"===e.row.status?n("el-tag",[t._v("未知")]):t._e(),t._v(" "),e.row.parentId>0&&("OUT_OF_SERVICE"===e.row.status||"DOWN"===e.row.status)?n("el-tag",{attrs:{type:"danger"}},[t._v("已下线")]):t._e()]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),t._v(" "),n("el-table-column",{attrs:{label:"操作",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOffline(e.row)}}},[t._v("下线")]):t._e(),t._v(" "),e.row.parentId>0&&"OUT_OF_SERVICE"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOnline(e.row)}}},[t._v("上线")]):t._e()]}}])})],1)],1)},r=[],i=(n("ac6a"),{data:function(){return{searchFormData:{serviceId:""},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(t){this.tableData=this.buildTreeData(t.data)})},buildTreeData:function(t){return t.forEach(function(e){var n=e.parentId;0===n||t.forEach(function(t){if(t.id===n){var a=t.children;a||(a=[]),a.push(e),t.children=a}})}),t=t.filter(function(t){return 0===t.parentId}),t},onSearchTable:function(){this.loadTable()},onOffline:function(t){this.confirm("确定要下线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.offline",t,function(){this.tip("下线成功"),e()})})},onOnline:function(t){this.confirm("确定要上线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.online",t,function(){this.tip("上线成功"),e()})})},renderServiceName:function(t){var e="";if(t.children&&t.children.length>0){var n=t.children.filter(function(t){return"UP"===t.status}).length;e=" (".concat(n,"/").concat(t.children.length,")")}return t.serviceId+e}}}),o=i,s=n("2877"),l=Object(s["a"])(o,a,r,!1,null,null,null);e["default"]=l.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d208c3a"],{a5d4:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"app-container"},[n("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[n("el-form-item",{attrs:{label:"serviceId"}},[n("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"serviceId"},model:{value:t.searchFormData.serviceId,callback:function(e){t.$set(t.searchFormData,"serviceId",e)},expression:"searchFormData.serviceId"}})],1),t._v(" "),n("el-form-item",[n("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:t.onSearchTable}},[t._v("查询")])],1)],1),t._v(" "),n("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","row-key":"id"}},[n("el-table-column",{attrs:{prop:"serviceId",label:"服务名称",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",{domProps:{innerHTML:t._s(t.renderServiceName(e.row))}})]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"ipPort",label:"IP端口",width:"250"}}),t._v(" "),n("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-tag",{attrs:{type:"success"}},[t._v("已上线")]):t._e(),t._v(" "),e.row.parentId>0&&"STARTING"===e.row.status?n("el-tag",{attrs:{type:"info"}},[t._v("正在启动")]):t._e(),t._v(" "),e.row.parentId>0&&"UNKNOWN"===e.row.status?n("el-tag",[t._v("未知")]):t._e(),t._v(" "),e.row.parentId>0&&("OUT_OF_SERVICE"===e.row.status||"DOWN"===e.row.status)?n("el-tag",{attrs:{type:"danger"}},[t._v("已下线")]):t._e()]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),t._v(" "),n("el-table-column",{attrs:{label:"操作",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOffline(e.row)}}},[t._v("下线")]):t._e(),t._v(" "),e.row.parentId>0&&"OUT_OF_SERVICE"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOnline(e.row)}}},[t._v("上线")]):t._e()]}}])})],1)],1)},r=[],i=(n("ac6a"),{data:function(){return{searchFormData:{serviceId:""},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(t){this.tableData=this.buildTreeData(t.data)})},buildTreeData:function(t){return t.forEach(function(e){var n=e.parentId;0===n||t.forEach(function(t){if(t.id===n){var a=t.children;a||(a=[]),a.push(e),t.children=a}})}),t=t.filter(function(t){return 0===t.parentId}),t},onSearchTable:function(){this.loadTable()},onOffline:function(t){this.confirm("确定要下线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.offline",t,function(){this.tip("下线成功"),e()})})},onOnline:function(t){this.confirm("确定要上线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.online",t,function(){this.tip("上线成功"),e()})})},renderServiceName:function(t){var e="";if(t.children&&t.children.length>0){var n=t.children.filter(function(t){return"UP"===t.status}).length;e=" (".concat(n,"/").concat(t.children.length,")")}return t.serviceId+e}}}),o=i,s=n("2877"),l=Object(s["a"])(o,a,r,!1,null,null,null);e["default"]=l.exports}}]);
|
@@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d221c34"],{cc75:function(a,t,e){"use strict";e.r(t);var i=function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("div",{staticClass:"app-container"},[e("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:a.searchFormData,size:"mini"}},[e("el-form-item",{attrs:{label:"IP"}},[e("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"输入IP"},model:{value:a.searchFormData.ip,callback:function(t){a.$set(a.searchFormData,"ip",t)},expression:"searchFormData.ip"}})],1),a._v(" "),e("el-form-item",[e("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:a.loadTable}},[a._v("查询")])],1)],1),a._v(" "),e("el-button",{staticStyle:{"margin-bottom":"10px"},attrs:{type:"primary",size:"mini",icon:"el-icon-plus"},on:{click:a.onAdd}},[a._v("新增IP")]),a._v(" "),e("el-table",{attrs:{data:a.pageInfo.rows,border:"","highlight-current-row":""}},[e("el-table-column",{attrs:{prop:"ip",label:"IP",width:"200"}}),a._v(" "),e("el-table-column",{attrs:{prop:"remark",label:"备注",width:"300"}}),a._v(" "),e("el-table-column",{attrs:{prop:"gmtCreate",label:"添加时间",width:"160"}}),a._v(" "),e("el-table-column",{attrs:{prop:"gmtModified",label:"修改时间",width:"160"}}),a._v(" "),e("el-table-column",{attrs:{label:"操作",width:"150"},scopedSlots:a._u([{key:"default",fn:function(t){return[e("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(e){return a.onTableUpdate(t.row)}}},[a._v("修改")]),a._v(" "),e("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(e){return a.onTableDelete(t.row)}}},[a._v("删除")])]}}])})],1),a._v(" "),e("el-pagination",{staticStyle:{"margin-top":"5px"},attrs:{background:"","current-page":a.searchFormData.pageIndex,"page-size":a.searchFormData.pageSize,"page-sizes":[5,10,20,40],total:a.pageInfo.total,layout:"total, sizes, prev, pager, next"},on:{"size-change":a.onSizeChange,"current-change":a.onPageIndexChange}}),a._v(" "),e("el-dialog",{attrs:{title:a.dialogTitle,visible:a.dialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(t){a.dialogVisible=t},close:function(t){return a.resetForm("dialogForm")}}},[e("el-form",{ref:"dialogForm",attrs:{rules:a.dialogFormRules,model:a.dialogFormData,"label-width":"120px",size:"mini"}},[e("el-form-item",{attrs:{prop:"ip",label:"IP"}},[e("el-input",{directives:[{name:"show",rawName:"v-show",value:0===a.dialogFormData.id,expression:"dialogFormData.id === 0"}],model:{value:a.dialogFormData.ip,callback:function(t){a.$set(a.dialogFormData,"ip",t)},expression:"dialogFormData.ip"}}),a._v(" "),e("span",{directives:[{name:"show",rawName:"v-show",value:a.dialogFormData.id>0,expression:"dialogFormData.id > 0"}]},[a._v(a._s(a.dialogFormData.ip))])],1),a._v(" "),e("el-form-item",{attrs:{prop:"remark",label:"备注"}},[e("el-input",{model:{value:a.dialogFormData.remark,callback:function(t){a.$set(a.dialogFormData,"remark",t)},expression:"dialogFormData.remark"}})],1)],1),a._v(" "),e("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[e("el-button",{on:{click:function(t){a.dialogVisible=!1}}},[a._v("取 消")]),a._v(" "),e("el-button",{attrs:{type:"primary"},on:{click:a.onDialogSave}},[a._v("保 存")])],1)],1)],1)},o=[],l={data:function(){var a=function(a,t,e){if(""===t)e(new Error("请输入IP"));else{var i=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;i.test(t)||e(new Error("IP格式不正确")),e()}};return{searchFormData:{ip:"",pageIndex:1,pageSize:10},pageInfo:{rows:[],total:0},dialogVisible:!1,dialogTitle:"",dialogFormData:{id:0,ip:"",remark:""},dialogFormRules:{ip:[{validator:a,trigger:"blur"},{min:1,max:64,message:"长度在 1 到 64 个字符",trigger:"blur"}],remark:[{max:100,message:"不能超过 100 个字符",trigger:"blur"}]}}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("ip.blacklist.page",this.searchFormData,function(a){this.pageInfo=a.data})},onTableUpdate:function(a){var t=this;this.dialogTitle="修改IP",this.dialogVisible=!0,this.$nextTick(function(){Object.assign(t.dialogFormData,a)})},onTableDelete:function(a){this.confirm("确认要移除IP【".concat(a.ip,"】吗?"),function(t){var e={id:a.id};this.post("ip.blacklist.del",e,function(){t(),this.tip("删除成功"),this.loadTable()})})},onDialogSave:function(){var a=this;this.$refs.dialogForm.validate(function(t){if(t){var e=a.dialogFormData.id?"ip.blacklist.update":"ip.blacklist.add";a.post(e,a.dialogFormData,function(){this.dialogVisible=!1,this.loadTable()})}})},onSizeChange:function(a){this.searchFormData.pageSize=a,this.loadTable()},onAdd:function(){this.dialogTitle="新增IP",this.dialogVisible=!0,this.dialogFormData.id=0},onPageIndexChange:function(a){this.searchFormData.pageIndex=a,this.loadTable()}}},r=l,n=e("2877"),s=Object(n["a"])(r,i,o,!1,null,null,null);t["default"]=s.exports}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -64,26 +64,32 @@ export const constantRoutes = [
|
||||
{
|
||||
path: 'list',
|
||||
name: 'ServiceList',
|
||||
component: () => import('@/views/service/list/index'),
|
||||
component: () => import('@/views/service/serviceList'),
|
||||
meta: { title: '服务列表' }
|
||||
},
|
||||
{
|
||||
path: 'route',
|
||||
name: 'Route',
|
||||
component: () => import('@/views/service/route/index'),
|
||||
component: () => import('@/views/service/route'),
|
||||
meta: { title: '路由管理' }
|
||||
},
|
||||
{
|
||||
path: 'limit',
|
||||
name: 'Limit',
|
||||
component: () => import('@/views/service/limit/index2'),
|
||||
component: () => import('@/views/service/limit'),
|
||||
meta: { title: '限流管理' }
|
||||
},
|
||||
{
|
||||
path: 'log',
|
||||
name: 'Log',
|
||||
component: () => import('@/views/service/log/index'),
|
||||
component: () => import('@/views/service/log'),
|
||||
meta: { title: '监控日志' }
|
||||
},
|
||||
{
|
||||
path: 'blacklist',
|
||||
name: 'Blacklist',
|
||||
component: () => import('@/views/service/ipBlacklist'),
|
||||
meta: { title: 'IP黑名单' }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -108,17 +108,11 @@ export default {
|
||||
roleDialogFormRules: {
|
||||
roleCode: [
|
||||
{ required: true, message: '不能为空', trigger: 'blur' },
|
||||
{ min: 1, max: 64, message: '长度在 1 到 100 个字符', trigger: 'blur' }
|
||||
{ min: 1, max: 64, message: '长度在 1 到 64 个字符', trigger: 'blur' }
|
||||
],
|
||||
description: [
|
||||
{ max: 64, message: '不能超过 64 个字符', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
rulesIsvForm: {
|
||||
appKey: [
|
||||
{ required: true, message: '不能为空', trigger: 'blur' },
|
||||
{ min: 1, max: 100, message: '长度在 1 到 100 个字符', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
184
sop-admin/sop-admin-vue/src/views/service/ipBlacklist.vue
Normal file
184
sop-admin/sop-admin-vue/src/views/service/ipBlacklist.vue
Normal file
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :inline="true" :model="searchFormData" class="demo-form-inline" size="mini">
|
||||
<el-form-item label="IP">
|
||||
<el-input v-model="searchFormData.ip" :clearable="true" placeholder="输入IP" style="width: 250px;" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="loadTable">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="primary" size="mini" icon="el-icon-plus" style="margin-bottom: 10px;" @click="onAdd">新增IP</el-button>
|
||||
<el-table
|
||||
:data="pageInfo.rows"
|
||||
border
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
prop="ip"
|
||||
label="IP"
|
||||
width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="remark"
|
||||
label="备注"
|
||||
width="300"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="gmtCreate"
|
||||
label="添加时间"
|
||||
width="160"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="gmtModified"
|
||||
label="修改时间"
|
||||
width="160"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="onTableUpdate(scope.row)">修改</el-button>
|
||||
<el-button type="text" size="mini" @click="onTableDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
background
|
||||
style="margin-top: 5px"
|
||||
:current-page="searchFormData.pageIndex"
|
||||
:page-size="searchFormData.pageSize"
|
||||
:page-sizes="[5, 10, 20, 40]"
|
||||
:total="pageInfo.total"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onPageIndexChange"
|
||||
/>
|
||||
<!--dialog-->
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
@close="resetForm('dialogForm')"
|
||||
>
|
||||
<el-form
|
||||
ref="dialogForm"
|
||||
:rules="dialogFormRules"
|
||||
:model="dialogFormData"
|
||||
label-width="120px"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item prop="ip" label="IP">
|
||||
<el-input v-show="dialogFormData.id === 0" v-model="dialogFormData.ip" />
|
||||
<span v-show="dialogFormData.id > 0">{{ dialogFormData.ip }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" label="备注">
|
||||
<el-input v-model="dialogFormData.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onDialogSave">保 存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
const ipValidator = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请输入IP'))
|
||||
} else {
|
||||
const regexIP = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
||||
if (!regexIP.test(value)) {
|
||||
callback(new Error('IP格式不正确'))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
searchFormData: {
|
||||
ip: '',
|
||||
pageIndex: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
pageInfo: {
|
||||
rows: [],
|
||||
total: 0
|
||||
},
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
dialogFormData: {
|
||||
id: 0,
|
||||
ip: '',
|
||||
remark: ''
|
||||
},
|
||||
dialogFormRules: {
|
||||
ip: [
|
||||
{ validator: ipValidator, trigger: 'blur' },
|
||||
{ min: 1, max: 64, message: '长度在 1 到 64 个字符', trigger: 'blur' }
|
||||
],
|
||||
remark: [
|
||||
{ max: 100, message: '不能超过 100 个字符', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadTable()
|
||||
},
|
||||
methods: {
|
||||
loadTable: function() {
|
||||
this.post('ip.blacklist.page', this.searchFormData, function(resp) {
|
||||
this.pageInfo = resp.data
|
||||
})
|
||||
},
|
||||
onTableUpdate: function(row) {
|
||||
this.dialogTitle = '修改IP'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
Object.assign(this.dialogFormData, row)
|
||||
})
|
||||
},
|
||||
onTableDelete: function(row) {
|
||||
this.confirm(`确认要移除IP【${row.ip}】吗?`, function(done) {
|
||||
const data = {
|
||||
id: row.id
|
||||
}
|
||||
this.post('ip.blacklist.del', data, function() {
|
||||
done()
|
||||
this.tip('删除成功')
|
||||
this.loadTable()
|
||||
})
|
||||
})
|
||||
},
|
||||
onDialogSave: function() {
|
||||
this.$refs.dialogForm.validate((valid) => {
|
||||
if (valid) {
|
||||
const uri = this.dialogFormData.id ? 'ip.blacklist.update' : 'ip.blacklist.add'
|
||||
this.post(uri, this.dialogFormData, function() {
|
||||
this.dialogVisible = false
|
||||
this.loadTable()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
onSizeChange: function(size) {
|
||||
this.searchFormData.pageSize = size
|
||||
this.loadTable()
|
||||
},
|
||||
onAdd: function() {
|
||||
this.dialogTitle = '新增IP'
|
||||
this.dialogVisible = true
|
||||
this.dialogFormData.id = 0
|
||||
},
|
||||
onPageIndexChange: function(pageIndex) {
|
||||
this.searchFormData.pageIndex = pageIndex
|
||||
this.loadTable()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -1,347 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-container>
|
||||
<el-aside style="min-height: 300px;width: 200px;">
|
||||
<el-input v-model="filterText" prefix-icon="el-icon-search" placeholder="搜索服务..." style="margin-bottom:20px;" size="mini" clearable />
|
||||
<el-tree
|
||||
ref="tree2"
|
||||
:data="treeData"
|
||||
:props="defaultProps"
|
||||
:filter-node-method="filterNode"
|
||||
:highlight-current="true"
|
||||
:expand-on-click-node="false"
|
||||
empty-text="无数据"
|
||||
node-key="id"
|
||||
class="filter-tree"
|
||||
default-expand-all
|
||||
@node-click="onNodeClick"
|
||||
>
|
||||
<span slot-scope="{ node, data }" class="custom-tree-node">
|
||||
<span v-if="data.label.length < 15">{{ data.label }}</span>
|
||||
<span v-else>
|
||||
<el-tooltip :content="data.label" class="item" effect="light" placement="right">
|
||||
<span>{{ data.label.substring(0, 15) + '...' }}</span>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</span>
|
||||
</el-tree>
|
||||
</el-aside>
|
||||
<el-main style="padding-top:0">
|
||||
<el-form :inline="true" :model="searchFormData" class="demo-form-inline">
|
||||
<el-form-item label="路由名称">
|
||||
<el-input v-model="searchFormData.id" placeholder="输入接口名或版本号" size="mini" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="onSearchTable">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
max-height="500"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="接口名 (版本号)"
|
||||
width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.name + (scope.row.version ? ' (' + scope.row.version + ')' : '') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="limitType"
|
||||
label="限流策略"
|
||||
width="120"
|
||||
>
|
||||
<template slot-scope slot="header">
|
||||
限流策略 <i class="el-icon-question" style="cursor: pointer" @click="onLimitTypeTipClick"></i>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.limitType === 1">漏桶策略</span>
|
||||
<span v-if="scope.row.limitType === 2">令牌桶策略</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="info"
|
||||
label="限流信息"
|
||||
width="500"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-html="infoRender(scope.row)"></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="limitStatus"
|
||||
label="状态"
|
||||
width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.limitStatus === 1" style="color:#67C23A">已开启</span>
|
||||
<span v-if="scope.row.limitStatus === 0" style="color:#909399">已关闭</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="onTableUpdate(scope.row)">修改</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- dialog -->
|
||||
<el-dialog
|
||||
title="设置限流"
|
||||
:visible.sync="limitDialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
@close="onLimitDialogClose"
|
||||
>
|
||||
<el-form ref="limitDialogFormMain" :model="limitDialogFormData">
|
||||
<el-form-item label="id" :label-width="formLabelWidth">
|
||||
<el-input v-model="limitDialogFormData.routeId" readonly="readonly"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="限流策略" :label-width="formLabelWidth">
|
||||
<el-radio-group v-model="limitDialogFormData.limitType">
|
||||
<el-radio :label="1">漏桶策略</el-radio>
|
||||
<el-radio :label="2">令牌桶策略</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" :label-width="formLabelWidth">
|
||||
<el-switch
|
||||
v-model="limitDialogFormData.limitStatus"
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
>
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form
|
||||
v-show="limitDialogFormData.limitType === 1 && limitDialogFormData.limitStatus"
|
||||
ref="limitDialogFormLeaky"
|
||||
:rules="rulesLeaky"
|
||||
:model="limitDialogFormData"
|
||||
>
|
||||
<el-form-item label="每秒可处理请求数" prop="execCountPerSecond" :label-width="formLabelWidth">
|
||||
<el-input-number v-model="limitDialogFormData.execCountPerSecond" controls-position="right" :min="1" />
|
||||
</el-form-item>
|
||||
<el-form-item label="错误码" prop="limitCode" :label-width="formLabelWidth">
|
||||
<el-input v-model="limitDialogFormData.limitCode" />
|
||||
</el-form-item>
|
||||
<el-form-item label="错误信息" prop="limitMsg" :label-width="formLabelWidth">
|
||||
<el-input v-model="limitDialogFormData.limitMsg" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form
|
||||
v-show="limitDialogFormData.limitType === 2 && limitDialogFormData.limitStatus"
|
||||
ref="limitDialogFormToken"
|
||||
:rules="rulesToken"
|
||||
:model="limitDialogFormData"
|
||||
>
|
||||
<el-form-item label="令牌桶容量" prop="tokenBucketCount" :label-width="formLabelWidth">
|
||||
<el-input-number v-model="limitDialogFormData.tokenBucketCount" controls-position="right" :min="1" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="limitDialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onLimitDialogSave">保 存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
filterText: '',
|
||||
treeData: [],
|
||||
tableData: [],
|
||||
serviceId: '',
|
||||
searchFormData: {},
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
},
|
||||
// dialog
|
||||
limitDialogFormData: {
|
||||
routeId: '',
|
||||
execCountPerSecond: 5,
|
||||
limitCode: '',
|
||||
limitMsg: '',
|
||||
tokenBucketCount: 5,
|
||||
limitStatus: 0, // 0: 停用,1:启用
|
||||
limitType: 1
|
||||
},
|
||||
rulesLeaky: {
|
||||
execCountPerSecond: [
|
||||
{ required: true, message: '不能为空', trigger: 'blur' }
|
||||
],
|
||||
limitCode: [
|
||||
{ required: true, message: '不能为空', trigger: 'blur' },
|
||||
{ min: 1, max: 64, message: '长度在 1 到 64 个字符', trigger: 'blur' }
|
||||
],
|
||||
limitMsg: [
|
||||
{ required: true, message: '不能为空', trigger: 'blur' },
|
||||
{ min: 1, max: 100, message: '长度在 1 到 100 个字符', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
rulesToken: {
|
||||
tokenBucketCount: [
|
||||
{ required: true, message: '不能为空', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
formLabelWidth: '150px',
|
||||
limitDialogVisible: false
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
filterText(val) {
|
||||
this.$refs.tree2.filter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadTree()
|
||||
},
|
||||
methods: {
|
||||
// 加载树
|
||||
loadTree: function() {
|
||||
this.post('zookeeper.service.list', {}, function(resp) {
|
||||
const respData = resp.data
|
||||
this.treeData = this.convertToTreeData(respData, 0)
|
||||
})
|
||||
},
|
||||
// 树搜索
|
||||
filterNode(value, data) {
|
||||
if (!value) return true
|
||||
return data.label.indexOf(value) !== -1
|
||||
},
|
||||
// 树点击事件
|
||||
onNodeClick(data, node, tree) {
|
||||
if (data.parentId) {
|
||||
this.serviceId = data.label
|
||||
this.searchFormData.serviceId = this.serviceId
|
||||
this.loadTable()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 数组转成树状结构
|
||||
* @param data 数据结构 [{
|
||||
"_parentId": 14,
|
||||
"gmtCreate": "2019-01-15 09:44:38",
|
||||
"gmtUpdate": "2019-01-15 09:44:38",
|
||||
"id": 15,
|
||||
"isShow": 1,
|
||||
"name": "用户注册",
|
||||
"orderIndex": 10000,
|
||||
"parentId": 14
|
||||
},...]
|
||||
* @param pid 初始父节点id,一般是0
|
||||
* @return 返回结果 [{
|
||||
label: '一级 1',
|
||||
children: [{
|
||||
label: '二级 1-1',
|
||||
children: [{
|
||||
label: '三级 1-1-1'
|
||||
}]
|
||||
}]
|
||||
}
|
||||
*/
|
||||
convertToTreeData(data, pid) {
|
||||
const result = []
|
||||
const root = {
|
||||
label: '服务列表',
|
||||
parentId: pid
|
||||
}
|
||||
const children = []
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const item = { label: data[i].serviceId, parentId: 1 }
|
||||
children.push(item)
|
||||
}
|
||||
root.children = children
|
||||
result.push(root)
|
||||
return result
|
||||
},
|
||||
// table
|
||||
loadTable: function() {
|
||||
this.post('route.limit.list', this.searchFormData, function(resp) {
|
||||
this.tableData = resp.data
|
||||
})
|
||||
},
|
||||
onSearchTable: function() {
|
||||
this.loadTable()
|
||||
},
|
||||
onTableUpdate: function(row) {
|
||||
this.limitDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
Object.assign(this.limitDialogFormData, row)
|
||||
})
|
||||
},
|
||||
resetForm(formName) {
|
||||
const frm = this.$refs[formName]
|
||||
frm && frm.resetFields()
|
||||
},
|
||||
onLimitDialogClose: function() {
|
||||
this.resetForm('limitDialogFormLeaky')
|
||||
this.resetForm('limitDialogFormToken')
|
||||
this.limitDialogVisible = false
|
||||
},
|
||||
infoRender: function(row) {
|
||||
if (!row.hasRecord) {
|
||||
return '--'
|
||||
}
|
||||
const html = []
|
||||
if (row.limitType === 1) {
|
||||
html.push('每秒可处理请求数:' + row.execCountPerSecond)
|
||||
html.push('subCode:' + row.limitCode)
|
||||
html.push('subMsg:' + row.limitMsg)
|
||||
} else if (row.limitType === 2) {
|
||||
html.push('令牌桶容量:' + row.tokenBucketCount)
|
||||
}
|
||||
return html.join(',')
|
||||
},
|
||||
onLimitDialogSave: function() {
|
||||
this.doValidate(function() {
|
||||
this.limitDialogFormData.serviceId = this.serviceId
|
||||
this.post('route.limit.update', this.limitDialogFormData, function(resp) {
|
||||
this.limitDialogVisible = false
|
||||
this.loadTable()
|
||||
})
|
||||
})
|
||||
},
|
||||
doValidate: function(callback) {
|
||||
const that = this
|
||||
if (this.limitDialogFormData.limitStatus === 0) {
|
||||
callback.call(this)
|
||||
return
|
||||
}
|
||||
if (this.limitDialogFormData.limitType === 1) {
|
||||
this.$refs['limitDialogFormLeaky'].validate((valid) => {
|
||||
if (valid) {
|
||||
callback.call(that)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$refs['limitDialogFormToken'].validate((valid) => {
|
||||
if (valid) {
|
||||
callback.call(that)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onLimitTypeTipClick: function() {
|
||||
const leakyRemark = '漏桶策略:每秒处理固定数量的请求,超出请求返回错误信息。'
|
||||
const tokenRemark = '令牌桶策略:每秒放置固定数量的令牌数,每个请求进来后先去拿令牌,拿到了令牌才能继续,拿不到则等候令牌重新生成了再拿。'
|
||||
const content = leakyRemark + '<br>' + tokenRemark
|
||||
this.$alert(content, '限流策略', {
|
||||
dangerouslyUseHTMLString: true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Reference in New Issue
Block a user