complete show all frp server api info

This commit is contained in:
杨黄林
2023-09-10 15:06:09 +08:00
parent 91c202c786
commit c95ef224d8
7 changed files with 535 additions and 369 deletions

View File

@@ -145,8 +145,8 @@ section.server-info .chart-info > .chart-count {
margin-top: 30px; margin-top: 30px;
} }
section.server-info .chart-info #trafficChart, section.server-info .chart-info #trafficPieChart,
section.server-info .chart-info #countChart { section.server-info .chart-info #countPieChart {
width: 400px; width: 400px;
height: 250px; height: 250px;
} }
@@ -168,3 +168,7 @@ section.server-info .chart-info #countChart {
.proxy-info .layui-col-xs6 .layui-row{ .proxy-info .layui-col-xs6 .layui-row{
padding: 0; padding: 0;
} }
#trafficBarChart{
height: 100%;
}

View File

@@ -34,25 +34,47 @@ var loadProxyInfo = (function ($) {
function renderProxyListTable(data, proxyType) { function renderProxyListTable(data, proxyType) {
var $section = $('#content > section'); var $section = $('#content > section');
var cols = [ var cols = [
{field: 'id', title: '', width: 30, templet: '#toggleProxyInfoArrowTemplate'}, {field: 'id', type: 'space', width: 60, align: 'center', templet: '#toggleProxyInfoArrowTemplate'},
{field: 'name', title: 'Name', sort: true}, {field: 'name', title: 'Name', sort: true},
{ {
field: 'port', title: 'Port', sort: true, templet: '<span>{{ d.conf.remote_port }}</span>' field: 'port', title: 'Port', width: '12%', sort: true, templet: '<span>{{ d.conf.remote_port }}</span>'
}, },
{field: 'cur_conns', title: 'Connections', sort: true}, {field: 'cur_conns', title: 'Connections', minWidth: 140, width: '12%', sort: true},
{ {
field: 'today_traffic_in', title: 'Traffic In', sort: true, templet: function (d) { field: 'today_traffic_in',
title: 'Traffic In',
minWidth: 140,
width: '12%',
sort: true,
templet: function (d) {
return size(d.today_traffic_in); return size(d.today_traffic_in);
} }
}, },
{ {
field: 'today_traffic_out', title: 'Traffic Out', sort: true, templet: function (d) { field: 'today_traffic_out',
title: 'Traffic Out',
minWidth: 140,
width: '12%',
sort: true,
templet: function (d) {
return size(d.today_traffic_out); return size(d.today_traffic_out);
} }
}, },
{field: 'client_version', title: 'ClientVersion', sort: true}, {field: 'client_version', title: 'ClientVersion', minWidth: 140, width: '12%', sort: true},
{field: 'status', title: 'Status', sort: true} {field: 'status', title: 'Status', width: '12%', sort: true}
]; ];
proxyType = proxyType.toLowerCase();
if (proxyType === 'http' || proxyType === 'https') {
data.forEach(function (temp) {
if (proxyType === 'http') {
temp.conf.remote_port = http_port;
} else if (proxyType === 'https') {
temp.conf.remote_port = https_port;
}
});
}
var proxyListTable = layui.table.render({ var proxyListTable = layui.table.render({
elem: '#proxyListTable', elem: '#proxyListTable',
height: $section.height(), height: $section.height(),
@@ -89,5 +111,113 @@ var loadProxyInfo = (function ($) {
} }
} }
/**
* load traffic statistics data
*/
function loadTrafficStatistics() {
var proxyName = $(this).closest('.layui-row').find('input').val();
var loading = layui.layer.load();
$.getJSON('/proxy/api/traffic/' + proxyName).done(function (result) {
if (result.success) {
renderTrafficChart(JSON.parse(result.data));
} else {
layui.layer.msg(result.message);
}
}).always(function () {
layui.layer.close(loading);
});
}
/**
* render traffic statistics chart
* @param data traffic data
*/
function renderTrafficChart(data) {
var html = layui.laytpl($('#trafficStaticTemplate').html()).render();
var dates = [];
var now = new Date();
for (var i = 0; i < data.traffic_in.length; i++) {
dates.push(now.getFullYear() + "/" + (now.getMonth() + 1) + "/" + now.getDate());
now.setDate(now.getDate() - 1);
}
layui.layer.open({
title: 'Traffic Statistics',
type: 1,
content: html,
area: ['800px', '400px'],
success: function () {
var chartDom = document.getElementById('trafficBarChart');
var chart = echarts.init(chartDom);
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
formatter: function (data) {
var html = ''
if (data.length > 0) {
html += data[0].name + '<br/>'
}
for (var v of data) {
var colorEl = '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + v.color + '"></span>'
html += colorEl + v.seriesName + ': ' + size(v.value) + '<br/>'
}
return html
},
},
legend: {
data: ['Traffic In', 'Traffic Out'],
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
data: dates.reverse(),
},
],
yAxis: [
{
type: 'value',
axisLabel: {
formatter: function (value) {
return size(value)
},
},
},
],
series: [
{
name: 'Traffic In',
type: 'bar',
data: data.traffic_in.reverse(),
},
{
name: 'Traffic Out',
type: 'bar',
data: data.traffic_out.reverse(),
},
],
};
option && chart.setOption(option);
}
});
}
/**
* document event
*/
(function bindDocumentEvent() {
$(document).on('click.trafficStatistics', '.traffic-statistics', function () {
loadTrafficStatistics.call(this);
});
})();
return loadProxyInfo; return loadProxyInfo;
})(layui.$); })(layui.$);

View File

@@ -17,6 +17,8 @@ var loadServerInfo = (function ($) {
if (result.success) { if (result.success) {
var data = JSON.parse(result.data); var data = JSON.parse(result.data);
data.proxy_counts = 0; data.proxy_counts = 0;
http_port = data.vhost_http_port;
https_port = data.vhost_https_port;
for (var proxy in data.proxy_type_count) { for (var proxy in data.proxy_type_count) {
data.proxy_counts = data.proxy_counts + data.proxy_type_count[proxy]; data.proxy_counts = data.proxy_counts + data.proxy_type_count[proxy];
} }
@@ -46,11 +48,12 @@ var loadServerInfo = (function ($) {
* @param data traffic data * @param data traffic data
*/ */
function renderTrafficChart(data) { function renderTrafficChart(data) {
var chartLegend = ['total_traffic_in', 'total_traffic_out'];
var chartData = [ var chartData = [
{value: data.total_traffic_in, name: 'Traffic In'}, {value: data.total_traffic_in, name: 'Traffic In'},
{value: data.total_traffic_out, name: 'Traffic Out'} {value: data.total_traffic_out, name: 'Traffic Out'}
]; ];
var chartDom = document.getElementById('trafficChart'); var chartDom = document.getElementById('trafficPieChart');
var chart = echarts.init(chartDom); var chart = echarts.init(chartDom);
var option = { var option = {
title: { title: {
@@ -67,7 +70,7 @@ var loadServerInfo = (function ($) {
legend: { legend: {
orient: 'vertical', orient: 'vertical',
left: 'left', left: 'left',
data: ['total_traffic_in', 'total_traffic_out'], data: chartLegend,
}, },
series: [ series: [
{ {
@@ -95,7 +98,7 @@ var loadServerInfo = (function ($) {
*/ */
function renderCountChart(data) { function renderCountChart(data) {
var proxies = data.proxy_type_count; var proxies = data.proxy_type_count;
var charLegend = []; var chartLegend = [];
var chartData = []; var chartData = [];
for (var type in proxies) { for (var type in proxies) {
@@ -103,11 +106,10 @@ var loadServerInfo = (function ($) {
name: type.toUpperCase(), name: type.toUpperCase(),
value: proxies[type] value: proxies[type]
}; };
charLegend.push(type); chartLegend.push(type);
chartData.push(temp); chartData.push(temp);
} }
var chartDom = document.getElementById('countPieChart');
var chartDom = document.getElementById('countChart');
var chart = echarts.init(chartDom); var chart = echarts.init(chartDom);
var option = { var option = {
title: { title: {
@@ -118,13 +120,13 @@ var loadServerInfo = (function ($) {
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
formatter: function (v) { formatter: function (v) {
return v.value; return v.value + ' (' + v.percent + '%)';
}, }
}, },
legend: { legend: {
orient: 'vertical', orient: 'vertical',
left: 'left', left: 'left',
data: charLegend, data: chartLegend,
}, },
series: [ series: [
{ {

View File

@@ -1,4 +1,91 @@
var loadUserList = (function ($) { var loadUserList = (function ($) {
var i18n = {};
var apiType = {
Remove: 1,
Enable: 2,
Disable: 3
};
var verifyRules = {
user: function (value, item) {
var result = verifyUser(value);
if (!result.valid) {
return i18n['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 i18n['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 i18n['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 i18n['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 i18n['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 i18n['SubdomainsInvalid'];
}
if (item != null) {
if (typeof item === "function") {
item && item(result.trim);
} else {
$(item).val(result.trim);
}
}
}
};
/** /**
* verify user value * verify user value
* @param username * @param username
@@ -136,114 +223,32 @@ var loadUserList = (function ($) {
}; };
} }
/**
* set verify rule of layui.form
*/
(function setFormVerifyRule() {
layui.form.set({
verIncludeRequired: true,
verify: verifyRules
});
})();
/** /**
* load i18n language * load i18n language
* @param lang {{}} language json * @param lang {{}} language json
* @param title page title * @param title page title
*/ */
function loadUserList(lang, title) { function loadUserList(lang, title) {
i18n = lang;
$("#title").text(title); $("#title").text(title);
var html = layui.laytpl($('#userListTemplate').html()).render(); var html = layui.laytpl($('#userListTemplate').html()).render();
$('#content').html(html); $('#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
});
var $section = $('#content > section'); var $section = $('#content > section');
layui.table.render({ layui.table.render({
elem: '#tokenTable', elem: '#tokenTable',
height: $section.height() - $('#searchForm').height() + 8, height: $section.height() - $('#searchForm').height() + 8,
text: {none: lang['EmptyData']}, text: {none: i18n['EmptyData']},
url: '/tokens', url: '/tokens',
method: 'get', method: 'get',
where: {}, where: {},
@@ -254,35 +259,30 @@ var loadUserList = (function ($) {
defaultToolbar: false, defaultToolbar: false,
cols: [[ cols: [[
{type: 'checkbox'}, {type: 'checkbox'},
{field: 'user', title: lang['User'], width: 150, sort: true}, {field: 'user', title: i18n['User'], width: 150, sort: true},
{field: 'token', title: lang['Token'], width: 200, sort: true, edit: true}, {field: 'token', title: i18n['Token'], width: 200, sort: true, edit: true},
{field: 'comment', title: lang['Notes'], sort: true, edit: 'textarea'}, {field: 'comment', title: i18n['Notes'], sort: true, edit: 'textarea'},
{field: 'ports', title: lang['AllowedPorts'], sort: true, edit: 'textarea'}, {field: 'ports', title: i18n['AllowedPorts'], sort: true, edit: 'textarea'},
{field: 'domains', title: lang['AllowedDomains'], sort: true, edit: 'textarea'}, {field: 'domains', title: i18n['AllowedDomains'], sort: true, edit: 'textarea'},
{field: 'subdomains', title: lang['AllowedSubdomains'], sort: true, edit: 'textarea'}, {field: 'subdomains', title: i18n['AllowedSubdomains'], sort: true, edit: 'textarea'},
{ {
field: 'status', field: 'status',
title: lang['Status'], title: i18n['Status'],
width: 100, width: 100,
templet: '<span>{{d.status? "' + lang['Enable'] + '":"' + lang['Disable'] + '"}}</span>', templet: '<span>{{d.status? "' + i18n['Enable'] + '":"' + i18n['Disable'] + '"}}</span>',
sort: true sort: true
}, },
{title: lang['Operation'], width: 150, toolbar: '#userListOperationTemplate'} {title: i18n['Operation'], width: 150, toolbar: '#userListOperationTemplate'}
]] ]]
}); });
/** bindFormEvent();
* 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);
}
/**
* bind event of layui.form
*/
function bindFormEvent() {
layui.table.on('edit(tokenTable)', function (obj) { layui.table.on('edit(tokenTable)', function (obj) {
var field = obj.field; var field = obj.field;
var value = obj.value; var value = obj.value;
@@ -368,6 +368,7 @@ var loadUserList = (function ($) {
break break
} }
}); });
layui.table.on('tool(tokenTable)', function (obj) { layui.table.on('tool(tokenTable)', function (obj) {
var data = obj.data; var data = obj.data;
switch (obj.event) { switch (obj.event) {
@@ -382,253 +383,267 @@ var loadUserList = (function ($) {
break break
} }
}); });
}
/** /**
* add user popup * update layui table data
*/ * @param obj table update obj
function addPopup() { * @param field update field
layui.layer.open({ * @param trim new value
type: 1, */
title: lang['NewUser'], function updateTableField(obj, field, trim) {
area: ['500px'], var newData = {};
content: layui.laytpl(document.getElementById('addUserTemplate').innerHTML).render(), newData[field] = trim;
btn: [lang['Confirm'], lang['Cancel']], obj.update(newData);
btn1: function (index) { }
if (layui.form.validate('#addUserForm')) {
add(layui.form.val('addUserForm'), index); /**
} * add user popup
}, */
btn2: function (index) { function addPopup() {
layui.layer.open({
type: 1,
title: i18n['NewUser'],
area: ['500px'],
content: layui.laytpl(document.getElementById('addUserTemplate').innerHTML).render(),
btn: [i18n['Confirm'], i18n['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.close(index);
} layui.layer.msg(i18n['OperateSuccess'], function (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.close(index);
layui.layer.msg(lang['OperateSuccess'], function (index) { });
layui.layer.close(index); } else {
}); errorMsg(result);
} else {
errorMsg(result);
}
},
complete: function () {
layui.layer.close(loading);
} }
}); },
} complete: function () {
layui.layer.close(loading);
}
});
}
/** /**
* update user action * update user action
* @param before {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} data before update * @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 * @param after {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} data after update
*/ */
function update(before, after) { function update(before, after) {
var loading = layui.layer.load(); var loading = layui.layer.load();
$.ajax({ $.ajax({
url: '/update', url: '/update',
type: 'post', type: 'post',
contentType: 'application/json', contentType: 'application/json',
data: JSON.stringify({ data: JSON.stringify({
before: before, before: before,
after: after, after: after,
}), }),
success: function (result) { success: function (result) {
if (result.success) { if (result.success) {
layui.layer.msg(lang['OperateSuccess']); layui.layer.msg(i18n['OperateSuccess']);
} else { } else {
errorMsg(result); errorMsg(result);
}
},
complete: function () {
layui.layer.close(loading);
} }
}); },
} 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 * batch remove user popup
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list * @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
*/ */
function batchDisablePopup(data) { function batchRemovePopup(data) {
if (data.length === 0) { if (data.length === 0) {
layui.layer.msg(lang['ShouldCheckUser']); layui.layer.msg(i18n['ShouldCheckUser']);
return; return;
}
layui.layer.confirm(lang['ConfirmDisableUser'], {
title: lang['OperationConfirm'],
btn: [lang['Confirm'], lang['Cancel']]
}, function (index) {
operate(apiType.Disable, data, index);
});
} }
layui.layer.confirm(i18n['ConfirmRemoveUser'], {
title: i18n['OperationConfirm'],
btn: [i18n['Confirm'], i18n['Cancel']]
}, function (index) {
operate(apiType.Remove, data, index);
});
}
/** /**
* batch enable user popup * batch disable user popup
* @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list * @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
*/ */
function batchEnablePopup(data) { function batchDisablePopup(data) {
if (data.length === 0) { if (data.length === 0) {
layui.layer.msg(lang['ShouldCheckUser']); layui.layer.msg(i18n['ShouldCheckUser']);
return; return;
}
layui.layer.confirm(lang['ConfirmEnableUser'], {
title: lang['OperationConfirm'],
btn: [lang['Confirm'], lang['Cancel']]
}, function (index) {
operate(apiType.Enable, data, index);
});
} }
layui.layer.confirm(i18n['ConfirmDisableUser'], {
title: i18n['OperationConfirm'],
btn: [i18n['Confirm'], i18n['Cancel']]
}, function (index) {
operate(apiType.Disable, data, index);
});
}
/** /**
* remove one user popup * batch enable user popup
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data * @param data {[{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}]} user data list
*/ */
function removePopup(data) { function batchEnablePopup(data) {
layui.layer.confirm(lang['ConfirmRemoveUser'], { if (data.length === 0) {
title: lang['OperationConfirm'], layui.layer.msg(i18n['ShouldCheckUser']);
btn: [lang['Confirm'], lang['Cancel']] return;
}, function (index) {
operate(apiType.Remove, [data], index);
});
} }
layui.layer.confirm(i18n['ConfirmEnableUser'], {
title: i18n['OperationConfirm'],
btn: [i18n['Confirm'], i18n['Cancel']]
}, function (index) {
operate(apiType.Enable, data, index);
});
}
/** /**
* disable one user popup * remove one user popup
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data * @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data
*/ */
function disablePopup(data) { function removePopup(data) {
layui.layer.confirm(lang['ConfirmDisableUser'], { layui.layer.confirm(i18n['ConfirmRemoveUser'], {
title: lang['OperationConfirm'], title: i18n['OperationConfirm'],
btn: [lang['Confirm'], lang['Cancel']] btn: [i18n['Confirm'], i18n['Cancel']]
}, function (index) { }, function (index) {
operate(apiType.Disable, [data], 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(i18n['ConfirmDisableUser'], {
title: i18n['OperationConfirm'],
btn: [i18n['Confirm'], i18n['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(i18n['ConfirmEnableUser'], {
title: i18n['OperationConfirm'],
btn: [i18n['Confirm'], i18n['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 = ', ' + i18n['RemoveUser'] + i18n['TakeTimeMakeEffective'];
} else if (type === apiType.Disable) {
url = "/disable";
extendMessage = ', ' + i18n['RemoveUser'] + i18n['TakeTimeMakeEffective'];
} else if (type === apiType.Enable) {
url = "/enable";
} else {
layer.layer.msg(i18n['OperateError']);
return;
} }
var loading = layui.layer.load();
/** $.post({
* enable one user popup url: url,
* @param data {{user:string, token:string, comment:string, status:boolean, ports:string, domains:string, subdomains:string}} user data type: 'post',
*/ contentType: 'application/json',
function enablePopup(data) { data: JSON.stringify({
layui.layer.confirm(lang['ConfirmEnableUser'], { users: data
title: lang['OperationConfirm'], }),
btn: [lang['Confirm'], lang['Cancel']] success: function (result) {
}, function (index) { if (result.success) {
operate(apiType.Enable, [data], index); reloadTable();
}); layui.layer.close(index);
} layui.layer.msg(i18n['OperateSuccess'] + extendMessage, function (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.close(index);
layui.layer.msg(lang['OperateSuccess'] + extendMessage, function (index) { });
layui.layer.close(index); } else {
}); errorMsg(result);
} else {
errorMsg(result);
}
},
complete: function () {
layui.layer.close(loading);
} }
}); },
} complete: function () {
layui.layer.close(loading);
}
});
}
/** /**
* reload user table * reload user table
*/ */
function reloadTable() { function reloadTable() {
var searchData = layui.form.val('searchForm'); var searchData = layui.form.val('searchForm');
layui.table.reloadData('tokenTable', { layui.table.reloadData('tokenTable', {
where: searchData where: searchData
}, true) }, true)
} }
/** /**
* show error message popup * show error message popup
* @param result * @param result
*/ */
function errorMsg(result) { function errorMsg(result) {
var reason = lang['Other Error']; var reason = i18n['Other Error'];
if (result.code === 1) if (result.code === 1)
reason = lang['ParamError']; reason = i18n['ParamError'];
else if (result.code === 2) else if (result.code === 2)
reason = lang['UserExist']; reason = i18n['UserExist'];
else if (result.code === 3) else if (result.code === 3)
reason = lang['ParamError']; reason = i18n['ParamError'];
else if (result.code === 4) else if (result.code === 4)
reason = lang['UserFormatError']; reason = i18n['UserFormatError'];
else if (result.code === 5) else if (result.code === 5)
reason = lang['TokenFormatError']; reason = i18n['TokenFormatError'];
layui.layer.msg(lang['OperateFailed'] + ',' + reason) layui.layer.msg(i18n['OperateFailed'] + ',' + reason)
} }
/** /**
* click event * document event
*/ */
(function bindDocumentEvent() {
$(document).on('click.search', '#searchBtn', function () { $(document).on('click.search', '#searchBtn', function () {
reloadTable(); reloadTable();
return false; return false;
@@ -637,7 +652,7 @@ var loadUserList = (function ($) {
reloadTable(); reloadTable();
return false; return false;
}); });
} })();
return loadUserList; return loadUserList;
})(layui.$) })(layui.$)

View File

@@ -1,3 +1,4 @@
var http_port, https_port;
(function ($) { (function ($) {
$(function () { $(function () {
var langLoading = layui.layer.load() var langLoading = layui.layer.load()

View File

@@ -69,9 +69,7 @@
</ul> </ul>
</div> </div>
</div> </div>
<div class="layui-body" id="content"> <div class="layui-body" id="content"></div>
</div>
</div> </div>
<!--服务器信息模板--> <!--服务器信息模板-->
@@ -145,10 +143,10 @@
</div> </div>
<div class="chart-info"> <div class="chart-info">
<div class="chart-traffic"> <div class="chart-traffic">
<div id="trafficChart"></div> <div id="trafficPieChart"></div>
</div> </div>
<div class="chart-count"> <div class="chart-count">
<div id="countChart"></div> <div id="countPieChart"></div>
</div> </div>
</div> </div>
</section> </section>
@@ -285,6 +283,16 @@
<tr class="layui-hide proxy-info" id="childTr_{{= d.index }}"> <tr class="layui-hide proxy-info" id="childTr_{{= d.index }}">
<td></td> <td></td>
<td colspan="{{= d.colspan }}"> <td colspan="{{= d.colspan }}">
<div class="layui-row">
<div class="layui-col-xs12">
<div class="layui-row">
<div class="layui-col-md12">
<input type="hidden" value="{{= d.data.conf.name }}">
<div class="layui-btn traffic-statistics">Traffic Statistics</div>
</div>
</div>
</div>
</div>
{{# if (d.proxyType === 'http' || d.proxyType === 'https') { }} {{# if (d.proxyType === 'http' || d.proxyType === 'https') { }}
<div class="layui-row"> <div class="layui-row">
<div class="layui-col-xs6"> <div class="layui-col-xs6">
@@ -411,5 +419,10 @@
</td> </td>
</tr> </tr>
</script> </script>
<!--代理列表-每个代理的最近7天流量统计模板-->
<script type="text/html" id="trafficStaticTemplate">
<div id="trafficBarChart"></div>
</script>
</body> </body>
</html> </html>

View File

@@ -1,18 +1,19 @@
; basic options ; basic options
[common] [common]
; frps config info ; frps panel config info
plugin_addr = 127.0.0.1 plugin_addr = 127.0.0.1
plugin_port = 7200 plugin_port = 7200
admin_user = admin admin_user = admin
admin_pwd = admin admin_pwd = admin
; frp dashboard config info ; frp dashboard info
dashboard_addr = frp.yanghuanglin.com dashboard_addr = 127.0.0.1
dashboard_port = 7500 dashboard_port = 7500
dashboard_user = admin dashboard_user = admin
dashboard_pwd = 19910621 dashboard_pwd = admin
; user tokens ; user tokens
[users] [users]
user1 = token1
; user been disabled ; user been disabled
[disabled] [disabled]