mirror of
https://github.com/yhl452493373/frps-panel.git
synced 2026-04-04 06:16:59 +08:00
add server info page
This commit is contained in:
@@ -4,7 +4,14 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
padding: 15px 15px 0 15px;
|
padding: 15px 15px 0 15px;
|
||||||
|
overflow: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchForm input {
|
#searchForm input {
|
||||||
@@ -58,4 +65,48 @@ section {
|
|||||||
|
|
||||||
.layui-table-page {
|
.layui-table-page {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .text-info,
|
||||||
|
section.server-info .chart-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .text-row {
|
||||||
|
display: flex;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .text-row .text-col {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .text-row .text-col:first-child {
|
||||||
|
color: #99a9bf;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .chart-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .chart-info > .chart-traffic,
|
||||||
|
section.server-info .chart-info > .chart-count {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .chart-info > .chart-count {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.server-info .chart-info #trafficChart,
|
||||||
|
section.server-info .chart-info #countChart {
|
||||||
|
width: 400px;
|
||||||
|
height: 250px;
|
||||||
}
|
}
|
||||||
45
assets/static/js/echarts.min.js
vendored
Normal file
45
assets/static/js/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
assets/static/js/filesize.min.js
vendored
Normal file
6
assets/static/js/filesize.min.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*!
|
||||||
|
2022 Jason Mulligan <jason.mulligan@avoidwork.com>
|
||||||
|
@version 9.0.11
|
||||||
|
*/
|
||||||
|
!function(i,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(i="undefined"!=typeof globalThis?globalThis:i||self).filesize=t()}(this,(function(){"use strict";function i(t){return i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(i){return typeof i}:function(i){return i&&"function"==typeof Symbol&&i.constructor===Symbol&&i!==Symbol.prototype?"symbol":typeof i},i(t)}var t="array",o="bits",e="byte",n="bytes",r="",b="exponent",l="function",a="iec",d="Invalid number",f="Invalid rounding method",u="jedec",s="object",c=".",p="round",y="kbit",m="string",v={symbol:{iec:{bits:["bit","Kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],bytes:["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]},jedec:{bits:["bit","Kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],bytes:["B","KB","MB","GB","TB","PB","EB","ZB","YB"]}},fullform:{iec:["","kibi","mebi","gibi","tebi","pebi","exbi","zebi","yobi"],jedec:["","kilo","mega","giga","tera","peta","exa","zetta","yotta"]}};function g(g){var h=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},B=h.bits,M=void 0!==B&&B,S=h.pad,T=void 0!==S&&S,w=h.base,x=void 0===w?-1:w,E=h.round,j=void 0===E?2:E,N=h.locale,P=void 0===N?r:N,k=h.localeOptions,G=void 0===k?{}:k,K=h.separator,Y=void 0===K?r:K,Z=h.spacer,z=void 0===Z?" ":Z,I=h.symbols,L=void 0===I?{}:I,O=h.standard,q=void 0===O?r:O,A=h.output,C=void 0===A?m:A,D=h.fullform,F=void 0!==D&&D,H=h.fullforms,J=void 0===H?[]:H,Q=h.exponent,R=void 0===Q?-1:Q,U=h.roundingMethod,V=void 0===U?p:U,W=h.precision,X=void 0===W?0:W,$=R,_=Number(g),ii=[],ti=0,oi=r;-1===x&&0===q.length?(x=10,q=u):-1===x&&q.length>0?x=(q=q===a?a:u)===a?2:10:q=10===(x=2===x?2:10)||q===u?u:a;var ei=10===x?1e3:1024,ni=!0===F,ri=_<0,bi=Math[V];if(isNaN(g))throw new TypeError(d);if(i(bi)!==l)throw new TypeError(f);if(ri&&(_=-_),(-1===$||isNaN($))&&($=Math.floor(Math.log(_)/Math.log(ei)))<0&&($=0),$>8&&(X>0&&(X+=8-$),$=8),C===b)return $;if(0===_)ii[0]=0,oi=ii[1]=v.symbol[q][M?o:n][$];else{ti=_/(2===x?Math.pow(2,10*$):Math.pow(1e3,$)),M&&(ti*=8)>=ei&&$<8&&(ti/=ei,$++);var li=Math.pow(10,$>0?j:0);ii[0]=bi(ti*li)/li,ii[0]===ei&&$<8&&-1===R&&(ii[0]=1,$++),oi=ii[1]=10===x&&1===$?M?y:"kB":v.symbol[q][M?o:n][$]}if(ri&&(ii[0]=-ii[0]),X>0&&(ii[0]=ii[0].toPrecision(X)),ii[1]=L[ii[1]]||ii[1],!0===P?ii[0]=ii[0].toLocaleString():P.length>0?ii[0]=ii[0].toLocaleString(P,G):Y.length>0&&(ii[0]=ii[0].toString().replace(c,Y)),T&&!1===Number.isInteger(ii[0])&&j>0){var ai=Y||c,di=ii[0].toString().split(ai),fi=di[1]||r,ui=fi.length,si=j-ui;ii[0]="".concat(di[0]).concat(ai).concat(fi.padEnd(ui+si,"0"))}return ni&&(ii[1]=J[$]?J[$]:v.fullform[q][$]+(M?"bit":e)+(1===ii[0]?r:"s")),C===t?ii:C===s?{value:ii[0],symbol:ii[1],exponent:$,unit:oi}:ii.join(z)}return g.partial=function(i){return function(t){return g(t,i)}},g}));
|
||||||
|
//# sourceMappingURL=filesize.min.js.map
|
||||||
148
assets/static/js/index-server-info.js
Normal file
148
assets/static/js/index-server-info.js
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
var loadServerInfo = (function ($) {
|
||||||
|
var size = filesize.partial({base: 2, standard: "jedec"});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get server info
|
||||||
|
* @param lang {{}} language json
|
||||||
|
*/
|
||||||
|
function loadServerInfo(lang) {
|
||||||
|
$('#content').empty();
|
||||||
|
var loading = layui.layer.load();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'http://127.0.0.1:7500/api/serverinfo',
|
||||||
|
dataType: 'jsonp',
|
||||||
|
success: function (result) {
|
||||||
|
result = {
|
||||||
|
"version": "0.51.3",
|
||||||
|
"bind_port": 7000,
|
||||||
|
"vhost_http_port": 80,
|
||||||
|
"vhost_https_port": 443,
|
||||||
|
"tcpmux_httpconnect_port": 0,
|
||||||
|
"kcp_bind_port": 7000,
|
||||||
|
"quic_bind_port": 0,
|
||||||
|
"subdomain_host": "frp.yanghuanglin.com",
|
||||||
|
"max_pool_count": 100,
|
||||||
|
"max_ports_per_client": 0,
|
||||||
|
"heart_beat_timeout": 90,
|
||||||
|
"total_traffic_in": 1669491,
|
||||||
|
"total_traffic_out": 54422369,
|
||||||
|
"cur_conns": 0,
|
||||||
|
"client_counts": 1,
|
||||||
|
"proxy_type_count": {"http": 9, "https": 8, "tcp": 7}
|
||||||
|
};
|
||||||
|
renderServerInfo(result);
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
layui.layer.close(loading);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderServerInfo(data) {
|
||||||
|
var html = layui.laytpl($('#serverInfoTemplate').html()).render(data);
|
||||||
|
$('#content').html(html);
|
||||||
|
|
||||||
|
renderTrafficChart(data);
|
||||||
|
renderCountChart(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTrafficChart(data) {
|
||||||
|
var chartData = [
|
||||||
|
{value: data.total_traffic_in, name: 'total_traffic_in'},
|
||||||
|
{value: data.total_traffic_out, name: 'total_traffic_out'}
|
||||||
|
];
|
||||||
|
var chartDom = document.getElementById('trafficChart');
|
||||||
|
var chart = echarts.init(chartDom);
|
||||||
|
var option = {
|
||||||
|
title: {
|
||||||
|
text: 'Network Traffic',
|
||||||
|
subtext: 'today',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: function (v) {
|
||||||
|
return size(v.value) + ' (' + v.percent + '%)';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left',
|
||||||
|
data: ['total_traffic_in', 'total_traffic_out'],
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: '55%',
|
||||||
|
center: ['50%', '60%'],
|
||||||
|
data: chartData,
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
option && chart.setOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCountChart(data) {
|
||||||
|
var proxies = data.proxy_type_count;
|
||||||
|
var charLegend = [];
|
||||||
|
var chartData = [];
|
||||||
|
|
||||||
|
for (var type in proxies) {
|
||||||
|
var temp = {
|
||||||
|
name: type,
|
||||||
|
value: proxies[type]
|
||||||
|
};
|
||||||
|
charLegend.push(type);
|
||||||
|
chartData.push(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
var chartDom = document.getElementById('countChart');
|
||||||
|
var chart = echarts.init(chartDom);
|
||||||
|
var option = {
|
||||||
|
title: {
|
||||||
|
text: 'Proxies',
|
||||||
|
subtext: 'now',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: function (v) {
|
||||||
|
return v.value;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left',
|
||||||
|
data: charLegend,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: '55%',
|
||||||
|
center: ['50%', '60%'],
|
||||||
|
data: chartData,
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
option && chart.setOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadServerInfo;
|
||||||
|
})(layui.$);
|
||||||
639
assets/static/js/index-user-list.js
Normal file
639
assets/static/js/index-user-list.js
Normal file
@@ -0,0 +1,639 @@
|
|||||||
|
var loadUserList = (function ($) {
|
||||||
|
/**
|
||||||
|
* verify user value
|
||||||
|
* @param username
|
||||||
|
*/
|
||||||
|
function verifyUser(username) {
|
||||||
|
var valid = true;
|
||||||
|
if (username.trim() === '' || !/^\w+$/.test(username)) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: valid,
|
||||||
|
trim: username
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify token value
|
||||||
|
* @param token
|
||||||
|
*/
|
||||||
|
function verifyToken(token) {
|
||||||
|
var valid = true;
|
||||||
|
if (token.trim() === '' || !/^[\w!@#$%^&*()]+$/.test(token)) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: valid,
|
||||||
|
trim: token.trim()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify comment is valid
|
||||||
|
* @param comment
|
||||||
|
*
|
||||||
|
* @return {{valid:boolean, trim:string}}
|
||||||
|
*/
|
||||||
|
function verifyComment(comment) {
|
||||||
|
var valid = true;
|
||||||
|
if (comment.trim() !== '' && /[\n\t\r]/.test(comment)) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: valid,
|
||||||
|
trim: comment.replace(/[\n\t\r]/g, '')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify ports is valid
|
||||||
|
* @param ports
|
||||||
|
*
|
||||||
|
* @return {{valid:boolean, trim:string}}
|
||||||
|
*/
|
||||||
|
function verifyPorts(ports) {
|
||||||
|
var valid = true;
|
||||||
|
if (ports.trim() !== '') {
|
||||||
|
try {
|
||||||
|
ports.split(",").forEach(function (port) {
|
||||||
|
if (/^\s*\d{1,5}\s*$/.test(port)) {
|
||||||
|
if (parseInt(port) < 1 || parseInt(port) > 65535) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
} else if (/^\s*\d{1,5}\s*-\s*\d{1,5}\s*$/.test(port)) {
|
||||||
|
var portRange = port.split('-');
|
||||||
|
if (parseInt(portRange[0]) < 1 || parseInt(portRange[0]) > 65535) {
|
||||||
|
valid = false;
|
||||||
|
} else if (parseInt(portRange[1]) < 1 || parseInt(portRange[1]) > 65535) {
|
||||||
|
valid = false;
|
||||||
|
} else if (parseInt(portRange[0]) > parseInt(portRange[1])) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
if (valid === false) {
|
||||||
|
throw 'break';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: valid,
|
||||||
|
trim: ports.replace(/\s/g, '')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify domains is valid
|
||||||
|
* @param domains
|
||||||
|
*
|
||||||
|
* @return {{valid:boolean, trim:string}}
|
||||||
|
*/
|
||||||
|
function verifyDomains(domains) {
|
||||||
|
var valid = true;
|
||||||
|
if (domains.trim() !== '') {
|
||||||
|
try {
|
||||||
|
domains.split(',').forEach(function (domain) {
|
||||||
|
if (!/^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62}){1,3}$/.test(domain.trim())) {
|
||||||
|
valid = false;
|
||||||
|
throw 'break';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: valid,
|
||||||
|
trim: domains.replace(/\s/g, '')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify subdomains is valid
|
||||||
|
* @param subdomains
|
||||||
|
*
|
||||||
|
* @return {{valid:boolean, trim:string}}
|
||||||
|
*/
|
||||||
|
function verifySubdomains(subdomains) {
|
||||||
|
var valid = true;
|
||||||
|
if (subdomains.trim() !== '') {
|
||||||
|
try {
|
||||||
|
subdomains.split(',').forEach(function (subdomain) {
|
||||||
|
if (!/^[a-zA-z0-9][a-zA-Z0-9-]{0,19}$/.test(subdomain.trim())) {
|
||||||
|
valid = false;
|
||||||
|
throw 'break';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: valid,
|
||||||
|
trim: subdomains.replace(/\s/g, '')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load i18n language
|
||||||
|
* @param lang {{}} language json
|
||||||
|
*/
|
||||||
|
function loadUserList(lang) {
|
||||||
|
var html = layui.laytpl($('#userListTemplate').html()).render();
|
||||||
|
$('#content').html(html);
|
||||||
|
|
||||||
|
var apiType = {
|
||||||
|
Remove: 1,
|
||||||
|
Enable: 2,
|
||||||
|
Disable: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
//set verify rules
|
||||||
|
var verifyRules = {
|
||||||
|
user: function (value, item) {
|
||||||
|
var result = verifyUser(value);
|
||||||
|
if (!result.valid) {
|
||||||
|
return lang['UserFormatError'];
|
||||||
|
}
|
||||||
|
if (item != null) {
|
||||||
|
if (typeof item === "function") {
|
||||||
|
item && item(result.trim);
|
||||||
|
} else {
|
||||||
|
$(item).val(result.trim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
token: function (value, item) {
|
||||||
|
var result = verifyToken(value);
|
||||||
|
if (!result.valid) {
|
||||||
|
return lang['TokenFormatError'];
|
||||||
|
}
|
||||||
|
if (item != null) {
|
||||||
|
if (typeof item === "function") {
|
||||||
|
item && item(result.trim);
|
||||||
|
} else {
|
||||||
|
$(item).val(result.trim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
comment: function (value, item) {
|
||||||
|
var result = verifyComment(value);
|
||||||
|
if (!result.valid) {
|
||||||
|
return lang['CommentInvalid'];
|
||||||
|
}
|
||||||
|
if (item != null) {
|
||||||
|
if (typeof item === "function") {
|
||||||
|
item && item(result.trim);
|
||||||
|
} else {
|
||||||
|
$(item).val(result.trim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ports: function (value, item) {
|
||||||
|
var result = verifyPorts(value);
|
||||||
|
if (!result.valid) {
|
||||||
|
return lang['PortsInvalid'];
|
||||||
|
}
|
||||||
|
if (item != null) {
|
||||||
|
if (typeof item === "function") {
|
||||||
|
item && item(result.trim);
|
||||||
|
} else {
|
||||||
|
$(item).val(result.trim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
domains: function (value, item) {
|
||||||
|
var result = verifyDomains(value);
|
||||||
|
if (!result.valid) {
|
||||||
|
return lang['DomainsInvalid'];
|
||||||
|
}
|
||||||
|
if (item != null) {
|
||||||
|
if (typeof item === "function") {
|
||||||
|
item && item(result.trim);
|
||||||
|
} else {
|
||||||
|
$(item).val(result.trim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subdomains: function (value, item) {
|
||||||
|
var result = verifySubdomains(value);
|
||||||
|
if (!result.valid) {
|
||||||
|
return lang['SubdomainsInvalid'];
|
||||||
|
}
|
||||||
|
if (item != null) {
|
||||||
|
if (typeof item === "function") {
|
||||||
|
item && item(result.trim);
|
||||||
|
} else {
|
||||||
|
$(item).val(result.trim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
layui.form.set({
|
||||||
|
verIncludeRequired: true,
|
||||||
|
verify: verifyRules
|
||||||
|
});
|
||||||
|
|
||||||
|
layui.table.render({
|
||||||
|
elem: '#tokenTable',
|
||||||
|
url: '/tokens',
|
||||||
|
method: 'get',
|
||||||
|
where: {},
|
||||||
|
dataType: 'json',
|
||||||
|
editTrigger: 'dblclick',
|
||||||
|
page: navigator.language.indexOf("zh") === 0,
|
||||||
|
toolbar: '#toolbarTemplate',
|
||||||
|
defaultToolbar: false,
|
||||||
|
text: {none: lang['EmptyData']},
|
||||||
|
cols: [[
|
||||||
|
{type: 'checkbox'},
|
||||||
|
{field: 'user', title: lang['User'], width: 150, sort: true},
|
||||||
|
{field: 'token', title: lang['Token'], width: 200, sort: true, edit: true},
|
||||||
|
{field: 'comment', title: lang['Notes'], sort: true, edit: 'textarea'},
|
||||||
|
{field: 'ports', title: lang['AllowedPorts'], sort: true, edit: 'textarea'},
|
||||||
|
{field: 'domains', title: lang['AllowedDomains'], sort: true, edit: 'textarea'},
|
||||||
|
{field: 'subdomains', title: lang['AllowedSubdomains'], sort: true, edit: 'textarea'},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: lang['Status'],
|
||||||
|
width: 100,
|
||||||
|
templet: '<span>{{d.status? "' + lang['Enable'] + '":"' + lang['Disable'] + '"}}</span>',
|
||||||
|
sort: true
|
||||||
|
},
|
||||||
|
{title: lang['Operation'], width: 150, toolbar: '#operationTemplate'}
|
||||||
|
]]
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update layui table data
|
||||||
|
* @param obj table update obj
|
||||||
|
* @param field update field
|
||||||
|
* @param trim new value
|
||||||
|
*/
|
||||||
|
function updateTableField(obj, field, trim) {
|
||||||
|
var newData = {};
|
||||||
|
newData[field] = trim;
|
||||||
|
obj.update(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
layui.table.on('edit(tokenTable)', function (obj) {
|
||||||
|
var field = obj.field;
|
||||||
|
var value = obj.value;
|
||||||
|
var oldValue = obj.oldValue;
|
||||||
|
var before = $.extend(true, {}, obj.data);
|
||||||
|
var after = $.extend(true, {}, obj.data);
|
||||||
|
var verifyMsg = false;
|
||||||
|
if (field === 'token') {
|
||||||
|
verifyMsg = verifyRules.token(value, function (trim) {
|
||||||
|
updateTableField(obj, field, trim)
|
||||||
|
});
|
||||||
|
if (verifyMsg) {
|
||||||
|
layui.layer.msg(verifyMsg);
|
||||||
|
return obj.reedit();
|
||||||
|
}
|
||||||
|
|
||||||
|
before.token = oldValue;
|
||||||
|
after.token = value;
|
||||||
|
} else if (field === 'comment') {
|
||||||
|
verifyMsg = verifyRules.comment(value, function (trim) {
|
||||||
|
updateTableField(obj, field, trim)
|
||||||
|
});
|
||||||
|
if (verifyMsg) {
|
||||||
|
layui.layer.msg(verifyMsg);
|
||||||
|
return obj.reedit();
|
||||||
|
}
|
||||||
|
|
||||||
|
before.comment = oldValue;
|
||||||
|
after.comment = value;
|
||||||
|
} else if (field === 'ports') {
|
||||||
|
verifyMsg = verifyRules.ports(value, function (trim) {
|
||||||
|
updateTableField(obj, field, trim)
|
||||||
|
});
|
||||||
|
if (verifyMsg) {
|
||||||
|
layui.layer.msg(verifyMsg);
|
||||||
|
return obj.reedit();
|
||||||
|
}
|
||||||
|
|
||||||
|
before.ports = oldValue;
|
||||||
|
after.ports = value;
|
||||||
|
} else if (field === 'domains') {
|
||||||
|
verifyMsg = verifyRules.domains(value, function (trim) {
|
||||||
|
updateTableField(obj, field, trim)
|
||||||
|
});
|
||||||
|
if (verifyMsg) {
|
||||||
|
layui.layer.msg(verifyMsg);
|
||||||
|
return obj.reedit();
|
||||||
|
}
|
||||||
|
|
||||||
|
before.domains = oldValue;
|
||||||
|
after.domains = value;
|
||||||
|
} else if (field === 'subdomains') {
|
||||||
|
verifyMsg = verifyRules.subdomains(value, function (trim) {
|
||||||
|
updateTableField(obj, field, trim)
|
||||||
|
});
|
||||||
|
if (verifyMsg) {
|
||||||
|
layui.layer.msg(verifyMsg);
|
||||||
|
return obj.reedit();
|
||||||
|
}
|
||||||
|
|
||||||
|
before.subdomains = oldValue;
|
||||||
|
after.subdomains = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(before, after);
|
||||||
|
});
|
||||||
|
|
||||||
|
layui.table.on('toolbar(tokenTable)', function (obj) {
|
||||||
|
var id = obj.config.id;
|
||||||
|
var checkStatus = layui.table.checkStatus(id);
|
||||||
|
switch (obj.event) {
|
||||||
|
case 'add':
|
||||||
|
addPopup();
|
||||||
|
break
|
||||||
|
case 'remove':
|
||||||
|
batchRemovePopup(checkStatus.data);
|
||||||
|
break
|
||||||
|
case 'disable':
|
||||||
|
batchDisablePopup(checkStatus.data);
|
||||||
|
break
|
||||||
|
case 'enable':
|
||||||
|
batchEnablePopup(checkStatus.data);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
});
|
||||||
|
layui.table.on('tool(tokenTable)', function (obj) {
|
||||||
|
var data = obj.data;
|
||||||
|
switch (obj.event) {
|
||||||
|
case 'remove':
|
||||||
|
removePopup(data);
|
||||||
|
break;
|
||||||
|
case 'disable':
|
||||||
|
disablePopup(data);
|
||||||
|
break;
|
||||||
|
case 'enable':
|
||||||
|
enablePopup(data);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add user popup
|
||||||
|
*/
|
||||||
|
function addPopup() {
|
||||||
|
layui.layer.open({
|
||||||
|
type: 1,
|
||||||
|
title: lang['NewUser'],
|
||||||
|
area: ['500px'],
|
||||||
|
content: layui.laytpl(document.getElementById('addTemplate').innerHTML).render(),
|
||||||
|
btn: [lang['Confirm'], lang['Cancel']],
|
||||||
|
btn1: function (index) {
|
||||||
|
if (layui.form.validate('#addUserForm')) {
|
||||||
|
add(layui.form.val('addUserForm'), index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
btn2: function (index) {
|
||||||
|
layui.layer.close(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add user action
|
||||||
|
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
||||||
|
* @param index popup index
|
||||||
|
*/
|
||||||
|
function add(data, index) {
|
||||||
|
var loading = layui.layer.load();
|
||||||
|
$.ajax({
|
||||||
|
url: '/add',
|
||||||
|
type: 'post',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
success: function (result) {
|
||||||
|
if (result.success) {
|
||||||
|
reloadTable();
|
||||||
|
layui.layer.close(index);
|
||||||
|
layui.layer.msg(lang['OperateSuccess'], function (index) {
|
||||||
|
layui.layer.close(index);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
errorMsg(result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
layui.layer.close(loading);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update user action
|
||||||
|
* @param before {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} data before update
|
||||||
|
* @param after {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} data after update
|
||||||
|
*/
|
||||||
|
function update(before, after) {
|
||||||
|
var loading = layui.layer.load();
|
||||||
|
$.ajax({
|
||||||
|
url: '/update',
|
||||||
|
type: 'post',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify({
|
||||||
|
before: before,
|
||||||
|
after: after,
|
||||||
|
}),
|
||||||
|
success: function (result) {
|
||||||
|
if (result.success) {
|
||||||
|
layui.layer.msg(lang['OperateSuccess']);
|
||||||
|
} else {
|
||||||
|
errorMsg(result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
layui.layer.close(loading);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* batch remove user popup
|
||||||
|
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
||||||
|
*/
|
||||||
|
function batchRemovePopup(data) {
|
||||||
|
if (data.length === 0) {
|
||||||
|
layui.layer.msg(lang['ShouldCheckUser']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
layui.layer.confirm(lang['ConfirmRemoveUser'], {
|
||||||
|
title: lang['OperationConfirm'],
|
||||||
|
btn: [lang['Confirm'], lang['Cancel']]
|
||||||
|
}, function (index) {
|
||||||
|
operate(apiType.Remove, data, index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* batch disable user popup
|
||||||
|
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
||||||
|
*/
|
||||||
|
function batchDisablePopup(data) {
|
||||||
|
if (data.length === 0) {
|
||||||
|
layui.layer.msg(lang['ShouldCheckUser']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
layui.layer.confirm(lang['ConfirmDisableUser'], {
|
||||||
|
title: lang['OperationConfirm'],
|
||||||
|
btn: [lang['Confirm'], lang['Cancel']]
|
||||||
|
}, function (index) {
|
||||||
|
operate(apiType.Disable, data, index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* batch enable user popup
|
||||||
|
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
||||||
|
*/
|
||||||
|
function batchEnablePopup(data) {
|
||||||
|
if (data.length === 0) {
|
||||||
|
layui.layer.msg(lang['ShouldCheckUser']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
layui.layer.confirm(lang['ConfirmEnableUser'], {
|
||||||
|
title: lang['OperationConfirm'],
|
||||||
|
btn: [lang['Confirm'], lang['Cancel']]
|
||||||
|
}, function (index) {
|
||||||
|
operate(apiType.Enable, data, index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove one user popup
|
||||||
|
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
||||||
|
*/
|
||||||
|
function removePopup(data) {
|
||||||
|
layui.layer.confirm(lang['ConfirmRemoveUser'], {
|
||||||
|
title: lang['OperationConfirm'],
|
||||||
|
btn: [lang['Confirm'], lang['Cancel']]
|
||||||
|
}, function (index) {
|
||||||
|
operate(apiType.Remove, [data], index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disable one user popup
|
||||||
|
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
||||||
|
*/
|
||||||
|
function disablePopup(data) {
|
||||||
|
layui.layer.confirm(lang['ConfirmDisableUser'], {
|
||||||
|
title: lang['OperationConfirm'],
|
||||||
|
btn: [lang['Confirm'], lang['Cancel']]
|
||||||
|
}, function (index) {
|
||||||
|
operate(apiType.Disable, [data], index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enable one user popup
|
||||||
|
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
||||||
|
*/
|
||||||
|
function enablePopup(data) {
|
||||||
|
layui.layer.confirm(lang['ConfirmEnableUser'], {
|
||||||
|
title: lang['OperationConfirm'],
|
||||||
|
btn: [lang['Confirm'], lang['Cancel']]
|
||||||
|
}, function (index) {
|
||||||
|
operate(apiType.Enable, [data], index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* operate actions
|
||||||
|
* @param type {apiType} action type
|
||||||
|
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
||||||
|
* @param index popup index
|
||||||
|
*/
|
||||||
|
function operate(type, data, index) {
|
||||||
|
var url;
|
||||||
|
var extendMessage = '';
|
||||||
|
if (type === apiType.Remove) {
|
||||||
|
url = "/remove";
|
||||||
|
extendMessage = ', ' + lang['RemoveUser'] + lang['TakeTimeMakeEffective'];
|
||||||
|
} else if (type === apiType.Disable) {
|
||||||
|
url = "/disable";
|
||||||
|
extendMessage = ', ' + lang['RemoveUser'] + lang['TakeTimeMakeEffective'];
|
||||||
|
} else if (type === apiType.Enable) {
|
||||||
|
url = "/enable";
|
||||||
|
} else {
|
||||||
|
layer.layer.msg(lang['OperateError']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var loading = layui.layer.load();
|
||||||
|
$.post({
|
||||||
|
url: url,
|
||||||
|
type: 'post',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify({
|
||||||
|
users: data
|
||||||
|
}),
|
||||||
|
success: function (result) {
|
||||||
|
if (result.success) {
|
||||||
|
reloadTable();
|
||||||
|
layui.layer.close(index);
|
||||||
|
layui.layer.msg(lang['OperateSuccess'] + extendMessage, function (index) {
|
||||||
|
layui.layer.close(index);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
errorMsg(result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
layui.layer.close(loading);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reload user table
|
||||||
|
*/
|
||||||
|
function reloadTable() {
|
||||||
|
var searchData = layui.form.val('searchForm');
|
||||||
|
layui.table.reloadData('tokenTable', {
|
||||||
|
where: searchData
|
||||||
|
}, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* show error message popup
|
||||||
|
* @param result
|
||||||
|
*/
|
||||||
|
function errorMsg(result) {
|
||||||
|
var reason = lang['Other Error'];
|
||||||
|
if (result.code === 1)
|
||||||
|
reason = lang['ParamError'];
|
||||||
|
else if (result.code === 2)
|
||||||
|
reason = lang['UserExist'];
|
||||||
|
else if (result.code === 3)
|
||||||
|
reason = lang['ParamError'];
|
||||||
|
else if (result.code === 4)
|
||||||
|
reason = lang['UserFormatError'];
|
||||||
|
else if (result.code === 5)
|
||||||
|
reason = lang['TokenFormatError'];
|
||||||
|
layui.layer.msg(lang['OperateFailed'] + ',' + reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* click event
|
||||||
|
*/
|
||||||
|
$(document).on('click.search', '#searchBtn', function () {
|
||||||
|
reloadTable();
|
||||||
|
return false;
|
||||||
|
}).on('click.reset', '#resetBtn', function () {
|
||||||
|
$('#searchForm')[0].reset();
|
||||||
|
reloadTable();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadUserList;
|
||||||
|
})(layui.$)
|
||||||
@@ -1,652 +1,18 @@
|
|||||||
var $ = layui.$;
|
(function ($) {
|
||||||
$(function () {
|
$(function () {
|
||||||
var apiType = {
|
var langLoading = layui.layer.load()
|
||||||
Remove: 1,
|
$.getJSON('/lang').done(function (lang) {
|
||||||
Enable: 2,
|
layui.element.on('nav(leftNav)', function (elem) {
|
||||||
Disable: 3
|
if (elem.attr('id') === 'serverInfo') {
|
||||||
}
|
loadServerInfo(lang);
|
||||||
|
} else if (elem.attr('id') === 'userList') {
|
||||||
|
loadUserList(lang);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
$('#leftNav .layui-this > a').click();
|
||||||
* verify user value
|
}).always(function () {
|
||||||
* @param username
|
layui.layer.close(langLoading);
|
||||||
*/
|
|
||||||
function verifyUser(username) {
|
|
||||||
var valid = true;
|
|
||||||
if (username.trim() === '' || !/^\w+$/.test(username)) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
valid: valid,
|
|
||||||
trim: username
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify token value
|
|
||||||
* @param token
|
|
||||||
*/
|
|
||||||
function verifyToken(token) {
|
|
||||||
var valid = true;
|
|
||||||
if (token.trim() === '' || !/^[\w!@#$%^&*()]+$/.test(token)) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
valid: valid,
|
|
||||||
trim: token.trim()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify comment is valid
|
|
||||||
* @param comment
|
|
||||||
*
|
|
||||||
* @return {{valid:boolean, trim:string}}
|
|
||||||
*/
|
|
||||||
function verifyComment(comment) {
|
|
||||||
var valid = true;
|
|
||||||
if (comment.trim() !== '' && /[\n\t\r]/.test(comment)) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
valid: valid,
|
|
||||||
trim: comment.replace(/[\n\t\r]/g, '')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify ports is valid
|
|
||||||
* @param ports
|
|
||||||
*
|
|
||||||
* @return {{valid:boolean, trim:string}}
|
|
||||||
*/
|
|
||||||
function verifyPorts(ports) {
|
|
||||||
var valid = true;
|
|
||||||
if (ports.trim() !== '') {
|
|
||||||
try {
|
|
||||||
ports.split(",").forEach(function (port) {
|
|
||||||
if (/^\s*\d{1,5}\s*$/.test(port)) {
|
|
||||||
if (parseInt(port) < 1 || parseInt(port) > 65535) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
} else if (/^\s*\d{1,5}\s*-\s*\d{1,5}\s*$/.test(port)) {
|
|
||||||
var portRange = port.split('-');
|
|
||||||
if (parseInt(portRange[0]) < 1 || parseInt(portRange[0]) > 65535) {
|
|
||||||
valid = false;
|
|
||||||
} else if (parseInt(portRange[1]) < 1 || parseInt(portRange[1]) > 65535) {
|
|
||||||
valid = false;
|
|
||||||
} else if (parseInt(portRange[0]) > parseInt(portRange[1])) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
if (valid === false) {
|
|
||||||
throw 'break';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
valid: valid,
|
|
||||||
trim: ports.replace(/\s/g, '')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify domains is valid
|
|
||||||
* @param domains
|
|
||||||
*
|
|
||||||
* @return {{valid:boolean, trim:string}}
|
|
||||||
*/
|
|
||||||
function verifyDomains(domains) {
|
|
||||||
var valid = true;
|
|
||||||
if (domains.trim() !== '') {
|
|
||||||
try {
|
|
||||||
domains.split(',').forEach(function (domain) {
|
|
||||||
if (!/^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62}){1,3}$/.test(domain.trim())) {
|
|
||||||
valid = false;
|
|
||||||
throw 'break';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
valid: valid,
|
|
||||||
trim: domains.replace(/\s/g, '')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* verify subdomains is valid
|
|
||||||
* @param subdomains
|
|
||||||
*
|
|
||||||
* @return {{valid:boolean, trim:string}}
|
|
||||||
*/
|
|
||||||
function verifySubdomains(subdomains) {
|
|
||||||
var valid = true;
|
|
||||||
if (subdomains.trim() !== '') {
|
|
||||||
try {
|
|
||||||
subdomains.split(',').forEach(function (subdomain) {
|
|
||||||
if (!/^[a-zA-z0-9][a-zA-Z0-9-]{0,19}$/.test(subdomain.trim())) {
|
|
||||||
valid = false;
|
|
||||||
throw 'break';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
valid: valid,
|
|
||||||
trim: subdomains.replace(/\s/g, '')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load i18n language
|
|
||||||
* @param lang {{}}
|
|
||||||
*/
|
|
||||||
function langLoaded(lang) {
|
|
||||||
//set verify rules
|
|
||||||
var verifyRules = {
|
|
||||||
user: function (value, item) {
|
|
||||||
var result = verifyUser(value);
|
|
||||||
if (!result.valid) {
|
|
||||||
return lang['UserFormatError'];
|
|
||||||
}
|
|
||||||
if (item != null) {
|
|
||||||
if (typeof item === "function") {
|
|
||||||
item && item(result.trim);
|
|
||||||
} else {
|
|
||||||
$(item).val(result.trim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
token: function (value, item) {
|
|
||||||
var result = verifyToken(value);
|
|
||||||
if (!result.valid) {
|
|
||||||
return lang['TokenFormatError'];
|
|
||||||
}
|
|
||||||
if (item != null) {
|
|
||||||
if (typeof item === "function") {
|
|
||||||
item && item(result.trim);
|
|
||||||
} else {
|
|
||||||
$(item).val(result.trim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
comment: function (value, item) {
|
|
||||||
var result = verifyComment(value);
|
|
||||||
if (!result.valid) {
|
|
||||||
return lang['CommentInvalid'];
|
|
||||||
}
|
|
||||||
if (item != null) {
|
|
||||||
if (typeof item === "function") {
|
|
||||||
item && item(result.trim);
|
|
||||||
} else {
|
|
||||||
$(item).val(result.trim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ports: function (value, item) {
|
|
||||||
var result = verifyPorts(value);
|
|
||||||
if (!result.valid) {
|
|
||||||
return lang['PortsInvalid'];
|
|
||||||
}
|
|
||||||
if (item != null) {
|
|
||||||
if (typeof item === "function") {
|
|
||||||
item && item(result.trim);
|
|
||||||
} else {
|
|
||||||
$(item).val(result.trim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
domains: function (value, item) {
|
|
||||||
var result = verifyDomains(value);
|
|
||||||
if (!result.valid) {
|
|
||||||
return lang['DomainsInvalid'];
|
|
||||||
}
|
|
||||||
if (item != null) {
|
|
||||||
if (typeof item === "function") {
|
|
||||||
item && item(result.trim);
|
|
||||||
} else {
|
|
||||||
$(item).val(result.trim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
subdomains: function (value, item) {
|
|
||||||
var result = verifySubdomains(value);
|
|
||||||
if (!result.valid) {
|
|
||||||
return lang['SubdomainsInvalid'];
|
|
||||||
}
|
|
||||||
if (item != null) {
|
|
||||||
if (typeof item === "function") {
|
|
||||||
item && item(result.trim);
|
|
||||||
} else {
|
|
||||||
$(item).val(result.trim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
layui.form.set({
|
|
||||||
verIncludeRequired: true,
|
|
||||||
verify: verifyRules
|
|
||||||
});
|
});
|
||||||
|
|
||||||
layui.table.render({
|
|
||||||
elem: '#tokenTable',
|
|
||||||
url: '/tokens',
|
|
||||||
method: 'get',
|
|
||||||
where: {},
|
|
||||||
dataType: 'json',
|
|
||||||
editTrigger: 'dblclick',
|
|
||||||
page: navigator.language.indexOf("zh") === 0,
|
|
||||||
toolbar: '#toolbarTemplate',
|
|
||||||
defaultToolbar: false,
|
|
||||||
text: {none: lang['EmptyData']},
|
|
||||||
cols: [[
|
|
||||||
{type: 'checkbox'},
|
|
||||||
{field: 'user', title: lang['User'], width: 150, sort: true},
|
|
||||||
{field: 'token', title: lang['Token'], width: 200, sort: true, edit: true},
|
|
||||||
{field: 'comment', title: lang['Notes'], sort: true, edit: 'textarea'},
|
|
||||||
{field: 'ports', title: lang['AllowedPorts'], sort: true, edit: 'textarea'},
|
|
||||||
{field: 'domains', title: lang['AllowedDomains'], sort: true, edit: 'textarea'},
|
|
||||||
{field: 'subdomains', title: lang['AllowedSubdomains'], sort: true, edit: 'textarea'},
|
|
||||||
{
|
|
||||||
field: 'status',
|
|
||||||
title: lang['Status'],
|
|
||||||
width: 100,
|
|
||||||
templet: '<span>{{d.status? "' + lang['Enable'] + '":"' + lang['Disable'] + '"}}</span>',
|
|
||||||
sort: true
|
|
||||||
},
|
|
||||||
{title: lang['Operation'], width: 150, toolbar: '#operationTemplate'}
|
|
||||||
]]
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update layui table data
|
|
||||||
* @param obj table update obj
|
|
||||||
* @param field update field
|
|
||||||
* @param trim new value
|
|
||||||
*/
|
|
||||||
function updateTableField(obj, field, trim) {
|
|
||||||
var newData = {};
|
|
||||||
newData[field] = trim;
|
|
||||||
obj.update(newData);
|
|
||||||
}
|
|
||||||
|
|
||||||
layui.table.on('edit(tokenTable)', function (obj) {
|
|
||||||
var field = obj.field;
|
|
||||||
var value = obj.value;
|
|
||||||
var oldValue = obj.oldValue;
|
|
||||||
var before = $.extend(true, {}, obj.data);
|
|
||||||
var after = $.extend(true, {}, obj.data);
|
|
||||||
var verifyMsg = false;
|
|
||||||
if (field === 'token') {
|
|
||||||
verifyMsg = verifyRules.token(value, function (trim) {
|
|
||||||
updateTableField(obj, field, trim)
|
|
||||||
});
|
|
||||||
if (verifyMsg) {
|
|
||||||
layui.layer.msg(verifyMsg);
|
|
||||||
return obj.reedit();
|
|
||||||
}
|
|
||||||
|
|
||||||
before.token = oldValue;
|
|
||||||
after.token = value;
|
|
||||||
} else if (field === 'comment') {
|
|
||||||
verifyMsg = verifyRules.comment(value, function (trim) {
|
|
||||||
updateTableField(obj, field, trim)
|
|
||||||
});
|
|
||||||
if (verifyMsg) {
|
|
||||||
layui.layer.msg(verifyMsg);
|
|
||||||
return obj.reedit();
|
|
||||||
}
|
|
||||||
|
|
||||||
before.comment = oldValue;
|
|
||||||
after.comment = value;
|
|
||||||
} else if (field === 'ports') {
|
|
||||||
verifyMsg = verifyRules.ports(value, function (trim) {
|
|
||||||
updateTableField(obj, field, trim)
|
|
||||||
});
|
|
||||||
if (verifyMsg) {
|
|
||||||
layui.layer.msg(verifyMsg);
|
|
||||||
return obj.reedit();
|
|
||||||
}
|
|
||||||
|
|
||||||
before.ports = oldValue;
|
|
||||||
after.ports = value;
|
|
||||||
} else if (field === 'domains') {
|
|
||||||
verifyMsg = verifyRules.domains(value, function (trim) {
|
|
||||||
updateTableField(obj, field, trim)
|
|
||||||
});
|
|
||||||
if (verifyMsg) {
|
|
||||||
layui.layer.msg(verifyMsg);
|
|
||||||
return obj.reedit();
|
|
||||||
}
|
|
||||||
|
|
||||||
before.domains = oldValue;
|
|
||||||
after.domains = value;
|
|
||||||
} else if (field === 'subdomains') {
|
|
||||||
verifyMsg = verifyRules.subdomains(value, function (trim) {
|
|
||||||
updateTableField(obj, field, trim)
|
|
||||||
});
|
|
||||||
if (verifyMsg) {
|
|
||||||
layui.layer.msg(verifyMsg);
|
|
||||||
return obj.reedit();
|
|
||||||
}
|
|
||||||
|
|
||||||
before.subdomains = oldValue;
|
|
||||||
after.subdomains = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(before, after);
|
|
||||||
});
|
|
||||||
|
|
||||||
layui.table.on('toolbar(tokenTable)', function (obj) {
|
|
||||||
var id = obj.config.id;
|
|
||||||
var checkStatus = layui.table.checkStatus(id);
|
|
||||||
switch (obj.event) {
|
|
||||||
case 'add':
|
|
||||||
addPopup();
|
|
||||||
break
|
|
||||||
case 'remove':
|
|
||||||
batchRemovePopup(checkStatus.data);
|
|
||||||
break
|
|
||||||
case 'disable':
|
|
||||||
batchDisablePopup(checkStatus.data);
|
|
||||||
break
|
|
||||||
case 'enable':
|
|
||||||
batchEnablePopup(checkStatus.data);
|
|
||||||
break
|
|
||||||
}
|
|
||||||
});
|
|
||||||
layui.table.on('tool(tokenTable)', function (obj) {
|
|
||||||
var data = obj.data;
|
|
||||||
switch (obj.event) {
|
|
||||||
case 'remove':
|
|
||||||
removePopup(data);
|
|
||||||
break;
|
|
||||||
case 'disable':
|
|
||||||
disablePopup(data);
|
|
||||||
break;
|
|
||||||
case 'enable':
|
|
||||||
enablePopup(data);
|
|
||||||
break
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add user popup
|
|
||||||
*/
|
|
||||||
function addPopup() {
|
|
||||||
layui.layer.open({
|
|
||||||
type: 1,
|
|
||||||
title: lang['NewUser'],
|
|
||||||
area: ['500px'],
|
|
||||||
content: layui.laytpl(document.getElementById('addTemplate').innerHTML).render(),
|
|
||||||
btn: [lang['Confirm'], lang['Cancel']],
|
|
||||||
btn1: function (index) {
|
|
||||||
if (layui.form.validate('#addUserForm')) {
|
|
||||||
add(layui.form.val('addUserForm'), index);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
btn2: function (index) {
|
|
||||||
layui.layer.close(index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add user action
|
|
||||||
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
|
||||||
* @param index popup index
|
|
||||||
*/
|
|
||||||
function add(data, index) {
|
|
||||||
var loading = layui.layer.load();
|
|
||||||
$.ajax({
|
|
||||||
url: '/add',
|
|
||||||
type: 'post',
|
|
||||||
contentType: 'application/json',
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
reloadTable();
|
|
||||||
layui.layer.close(index);
|
|
||||||
layui.layer.msg(lang['OperateSuccess'], function (index) {
|
|
||||||
layui.layer.close(index);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
errorMsg(result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
layui.layer.close(loading);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update user action
|
|
||||||
* @param before {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} data before update
|
|
||||||
* @param after {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} data after update
|
|
||||||
*/
|
|
||||||
function update(before, after) {
|
|
||||||
var loading = layui.layer.load();
|
|
||||||
$.ajax({
|
|
||||||
url: '/update',
|
|
||||||
type: 'post',
|
|
||||||
contentType: 'application/json',
|
|
||||||
data: JSON.stringify({
|
|
||||||
before: before,
|
|
||||||
after: after,
|
|
||||||
}),
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layui.layer.msg(lang['OperateSuccess']);
|
|
||||||
} else {
|
|
||||||
errorMsg(result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
layui.layer.close(loading);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* batch remove user popup
|
|
||||||
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
|
||||||
*/
|
|
||||||
function batchRemovePopup(data) {
|
|
||||||
if (data.length === 0) {
|
|
||||||
layui.layer.msg(lang['ShouldCheckUser']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
layui.layer.confirm(lang['ConfirmRemoveUser'], {
|
|
||||||
title: lang['OperationConfirm'],
|
|
||||||
btn: [lang['Confirm'], lang['Cancel']]
|
|
||||||
}, function (index) {
|
|
||||||
operate(apiType.Remove, data, index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* batch disable user popup
|
|
||||||
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
|
||||||
*/
|
|
||||||
function batchDisablePopup(data) {
|
|
||||||
if (data.length === 0) {
|
|
||||||
layui.layer.msg(lang['ShouldCheckUser']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
layui.layer.confirm(lang['ConfirmDisableUser'], {
|
|
||||||
title: lang['OperationConfirm'],
|
|
||||||
btn: [lang['Confirm'], lang['Cancel']]
|
|
||||||
}, function (index) {
|
|
||||||
operate(apiType.Disable, data, index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* batch enable user popup
|
|
||||||
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
|
||||||
*/
|
|
||||||
function batchEnablePopup(data) {
|
|
||||||
if (data.length === 0) {
|
|
||||||
layui.layer.msg(lang['ShouldCheckUser']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
layui.layer.confirm(lang['ConfirmEnableUser'], {
|
|
||||||
title: lang['OperationConfirm'],
|
|
||||||
btn: [lang['Confirm'], lang['Cancel']]
|
|
||||||
}, function (index) {
|
|
||||||
operate(apiType.Enable, data, index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove one user popup
|
|
||||||
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
|
||||||
*/
|
|
||||||
function removePopup(data) {
|
|
||||||
layui.layer.confirm(lang['ConfirmRemoveUser'], {
|
|
||||||
title: lang['OperationConfirm'],
|
|
||||||
btn: [lang['Confirm'], lang['Cancel']]
|
|
||||||
}, function (index) {
|
|
||||||
operate(apiType.Remove, [data], index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* disable one user popup
|
|
||||||
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
|
||||||
*/
|
|
||||||
function disablePopup(data) {
|
|
||||||
layui.layer.confirm(lang['ConfirmDisableUser'], {
|
|
||||||
title: lang['OperationConfirm'],
|
|
||||||
btn: [lang['Confirm'], lang['Cancel']]
|
|
||||||
}, function (index) {
|
|
||||||
operate(apiType.Disable, [data], index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* enable one user popup
|
|
||||||
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
|
|
||||||
*/
|
|
||||||
function enablePopup(data) {
|
|
||||||
layui.layer.confirm(lang['ConfirmEnableUser'], {
|
|
||||||
title: lang['OperationConfirm'],
|
|
||||||
btn: [lang['Confirm'], lang['Cancel']]
|
|
||||||
}, function (index) {
|
|
||||||
operate(apiType.Enable, [data], index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* operate actions
|
|
||||||
* @param type {apiType} action type
|
|
||||||
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
|
|
||||||
* @param index popup index
|
|
||||||
*/
|
|
||||||
function operate(type, data, index) {
|
|
||||||
var url;
|
|
||||||
var extendMessage = '';
|
|
||||||
if (type === apiType.Remove) {
|
|
||||||
url = "/remove";
|
|
||||||
extendMessage = ', ' + lang['RemoveUser'] + lang['TakeTimeMakeEffective'];
|
|
||||||
} else if (type === apiType.Disable) {
|
|
||||||
url = "/disable";
|
|
||||||
extendMessage = ', ' + lang['RemoveUser'] + lang['TakeTimeMakeEffective'];
|
|
||||||
} else if (type === apiType.Enable) {
|
|
||||||
url = "/enable";
|
|
||||||
} else {
|
|
||||||
layer.layer.msg(lang['OperateError']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var loading = layui.layer.load();
|
|
||||||
$.post({
|
|
||||||
url: url,
|
|
||||||
type: 'post',
|
|
||||||
contentType: 'application/json',
|
|
||||||
data: JSON.stringify({
|
|
||||||
users: data
|
|
||||||
}),
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
reloadTable();
|
|
||||||
layui.layer.close(index);
|
|
||||||
layui.layer.msg(lang['OperateSuccess'] + extendMessage, function (index) {
|
|
||||||
layui.layer.close(index);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
errorMsg(result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
layui.layer.close(loading);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reload user table
|
|
||||||
*/
|
|
||||||
function reloadTable() {
|
|
||||||
var searchData = layui.form.val('searchForm');
|
|
||||||
layui.table.reloadData('tokenTable', {
|
|
||||||
where: searchData
|
|
||||||
}, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* show error message popup
|
|
||||||
* @param result
|
|
||||||
*/
|
|
||||||
function errorMsg(result) {
|
|
||||||
var reason = lang['Other Error'];
|
|
||||||
if (result.code === 1)
|
|
||||||
reason = lang['ParamError'];
|
|
||||||
else if (result.code === 2)
|
|
||||||
reason = lang['UserExist'];
|
|
||||||
else if (result.code === 3)
|
|
||||||
reason = lang['ParamError'];
|
|
||||||
else if (result.code === 4)
|
|
||||||
reason = lang['UserFormatError'];
|
|
||||||
else if (result.code === 5)
|
|
||||||
reason = lang['TokenFormatError'];
|
|
||||||
layui.layer.msg(lang['OperateFailed'] + ',' + reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* click event
|
|
||||||
*/
|
|
||||||
$(document).on('click.search', '#searchBtn', function () {
|
|
||||||
reloadTable();
|
|
||||||
return false;
|
|
||||||
}).on('click.reset', '#resetBtn', function () {
|
|
||||||
$('#searchForm')[0].reset();
|
|
||||||
reloadTable();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var langLoading = layui.layer.load()
|
|
||||||
$.getJSON('/lang').done(function (lang){
|
|
||||||
var html = layui.laytpl($('#userList').html()).render();
|
|
||||||
$('#layuiBody').html(html);
|
|
||||||
langLoaded(lang);
|
|
||||||
}).always(function () {
|
|
||||||
layui.layer.close(langLoading);
|
|
||||||
});
|
});
|
||||||
|
})(layui.$);
|
||||||
// $.ajax({
|
|
||||||
// url:'http://127.0.0.1:7500/api/serverinfo',
|
|
||||||
// dataType:'jsonp',
|
|
||||||
// success:function (result){
|
|
||||||
// console.log(result)
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
<link rel="stylesheet" href="./static/css/index.css">
|
<link rel="stylesheet" href="./static/css/index.css">
|
||||||
<link rel="stylesheet" href="./static/css/index-color.css">
|
<link rel="stylesheet" href="./static/css/index-color.css">
|
||||||
<script src="./static/layui/layui.js"></script>
|
<script src="./static/layui/layui.js"></script>
|
||||||
|
<script src="./static/js/echarts.min.js"></script>
|
||||||
|
<script src="./static/js/filesize.min.js"></script>
|
||||||
|
<script src="./static/js/index-server-info.js"></script>
|
||||||
|
<script src="./static/js/index-user-list.js"></script>
|
||||||
<script src="./static/js/index.js"></script>
|
<script src="./static/js/index.js"></script>
|
||||||
<style>
|
<style>
|
||||||
.layui-table-cell:empty::after {
|
.layui-table-cell:empty::after {
|
||||||
@@ -25,7 +29,7 @@
|
|||||||
|
|
||||||
.layui-layout-admin .layui-body {
|
.layui-layout-admin .layui-body {
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 15px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -36,82 +40,159 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="layui-side layui-bg-black">
|
<div class="layui-side layui-bg-black">
|
||||||
<div class="layui-side-scroll">
|
<div class="layui-side-scroll">
|
||||||
<ul class="layui-nav layui-nav-tree" lay-filter="leftNav">
|
<ul class="layui-nav layui-nav-tree" lay-filter="leftNav" id="leftNav">
|
||||||
<li class="layui-nav-item">
|
|
||||||
<a href="javascript:void(0)">服务器信息</a>
|
|
||||||
</li>
|
|
||||||
<li class="layui-nav-item layui-this">
|
<li class="layui-nav-item layui-this">
|
||||||
<a href="javascript:void(0)">用户信息</a>
|
<a href="javascript:void(0)" id="serverInfo">服务器信息</a>
|
||||||
|
</li>
|
||||||
|
<li class="layui-nav-item">
|
||||||
|
<a href="javascript:void(0)" id="userList">用户列表</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="layui-nav-item layui-nav-itemed">
|
<li class="layui-nav-item layui-nav-itemed">
|
||||||
<a class="" href="javascript:void(0)">代理信息</a>
|
<a class="" href="javascript:void(0)">代理列表</a>
|
||||||
<dl class="layui-nav-child">
|
<dl class="layui-nav-child">
|
||||||
<dd>
|
<dd>
|
||||||
<a href="javascript:void(0)">TCP</a>
|
<a href="javascript:void(0)" id="tcpList">TCP</a>
|
||||||
</dd>
|
</dd>
|
||||||
<dd>
|
<dd>
|
||||||
<a href="javascript:void(0)">UDP</a>
|
<a href="javascript:void(0)" id="udpList">UDP</a>
|
||||||
</dd>
|
</dd>
|
||||||
<dd>
|
<dd>
|
||||||
<a href="javascript:void(0)">HTTP</a>
|
<a href="javascript:void(0)" id="httpList">HTTP</a>
|
||||||
</dd>
|
</dd>
|
||||||
<dd>
|
<dd>
|
||||||
<a href="javascript:void(0)">HTTPS</a>
|
<a href="javascript:void(0)" id="httpsList">HTTPS</a>
|
||||||
</dd>
|
</dd>
|
||||||
<dd>
|
<dd>
|
||||||
<a href="javascript:void(0)">STCP</a>
|
<a href="javascript:void(0)" id="stcpList">STCP</a>
|
||||||
</dd>
|
</dd>
|
||||||
<dd>
|
<dd>
|
||||||
<a href="javascript:void(0)">SUDP</a>
|
<a href="javascript:void(0)" id="sudpList">SUDP</a>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-body" id="layuiBody">
|
<div class="layui-body" id="content">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/html" id="userList">
|
<script type="text/html" id="serverInfoTemplate">
|
||||||
<form class="layui-form layui-row layui-col-space16" id="searchForm" lay-filter="searchForm">
|
<section class="server-info">
|
||||||
<div class="layui-col-md3">
|
<div class="text-info">
|
||||||
<div class="layui-input-wrap">
|
<div class="text-row">
|
||||||
<div class="layui-input-prefix">
|
<div class="text-col">version</div>
|
||||||
<i class="layui-icon layui-icon-username"></i>
|
<div class="text-col">{{= d.version }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">bind_port</div>
|
||||||
|
<div class="text-col">{{= d.bind_port }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">vhost_http_port</div>
|
||||||
|
<div class="text-col">{{= d.vhost_http_port }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">vhost_https_port</div>
|
||||||
|
<div class="text-col">{{= d.vhost_https_port }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">tcpmux_httpconnect_port</div>
|
||||||
|
<div class="text-col">{{= d.tcpmux_httpconnect_port }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">kcp_bind_port</div>
|
||||||
|
<div class="text-col">{{= d.kcp_bind_port }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">quic_bind_port</div>
|
||||||
|
<div class="text-col">{{= d.quic_bind_port }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">subdomain_host</div>
|
||||||
|
<div class="text-col">{{= d.subdomain_host }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">max_pool_count</div>
|
||||||
|
<div class="text-col">{{= d.max_pool_count }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">max_ports_per_client</div>
|
||||||
|
<div class="text-col">{{= d.max_ports_per_client }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">heart_beat_timeout</div>
|
||||||
|
<div class="text-col">{{= d.heart_beat_timeout }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">allow_ports_str</div>
|
||||||
|
<div class="text-col">{{= d.allow_ports_str }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">tls_only</div>
|
||||||
|
<div class="text-col">{{= d.tls_only }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">cur_conns</div>
|
||||||
|
<div class="text-col">{{= d.cur_conns }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-row">
|
||||||
|
<div class="text-col">client_counts</div>
|
||||||
|
<div class="text-col">{{= d.client_counts }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-info">
|
||||||
|
<div class="chart-traffic">
|
||||||
|
<div id="trafficChart"></div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-count">
|
||||||
|
<div id="countChart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" id="userListTemplate">
|
||||||
|
<section class="user-list">
|
||||||
|
<form class="layui-form layui-row layui-col-space16" id="searchForm" lay-filter="searchForm">
|
||||||
|
<div class="layui-col-md3">
|
||||||
|
<div class="layui-input-wrap">
|
||||||
|
<div class="layui-input-prefix">
|
||||||
|
<i class="layui-icon layui-icon-username"></i>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="user" placeholder="${ .User }" class="layui-input" autocomplete="off"
|
||||||
|
lay-affix="clear">
|
||||||
</div>
|
</div>
|
||||||
<input type="text" name="user" placeholder="${ .User }" class="layui-input" autocomplete="off"
|
|
||||||
lay-affix="clear">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="layui-col-md3">
|
||||||
<div class="layui-col-md3">
|
<div class="layui-input-wrap">
|
||||||
<div class="layui-input-wrap">
|
<div class="layui-input-prefix">
|
||||||
<div class="layui-input-prefix">
|
<i class="layui-icon layui-icon-vercode"></i>
|
||||||
<i class="layui-icon layui-icon-vercode"></i>
|
</div>
|
||||||
|
<input type="text" name="token" placeholder="${ .Token }" class="layui-input" autocomplete="off"
|
||||||
|
lay-affix="clear">
|
||||||
</div>
|
</div>
|
||||||
<input type="text" name="token" placeholder="${ .Token }" class="layui-input" autocomplete="off"
|
|
||||||
lay-affix="clear">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="layui-col-md3">
|
||||||
<div class="layui-col-md3">
|
<div class="layui-input-wrap">
|
||||||
<div class="layui-input-wrap">
|
<div class="layui-input-prefix">
|
||||||
<div class="layui-input-prefix">
|
<i class="layui-icon layui-icon-note"></i>
|
||||||
<i class="layui-icon layui-icon-note"></i>
|
</div>
|
||||||
|
<input type="text" name="comment" placeholder="${ .Notes }" class="layui-input" autocomplete="off"
|
||||||
|
lay-affix="clear">
|
||||||
</div>
|
</div>
|
||||||
<input type="text" name="comment" placeholder="${ .Notes }" class="layui-input" autocomplete="off"
|
|
||||||
lay-affix="clear">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="layui-col-md3">
|
||||||
<div class="layui-col-md3">
|
<div class="layui-btn-container">
|
||||||
<div class="layui-btn-container">
|
<button class="layui-btn layui-btn-sm" id="searchBtn">${ .Search }</button>
|
||||||
<button class="layui-btn layui-btn-sm" id="searchBtn">${ .Search }</button>
|
<button class="layui-btn layui-btn-sm layui-btn-primary" type="reset" id="resetBtn">${ .Reset }
|
||||||
<button class="layui-btn layui-btn-sm layui-btn-primary" type="reset" id="resetBtn">${ .Reset }
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</form>
|
<table id="tokenTable" lay-filter="tokenTable"></table>
|
||||||
<table id="tokenTable" lay-filter="tokenTable"></table>
|
</section>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/html" id="toolbarTemplate">
|
<script type="text/html" id="toolbarTemplate">
|
||||||
|
|||||||
Reference in New Issue
Block a user