show proxy detail

This commit is contained in:
杨黄林
2023-09-10 01:02:43 +08:00
parent f7ccc9c386
commit 134069df34
8 changed files with 413 additions and 64 deletions

View File

@@ -1,6 +1,5 @@
header { .layui-bg-blue {
background-color: #58b7ff; background-color: #58b7ff !important;
color: #fff;
} }
.layui-btn { .layui-btn {
@@ -64,9 +63,25 @@ header {
border-color: #79bbff; border-color: #79bbff;
} }
.layui-nav-tree .layui-nav-child dd.layui-this,
.layui-nav-tree .layui-nav-child dd.layui-this a,
.layui-nav-tree .layui-this,
.layui-nav-tree .layui-this > a,
.layui-nav-tree .layui-this > a:hover {
background-color: #409eff;
}
.layui-nav-tree .layui-nav-bar {
background-color: #409eff;
}
.proxy-expand .layui-row .layui-row > div:first-child {
color: #99a9bf;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
header { .layui-bg-blue {
background-color: #395c74; background-color: #395c74 !important;
} }
.layui-btn { .layui-btn {
@@ -125,4 +140,16 @@ header {
.layui-table-cell-c:hover { .layui-table-cell-c:hover {
border-color: #5f5f60; border-color: #5f5f60;
} }
.layui-nav-tree .layui-nav-child dd.layui-this,
.layui-nav-tree .layui-nav-child dd.layui-this a,
.layui-nav-tree .layui-this,
.layui-nav-tree .layui-this > a,
.layui-nav-tree .layui-this > a:hover {
background-color: #4f80a1;
}
.layui-nav-tree .layui-nav-bar {
background-color: #4f80a1;
}
} }

View File

@@ -9,8 +9,8 @@ section {
right: 0; right: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
padding: 15px 15px 0 15px; padding: 15px;
overflow: auto; overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -19,9 +19,21 @@ section {
font-size: 16px; font-size: 16px;
} }
.layui-layout-admin .layui-side {
width: 225px !important;
}
.layui-side-scroll {
width: 245px !important;
}
.layui-logo {
width: 225px !important;
}
.layui-title { .layui-title {
position: absolute; position: absolute;
left: 200px; left: 225px !important;
right: 0; right: 0;
top: 0; top: 0;
height: 100%; height: 100%;
@@ -30,6 +42,14 @@ section {
box-sizing: border-box; box-sizing: border-box;
} }
.layui-nav.layui-nav-tree {
width: 225px !important;
}
.layui-body {
left: 225px;
}
#searchForm input { #searchForm input {
height: 30px; height: 30px;
line-height: 28px; line-height: 28px;
@@ -92,6 +112,10 @@ section.server-info .chart-info {
flex: 1; flex: 1;
} }
section.server-info .text-info{
padding: 0 20px;
}
section.server-info .text-row { section.server-info .text-row {
display: flex; display: flex;
font-size: 14px; font-size: 14px;
@@ -126,3 +150,21 @@ section.server-info .chart-info #countChart {
width: 400px; width: 400px;
height: 250px; height: 250px;
} }
.toggle-proxy-info-arrow{
display: inline-block;
transition-duration: 0.2s;
}
.toggle-proxy-info-arrow.open{
transform: rotate(90deg);
}
.proxy-info .layui-row {
font-size: 14px !important;
padding: 10px;
}
.proxy-info .layui-col-xs6 .layui-row{
padding: 0;
}

View File

@@ -0,0 +1,95 @@
var loadProxyInfo = (function ($) {
var size = filesize.partial({base: 2, standard: "jedec"});
var i18n = {};
/**
* get proxy info
* @param lang {{}} language json
* @param title page title
* @param proxyType proxy type
*/
function loadProxyInfo(lang, title, proxyType) {
i18n = lang;
$("#title").text(title);
$('#content').empty();
var loading = layui.layer.load();
$.getJSON('/proxy/api/proxy/' + proxyType).done(function (result) {
if (result.success) {
$('#content').html($('#proxyListTableTemplate').html());
renderProxyListTable(JSON.parse(result.data)['proxies'], proxyType);
} else {
layui.layer.msg(result.message);
}
}).always(function () {
layui.layer.close(loading);
});
}
/**
* render proxy list table
* @param data proxy data
* @param proxyType proxy type
*/
function renderProxyListTable(data, proxyType) {
data = data.concat(data)
data = data.concat(data)
var $section = $('#content > section');
var cols = [
{field: 'id', title: '', width: 30, templet: '#toggleProxyInfoArrowTemplate'},
{field: 'name', title: 'Name', sort: true},
{
field: 'port', title: 'Port', sort: true, templet: '<span>{{ d.conf.remote_port }}</span>'
},
{field: 'cur_conns', title: 'Connections', sort: true},
{
field: 'today_traffic_in', title: 'Traffic In', sort: true, templet: function (d) {
return size(d.today_traffic_in);
}
},
{
field: 'today_traffic_out', title: 'Traffic Out', sort: true, templet: function (d) {
return size(d.today_traffic_out);
}
},
{field: 'client_version', title: 'ClientVersion', sort: true},
{field: 'status', title: 'Status', sort: true}
];
var proxyListTable = layui.table.render({
elem: '#proxyListTable',
height: $section.height(),
text: {none: i18n['EmptyData']},
cols: [cols],
page: navigator.language.indexOf("zh") !== -1,
data: data,
done: function (res, curr, count, origin) {
//向每一行tr后面追加显示子table的tr
var $tr = $('.layui-table-view[lay-id=' + this.id + '] tbody tr');
var expandTrTemplateHtml = $('#expandTrTemplate').html();
for (var i = 0; i < $tr.length; i++) {
var html = layui.laytpl(expandTrTemplateHtml).render({
index: i,
colspan: cols.length - 1,
proxyType: proxyType,
data: res.data[i]
});
$($tr[i]).after(html);
}
}
});
layui.table.on('tool(proxyListTable)', function (obj) {
var index = obj.index;
$(this).toggleClass('open');
var open = $(this).hasClass('open');
$('#childTr_' + index).toggleClass('layui-hide', !open);
proxyListTable.resize();
});
window.onresize = function () {
proxyListTable.resize();
}
}
return loadProxyInfo;
})(layui.$);

View File

@@ -1,19 +1,26 @@
var loadServerInfo = (function ($) { var loadServerInfo = (function ($) {
var size = filesize.partial({base: 2, standard: "jedec"}); var size = filesize.partial({base: 2, standard: "jedec"});
var i18n = {};
/** /**
* get server info * get server info
* @param lang {{}} language json * @param lang {{}} language json
* @param title page title
*/ */
function loadServerInfo(lang, title) { function loadServerInfo(lang, title) {
console.log(title) i18n = lang;
$("#title").text(title); $("#title").text(title);
$('#content').empty(); $('#content').empty();
var loading = layui.layer.load(); var loading = layui.layer.load();
$.getJSON('/proxy/api/serverinfo').done(function (result) { $.getJSON('/proxy/api/serverinfo').done(function (result) {
if (result.success) { if (result.success) {
renderServerInfo(JSON.parse(result.data)); var data = JSON.parse(result.data);
data.proxy_counts = 0;
for (var proxy in data.proxy_type_count) {
data.proxy_counts = data.proxy_counts + data.proxy_type_count[proxy];
}
renderServerInfo(data);
} else { } else {
layui.layer.msg(result.message); layui.layer.msg(result.message);
} }
@@ -22,6 +29,10 @@ var loadServerInfo = (function ($) {
}); });
} }
/**
* render server info page
* @param data server info data
*/
function renderServerInfo(data) { function renderServerInfo(data) {
var html = layui.laytpl($('#serverInfoTemplate').html()).render(data); var html = layui.laytpl($('#serverInfoTemplate').html()).render(data);
$('#content').html(html); $('#content').html(html);
@@ -30,10 +41,14 @@ var loadServerInfo = (function ($) {
renderCountChart(data); renderCountChart(data);
} }
/**
* render traffic chart with echarts
* @param data traffic data
*/
function renderTrafficChart(data) { function renderTrafficChart(data) {
var chartData = [ var chartData = [
{value: data.total_traffic_in, name: 'total_traffic_in'}, {value: data.total_traffic_in, name: 'Traffic In'},
{value: data.total_traffic_out, name: 'total_traffic_out'} {value: data.total_traffic_out, name: 'Traffic Out'}
]; ];
var chartDom = document.getElementById('trafficChart'); var chartDom = document.getElementById('trafficChart');
var chart = echarts.init(chartDom); var chart = echarts.init(chartDom);
@@ -74,6 +89,10 @@ var loadServerInfo = (function ($) {
option && chart.setOption(option); option && chart.setOption(option);
} }
/**
* render proxy count chat with echarts
* @param data proxy count data
*/
function renderCountChart(data) { function renderCountChart(data) {
var proxies = data.proxy_type_count; var proxies = data.proxy_type_count;
var charLegend = []; var charLegend = [];
@@ -81,7 +100,7 @@ var loadServerInfo = (function ($) {
for (var type in proxies) { for (var type in proxies) {
var temp = { var temp = {
name: type, name: type.toUpperCase(),
value: proxies[type] value: proxies[type]
}; };
charLegend.push(type); charLegend.push(type);

View File

@@ -139,6 +139,7 @@ var loadUserList = (function ($) {
/** /**
* load i18n language * load i18n language
* @param lang {{}} language json * @param lang {{}} language json
* @param title page title
*/ */
function loadUserList(lang, title) { function loadUserList(lang, title) {
$("#title").text(title); $("#title").text(title);
@@ -245,8 +246,8 @@ var loadUserList = (function ($) {
where: {}, where: {},
dataType: 'json', dataType: 'json',
editTrigger: 'dblclick', editTrigger: 'dblclick',
page: navigator.language.indexOf("zh") === 0, page: navigator.language.indexOf("zh") !== -1,
toolbar: '#toolbarTemplate', toolbar: '#userListToolbarTemplate',
defaultToolbar: false, defaultToolbar: false,
text: {none: lang['EmptyData']}, text: {none: lang['EmptyData']},
cols: [[ cols: [[
@@ -264,7 +265,7 @@ var loadUserList = (function ($) {
templet: '<span>{{d.status? "' + lang['Enable'] + '":"' + lang['Disable'] + '"}}</span>', templet: '<span>{{d.status? "' + lang['Enable'] + '":"' + lang['Disable'] + '"}}</span>',
sort: true sort: true
}, },
{title: lang['Operation'], width: 150, toolbar: '#operationTemplate'} {title: lang['Operation'], width: 150, toolbar: '#userListOperationTemplate'}
]] ]]
}); });
@@ -388,7 +389,7 @@ var loadUserList = (function ($) {
type: 1, type: 1,
title: lang['NewUser'], title: lang['NewUser'],
area: ['500px'], area: ['500px'],
content: layui.laytpl(document.getElementById('addTemplate').innerHTML).render(), content: layui.laytpl(document.getElementById('addUserTemplate').innerHTML).render(),
btn: [lang['Confirm'], lang['Cancel']], btn: [lang['Confirm'], lang['Cancel']],
btn1: function (index) { btn1: function (index) {
if (layui.form.validate('#addUserForm')) { if (layui.form.validate('#addUserForm')) {

View File

@@ -3,10 +3,17 @@
var langLoading = layui.layer.load() var langLoading = layui.layer.load()
$.getJSON('/lang').done(function (lang) { $.getJSON('/lang').done(function (lang) {
layui.element.on('nav(leftNav)', function (elem) { layui.element.on('nav(leftNav)', function (elem) {
if (elem.attr('id') === 'serverInfo') { var id = elem.attr('id');
loadServerInfo(lang, elem.text().trim()); var title = elem.text();
} else if (elem.attr('id') === 'userList') { if (id === 'serverInfo') {
loadUserList(lang, elem.text().trim()); loadServerInfo(lang, title.trim());
} else if (id === 'userList') {
loadUserList(lang, title.trim());
} else if (elem.closest('.layui-nav-item').attr('id') === 'proxyList') {
if (id != null && id.trim() !== '') {
var suffix = elem.closest('.layui-nav-item').children('a').text().trim();
loadProxyInfo(lang, title + " " + suffix, id);
}
} }
}); });

View File

@@ -11,9 +11,10 @@
<script src="./static/lib/filesize.min.js"></script> <script src="./static/lib/filesize.min.js"></script>
<script src="./static/js/index-server-info.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-user-list.js"></script>
<script src="./static/js/index-proxy-list.js"></script>
<script src="./static/js/index.js"></script> <script src="./static/js/index.js"></script>
<style> <style>
.layui-table-cell:empty::after { section.user-list .layui-table-cell:empty::after {
content: '${ .NotLimit }'; content: '${ .NotLimit }';
} }
@@ -29,7 +30,7 @@
</head> </head>
<body> <body>
<div class="layui-layout layui-layout-admin"> <div class="layui-layout layui-layout-admin">
<div class="layui-header"> <div class="layui-header layui-bg-blue">
<div class="layui-logo layui-hide-xs layui-bg-black">${ .FrpsMultiuser }</div> <div class="layui-logo layui-hide-xs layui-bg-black">${ .FrpsMultiuser }</div>
<div class="layui-title" id="title"></div> <div class="layui-title" id="title"></div>
</div> </div>
@@ -42,26 +43,26 @@
<li class="layui-nav-item"> <li class="layui-nav-item">
<a href="javascript:void(0)" id="userList">用户列表</a> <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" id="proxyList">
<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)" id="tcpList">TCP</a> <a href="javascript:void(0)" id="tcp">TCP</a>
</dd> </dd>
<dd> <dd>
<a href="javascript:void(0)" id="udpList">UDP</a> <a href="javascript:void(0)" id="udp">UDP</a>
</dd> </dd>
<dd> <dd>
<a href="javascript:void(0)" id="httpList">HTTP</a> <a href="javascript:void(0)" id="http">HTTP</a>
</dd> </dd>
<dd> <dd>
<a href="javascript:void(0)" id="httpsList">HTTPS</a> <a href="javascript:void(0)" id="https">HTTPS</a>
</dd> </dd>
<dd> <dd>
<a href="javascript:void(0)" id="stcpList">STCP</a> <a href="javascript:void(0)" id="stcp">STCP</a>
</dd> </dd>
<dd> <dd>
<a href="javascript:void(0)" id="sudpList">SUDP</a> <a href="javascript:void(0)" id="sudp">SUDP</a>
</dd> </dd>
</dl> </dl>
</li> </li>
@@ -73,69 +74,74 @@
</div> </div>
</div> </div>
<!--服务器信息模板-->
<script type="text/html" id="serverInfoTemplate"> <script type="text/html" id="serverInfoTemplate">
<section class="server-info"> <section class="server-info">
<div class="text-info"> <div class="text-info">
<div class="text-row"> <div class="text-row">
<div class="text-col">version</div> <div class="text-col">Version</div>
<div class="text-col">{{= d.version }}</div> <div class="text-col">{{= d.version }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">bind_port</div> <div class="text-col">BindPort</div>
<div class="text-col">{{= d.bind_port }}</div> <div class="text-col">{{= d.bind_port }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">vhost_http_port</div> <div class="text-col">KCP Bind 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 class="text-col">{{= d.kcp_bind_port }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">quic_bind_port</div> <div class="text-col">QUIC Bind Port</div>
<div class="text-col">{{= d.quic_bind_port }}</div> <div class="text-col">{{= d.quic_bind_port }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">subdomain_host</div> <div class="text-col">Http Port</div>
<div class="text-col">{{= d.vhost_http_port }}</div>
</div>
<div class="text-row">
<div class="text-col">Https Port</div>
<div class="text-col">{{= d.vhost_https_port }}</div>
</div>
<div class="text-row">
<div class="text-col">TCPMUX Port</div>
<div class="text-col">{{= d.tcpmux_httpconnect_port }}</div>
</div>
<div class="text-row">
<div class="text-col">Subdomain Host</div>
<div class="text-col">{{= d.subdomain_host }}</div> <div class="text-col">{{= d.subdomain_host }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">max_pool_count</div> <div class="text-col">Max PoolCount</div>
<div class="text-col">{{= d.max_pool_count }}</div> <div class="text-col">{{= d.max_pool_count }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">max_ports_per_client</div> <div class="text-col">Max Ports Per Client</div>
<div class="text-col">{{= d.max_ports_per_client }}</div> <div class="text-col">{{= d.max_ports_per_client }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">heart_beat_timeout</div> <div class="text-col">HeartBeat Timeout</div>
<div class="text-col">{{= d.heart_beat_timeout }}</div> <div class="text-col">{{= d.heart_beat_timeout }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">allow_ports_str</div> <div class="text-col">Allow Ports</div>
<div class="text-col">{{= d.allow_ports_str }}</div> <div class="text-col">{{= d.allow_ports_str || 'Not limit' }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">tls_only</div> <div class="text-col">TLS Only</div>
<div class="text-col">{{= d.tls_only }}</div> <div class="text-col">{{= d.tls_only || 'No' }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">cur_conns</div> <div class="text-col">Current Connections</div>
<div class="text-col">{{= d.cur_conns }}</div> <div class="text-col">{{= d.cur_conns }}</div>
</div> </div>
<div class="text-row"> <div class="text-row">
<div class="text-col">client_counts</div> <div class="text-col">Client Counts</div>
<div class="text-col">{{= d.client_counts }}</div> <div class="text-col">{{= d.client_counts }}</div>
</div> </div>
<div class="text-row">
<div class="text-col">Proxy Counts</div>
<div class="text-col">{{= d.proxy_counts }}</div>
</div>
</div> </div>
<div class="chart-info"> <div class="chart-info">
<div class="chart-traffic"> <div class="chart-traffic">
@@ -148,6 +154,7 @@
</section> </section>
</script> </script>
<!--用户列表模板-->
<script type="text/html" id="userListTemplate"> <script type="text/html" id="userListTemplate">
<section class="user-list"> <section class="user-list">
<form class="layui-form layui-row layui-col-space16" id="searchForm" lay-filter="searchForm"> <form class="layui-form layui-row layui-col-space16" id="searchForm" lay-filter="searchForm">
@@ -190,7 +197,8 @@
</section> </section>
</script> </script>
<script type="text/html" id="toolbarTemplate"> <!--用户列表-表格工具条按钮模板-->
<script type="text/html" id="userListToolbarTemplate">
<div class="layui-btn-container"> <div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="add">${ .NewUser }</button> <button class="layui-btn layui-btn-sm" lay-event="add">${ .NewUser }</button>
<button class="layui-btn layui-btn-sm" lay-event="remove">${ .RemoveUser }</button> <button class="layui-btn layui-btn-sm" lay-event="remove">${ .RemoveUser }</button>
@@ -198,7 +206,9 @@
<button class="layui-btn layui-btn-sm" lay-event="enable">${ .EnableUser }</button> <button class="layui-btn layui-btn-sm" lay-event="enable">${ .EnableUser }</button>
</div> </div>
</script> </script>
<script type="text/html" id="operationTemplate">
<!--用户列表-操作按钮模板-->
<script type="text/html" id="userListOperationTemplate">
<div class="layui-clear-space"> <div class="layui-clear-space">
<a class="layui-btn layui-btn-xs" lay-event="remove">${ .Remove }</a> <a class="layui-btn layui-btn-xs" lay-event="remove">${ .Remove }</a>
{{# if (d.status) { }} {{# if (d.status) { }}
@@ -208,7 +218,9 @@
{{# } }} {{# } }}
</div> </div>
</script> </script>
<script type="text/html" id="addTemplate">
<!--用户列表-添加用户表单模板-->
<script type="text/html" id="addUserTemplate">
<form class="layui-form" id="addUserForm" lay-filter="addUserForm"> <form class="layui-form" id="addUserForm" lay-filter="addUserForm">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">${ .User }</label> <label class="layui-form-label">${ .User }</label>
@@ -254,5 +266,150 @@
</div> </div>
</form> </form>
</script> </script>
<!--代理列表-代理表格模板-->
<script type="text/html" id="proxyListTableTemplate">
<section class="proxy-list">
<table id="proxyListTable" lay-filter="proxyListTable"></table>
</section>
</script>
<!--代理列表-代理表格展示代理详情的箭头模板-->
<script type="text/html" id="toggleProxyInfoArrowTemplate">
<i class='layui-icon layui-icon-triangle-r toggle-proxy-info-arrow' data-index='{{ d.LAY_INDEX }}'
lay-event='toggleProxyInfo'></i>
</script>
<!--代理列表-代理列表每行展开后的表格模板-->
<script type="text/html" id="expandTrTemplate">
<tr class="layui-hide proxy-info" id="childTr_{{= d.index }}">
<td></td>
<td colspan="{{= d.colspan }}">
{{# if (d.proxyType === 'http' || d.proxyType === 'https') { }}
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Name</div>
<div class="layui-col-md9">{{= d.data.conf.name }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Type</div>
<div class="layui-col-md9">{{= d.data.conf.type }}</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Domains</div>
<div class="layui-col-md9">{{= JSON.stringify(d.data.conf.custom_domains) }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">SubDomain</div>
<div class="layui-col-md9">{{= d.data.conf.subdomain }}</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">locations</div>
<div class="layui-col-md9">{{= d.data.conf.locations }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">HostRewrite</div>
<div class="layui-col-md9">{{= d.data.conf.host_header_rewrite }}</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Encryption</div>
<div class="layui-col-md9">{{= d.data.conf.use_encryption }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Compression</div>
<div class="layui-col-md9">{{= d.data.conf.use_compression }}</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Last Start</div>
<div class="layui-col-md9">{{= d.data.last_start_time }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Last Close</div>
<div class="layui-col-md9">{{= d.data.last_close_time }}</div>
</div>
</div>
</div>
{{# } else { }}
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Name</div>
<div class="layui-col-md9">{{= d.data.conf.name }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Type</div>
<div class="layui-col-md9">{{= d.data.conf.type }}</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Addr</div>
<div class="layui-col-md9">:{{= d.data.conf.remote_port }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Encryption</div>
<div class="layui-col-md9">{{= d.data.conf.use_encryption }}</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Compression</div>
<div class="layui-col-md9">{{= d.data.conf.use_compression }}</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Last Start</div>
<div class="layui-col-md9">{{= d.data.last_start_time }}</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-row">
<div class="layui-col-md3">Last Close</div>
<div class="layui-col-md9">{{= d.data.last_close_time }}</div>
</div>
</div>
</div>
{{# } }}
</td>
</tr>
</script>
</body> </body>
</html> </html>

View File

@@ -667,6 +667,7 @@ func (c *HandleController) MakeProxyFunc() func(context *gin.Context) {
res.Code = FrpServerError res.Code = FrpServerError
res.Success = false res.Success = false
res.Message = err.Error() res.Message = err.Error()
log.Print(err)
context.JSON(http.StatusOK, &res) context.JSON(http.StatusOK, &res)
return return
} }