mirror of
https://github.com/arch3rPro/1Panel-Appstore.git
synced 2026-04-16 17:27:11 +08:00
feat: update nps v0.29.36
This commit is contained in:
140
apps/nps/v0.29.36/web/views/client/add.html
Normal file
140
apps/nps/v0.29.36/web/views/client/add.html
Normal file
@@ -0,0 +1,140 @@
|
||||
<div class="row tile">
|
||||
<div class="col-md-12 col-md-auto">
|
||||
<div class="ibox float-e-margins">
|
||||
<h3 class="ibox-title" langtag="page-clientadd"></h3>
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group" id="remark">
|
||||
<label class="control-label font-bold" langtag="word-remark"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="word-remark" name="remark" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_flow_limit}}
|
||||
<div class="form-group" id="flow_limit">
|
||||
<label class="control-label font-bold" langtag="word-flowlimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="flow_limit" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: M
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_time_limit}}
|
||||
<div class="form-group" id="time_limit">
|
||||
<label class="control-label font-bold" langtag="word-timelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" id="time_limit_input" langtag="info-unrestricted" name="time_limit" placeholder="" type="datetime-local">
|
||||
<span class="help-block m-b-none" langtag="info-timelimit"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_rate_limit}}
|
||||
<div class="form-group" id="rate_limit">
|
||||
<label class="control-label font-bold" langtag="word-ratelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="rate_limit" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: KB/S
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_connection_num_limit}}
|
||||
<div class="form-group" id="max_conn">
|
||||
<label class="control-label font-bold" langtag="word-maxconnections"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="max_conn" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_tunnel_num_limit}}
|
||||
<div class="form-group" id="max_tunnel">
|
||||
<label class="control-label font-bold" langtag="word-maxtunnels"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="max_tunnel" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="u">
|
||||
<label class="control-label font-bold" langtag="word-basicusername"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="u" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="info-onlyproxy"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="p">
|
||||
<label class="control-label font-bold" langtag="word-basicpassword"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="p" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="info-onlyproxy"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="vkey">
|
||||
<label class="control-label font-bold" langtag="word-verifyKey"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="vkey" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="info-autogenerated"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_user_login}}
|
||||
<div class="form-group" id="web_username">
|
||||
<label class="control-label font-bold" langtag="word-webusername"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="web_username" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="web_password">
|
||||
<label class="control-label font-bold" langtag="word-webpassword"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="web_password" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="config_conn_allow">
|
||||
<label class="control-label font-bold" langtag="word-connectbyconfig"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="config_conn_allow">
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
<option langtag="word-no" value="0"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="compress">
|
||||
<label class="control-label font-bold" langtag="word-compress"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="compress">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="crypt">
|
||||
<label class="control-label font-bold" langtag="word-crypt"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="crypt">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="black_ip_list">
|
||||
<label class="control-label font-bold" langtag="word-blackiplist"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasblackiplist" name="blackiplist" placeholder="" rows="4" type="text">{{.BlackIpList}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-descblackiplist"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12 col-sm-offset-2">
|
||||
<button class="btn btn-secondary" onclick="goback()" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-window-close"></i> <span langtag="word-cancel"></span>
|
||||
</button>
|
||||
<button class="btn btn-success" onclick="submitform('add', '{{.web_base_url}}/client/add', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-check-circle"></i> <span langtag="word-add"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
156
apps/nps/v0.29.36/web/views/client/edit.html
Normal file
156
apps/nps/v0.29.36/web/views/client/edit.html
Normal file
@@ -0,0 +1,156 @@
|
||||
<div class="row tile">
|
||||
<div class="col-md-12 col-md-auto">
|
||||
<div class="ibox float-e-margins">
|
||||
<h3 class="ibox-title" langtag="page-clientedit"></h3>
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal">
|
||||
<input name="id" type="hidden" value="{{.c.Id}}">
|
||||
<div class="form-group" id="remark">
|
||||
<label class="control-label font-bold" langtag="word-remark"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="word-remark" name="remark" placeholder="" type="text" value="{{.c.Remark}}">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .isAdmin}}
|
||||
<div class="form-group" id="flow_reset">
|
||||
<label class="control-label font-bold" langtag="word-flowreset"></label>
|
||||
<div class="col-sm-12">
|
||||
<input name="flow_reset" type="checkbox" value="1">
|
||||
<span class="help-block m-b-none" langtag="info-flowreset"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_flow_limit}}
|
||||
<div class="form-group" id="flow_limit">
|
||||
<label class="control-label font-bold" langtag="word-flowlimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="flow_limit" placeholder="" type="text" value="{{.c.Flow.FlowLimit}}">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: M
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_time_limit}}
|
||||
<div class="form-group" id="time_limit">
|
||||
<label class="control-label font-bold" langtag="word-timelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" id="time_limit_input" langtag="info-unrestricted" name="time_limit" placeholder="" type="text" value="{{.c.Flow.TimeLimit}}">
|
||||
<span class="help-block m-b-none" langtag="info-timelimit"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_rate_limit}}
|
||||
|
||||
<div class="form-group" id="rate_limit">
|
||||
<label class="control-label font-bold" langtag="word-ratelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="rate_limit" placeholder="" type="text" value="{{.c.RateLimit}}">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: KB/S
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_connection_num_limit}}
|
||||
|
||||
<div class="form-group" id="max_conn">
|
||||
<label class="control-label font-bold" langtag="word-maxconnections"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="max_conn" placeholder="" type="text" value="{{.c.MaxConn}}">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_tunnel_num_limit}}
|
||||
<div class="form-group" id="max_tunnel">
|
||||
<label class="control-label font-bold" langtag="word-maxtunnels"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="max_tunnel" placeholder="" type="text" value="{{.c.MaxTunnelNum}}">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="form-group" id="u">
|
||||
<label class="control-label font-bold" langtag="word-basicusername"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="u" placeholder="" type="text" value="{{.c.Cnf.U}}">
|
||||
<span class="help-block m-b-none" langtag="info-onlyproxy"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="p">
|
||||
<label class="control-label font-bold" langtag="word-basicpassword"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="p" placeholder="" type="text" value="{{.c.Cnf.P}}">
|
||||
<span class="help-block m-b-none" langtag="info-onlyproxy"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .isAdmin}}
|
||||
<div class="form-group" id="vkey">
|
||||
<label class="control-label font-bold" langtag="word-verifyKey"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="vkey" placeholder="" type="text" value="{{.c.VerifyKey}}">
|
||||
<span class="help-block m-b-none" langtag="info-autogenerated"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_user_login}}
|
||||
{{if or (eq true .allow_user_change_username) (eq true .isAdmin)}}
|
||||
<div class="form-group" id="web_username">
|
||||
<label class="control-label font-bold" langtag="word-webusername"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="web_username" placeholder="" type="text" value="{{.c.WebUserName}}">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="web_password">
|
||||
<label class="control-label font-bold" langtag="word-webpassword"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="web_password" placeholder="" type="text" value="{{.c.WebPassword}}">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="config_conn_allow">
|
||||
<label class="control-label font-bold" langtag="word-connectbyconfig"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="config_conn_allow">
|
||||
<option {{if eq true .c.ConfigConnAllow}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
<option {{if eq false .c.ConfigConnAllow}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="compress">
|
||||
<label class="control-label font-bold" langtag="word-compress"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="compress">
|
||||
<option {{if eq false .c.Cnf.Compress}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .c.Cnf.Compress}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="crypt">
|
||||
<label class="control-label font-bold" langtag="word-crypt"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="crypt">
|
||||
<option {{if eq false .c.Cnf.Crypt}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .c.Cnf.Crypt}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="black_ip_list">
|
||||
<label class="control-label font-bold" langtag="word-blackiplist"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasblackiplist" name="blackiplist" placeholder="" rows="4" type="text">{{.BlackIpList}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-descblackiplist"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12 col-sm-offset-2">
|
||||
<button class="btn btn-secondary" onclick="goback()" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-window-close"></i> <span langtag="word-cancel"></span>
|
||||
</button>
|
||||
<button class="btn btn-success" onclick="submitform('add', '{{.web_base_url}}/client/edit', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-save"></i><span langtag="word-save"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
345
apps/nps/v0.29.36/web/views/client/list.html
Normal file
345
apps/nps/v0.29.36/web/views/client/list.html
Normal file
@@ -0,0 +1,345 @@
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="page-clientlist"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .isAdmin}}
|
||||
<div class="content">
|
||||
<div class="table-responsive">
|
||||
<div id="toolbar">
|
||||
<div class="d-flex w-100">
|
||||
<a class="btn btn-primary dim mr-2" href="{{.web_base_url}}/client/add">
|
||||
<i class="fa fa-fw fa-lg fa-plus"></i>
|
||||
<span langtag="word-add"></span></a>
|
||||
<a class="btn btn-danger dim" onclick="submitform('clear', '{{.web_base_url}}/client/clear', {'id': 0, 'mode': 'flow'})">
|
||||
<i class="fa fa-fw fa-lg fa-eraser"></i>
|
||||
<span langtag="word-clearflow"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table-striped table-hover" data-mobile-responsive="true" id="taskList_table"></table>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="ibox-content">
|
||||
<table id="table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/*bootstrap table*/
|
||||
$('#table').bootstrapTable({
|
||||
toolbar: "#toolbar",
|
||||
method: 'post', // 服务器数据的请求方式 get or post
|
||||
url: "{{.web_base_url}}/client/list", // 服务器数据的加载地址
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
striped: true, // 设置为true会有隔行变色效果
|
||||
search: true,
|
||||
showHeader: true,
|
||||
showColumns: true,
|
||||
showRefresh: true,
|
||||
pagination: true,//分页
|
||||
sidePagination: 'server',//服务器端分页
|
||||
pageNumber: 1,
|
||||
pageList: [5, 10, 20, 50, 100, 'all'],
|
||||
cookie: true,
|
||||
cookieIdTable: 'client',
|
||||
cookieStorage: 'localStorage',
|
||||
detailView: true,
|
||||
smartDisplay: true, // 智能显示 pagination 和 cardview 等
|
||||
onExpandRow: function () {$('body').setLang ('.detail-view');},
|
||||
onPostBody: function (data) { if ($(this)[0].locale != undefined ) $('body').setLang ('#table'); },
|
||||
detailFormatter: function (index, row, element) {
|
||||
return '<b langtag="word-maxconnections"></b>: '
|
||||
{{if eq true .isAdmin}}
|
||||
+ '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'conn_limit\'})">' + row.MaxConn + '</span>'
|
||||
{{else}}
|
||||
+ row.MaxConn
|
||||
{{end}}
|
||||
+ ' '
|
||||
+ '<b langtag="word-curconnections"></b>: ' + row.NowConn + ' '
|
||||
+ '<b langtag="word-flowlimit"></b>: '
|
||||
{{if eq true .isAdmin}}
|
||||
+ '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow_limit\'})">' + row.Flow.FlowLimit + '</span>'
|
||||
{{else}}
|
||||
+ row.Flow.FlowLimit
|
||||
{{end}}
|
||||
+ 'MB '
|
||||
+ '<b langtag="word-timelimit"></b>: '
|
||||
{{if eq true .isAdmin}}
|
||||
+ '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'time_limit\'})">' + row.Flow.TimeLimit + '</span>'
|
||||
{{else}}
|
||||
+ row.Flow.TimeLimit
|
||||
{{end}}
|
||||
+ ' '
|
||||
+ '<b langtag="word-ratelimit"></b>: '
|
||||
{{if eq true .isAdmin}}
|
||||
+ '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'rate_limit\'})">' + row.RateLimit + '</span>'
|
||||
{{else}}
|
||||
+ row.RateLimit
|
||||
{{end}}
|
||||
+ 'KB/s '
|
||||
+ '<b langtag="word-maxtunnels"></b>: '
|
||||
{{if eq true .isAdmin}}
|
||||
+ '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'tunnel_limit\'})">' + row.MaxTunnelNum + '</span>'
|
||||
{{else}}
|
||||
+ row.MaxTunnelNum
|
||||
{{end}}
|
||||
+ ' <br/><br/>'
|
||||
+ '<b langtag="word-createtime"></b>: ' + row.CreateTime + ' '
|
||||
+ '<b langtag="word-lastonlinetime"></b>: ' + row.LastOnlineTime + ' '
|
||||
+ '<b langtag="word-address"></b>: <span onclick="oCopy(this)">' + row.Addr + '</span> '
|
||||
+ '<b langtag="word-localaddress"></b>: <span onclick="oCopy(this)">' + row.LocalAddr + '</span> <br/><br/>'
|
||||
+ '<b langtag="word-webusername"></b>: ' + row.WebUserName + ' '
|
||||
+ '<b langtag="word-webpassword"></b>: ' + row.WebPassword + ' '
|
||||
+ '<b langtag="word-basicusername"></b>: ' + row.Cnf.U + ' '
|
||||
+ '<b langtag="word-basicpassword"></b>: ' + row.Cnf.P + ' <br/><br/>'
|
||||
+ '<b langtag="word-crypt"></b>: <span langtag="word-' + row.Cnf.Crypt + '"></span> '
|
||||
+ '<b langtag="word-compress"></b>: <span langtag="word-' + row.Cnf.Compress + '"></span> '
|
||||
+ '<b langtag="word-connectbyconfig"></b>: <span langtag="word-' + row.ConfigConnAllow + '"></span> <br/><br/>'
|
||||
+ '<b langtag="word-blackip"></b>: ' + row.BlackIpList + ' <br/><br/>'
|
||||
{{if index . "tcp_p"}}
|
||||
+ '<b langtag="word-commandclient-tcp"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.ip}}:{{.tcp_p}} -vkey=" + row.VerifyKey + " -type=tcp</code> <br/><br/>"
|
||||
{{end}}
|
||||
{{if index . "kcp_p"}}
|
||||
+ '<b langtag="word-commandclient-kcp"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.ip}}:{{.kcp_p}} -vkey=" + row.VerifyKey + " -type=kcp</code> <br/><br/>"
|
||||
{{end}}
|
||||
{{if index . "tls_p"}}
|
||||
+ '<b langtag="word-commandclient-tls"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.ip}}:{{.tls_p}} -vkey=" + row.VerifyKey + " -type=tls</code> <br/><br/>"
|
||||
{{end}}
|
||||
{{if index . "ws_p"}}
|
||||
+ '<b langtag="word-commandclient-ws"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.ip}}:{{.ws_p}}{{.ws_path}} -vkey=" + row.VerifyKey + " -type=ws</code> <br/><br/>"
|
||||
{{end}}
|
||||
{{if index . "wss_p"}}
|
||||
+ '<b langtag="word-commandclient-wss"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.ip}}:{{.wss_p}}{{.ws_path}} -vkey=" + row.VerifyKey + " -type=wss</code> <br/><br/>"
|
||||
{{end}}
|
||||
},
|
||||
//表格的列
|
||||
columns: [
|
||||
{
|
||||
field: 'Id',//域值
|
||||
title: '<span langtag="word-id"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Remark',//域值
|
||||
title: '<span langtag="word-remark"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Version',//域值
|
||||
title: '<span langtag="word-version"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + escapeHtml(value) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Mode',//域值
|
||||
title: '<span langtag="word-scheme"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + getBridgeMode(value) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'VerifyKey',//域值
|
||||
title: '<span langtag="word-verifykey"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (!row.NoStore) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
} else {
|
||||
return '<span langtag="word-publicvkey"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Addr',//域值
|
||||
title: '<span langtag="word-address"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: false,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'LocalAddr',//域值
|
||||
title: '<span langtag="word-localaddress"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: false,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'InletFlow',//域值
|
||||
title: '<span langtag="word-inletflow"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: false,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
{{if eq true .isAdmin}}
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow) + '</span>'
|
||||
{{else}}
|
||||
return changeunit(row.Flow.InletFlow)
|
||||
{{end}}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'ExportFlow',//域值
|
||||
title: '<span langtag="word-exportflow"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: false,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
{{if eq true .isAdmin}}
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.ExportFlow) + '</span>'
|
||||
{{else}}
|
||||
return changeunit(row.Flow.ExportFlow)
|
||||
{{end}}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'TotalFlow',//域值
|
||||
title: '<span langtag="word-totalflow"></span>',//标题
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
{{if eq true .isAdmin}}
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/client/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow + row.Flow.ExportFlow) + '</span>'
|
||||
{{else}}
|
||||
return changeunit(row.Flow.InletFlow + row.Flow.ExportFlow)
|
||||
{{end}}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'NowConn',//域值
|
||||
title: '<span langtag="word-nowconn"></span>',//内容
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Rate.NowRate',//域值
|
||||
title: '<span langtag="word-speed"></span>',//内容
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return changeunit(value) + "/s"
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Status',//域值
|
||||
title: '<span langtag="word-status"></span>',//内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span class="badge badge-primary" langtag="word-open"></span>'
|
||||
} else {
|
||||
return '<span class="badge badge-badge" langtag="word-close"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'IsConnect',//域值
|
||||
title: '<span langtag="word-connect"></span>',//内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span class="badge badge-primary" langtag="word-online"></span>'
|
||||
} else {
|
||||
return '<span class="badge badge-badge" langtag="word-offline"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'option',//域值
|
||||
title: '<span langtag="word-option"></span>',//内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
formatter: function (value, row, index) {
|
||||
btn_group = '<div class="btn-group">'
|
||||
|
||||
{{if eq true .isAdmin}}
|
||||
if (row.Status) {
|
||||
btn_group += '<a onclick="submitform(\'stop\', \'{{.web_base_url}}/client/changestatus\', {\'id\':' + row.Id
|
||||
btn_group += ', \'status\': 0})" class="btn btn-outline btn-warning"><i class="fa fa-pause"></i></a>'
|
||||
} else {
|
||||
btn_group += '<a onclick="submitform(\'start\', \'{{.web_base_url}}/client/changestatus\', {\'id\':' + row.Id
|
||||
btn_group += ', \'status\': 1})" class="btn btn-outline btn-primary"><i class="fa fa-play"></i></a>'
|
||||
}
|
||||
{{if eq true .allow_local_proxy}}
|
||||
if (row.Id > 0) {
|
||||
btn_group += '<a onclick="submitform(\'delete\', \'{{.web_base_url}}/client/del\', {\'id\':' + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-danger"><i class="fa fa-trash"></i></a>'
|
||||
}
|
||||
{{else}}
|
||||
btn_group += '<a onclick="submitform(\'delete\', \'{{.web_base_url}}/client/del\', {\'id\':' + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-danger"><i class="fa fa-trash"></i></a>'
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
btn_group += '<a href="{{.web_base_url}}/client/edit?id=' + row.Id
|
||||
btn_group += '" class="btn btn-outline btn-success"><i class="fa fa-edit"></i></a></div>'
|
||||
return btn_group
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'show',//域值
|
||||
title: '<span langtag="word-show">',//内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true,//false表示不显示
|
||||
formatter: function (value, row, index) {
|
||||
return '<div class="btn-group"><a href="{{.web_base_url}}/index/all?client_id=' + row.Id
|
||||
+ '" class="btn btn-outline btn-primary" langtag="word-tunnel"></a>'
|
||||
+ '<a href="{{.web_base_url}}/index/hostlist?client_id=' + row.Id
|
||||
+ '" class="btn btn-outline btn-success" langtag="word-host"></a></div>'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
</script>
|
||||
38
apps/nps/v0.29.36/web/views/global/index.html
Normal file
38
apps/nps/v0.29.36/web/views/global/index.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<div class="wrapper wrapper-content">
|
||||
<!--全局参数-->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-globalparam"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group" id="black_ip_list">
|
||||
<label class="control-label font-bold" langtag="word-globalblackiplist"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasblackiplist" name="globalBlackIpList" placeholder="" rows="10" type="text">{{.globalBlackIpList}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-descblackiplist"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12 col-sm-offset-2">
|
||||
<button class="btn btn-success" onclick="submitform('global', '{{.web_base_url}}/global/save', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-check-circle"></i> <span langtag="word-save"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.addEventListener('resize', () => {
|
||||
for (var key in charts) {
|
||||
charts[key].resize();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
255
apps/nps/v0.29.36/web/views/index/add.html
Normal file
255
apps/nps/v0.29.36/web/views/index/add.html
Normal file
@@ -0,0 +1,255 @@
|
||||
<div class="row tile">
|
||||
<div class="col-md-12 col-md-auto">
|
||||
<div class="ibox float-e-margins">
|
||||
<h3 class="ibox-title" langtag="page-add"></h3>
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-scheme"></label>
|
||||
<div class="col-sm-12">
|
||||
<span class="help-block m-b-none font-bold" langtag="word-usecase"></span>:
|
||||
<span id="usecase">
|
||||
<span id="casetcp" langtag="info-casetcp"></span>
|
||||
<span id="caseudp" langtag="info-caseudp"></span>
|
||||
<span id="casehttpProxy" langtag="info-casehttpproxy"></span>
|
||||
<span id="casesocks5" langtag="info-casesocks5"></span>
|
||||
<span id="casemixProxy" langtag="info-casemixproxy"></span>
|
||||
<span id="casesecret" langtag="info-casesecret"></span>
|
||||
<span id="casep2p" langtag="info-casep2p"></span>
|
||||
<span id="casefile" langtag="info-casefile"></span>
|
||||
</span>
|
||||
<select class="form-control selectpicker" id="type" name="type">
|
||||
<option value="tcp" langtag="scheme-tcp"></option>
|
||||
<option value="udp" langtag="scheme-udp"></option>
|
||||
<option value="mixProxy" langtag="scheme-mixProxy"></option>
|
||||
{{/*<option value="httpProxy" langtag="scheme-httpProxy"></option>*/}}
|
||||
{{/*<option value="socks5" langtag="scheme-socks5"></option>*/}}
|
||||
<option value="secret" langtag="scheme-secret"></option>
|
||||
<option value="p2p" langtag="scheme-p2p"></option>
|
||||
{{/*<option value="file" langtag="scheme-file"></option>*/}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="client_id">
|
||||
<label class="control-label font-bold" langtag="word-clientid"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control" name="client_id" data-live-search="true"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-remark"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="remark" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_multi_ip}}
|
||||
<div class="form-group" id="server_ip">
|
||||
<label class="control-label font-bold" langtag="word-serverip"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchasip" name="server_ip" placeholder="" type="text" value="0.0.0.0">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="port">
|
||||
<label class="control-label font-bold" langtag="word-serverport"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchasport" name="port" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="mix_proxy">
|
||||
<label class="control-label font-bold" langtag="scheme-mixproxy"></label>
|
||||
<div class="col-sm-12">
|
||||
<input name="enable_http" type="checkbox" value="1" checked>
|
||||
<span class="help-block m-b-none" langtag="word-enablehttpproxy"></span>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<input name="enable_socks5" type="checkbox" value="1" checked>
|
||||
<span class="help-block m-b-none" langtag="word-enablesocks5proxy"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_flow_limit}}
|
||||
<div class="form-group" id="flow_limit">
|
||||
<label class="control-label font-bold" langtag="word-flowlimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="flow_limit" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: M
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_time_limit}}
|
||||
<div class="form-group" id="time_limit">
|
||||
<label class="control-label font-bold" langtag="word-timelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" id="time_limit_input" langtag="info-unrestricted" name="time_limit" placeholder="" type="datetime-local">
|
||||
<span class="help-block m-b-none" langtag="info-timelimit"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="proxy_protocol">
|
||||
<label class="control-label font-bold" langtag="word-proxyprotocol"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="proxy_protocol">
|
||||
<option langtag="word-disable" value="0"></option>
|
||||
<option langtag="word-proxyprotocolv1" value="1"></option>
|
||||
<option langtag="word-proxyprotocolv2" value="2"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label font-bold" langtag="word-proxytolocal"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control" name="local_proxy">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="auth">
|
||||
<label class="control-label font-bold" langtag="word-auth"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasauth" name="auth" placeholder="" rows="4"></textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targetauth"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="target">
|
||||
<label class="control-label font-bold" langtag="word-target"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasiplist" name="target" placeholder="" rows="4"></textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targettunnel"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="local_path">
|
||||
<label class="control-label font-bold" langtag="word-localpath"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchaslocalpath" name="local_path" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="strip_pre">
|
||||
<label class="control-label font-bold" langtag="word-stripprefix"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchasstripprefix" name="strip_pre" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="password">
|
||||
<label class="control-label font-bold" langtag="word-identificationkey"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="word-identificationkey" name="password" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="info-identificationkey"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12 col-sm-offset-2">
|
||||
<button class="btn btn-secondary" onclick="goback()" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-window-close"></i> <span langtag="word-cancel"></span>
|
||||
</button>
|
||||
<button class="btn btn-success" onclick="submitform('add', '{{.web_base_url}}/index/add', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-check-circle"></i> <span langtag="word-add"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var arr = []
|
||||
arr["all"] = ["auth", "port", "target", "password", "flow_reset", "flow_limit", "time_limit", "mix_proxy", "local_path", "strip_pre", "proxy_protocol", "local_proxy", "client_id", "server_ip"]
|
||||
arr["tcp"] = ["port", "target", "proxy_protocol", "local_proxy", "client_id", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["udp"] = ["port", "target", "local_proxy", "client_id", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["mixProxy"] = ["auth", "port", "client_id", "server_ip", "mix_proxy", "flow_reset", "flow_limit", "time_limit"]
|
||||
//arr["socks5"] = ["auth", "port", "client_id", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
//arr["httpProxy"] = ["auth", "port", "client_id", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["secret"] = ["target", "password", "client_id", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["p2p"] = ["target", "password", "client_id", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["file"] = ["port", "local_path", "strip_pre", "client_id", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
|
||||
function resetForm() {
|
||||
$(".form-group[id]").css("display", "none");
|
||||
$("#usecase span").css("display", "none");
|
||||
o = $("#type").val();
|
||||
$('#case' + o).css("display", "inline")
|
||||
for (var i = 0; i < arr[o].length; i++) {
|
||||
$("#" + arr[o][i]).css("display", "block")
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#type").val(('{{.type}}' == '') ? 'tcp' : '{{.type}}');
|
||||
resetForm()
|
||||
$("#type").on("change", function () {
|
||||
resetForm()
|
||||
})
|
||||
$("#use_client").on("change", function () {
|
||||
resetForm()
|
||||
})
|
||||
});
|
||||
|
||||
function getClientList() {
|
||||
const clientId = "{{if .t.Client.Id}}{{.t.Client.Id}}{{else}}{{.client_id}}{{end}}"; // 根据优先级选择
|
||||
$("select[name='client_id']").selectpicker({
|
||||
liveSearch: true,
|
||||
source: {
|
||||
data: function (callback, page) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
dataType: 'json',
|
||||
data: { order: "asc", offset: 0, limit: 0 },
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
},
|
||||
search: function (callback, page, searchTerm) {
|
||||
let data = { search: searchTerm, order: "asc", offset: 0, limit: 0 };
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
data: data,
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function internationalized(current) {
|
||||
$.fn.selectpicker.defaults = {
|
||||
noneSelectedText: languages['content']['bootstrap-select']['noneSelectedText'][current],
|
||||
noneResultsText: languages['content']['bootstrap-select']['noneResultsText'][current]
|
||||
};
|
||||
getClientList();
|
||||
}
|
||||
</script>
|
||||
266
apps/nps/v0.29.36/web/views/index/edit.html
Normal file
266
apps/nps/v0.29.36/web/views/index/edit.html
Normal file
@@ -0,0 +1,266 @@
|
||||
<div class="row tile">
|
||||
<div class="col-md-12 col-md-auto">
|
||||
<div class="ibox float-e-margins">
|
||||
<h3 class="ibox-title" langtag="page-edit"></h3>
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal">
|
||||
<input name="id" type="hidden" value="{{.t.Id}}">
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-scheme"></label>
|
||||
<div class="col-sm-12">
|
||||
<span class="help-block m-b-none font-bold" langtag="word-usecase"></span>:
|
||||
<span id="usecase">
|
||||
<span id="casetcp" langtag="info-casetcp"></span>
|
||||
<span id="caseudp" langtag="info-caseudp"></span>
|
||||
<span id="casehttpProxy" langtag="info-casehttpproxy"></span>
|
||||
<span id="casesocks5" langtag="info-casesocks5"></span>
|
||||
<span id="casemixProxy" langtag="info-casemixproxy"></span>
|
||||
<span id="casesecret" langtag="info-casesecret"></span>
|
||||
<span id="casep2p" langtag="info-casep2p"></span>
|
||||
<span id="casefile" langtag="info-casefile"></span>
|
||||
</span>
|
||||
<select class="form-control selectpicker" id="type" name="type">
|
||||
<option value="tcp" langtag="scheme-tcp"></option>
|
||||
<option value="udp" langtag="scheme-udp"></option>
|
||||
<option value="mixProxy" langtag="scheme-mixProxy"></option>
|
||||
{{/*<option value="httpProxy" langtag="scheme-httpProxy"></option>*/}}
|
||||
{{/*<option value="socks5" langtag="scheme-socks5"></option>*/}}
|
||||
<option value="secret" langtag="scheme-secret"></option>
|
||||
<option value="p2p" langtag="scheme-p2p"></option>
|
||||
{{/*<option value="file" langtag="scheme-file"></option>*/}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="client_id">
|
||||
<label class="control-label font-bold" langtag="word-clientid"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control" name="client_id" data-live-search="true"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-remark"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="remark" placeholder="" type="text" value="{{.t.Remark}}">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_multi_ip}}
|
||||
<div class="form-group" id="server_ip">
|
||||
<label class="control-label font-bold" langtag="word-serverip"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchasip" name="server_ip" placeholder="" type="text" value="{{.t.ServerIp}}">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="port">
|
||||
<label class="control-label font-bold" langtag="word-serverport"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchasport" name="port" placeholder="" type="text" value="{{.t.Port}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="mix_proxy">
|
||||
<label class="control-label font-bold" langtag="scheme-mixproxy"></label>
|
||||
<div class="col-sm-12">
|
||||
<input name="enable_http" type="checkbox" value="1" {{if .t.HttpProxy}}checked{{end}}>
|
||||
<span class="help-block m-b-none" langtag="word-enablehttpproxy"></span>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<input name="enable_socks5" type="checkbox" value="1" {{if .t.Socks5Proxy}}checked{{end}}>
|
||||
<span class="help-block m-b-none" langtag="word-enablesocks5proxy"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="flow_reset">
|
||||
<label class="control-label font-bold" langtag="word-flowreset"></label>
|
||||
<div class="col-sm-12">
|
||||
<input name="flow_reset" type="checkbox" value="1">
|
||||
<span class="help-block m-b-none" langtag="info-flowreset"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_flow_limit}}
|
||||
<div class="form-group" id="flow_limit">
|
||||
<label class="control-label font-bold" langtag="word-flowlimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="flow_limit" placeholder="" type="text" value="{{.t.Flow.FlowLimit}}">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: M
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_time_limit}}
|
||||
<div class="form-group" id="time_limit">
|
||||
<label class="control-label font-bold" langtag="word-timelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" id="time_limit_input" langtag="info-unrestricted" name="time_limit" placeholder="" type="text" value="{{.t.Flow.TimeLimit}}">
|
||||
<span class="help-block m-b-none" langtag="info-timelimit"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="proxy_protocol">
|
||||
<label class="control-label font-bold" langtag="word-proxyprotocol"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="proxy_protocol">
|
||||
<option value="0" {{if eq .t.Target.ProxyProtocol 0}}selected{{end}} langtag="word-disable"></option>
|
||||
<option value="1" {{if eq .t.Target.ProxyProtocol 1}}selected{{end}} langtag="word-proxyprotocolv1"></option>
|
||||
<option value="2" {{if eq .t.Target.ProxyProtocol 2}}selected{{end}} langtag="word-proxyprotocolv2"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label font-bold" langtag="word-proxytolocal"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="local_proxy">
|
||||
<option {{if eq false .t.Target.LocalProxy}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .t.Target.LocalProxy}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="auth">
|
||||
<label class="control-label font-bold" langtag="word-auth"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasauth" name="auth" placeholder="" rows="4">{{.auth}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targetauth"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="target">
|
||||
<label class="control-label font-bold" langtag="word-target"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasiplist" name="target" placeholder="" rows="4">{{.t.Target.TargetStr}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targettunnel"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="local_path">
|
||||
<label class="control-label font-bold" langtag="word-localpath"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchaslocalpath" name="local_path" placeholder="" type="text" value="{{.t.LocalPath}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="strip_pre">
|
||||
<label class="control-label font-bold" langtag="word-stripprefix"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchasstripprefix" name="strip_pre" placeholder="" type="text" value="{{.t.StripPre}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="password">
|
||||
<label class="control-label font-bold" langtag="word-identificationkey"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="word-identificationkey" name="password" placeholder="" type="text" value="{{.t.Password}}">
|
||||
<span class="help-block m-b-none" langtag="info-identificationkey"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12 col-sm-offset-2">
|
||||
<button class="btn btn-secondary" onclick="goback()" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-window-close"></i> <span langtag="word-cancel"></span>
|
||||
</button>
|
||||
<button class="btn btn-success" onclick="submitform('edit', '{{.web_base_url}}/index/edit', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-check-circle"></i> <span langtag="word-save"></span>
|
||||
</button>
|
||||
<button class="btn btn-warning" onclick="if ($('input[name=\'port\']').val() == '{{.t.Port}}') $('input[name=\'port\']').val(0); submitform('add', '{{.web_base_url}}/index/add', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-check-circle"></i> <span langtag="word-add"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var arr = []
|
||||
arr["all"] = ["auth", "server_ip", "port", "target", "password", "flow_reset", "flow_limit", "time_limit", "mix_proxy", "local_path", "strip_pre", "proxy_protocol", "local_proxy"]
|
||||
arr["tcp"] = ["client_id", "port", "target", "proxy_protocol", "local_proxy", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["udp"] = ["client_id", "port", "target", "local_proxy", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["mixProxy"] = ["auth", "client_id", "port", "server_ip", "mix_proxy", "flow_reset", "flow_limit", "time_limit"]
|
||||
//arr["socks5"] = ["auth", "client_id", "port", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
//arr["httpProxy"] = ["auth", "client_id", "port", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["secret"] = ["client_id", "target", "password", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["p2p"] = ["client_id", "target", "password", "flow_reset", "flow_limit", "time_limit"]
|
||||
arr["file"] = ["client_id", "port", "local_path", "strip_pre", "server_ip", "flow_reset", "flow_limit", "time_limit"]
|
||||
|
||||
function resetForm() {
|
||||
$(".form-group[id]").css("display", "none");
|
||||
$("#usecase span").css("display", "none");
|
||||
o = $("#type").val();
|
||||
$('#case' + o).css("display", "inline")
|
||||
for (var i = 0; i < arr[o].length; i++) {
|
||||
$("#" + arr[o][i]).css("display", "block")
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#type").val('{{.t.Mode}}');
|
||||
resetForm()
|
||||
$("#type").on("change", function () {
|
||||
resetForm()
|
||||
})
|
||||
$("#use_client").on("change", function () {
|
||||
resetForm()
|
||||
})
|
||||
});
|
||||
|
||||
function getClientList() {
|
||||
const clientId = "{{if .t.Client.Id}}{{.t.Client.Id}}{{else}}{{.client_id}}{{end}}"; // 根据优先级选择
|
||||
$("select[name='client_id']").selectpicker({
|
||||
liveSearch: true,
|
||||
source: {
|
||||
data: function (callback, page) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
dataType: 'json',
|
||||
data: { order: "asc", offset: 0, limit: 0 },
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
},
|
||||
search: function (callback, page, searchTerm) {
|
||||
let data = { search: searchTerm, order: "asc", offset: 0, limit: 0 };
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
data: data,
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function internationalized(current) {
|
||||
$.fn.selectpicker.defaults = {
|
||||
noneSelectedText: languages['content']['bootstrap-select']['noneSelectedText'][current],
|
||||
noneResultsText: languages['content']['bootstrap-select']['noneResultsText'][current]
|
||||
};
|
||||
getClientList();
|
||||
}
|
||||
</script>
|
||||
329
apps/nps/v0.29.36/web/views/index/hadd.html
Normal file
329
apps/nps/v0.29.36/web/views/index/hadd.html
Normal file
@@ -0,0 +1,329 @@
|
||||
<div class="row tile">
|
||||
<div class="col-md-12 col-md-auto">
|
||||
<div class="ibox float-e-margins">
|
||||
<h3 class="ibox-title" langtag="page-hostadd"></h3>
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-clientid"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control" name="client_id" data-live-search="true"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-remark"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" type="text" name="remark" placeholder="" langtag="word-remark">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-host"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" type="text" name="host" placeholder="" langtag="info-suchashost">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="scheme">
|
||||
<label class="control-label font-bold" langtag="word-scheme"></label>
|
||||
<div class="col-sm-12">
|
||||
<select id="scheme_select" class="form-control selectpicker" name="scheme">
|
||||
<option value="all" langtag="word-all"></option>
|
||||
<option value="http" langtag="word-http"></option>
|
||||
<option value="https" langtag="word-https"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_flow_limit}}
|
||||
<div class="form-group" id="flow_limit">
|
||||
<label class="control-label font-bold" langtag="word-flowlimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="flow_limit" placeholder="" type="text">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: M
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_time_limit}}
|
||||
<div class="form-group" id="time_limit">
|
||||
<label class="control-label font-bold" langtag="word-timelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" id="time_limit_input" langtag="info-unrestricted" name="time_limit" placeholder="" type="datetime-local">
|
||||
<span class="help-block m-b-none" langtag="info-timelimit"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="auto_https">
|
||||
<label class="control-label font-bold" langtag="word-autohttps"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="auto_https">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="auto_cors">
|
||||
<label class="control-label font-bold" langtag="word-autocors"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="auto_cors">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="compat_mode">
|
||||
<label class="control-label font-bold" langtag="word-compatmode"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="compat_mode">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="https_just_proxy">
|
||||
<label class="control-label font-bold" langtag="word-httpsjustproxy"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" id="https_just_proxy_select" name="https_just_proxy">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="proxy_protocol">
|
||||
<label class="control-label font-bold" langtag="word-proxyprotocol"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="proxy_protocol">
|
||||
<option langtag="word-disable" value="0"></option>
|
||||
<option langtag="word-proxyprotocolv1" value="1"></option>
|
||||
<option langtag="word-proxyprotocolv2" value="2"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="auto_ssl">
|
||||
<label class="control-label font-bold" langtag="word-autossl"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="auto_ssl">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="cert_file">
|
||||
<label class="control-label font-bold" langtag="word-httpscert"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" id="pemText" langtag="info-pemtext" name="cert_file" placeholder="" rows="6" type="text"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="key_file">
|
||||
<label class="control-label font-bold" langtag="word-httpskey"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" id="pemKey" langtag="info-pemkey" name="key_file" placeholder="" rows="6" type="text"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-urlroute"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="location" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-urlrewrite"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-urlrewrite" name="path_rewrite" placeholder="" type="text">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label font-bold" langtag="word-proxytolocal"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="local_proxy">
|
||||
<option langtag="word-no" value="0"></option>
|
||||
<option langtag="word-yes" value="1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="auth">
|
||||
<label class="control-label font-bold" langtag="word-auth"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasauth" name="auth" placeholder="" rows="4"></textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targetauth"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="target_is_https">
|
||||
<label class="control-label font-bold" langtag="word-targetishttps"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="target_is_https">
|
||||
<option value="0">HTTP</option>
|
||||
<option value="1">HTTPS</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-target"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasiplist" name="target" placeholder="" rows="4" type="text"></textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targethost"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="header">
|
||||
<label class="control-label font-bold" langtag="word-requestheader"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" name="header" placeholder="Cache-Control: no-cache" rows="4" type="text"></textarea>
|
||||
<span class="help-block m-b-none" langtag="info-header"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="hostchange">
|
||||
<label class="control-label font-bold" langtag="word-requesthost"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="word-requesthost" name="hostchange" placeholder="" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12 col-sm-offset-2">
|
||||
<button class="btn btn-secondary" onclick="goback()" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-window-close"></i> <span langtag="word-cancel"></span>
|
||||
</button>
|
||||
<button class="btn btn-success" onclick="submitform('add', '{{.web_base_url}}/index/addhost', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-check-circle"></i> <span langtag="word-add"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
const pemText = document.getElementById("pemText");
|
||||
const pemKey = document.getElementById("pemKey");
|
||||
|
||||
// 阻止浏览器默认打开文件的行为
|
||||
document.addEventListener("dragover", function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
pemText.addEventListener("drop", function (event) {
|
||||
event.preventDefault();
|
||||
const file = event.dataTransfer.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
pemText.value = e.target.result;
|
||||
console.log("Upload pem")
|
||||
$('#edit_form').data('bootstrapValidator').updateStatus('pemText', 'NOT_VALIDATED');
|
||||
$('#edit_form').data('bootstrapValidator').validateField('pemText');
|
||||
}
|
||||
reader.readAsText(file);
|
||||
});
|
||||
|
||||
pemKey.addEventListener("drop", function (event) {
|
||||
event.preventDefault();
|
||||
const file = event.dataTransfer.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
pemKey.value = e.target.result;
|
||||
$('#edit_form').data('bootstrapValidator').updateStatus('pemKey', 'NOT_VALIDATED');
|
||||
$('#edit_form').data('bootstrapValidator').validateField('pemKey');
|
||||
}
|
||||
reader.readAsText(file);
|
||||
});
|
||||
|
||||
$("#scheme_select").on("change", function () {
|
||||
if ($("#scheme_select").val() == "all" || $("#scheme_select").val() == "https") {
|
||||
$("#auto_https").css("display", "block")
|
||||
$("#https_just_proxy").css("display", "block")
|
||||
if ($("#https_just_proxy_select").val() == "1") {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "block")
|
||||
$("#cert_file").css("display", "block")
|
||||
$("#key_file").css("display", "block")
|
||||
}
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
$("#https_just_proxy").css("display", "none")
|
||||
$("#auto_https").css("display", "none")
|
||||
}
|
||||
})
|
||||
|
||||
$("#https_just_proxy_select").on("change", function () {
|
||||
if ($("#https_just_proxy_select").val() == "1") {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "block")
|
||||
$("#cert_file").css("display", "block")
|
||||
$("#key_file").css("display", "block")
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function getClientList() {
|
||||
const clientId = "{{.client_id}}"; // 获取 client_id
|
||||
$("select[name='client_id']").selectpicker({
|
||||
liveSearch: true,
|
||||
source: {
|
||||
data: function (callback, page) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
dataType: 'json',
|
||||
data: { order: "asc", offset: 0, limit: 0 },
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
},
|
||||
search: function (callback, page, searchTerm) {
|
||||
let data = { search: searchTerm, order: "asc", offset: 0, limit: 0 };
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
data: data,
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function internationalized(current) {
|
||||
$.fn.selectpicker.defaults = {
|
||||
noneSelectedText: languages['content']['bootstrap-select']['noneSelectedText'][current],
|
||||
noneResultsText: languages['content']['bootstrap-select']['noneResultsText'][current]
|
||||
};
|
||||
getClientList();
|
||||
}
|
||||
</script>
|
||||
360
apps/nps/v0.29.36/web/views/index/hedit.html
Normal file
360
apps/nps/v0.29.36/web/views/index/hedit.html
Normal file
@@ -0,0 +1,360 @@
|
||||
<div class="row tile">
|
||||
<div class="col-md-12 col-md-auto">
|
||||
<div class="ibox float-e-margins">
|
||||
<h3 class="ibox-title" langtag="page-hostedit"></h3>
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal">
|
||||
<input name="id" type="hidden" value="{{.h.Id}}">
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-clientid"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control" name="client_id" data-live-search="true"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-remark"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" name="remark" placeholder="remark" type="text" value="{{.h.Remark}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-host"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-suchashost" name="host" placeholder="" type="text" value="{{.h.Host}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="scheme">
|
||||
<label class="control-label font-bold" langtag="word-scheme"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" id="scheme_select" name="scheme">
|
||||
<option {{if eq "all" .h.Scheme}}selected{{end}} value="all" langtag="word-all"></option>
|
||||
<option {{if eq "http" .h.Scheme}}selected{{end}} value="http" langtag="word-http"></option>
|
||||
<option {{if eq "https" .h.Scheme}}selected{{end}} value="https" langtag="word-https"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="flow_reset">
|
||||
<label class="control-label font-bold" langtag="word-flowreset"></label>
|
||||
<div class="col-sm-12">
|
||||
<input name="flow_reset" type="checkbox" value="1">
|
||||
<span class="help-block m-b-none" langtag="info-flowreset"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_flow_limit}}
|
||||
<div class="form-group" id="flow_limit">
|
||||
<label class="control-label font-bold" langtag="word-flowlimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="flow_limit" placeholder="" type="text" value="{{.h.Flow.FlowLimit}}">
|
||||
<span class="help-block m-b-none" langtag="word-unit"></span>: M
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_time_limit}}
|
||||
<div class="form-group" id="time_limit">
|
||||
<label class="control-label font-bold" langtag="word-timelimit"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" id="time_limit_input" langtag="info-unrestricted" name="time_limit" placeholder="" type="text" value="{{.h.Flow.TimeLimit}}">
|
||||
<span class="help-block m-b-none" langtag="info-timelimit"></span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="auto_https">
|
||||
<label class="control-label font-bold" langtag="word-autohttps"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="auto_https">
|
||||
<option {{if eq false .h.AutoHttps}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .h.AutoHttps}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="auto_cors">
|
||||
<label class="control-label font-bold" langtag="word-autocors"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="auto_cors">
|
||||
<option {{if eq false .h.AutoCORS}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .h.AutoCORS}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="compat_mode">
|
||||
<label class="control-label font-bold" langtag="word-compatmode"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="compat_mode">
|
||||
<option {{if eq false .h.CompatMode}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .h.CompatMode}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="https_just_proxy">
|
||||
<label class="control-label font-bold" langtag="word-httpsjustproxy"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" id="https_just_proxy_select" name="https_just_proxy">
|
||||
<option {{if eq false .h.HttpsJustProxy}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .h.HttpsJustProxy}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="proxy_protocol">
|
||||
<label class="control-label font-bold" langtag="word-proxyprotocol"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="proxy_protocol">
|
||||
<option value="0" {{if eq .h.Target.ProxyProtocol 0}}selected{{end}} langtag="word-disable"></option>
|
||||
<option value="1" {{if eq .h.Target.ProxyProtocol 1}}selected{{end}} langtag="word-proxyprotocolv1"></option>
|
||||
<option value="2" {{if eq .h.Target.ProxyProtocol 2}}selected{{end}} langtag="word-proxyprotocolv2"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="auto_ssl">
|
||||
<label class="control-label font-bold" langtag="word-autossl"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="auto_ssl">
|
||||
<option {{if eq false .h.AutoSSL}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .h.AutoSSL}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="cert_file">
|
||||
<label class="control-label font-bold" langtag="word-httpscert"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" id="pemText" langtag="info-pemtext" name="cert_file" placeholder="" rows="6" type="text">{{.h.CertFile}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="key_file">
|
||||
<label class="control-label font-bold" langtag="word-httpskey"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" id="pemKey" langtag="info-pemkey" name="key_file" placeholder="" rows="6" type="text">{{.h.KeyFile}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-urlroute"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-unrestricted" name="location" placeholder="" type="text" value="{{.h.Location}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-urlrewrite"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="info-urlrewrite" name="path_rewrite" placeholder="" type="text" value="{{.h.PathRewrite}}">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label font-bold" langtag="word-proxytolocal"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="local_proxy">
|
||||
<option {{if eq false .h.Target.LocalProxy}}selected{{end}} value="0" langtag="word-no"></option>
|
||||
<option {{if eq true .h.Target.LocalProxy}}selected{{end}} value="1" langtag="word-yes"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="auth">
|
||||
<label class="control-label font-bold" langtag="word-auth"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasauth" name="auth" placeholder="" rows="4">{{.auth}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targetauth"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="target_is_https">
|
||||
<label class="control-label font-bold" langtag="word-targetishttps"></label>
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control selectpicker" name="target_is_https">
|
||||
<option {{if eq false .h.TargetIsHttps}}selected{{end}} value="0">HTTP</option>
|
||||
<option {{if eq true .h.TargetIsHttps}}selected{{end}} value="1">HTTPS</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label font-bold" langtag="word-target"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" langtag="info-suchasiplist" name="target" placeholder="" rows="4" type="text">{{.h.Target.TargetStr}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-targethost"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="header">
|
||||
<label class="control-label font-bold" langtag="word-requestheader"></label>
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" name="header" placeholder="Cache-Control: no-cache" rows="4" type="text">{{.h.HeaderChange}}</textarea>
|
||||
<span class="help-block m-b-none" langtag="info-header"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="hostchange">
|
||||
<label class="control-label font-bold" langtag="word-requesthost"></label>
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" langtag="word-requesthost" name="hostchange" placeholder="" type="text" value="{{.h.HostChange}}" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12 col-sm-offset-2">
|
||||
<button class="btn btn-secondary" onclick="goback()" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-window-close"></i> <span langtag="word-cancel"></span>
|
||||
</button>
|
||||
<button class="btn btn-success" onclick="submitform('edit', '{{.web_base_url}}/index/edithost', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-save"></i> <span langtag="word-save"></span>
|
||||
</button>
|
||||
<button class="btn btn-warning" onclick="submitform('add', '{{.web_base_url}}/index/addhost', $('form').serializeArray())" type="button">
|
||||
<i class="fa fa-fw fa-lg fa-check-circle"></i> <span langtag="word-add"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
if ($("#scheme_select").val() == "all" || $("#scheme_select").val() == "https") {
|
||||
$("#auto_https").css("display", "block")
|
||||
$("#https_just_proxy").css("display", "block")
|
||||
if ($("#https_just_proxy_select").val() == "1") {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "block")
|
||||
$("#cert_file").css("display", "block")
|
||||
$("#key_file").css("display", "block")
|
||||
}
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
$("#https_just_proxy").css("display", "none")
|
||||
$("#auto_https").css("display", "none")
|
||||
}
|
||||
|
||||
const pemText = document.getElementById("pemText");
|
||||
const pemKey = document.getElementById("pemKey");
|
||||
|
||||
// 阻止浏览器默认打开文件的行为
|
||||
document.addEventListener("dragover", function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
pemText.addEventListener("drop", function (event) {
|
||||
event.preventDefault();
|
||||
const file = event.dataTransfer.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
pemText.value = e.target.result;
|
||||
console.log("Upload pem")
|
||||
$('#edit_form').data('bootstrapValidator').updateStatus('pemText', 'NOT_VALIDATED');
|
||||
$('#edit_form').data('bootstrapValidator').validateField('pemText');
|
||||
}
|
||||
reader.readAsText(file);
|
||||
});
|
||||
|
||||
pemKey.addEventListener("drop", function (event) {
|
||||
event.preventDefault();
|
||||
const file = event.dataTransfer.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
pemKey.value = e.target.result;
|
||||
$('#edit_form').data('bootstrapValidator').updateStatus('pemKey', 'NOT_VALIDATED');
|
||||
$('#edit_form').data('bootstrapValidator').validateField('pemKey');
|
||||
}
|
||||
reader.readAsText(file);
|
||||
});
|
||||
|
||||
$("#scheme_select").on("change", function () {
|
||||
if ($("#scheme_select").val() == "all" || $("#scheme_select").val() == "https") {
|
||||
$("#auto_https").css("display", "block")
|
||||
$("#https_just_proxy").css("display", "block")
|
||||
if ($("#https_just_proxy_select").val() == "1") {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "block")
|
||||
$("#cert_file").css("display", "block")
|
||||
$("#key_file").css("display", "block")
|
||||
}
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
$("#https_just_proxy").css("display", "none")
|
||||
$("#auto_https").css("display", "none")
|
||||
}
|
||||
})
|
||||
|
||||
$("#https_just_proxy_select").on("change", function () {
|
||||
if ($("#https_just_proxy_select").val() == "1") {
|
||||
$("#auto_ssl").css("display", "none")
|
||||
$("#cert_file").css("display", "none")
|
||||
$("#key_file").css("display", "none")
|
||||
} else {
|
||||
$("#auto_ssl").css("display", "block")
|
||||
$("#cert_file").css("display", "block")
|
||||
$("#key_file").css("display", "block")
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function getClientList() {
|
||||
const clientId = "{{if .h.Client.Id}}{{.h.Client.Id}}{{else}}{{.client_id}}{{end}}"; // 根据优先级选择
|
||||
$("select[name='client_id']").selectpicker({
|
||||
liveSearch: true,
|
||||
source: {
|
||||
data: function (callback, page) {
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
dataType: 'json',
|
||||
data: { order: "asc", offset: 0, limit: 0 },
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
},
|
||||
search: function (callback, page, searchTerm) {
|
||||
let data = { search: searchTerm, order: "asc", offset: 0, limit: 0 };
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: "{{.web_base_url}}/client/list",
|
||||
data: data,
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
// 转换数据格式(必须包含 `value` 和 `text`)
|
||||
const results = $.map(response.rows, function(item) {
|
||||
let displayText = item.Remark ? item.Id + ' · ' + item.Remark : item.Id.toString();
|
||||
return {
|
||||
value: item.Id, // 选项的 value
|
||||
text: displayText, // 选项的显示文本
|
||||
selected: item.Id == clientId // 默认选中
|
||||
};
|
||||
});
|
||||
callback(results); // 返回给 selectpicker
|
||||
},
|
||||
error: function() {
|
||||
callback([]); // 出错时返回空数组
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function internationalized(current) {
|
||||
$.fn.selectpicker.defaults = {
|
||||
noneSelectedText: languages['content']['bootstrap-select']['noneSelectedText'][current],
|
||||
noneResultsText: languages['content']['bootstrap-select']['noneResultsText'][current]
|
||||
};
|
||||
getClientList();
|
||||
}
|
||||
</script>
|
||||
153
apps/nps/v0.29.36/web/views/index/help.html
Normal file
153
apps/nps/v0.29.36/web/views/index/help.html
Normal file
@@ -0,0 +1,153 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="tile">
|
||||
<iframe frameborder="0" height="30px" scrolling="0"
|
||||
src="https://ghbtns.com/github-btn.html?user=djylb&repo=nps&type=star&count=true&size=large"
|
||||
width="160px"></iframe>
|
||||
<iframe frameborder="0" height="30px" scrolling="0"
|
||||
src="https://ghbtns.com/github-btn.html?user=djylb&repo=nps&type=watch&count=true&size=large&v=2"
|
||||
width="160px"></iframe>
|
||||
<iframe frameborder="0" height="30px" scrolling="0"
|
||||
src="https://ghbtns.com/github-btn.html?user=djylb&repo=nps&type=fork&count=true&size=large"
|
||||
width="158px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="tile">
|
||||
<h3 class="tile-title">域名代理模式</h3>
|
||||
<p>
|
||||
<b>适用范围:</b> 小程序开发、微信公众号开发、产品演示
|
||||
</p>
|
||||
<p>
|
||||
<b>假设场景:</b>
|
||||
<li>有一个域名proxy.com,有一台公网机器ip为{{.ip}}</li>
|
||||
<li>两个内网开发站点127.0.0.1:81,127.0.0.1:82</li>
|
||||
<li>想通过a.proxy.com访问127.0.0.1:81,通过b.proxy.com访问127.0.0.1:82</li>
|
||||
</p>
|
||||
<p><b>使用步骤:</b></p>
|
||||
<ul>
|
||||
<li>将*.proxy.com解析到公网服务器{{.ip}}</li>
|
||||
<li>在客户端管理中创建一个客户端,记录下验证密钥</li>
|
||||
<li>
|
||||
点击该客户端的域名管理,添加两条规则规则:1、域名:a.proxy.com,内网目标:127.0.0.1:81,2、域名:b.proxy.com,内网目标:127.0.0.1:82
|
||||
</li>
|
||||
<li>内网客户端运行<code>
|
||||
<pre>./npc -server={{.ip}}:{{.p}} -vkey=客户端的密钥</pre>
|
||||
</code></pre></li>
|
||||
<li>现在访问a.proxy.com,b.proxy.com即可成功</li>
|
||||
</ul>
|
||||
<p>注:上文中提到公网ip({{.ip}})为系统自动识别,如果是在测试环境中请自行对应,<b>如需使用https请在配置文件中将https端口设置为443,和将对应的证书文件路径添加到配置文件中
|
||||
</b></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="tile">
|
||||
<h3 class="tile-title">tcp隧道模式</h3>
|
||||
<p>
|
||||
<b>适用范围:</b> ssh、远程桌面等tcp连接场景
|
||||
</p>
|
||||
<p>
|
||||
<b>假设场景:</b> 想通过访问公网服务器{{.ip}}的8001端口,连接内网机器10.1.50.101的22端口,实现ssh连接
|
||||
</p>
|
||||
<p><b>使用步骤:</b></p>
|
||||
<ul>
|
||||
<li>在客户端管理中创建一个客户端,记录下验证密钥</li>
|
||||
<li>内网客户端运行<code>
|
||||
<pre>./npc -server={{.ip}}:{{.p}} -vkey=客户端的密钥</pre>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
在该客户端隧道管理中添加一条tcp隧道,填写监听的端口(8001)、内网目标ip和目标端口(10.1.50.101:22),选择压缩方式,保存。
|
||||
</li>
|
||||
<li>
|
||||
访问公网服务器ip({{.ip}}),填写的监听端口(8001),相当于访问内网ip(10.1.50.101):目标端口(22),例如:ssh -p 8001 root@{{.ip}}
|
||||
</li>
|
||||
</ul>
|
||||
<p>注:上文中提到公网ip({{.ip}})为系统自动识别,如果是在测试环境中请自行对应,默认内网客户端已经启动</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="tile">
|
||||
<h3 class="tile-title">udp隧道模式</h3>
|
||||
<p>
|
||||
<b>适用范围:</b> 内网dns解析等udp连接场景
|
||||
</p>
|
||||
<p>
|
||||
<b>假设场景:</b> 内网有一台dns(10.1.50.102:53),在非内网环境下想使用该dns,公网服务器为{{.ip}}
|
||||
</p>
|
||||
<p><b>使用步骤:</b></p>
|
||||
<ul>
|
||||
<li>在客户端管理中创建一个客户端,记录下验证密钥</li>
|
||||
<li>内网客户端运行<code>
|
||||
<pre>./npc -server={{.ip}}:{{.p}} -vkey=客户端的密钥</pre>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
在该客户端的隧道管理中添加一条udp隧道,填写监听的端口(53)、内网目标ip和目标端口(10.1.50.102:53),选择压缩方式,保存。
|
||||
</li>
|
||||
<li>修改本机dns为{{.ip}},则相当于使用10.1.50.202作为dns服务器</li>
|
||||
</ul>
|
||||
<p>注:上文中提到公网ip({{.ip}})为系统自动识别,如果是在测试环境中请自行对应,默认内网客户端已经启动</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="tile">
|
||||
<h3 class="tile-title">socks5代理模式</h3>
|
||||
<p>
|
||||
<b>适用范围:</b> 在外网环境下如同使用vpn一样访问内网设备或者资源
|
||||
</p>
|
||||
<p>
|
||||
<b>假设场景:</b> 想将公网服务器{{.ip}}的8003端口作为socks5代理,达到访问内网任意设备或者资源的效果
|
||||
</p>
|
||||
<p><b>使用步骤:</b></p>
|
||||
<ul>
|
||||
<li>在客户端管理中创建一个客户端,记录下验证密钥</li>
|
||||
<li>内网客户端运行<code>
|
||||
<pre>./npc -server={{.ip}}:{{.p}} -vkey=客户端的密钥</pre>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
在该客户端隧道管理中添加一条socks5代理,填写监听的端口(8003),验证用户名和密码自行选择(建议先不填,部分客户端不支持,proxifer支持),选择压缩方式,保存。
|
||||
</li>
|
||||
<li>
|
||||
在外网环境的本机配置socks5代理,ip为公网服务器ip({{.ip}}),端口为填写的监听端口(8003),即可畅享内网了
|
||||
</li>
|
||||
</ul>
|
||||
<p>注:上文中提到公网ip({{.ip}})为系统自动识别,如果是在测试环境中请自行对应,默认内网客户端已经启动</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="tile">
|
||||
<h3 class="tile-title">http代理模式</h3>
|
||||
<p>
|
||||
<b>适用范围:</b> 在外网环境下访问内网站点
|
||||
</p>
|
||||
<p>
|
||||
<b>假设场景:</b> 想将公网服务器{{.ip}}的8004端口作为http代理,访问内网网站
|
||||
</p>
|
||||
<p><b>使用步骤:</b></p>
|
||||
<ul>
|
||||
<li>在客户端管理中创建一个客户端,记录下验证密钥</li>
|
||||
<li>内网客户端运行<code>
|
||||
<pre>./npc -server={{.ip}}:{{.p}} -vkey=客户端的密钥</pre>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>在该客户端隧道管理中添加一条http代理,填写监听的端口(8004),选择压缩方式,保存。</li>
|
||||
<li>在外网环境的本机配置http代理,ip为公网服务器ip({{.ip}}),端口为填写的监听端口(8004),即可访问了</li>
|
||||
</ul>
|
||||
<p>注:上文中提到公网ip({{.ip}})为系统自动识别,如果是在测试环境中请自行对应,默认内网客户端已经启动</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="tile">
|
||||
<p><b>单个客户端可以添加多条隧道或者域名解析</b></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
374
apps/nps/v0.29.36/web/views/index/hlist.html
Normal file
374
apps/nps/v0.29.36/web/views/index/hlist.html
Normal file
@@ -0,0 +1,374 @@
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="page-hostlist"></h5>
|
||||
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="table-responsive">
|
||||
<div id="toolbar">
|
||||
<a class="btn btn-primary dim" href="{{.web_base_url}}/index/addhost?vkey={{.task_id}}&client_id={{.client_id}}">
|
||||
<i class="fa fa-fw fa-lg fa-plus"></i>
|
||||
<span langtag="word-add"></span>
|
||||
</a>
|
||||
</div>
|
||||
<table class="table-striped table-hover" data-mobile-responsive="true" id="taskList_table"></table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
|
||||
<table id="table"></table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/*bootstrap table*/
|
||||
$('#table').bootstrapTable({
|
||||
toolbar: "#toolbar",
|
||||
method: 'post', // 服务器数据的请求方式 get or post
|
||||
url: window.location, // 服务器数据的加载地址
|
||||
queryParams: function (params) {
|
||||
return {
|
||||
"offset": params.offset,
|
||||
"limit": params.limit,
|
||||
"client_id": {{.client_id}},
|
||||
"search": params.search,
|
||||
"sort": params.sort,
|
||||
"order": params.order
|
||||
}
|
||||
},
|
||||
search: true,
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
striped: true, // 设置为true会有隔行变色效果
|
||||
showHeader: true,
|
||||
showColumns: true,
|
||||
showRefresh: true,
|
||||
pagination: true,//分页
|
||||
sidePagination: 'server',//服务器端分页
|
||||
pageNumber: 1,
|
||||
pageList: [5, 10, 20, 50, 100, 'all'],
|
||||
cookie: true,
|
||||
cookieIdTable: 'host',
|
||||
cookieStorage: 'localStorage',
|
||||
detailView: true,
|
||||
smartDisplay: true, // 智能显示 pagination 和 cardview 等
|
||||
onExpandRow: function () {$('body').setLang ('.detail-view');},
|
||||
onPostBody: function (data) { if ($(this)[0].locale != undefined ) $('body').setLang ('#table'); },
|
||||
detailFormatter: function (index, row, element) {
|
||||
tmp = '<b langtag="word-exportflow"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.ExportFlow) + '</span> '
|
||||
+ '<b langtag="word-inletflow"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow) + '</span> '
|
||||
+ '<b langtag="word-crypt"></b>: <span langtag="word-' + row.Client.Cnf.Crypt + '"></span> '
|
||||
+ '<b langtag="word-compress"></b>: <span langtag="word-' + row.Client.Cnf.Compress + '"></span> '
|
||||
+ '<b langtag="word-flowlimit"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'flow_limit\'})">' + row.Flow.FlowLimit + 'MB</span> '
|
||||
+ '<b langtag="word-timelimit"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'time_limit\'})">' + row.Flow.TimeLimit + '</span> <br/><br>'
|
||||
+ '<b langtag="word-autohttps"></b>: <span onclick="submitform(\'turn\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'auto_https\'})" langtag="word-' + row.AutoHttps + '"></span> '
|
||||
+ '<b langtag="word-autocors"></b>: <span onclick="submitform(\'turn\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'auto_cors\'})" langtag="word-' + row.AutoCORS + '"></span> '
|
||||
+ '<b langtag="word-compatmode"></b>: <span onclick="submitform(\'turn\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'compat_mode\'})" langtag="word-' + row.CompatMode + '"></span> '
|
||||
+ '<b langtag="word-httpsjustproxy"></b>: <span onclick="submitform(\'turn\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'https_just_proxy\'})" langtag="word-' + row.HttpsJustProxy + '"></span> '
|
||||
+ '<b langtag="word-targetishttps"></b>: <span onclick="submitform(\'turn\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'target_is_https\'})" langtag="word-ishttps' + row.TargetIsHttps + '"></span> <br/><br>'
|
||||
+ '<b langtag="word-basicusername"></b>: ' + row.Client.Cnf.U + ' '
|
||||
+ '<b langtag="word-basicpassword"></b>: ' + row.Client.Cnf.P + ' <br/><br>'
|
||||
+ '<b langtag="word-auth"></b>: ' + (row.UserAuth && row.UserAuth.Content ? row.UserAuth.Content : '') + ' <br/><br>'
|
||||
+ '<b langtag="word-requesthost"></b>: ' + row.HostChange + ' <br/><br>'
|
||||
+ '<b langtag="word-requestheader"></b>: ' + row.HeaderChange + ' <br/><br>'
|
||||
+ '<b langtag="word-autossl"></b>: <span onclick="submitform(\'turn\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'auto_ssl\'})" langtag="word-' + row.AutoSSL + '"></span> '
|
||||
if (row.Scheme != "http" && row.HttpsJustProxy == false && row.AutoSSL == false) {
|
||||
return tmp + "<br/><br>"
|
||||
+ '<b langtag="word-httpscert"></b>: <div onclick="oCopy(this)" style="height:60px; max-width:75vw; overflow:auto; white-space:nowrap; border:1px solid #ccc; padding:5px; box-sizing:border-box;">' + row.CertFile + '</div> <br/>'
|
||||
+ '<b langtag="word-httpskey"></b>: <div onclick="oCopy(this)" style="height:60px; max-width:75vw; overflow:auto; white-space:nowrap; border:1px solid #ccc; padding:5px; box-sizing:border-box;">' + row.KeyFile + '</div> <br/><br>'
|
||||
}
|
||||
return tmp
|
||||
},
|
||||
// 表格的列
|
||||
columns: [
|
||||
{
|
||||
field: 'Id', //域值
|
||||
title: '<span langtag="word-id"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Client.Id', //域值
|
||||
title: '<span langtag="word-clientid"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
var text = row.Client.Remark ? (row.Client.Id + ' · ' + row.Client.Remark) : row.Client.Id
|
||||
return '<span onclick="copyText(\'' + row.Client.VerifyKey + '\')">' + text + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Remark', //域值
|
||||
title: '<span langtag="word-remark"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Client.VerifyKey', //域值
|
||||
title: '<span langtag="word-verifykey"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Host', //域值
|
||||
title: '<span langtag="word-host"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
hosturl = ((row.Scheme == 'http') ? 'http://' : 'https://') + row.Host + ((row.Scheme == 'http') ? ":{{.httpProxyPort}}" : ":{{.httpsProxyPort}}") + row.Location
|
||||
return '<a href="' + hosturl + '" target="_blank">' + row.Host + '</a>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Scheme', //域值
|
||||
title: '<span langtag="word-scheme"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span langtag="word-' + value + '"></span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'TargetIsHttps', //域值
|
||||
title: '<span langtag="word-targettype"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span langtag="word-ishttps' + value + '" onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stophost\', {\'id\':' + row.Id + ', \'mode\': \'target_is_https\'})"></span>'
|
||||
} else {
|
||||
return '<span langtag="word-ishttps' + value + '" onclick="submitform(\'start\', \'{{.web_base_url}}/index/starthost\', {\'id\':' + row.Id + ', \'mode\': \'target_is_https\'})"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Target.TargetStr', //域值
|
||||
title: '<span langtag="word-target"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Location', //域值
|
||||
title: '<span langtag="word-path"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'PathRewrite', //域值
|
||||
title: '<span langtag="word-pathrewrite"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'HttpsJustProxy', //域值
|
||||
title: '<span langtag="word-httpsjustproxytitle"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stophost\', {\'id\':' + row.Id + ', \'mode\': \'https_just_proxy\'})"></span>'
|
||||
} else {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'start\', \'{{.web_base_url}}/index/starthost\', {\'id\':' + row.Id + ', \'mode\': \'https_just_proxy\'})"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'AutoSSL', //域值
|
||||
title: '<span langtag="word-autossl"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stophost\', {\'id\':' + row.Id + ', \'mode\': \'auto_ssl\'})"></span>'
|
||||
} else {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'start\', \'{{.web_base_url}}/index/starthost\', {\'id\':' + row.Id + ', \'mode\': \'auto_ssl\'})"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'AutoHttps', //域值
|
||||
title: '<span langtag="word-autohttpstitle"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stophost\', {\'id\':' + row.Id + ', \'mode\': \'auto_https\'})"></span>'
|
||||
} else {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'start\', \'{{.web_base_url}}/index/starthost\', {\'id\':' + row.Id + ', \'mode\': \'auto_https\'})"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'AutoCORS', //域值
|
||||
title: '<span langtag="word-autocorstitle"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stophost\', {\'id\':' + row.Id + ', \'mode\': \'auto_cors\'})"></span>'
|
||||
} else {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'start\', \'{{.web_base_url}}/index/starthost\', {\'id\':' + row.Id + ', \'mode\': \'auto_cors\'})"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'CompatMode', //域值
|
||||
title: '<span langtag="word-compatmode"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stophost\', {\'id\':' + row.Id + ', \'mode\': \'compat_mode\'})"></span>'
|
||||
} else {
|
||||
return '<span langtag="word-' + value + '" onclick="submitform(\'start\', \'{{.web_base_url}}/index/starthost\', {\'id\':' + row.Id + ', \'mode\': \'compat_mode\'})"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'InletFlow', //域值
|
||||
title: '<span langtag="word-inletflow"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'ExportFlow', //域值
|
||||
title: '<span langtag="word-exportflow"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.ExportFlow) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'TotalFlow', //域值
|
||||
title: '<span langtag="word-totalflow"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clearhost\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow + row.Flow.ExportFlow) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'NowConn', //域值
|
||||
title: '<span langtag="word-nowconn"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'IsClose', //域值
|
||||
title: '<span langtag="word-runstatus"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span class="badge badge-badge" langtag="word-close"></span>'
|
||||
} else {
|
||||
return '<span class="badge badge-primary" langtag="word-open"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Client.IsConnect', //域值
|
||||
title: '<span langtag="word-clientstatus"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true,//启用排序
|
||||
formatter: function (value, row, index) {
|
||||
hosturl = ((row.Scheme == 'http') ? 'http://' : 'https://') + row.Host + row.Location
|
||||
if (value) {
|
||||
return '<a href="' + hosturl + '" target="_blank"><span class="badge badge-primary" langtag="word-online"></span></a>'
|
||||
} else {
|
||||
return '<span class="badge badge-badge" langtag="word-offline"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'option', //域值
|
||||
title: '<span langtag="word-option"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
formatter: function (value, row, index) {
|
||||
btn_group = '<div class="btn-group">'
|
||||
if (row.IsClose) {
|
||||
btn_group += "<a onclick=\"submitform('start', '{{.web_base_url}}/index/starthost', {\'id\':" + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-primary"><i class="fa fa-play"></i></a>'
|
||||
} else {
|
||||
btn_group += "<a onclick=\"submitform('stop', '{{.web_base_url}}/index/stophost', {'id':" + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-warning"><i class="fa fa-pause"></i></a>'
|
||||
}
|
||||
btn_group += "<a onclick=\"submitform('delete', '{{.web_base_url}}/index/delhost', {'id':" + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-danger"><i class="fa fa-trash"></i></a>'
|
||||
btn_group += '<a href="{{.web_base_url}}/index/edithost?id=' + row.Id
|
||||
btn_group += '" class="btn btn-outline btn-success"><i class="fa fa-edit"></i></a></div>'
|
||||
return btn_group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
</script>
|
||||
936
apps/nps/v0.29.36/web/views/index/index.html
Normal file
936
apps/nps/v0.29.36/web/views/index/index.html
Normal file
@@ -0,0 +1,936 @@
|
||||
<div class="wrapper wrapper-content">
|
||||
{{if eq false .isAdmin}}
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-tcpports"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins">{{or .tcp_p "0"}} / {{or .tls_p "0"}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-kcpport"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins">{{or .kcp_p "0"}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-wsports"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins">{{or .ws_p "0"}} / {{or .wss_p "0"}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-wspath"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins">{{or .ws_path "/ws"}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-serverip"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins">{{.ip}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-serverversion"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins">{{.data.version}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-minsupportversion"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins">{{.data.minVersion}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-iprestriction"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins" langtag="word-{{or .data.ipLimit "false"}}"></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq true .isAdmin}}
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-totalclients"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins" id="stat-clientCount">{{.data.clientCount}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
{{/*<span class="label label-primary pull-right">今日</span>*/}}
|
||||
<h5 langtag="word-onlineclients"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins" id="stat-clientOnlineCount">{{.data.clientOnlineCount}}</h1>
|
||||
{{/*<div class="stat-percent font-bold text-navy">44% <i class="fa fa-level-up"></i></div>*/}}
|
||||
{{/*<small>新访客</small>*/}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-tcpconnections"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins" id="stat-tcpCount">{{.data.tcpCount}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-uptime"></h5>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<h1 class="no-margins" id="stat-upTime">{{or .data.upTime ""}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-configurationinformation"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content no-padding">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<strong langtag="word-bridgingmode"></strong>
|
||||
</div>
|
||||
<div class="col-sm-8 text-right">
|
||||
<strong>{{if index . "tcp_p"}}TCP:{{.tcp_p}} {{end}}{{if index . "kcp_p"}}KCP:{{.kcp_p}} {{end}}{{if index . "tls_p"}}TLS:{{.tls_p}} {{end}}{{if index . "ws_p"}}WS:{{.ws_p}} {{end}}{{if index . "wss_p"}}WSS:{{.wss_p}} {{end}}{{if index . "ws_path"}}Path:{{.ws_path}}{{end}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-httpports"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong>{{or .data.httpProxyPort "0"}} / {{or .data.httpsProxyPort "0"}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-iprestriction"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong langtag="word-{{or .data.ipLimit "false"}}"></strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-trafficdatapersistence"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong>{{.data.flowStoreInterval}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-loglevel"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong>{{.data.logLevel}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<strong langtag="word-p2paddr"></strong>
|
||||
</div>
|
||||
<div class="col-sm-8 text-right">
|
||||
<strong>{{.data.p2pAddr}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<strong langtag="word-serverip"></strong>
|
||||
</div>
|
||||
<div class="col-sm-10 text-right">
|
||||
<strong>{{.data.p2pIp}} | {{.data.serverIpv4}} | {{.data.serverIpv6}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-serverversion"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong>{{.data.version}} ({{.data.minVersion}})</strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-systeminformation"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content no-padding">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-cpu"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong id="overview_cpu"></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress progress-small">
|
||||
<div class="progress-bar" id="overview_cpu_bar"></div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-memory"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong id="overview_memory"></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress progress-small">
|
||||
<div class="progress-bar" id="overview_memory_bar"></div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-load"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong id="overview_load"></strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-tcpconnections_established"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong id="overview_tcp"></strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-udpconnections_established"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong id="overview_udp"></strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-outbandwidth"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong id="overview_send"></strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item ">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<strong langtag="word-inbandwidth"></strong>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<strong id="overview_recv"></strong>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if eq true .isAdmin}}
|
||||
{{if eq true .system_info_display}}
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-load"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div id="load" style="height: 300px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-cpu"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div id="cpu" style="height: 300px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-memory"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div id="memory" style="height: 300px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-connections_established"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div id="connections" style="height: 300px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-bandwidth"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div id="bandwidth" style="height: 300px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-trafficstatistics"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div id="flow" style="height: 400px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 langtag="word-type"></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div id="counts" style="height:400px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if eq true .isAdmin}}
|
||||
<script>
|
||||
$("#overview_cpu").text("{{.data.cpu}}%")
|
||||
$("#overview_cpu_bar").width("{{.data.cpu}}%")
|
||||
$("#overview_memory").text("{{.data.virtual_mem}}%")
|
||||
$("#overview_memory_bar").width("{{.data.virtual_mem}}%")
|
||||
$.each( JSON.parse({{.data.load}}), function(i, value) { $("#overview_load").append(' ' + value) });
|
||||
$("#overview_tcp").text("{{.data.tcp}}")
|
||||
$("#overview_udp").text("{{.data.udp}}")
|
||||
$("#overview_send").text(changeunit({{.data.io_send}}) + "/s")
|
||||
$("#overview_recv").text(changeunit({{.data.io_recv}}) + "/s")
|
||||
|
||||
const chartTextColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--text').trim();
|
||||
const chartBgColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--bg').trim();
|
||||
|
||||
echarts.registerTheme('nps-theme', {
|
||||
textStyle: {
|
||||
color: chartTextColor,
|
||||
textBorderColor: chartBgColor,
|
||||
textBorderWidth: 0
|
||||
},
|
||||
axisPointer: { label: { color: chartTextColor, textBorderColor: chartBgColor } },
|
||||
tooltip: { textStyle: { color: chartTextColor, textBorderColor: chartBgColor } },
|
||||
legend: { textStyle: { color: chartTextColor, textBorderColor: chartBgColor } },
|
||||
xAxis: { axisLabel: { color: chartTextColor, textBorderColor: chartBgColor } },
|
||||
yAxis: { axisLabel: { color: chartTextColor, textBorderColor: chartBgColor } },
|
||||
series: [{
|
||||
label: {
|
||||
color: chartTextColor,
|
||||
textBorderColor: chartBgColor,
|
||||
textBorderWidth: 0
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
color: chartTextColor,
|
||||
textBorderColor: chartBgColor,
|
||||
textBorderWidth: 0
|
||||
}
|
||||
}
|
||||
}],
|
||||
pie: {
|
||||
label: {
|
||||
color: chartTextColor,
|
||||
textBorderColor: chartBgColor,
|
||||
textBorderWidth: 0
|
||||
},
|
||||
labelLine: {
|
||||
lineStyle: {
|
||||
color: chartTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chartdatas['load'] = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function (params) {
|
||||
var str = params[0].axisValue + '<br/>';
|
||||
for (i in params){
|
||||
str += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + params[i].color + ';"></span>' + params[i].seriesName +': '+ params[i].data +'</br>';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
top: '5%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['{{.data.sys1.time}}', '{{.data.sys2.time}}', '{{.data.sys3.time}}', '{{.data.sys4.time}}', '{{.data.sys5.time}}', '{{.data.sys6.time}}', '{{.data.sys7.time}}', '{{.data.sys8.time}}', '{{.data.sys9.time}}', '{{.data.sys10.time}}']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'load1',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.load1}}, {{.data.sys2.load1}}, {{.data.sys3.load1}}, {{.data.sys4.load1}}, {{.data.sys5.load1}}, {{.data.sys6.load1}}, {{.data.sys7.load1}}, {{.data.sys8.load1}}, {{.data.sys9.load1}}, {{.data.sys10.load1}}]
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'load5',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.load5}}, {{.data.sys2.load5}}, {{.data.sys3.load5}}, {{.data.sys4.load5}}, {{.data.sys5.load5}}, {{.data.sys6.load5}}, {{.data.sys7.load5}}, {{.data.sys8.load5}}, {{.data.sys9.load5}}, {{.data.sys10.load5}}]
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'load15',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.load15}}, {{.data.sys2.load15}}, {{.data.sys3.load15}}, {{.data.sys4.load15}}, {{.data.sys5.load15}}, {{.data.sys6.load15}}, {{.data.sys7.load15}}, {{.data.sys8.load15}}, {{.data.sys9.load15}}, {{.data.sys10.load15}}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chartdatas['cpu'] = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function (params) {
|
||||
var str = params[0].axisValue + '<br/>';
|
||||
for (i in params){
|
||||
str += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + params[i].color + ';"></span>' + params[i].seriesName +': '+ params[i].data +'%</br>';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
top: '5%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['{{.data.sys1.time}}', '{{.data.sys2.time}}', '{{.data.sys3.time}}', '{{.data.sys4.time}}', '{{.data.sys5.time}}', '{{.data.sys6.time}}', '{{.data.sys7.time}}', '{{.data.sys8.time}}', '{{.data.sys9.time}}', '{{.data.sys10.time}}']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
show: true,
|
||||
interval: 'auto',
|
||||
formatter: '{value} %'
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'cpu',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.cpu}}, {{.data.sys2.cpu}}, {{.data.sys3.cpu}}, {{.data.sys4.cpu}}, {{.data.sys5.cpu}}, {{.data.sys6.cpu}}, {{.data.sys7.cpu}}, {{.data.sys8.cpu}}, {{.data.sys9.cpu}}, {{.data.sys10.cpu}}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chartdatas['memory'] = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function (params) {
|
||||
var str = params[0].axisValue + '<br/>';
|
||||
for (i in params){
|
||||
str += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + params[i].color + ';"></span>' + params[i].seriesName +': '+ params[i].data +'MB</br>';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
top: '5%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['{{.data.sys1.time}}', '{{.data.sys2.time}}', '{{.data.sys3.time}}', '{{.data.sys4.time}}', '{{.data.sys5.time}}', '{{.data.sys6.time}}', '{{.data.sys7.time}}', '{{.data.sys8.time}}', '{{.data.sys9.time}}', '{{.data.sys10.time}}']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
show: true,
|
||||
interval: 'auto',
|
||||
formatter: '{value} MB'
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'virtual_mem',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.virtual_mem}}, {{.data.sys2.virtual_mem}}, {{.data.sys3.virtual_mem}}, {{.data.sys4.virtual_mem}}, {{.data.sys5.virtual_mem}}, {{.data.sys6.virtual_mem}}, {{.data.sys7.virtual_mem}}, {{.data.sys8.virtual_mem}}, {{.data.sys9.virtual_mem}}, {{.data.sys10.virtual_mem}}]
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'swap_mem',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.swap_mem}}, {{.data.sys2.swap_mem}}, {{.data.sys3.swap_mem}}, {{.data.sys4.swap_mem}}, {{.data.sys5.swap_mem}}, {{.data.sys6.swap_mem}}, {{.data.sys7.swap_mem}}, {{.data.sys8.swap_mem}}, {{.data.sys9.swap_mem}}, {{.data.sys10.swap_mem}}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chartdatas['connections'] = {
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
top: '5%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['{{.data.sys1.time}}', '{{.data.sys2.time}}', '{{.data.sys3.time}}', '{{.data.sys4.time}}', '{{.data.sys5.time}}', '{{.data.sys6.time}}', '{{.data.sys7.time}}', '{{.data.sys8.time}}', '{{.data.sys9.time}}', '{{.data.sys10.time}}']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'tcp',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.tcp}}, {{.data.sys2.tcp}}, {{.data.sys3.tcp}}, {{.data.sys4.tcp}}, {{.data.sys5.tcp}}, {{.data.sys6.tcp}}, {{.data.sys7.tcp}}, {{.data.sys8.tcp}}, {{.data.sys9.tcp}}, {{.data.sys10.tcp}}]
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'udp',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.udp}}, {{.data.sys2.udp}}, {{.data.sys3.udp}}, {{.data.sys4.udp}}, {{.data.sys5.udp}}, {{.data.sys6.udp}}, {{.data.sys7.udp}}, {{.data.sys8.udp}}, {{.data.sys9.udp}}, {{.data.sys10.udp}}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chartdatas['bandwidth'] = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function (params) {
|
||||
var str = params[0].axisValue + '<br/>';
|
||||
for (i in params){
|
||||
str += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + params[i].color + ';"></span>' + params[i].seriesName +': '+ changeunit(params[i].data) +'/s</br>';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
top: '5%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['{{.data.sys1.time}}', '{{.data.sys2.time}}', '{{.data.sys3.time}}', '{{.data.sys4.time}}', '{{.data.sys5.time}}', '{{.data.sys6.time}}', '{{.data.sys7.time}}', '{{.data.sys8.time}}', '{{.data.sys9.time}}', '{{.data.sys10.time}}']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
show: true,
|
||||
interval: 'auto',
|
||||
formatter: function (params){
|
||||
return changeunit (params);
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'in',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.io_recv}}, {{.data.sys2.io_recv}}, {{.data.sys3.io_recv}}, {{.data.sys4.io_recv}}, {{.data.sys5.io_recv}}, {{.data.sys6.io_recv}}, {{.data.sys7.io_recv}}, {{.data.sys8.io_recv}}, {{.data.sys9.io_recv}}, {{.data.sys10.io_recv}}]
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
type: 'line',
|
||||
stack: 'out',
|
||||
smooth: true,
|
||||
data: [{{.data.sys1.io_send}}, {{.data.sys2.io_send}}, {{.data.sys3.io_send}}, {{.data.sys4.io_send}}, {{.data.sys5.io_send}}, {{.data.sys6.io_send}}, {{.data.sys7.io_send}}, {{.data.sys8.io_send}}, {{.data.sys9.io_send}}, {{.data.sys10.io_send}}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chartdatas['flow'] = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function (p) {
|
||||
return p.seriesName + '<br>' + p.name + ':' + changeunit(p.data.value);
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: ['', '']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
radius: '55%',
|
||||
center: ['50%', '60%'],
|
||||
data: [
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.inletFlowCount}}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.exportFlowCount}}
|
||||
}
|
||||
],
|
||||
itemStyle: {
|
||||
emphasis: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chartdatas['counts'] = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: ['', '', '', '', '', '', '']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
radius: '55%',
|
||||
center: ['50%', '60%'],
|
||||
data: [
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.hostCount}}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.tcpC}}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.udpCount}}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.httpProxyCount}}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.socks5Count}}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.secretCount}}
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
value:{{.data.p2pCount}}
|
||||
}
|
||||
],
|
||||
itemStyle: {
|
||||
emphasis: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
window.charts = window.charts || {};
|
||||
Object.keys(chartdatas).forEach(key => {
|
||||
const dom = document.getElementById(key);
|
||||
if (dom) {
|
||||
window.charts[key] = echarts.init(dom, 'nps-theme');
|
||||
window.charts[key].setOption(chartdatas[key]);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
for (var key in charts) {
|
||||
charts[key].resize();
|
||||
}
|
||||
});
|
||||
|
||||
let upTimeSeconds = 0;
|
||||
|
||||
function formatUpTime(secs) {
|
||||
const d = Math.floor(secs / 86400);
|
||||
secs %= 86400;
|
||||
const h = Math.floor(secs / 3600);
|
||||
secs %= 3600;
|
||||
const m = Math.floor(secs / 60);
|
||||
const s = secs % 60;
|
||||
const parts = [];
|
||||
if (d) parts.push(d + 'd');
|
||||
if (h) parts.push(h + 'h');
|
||||
if (m) parts.push(m + 'm');
|
||||
parts.push(s + 's');
|
||||
return parts.join(' ');
|
||||
}
|
||||
|
||||
function ensureChart(key) {
|
||||
if (!charts[key]) {
|
||||
const dom = document.getElementById(key);
|
||||
if (dom) {
|
||||
charts[key] = echarts.init(dom, 'nps-theme');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function refreshStats() {
|
||||
$.getJSON('{{.web_base_url}}/index/stats', function(res) {
|
||||
if (res.code !== 1) return;
|
||||
const d = res.data;
|
||||
$('#stat-clientCount').text(d.clientCount);
|
||||
$('#stat-clientOnlineCount').text(d.clientOnlineCount);
|
||||
$('#stat-tcpCount').text(d.tcpCount);
|
||||
const nowSecs = Math.floor(Date.now() / 1000);
|
||||
upTimeSeconds = nowSecs - d.startTime;
|
||||
$('#overview_cpu').text(d.cpu + '%');
|
||||
$('#overview_cpu_bar').width(d.cpu + '%');
|
||||
$('#overview_memory').text(d.virtual_mem + '%');
|
||||
$('#overview_memory_bar').width(d.virtual_mem + '%');
|
||||
const loadObj = JSON.parse(d.load);
|
||||
$('#overview_load')
|
||||
.empty()
|
||||
.append([loadObj.load1, loadObj.load5, loadObj.load15]
|
||||
.map(v => ' '+v).join(''));
|
||||
$('#overview_tcp').text(d.tcp);
|
||||
$('#overview_udp').text(d.udp);
|
||||
$('#overview_send').text(changeunit(d.io_send) + '/s');
|
||||
$('#overview_recv').text(changeunit(d.io_recv) + '/s');
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
refreshStats();
|
||||
setInterval(refreshStats, 3000);
|
||||
setInterval(function() {
|
||||
upTimeSeconds++;
|
||||
$('#stat-upTime').text(formatUpTime(upTimeSeconds));
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
374
apps/nps/v0.29.36/web/views/index/list.html
Normal file
374
apps/nps/v0.29.36/web/views/index/list.html
Normal file
@@ -0,0 +1,374 @@
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5><span id="langtag"></span><span></span></h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="table-responsive">
|
||||
<div id="toolbar">
|
||||
{{ if or (not .type) (ne .type "file") }}
|
||||
<a class="btn btn-primary dim" href="{{.web_base_url}}/index/add?type={{.type}}&client_id={{.client_id}}">
|
||||
<i class="fa fa-fw fa-lg fa-plus"></i>
|
||||
<span langtag="word-add"></span>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
<table class="table-striped table-hover" data-mobile-responsive="true" id="taskList_table"></table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<table id="table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
name = '{{.name}}:'.replace(/\s*/g, "")
|
||||
$('#langtag').attr('langtag', 'page-list' + name.replace(/:.*/, "")).next().text(name.split(":")[1])
|
||||
|
||||
/*bootstrap table*/
|
||||
$('#table').bootstrapTable({
|
||||
toolbar: "#toolbar",
|
||||
method: 'post', // 服务器数据的请求方式 get or post
|
||||
url: "{{.web_base_url}}/index/gettunnel", // 服务器数据的加载地址
|
||||
queryParams: function (params) {
|
||||
return {
|
||||
"offset": params.offset,
|
||||
"limit": params.limit,
|
||||
"type": {{.type}},
|
||||
"client_id": {{.client_id}},
|
||||
"search": params.search,
|
||||
"sort": params.sort,
|
||||
"order": params.order
|
||||
}
|
||||
},
|
||||
search: true,
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
striped: true, // 设置为true会有隔行变色效果
|
||||
showHeader: true,
|
||||
showColumns: true,
|
||||
showRefresh: true,
|
||||
pagination: true, //分页
|
||||
sidePagination: 'server', //服务器端分页
|
||||
pageNumber: 1,
|
||||
pageList: [5, 10, 20, 50, 100, 'all'],
|
||||
cookie: true,
|
||||
cookieIdTable: '{{.type}}',
|
||||
cookieStorage: 'localStorage',
|
||||
detailView: true,
|
||||
smartDisplay: true, // 智能显示 pagination 和 cardview 等
|
||||
onExpandRow: function () {$('body').setLang ('.detail-view');},
|
||||
onLoadSuccess:function (data) {$('body').setLang ('.detail-view');},
|
||||
onPostBody: function (data) { if ($(this)[0].locale != undefined ) $('body').setLang ('#table'); },
|
||||
detailFormatter: function (index, row, element) {
|
||||
tmp = '<b langtag="word-exportflow"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.ExportFlow) + '</span> '
|
||||
+ '<b langtag="word-inletflow"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow) + '</span> '
|
||||
+ '<b langtag="word-crypt"></b>: <span langtag="word-' + row.Client.Cnf.Crypt + '"></span> '
|
||||
+ '<b langtag="word-compress"></b>: <span langtag="word-' + row.Client.Cnf.Compress + '"></span> '
|
||||
+ '<b langtag="word-ishttp"></b>: <span langtag="word-' + row.IsHttp + '"></span> <br/><br>'
|
||||
+ '<b langtag="word-flowlimit"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow_limit\'})">' + row.Flow.FlowLimit + 'MB</span> '
|
||||
+ '<b langtag="word-timelimit"></b>: <span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clear\', {\'id\':' + row.Id + ', \'mode\': \'time_limit\'})">' + row.Flow.TimeLimit + '</span> '
|
||||
if (row.Mode == "mixProxy") {
|
||||
return tmp + "<br/><br>"
|
||||
+ '<b langtag="word-basicusername"></b>: ' + row.Client.Cnf.U + ' '
|
||||
+ '<b langtag="word-basicpassword"></b>: ' + row.Client.Cnf.P + ' <br/><br>'
|
||||
+ '<b langtag="word-auth"></b>: ' + (row.UserAuth && row.UserAuth.Content ? row.UserAuth.Content : '') + ' <br/><br>'
|
||||
}
|
||||
if (row.Mode == "file") {
|
||||
return tmp + "<br/><br>"
|
||||
+ '<b langtag="word-localpath"></b>: ' + row.LocalPath + ' '
|
||||
+ '<b langtag="word-stripprefix"></b>: ' + row.StripPre + ' '
|
||||
}
|
||||
if (row.Mode == "p2p") {
|
||||
return tmp + "<br/><br>"
|
||||
+ '<b langtag="word-commandaccessp2p"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.addr}} -vkey=" + row.Client.VerifyKey
|
||||
+ " -type=" + {{.bridgeType}} + " -password=" + row.Password + " -target=" + row.Target.TargetStr + "</code>" + "<br/><br>"
|
||||
+ '<b langtag="word-commandaccessp2ps"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.addr}} -vkey=" + row.Client.VerifyKey
|
||||
+ " -type=" + {{.bridgeType}} + " -password=" + row.Password + " -local_type=p2ps" + "</code>" + "<br/><br>"
|
||||
+ '<b langtag="word-commandaccessp2pt"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.addr}} -vkey=" + row.Client.VerifyKey
|
||||
+ " -type=" + {{.bridgeType}} + " -password=" + row.Password + " -local_type=p2pt" + "</code>"
|
||||
}
|
||||
if (row.Mode == "secret") {
|
||||
return tmp + "<br/><br>" + '<b langtag="word-commandaccess"></b>: ' + '<code onclick="oCopy(this)">' + "./npc{{.win}} -server={{.addr}} -vkey=" + row.Client.VerifyKey
|
||||
+ " -type=" + {{.bridgeType}} + " -password=" + row.Password + " -local_type=secret" + "</code>"
|
||||
}
|
||||
return tmp
|
||||
},
|
||||
// 表格的列
|
||||
columns: [
|
||||
{
|
||||
field: 'Id', //域值
|
||||
title: '<span langtag="word-id"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Client.Id', //域值
|
||||
title: '<span langtag="word-clientid"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
var text = row.Client.Remark ? (row.Client.Id + ' · ' + row.Client.Remark) : row.Client.Id
|
||||
return '<span onclick="copyText(\'' + row.Client.VerifyKey + '\')">' + text + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Remark', //域值
|
||||
title: '<span langtag="word-remark"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Client.VerifyKey', //域值
|
||||
title: '<span langtag="word-verifykey"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{{ if not .type }}
|
||||
{
|
||||
field: 'Mode', //域值
|
||||
title: '<span langtag="word-scheme"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span langtag="scheme-' + value + '"></span>'
|
||||
}
|
||||
},
|
||||
{{ end }}
|
||||
{
|
||||
field: 'Port', //域值
|
||||
title: '<span langtag="word-port"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{{ if or (not .type) (eq .type "tcp") (eq .type "udp") (eq .type "secret") (eq .type "p2p") }}
|
||||
{
|
||||
field: 'Target.TargetStr', //域值
|
||||
title: '<span langtag="word-target"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{{ end }}
|
||||
{{ if or (not .type) (eq .type "secret") (eq .type "p2p") }}
|
||||
{
|
||||
field: 'Password', //域值
|
||||
title: '<span langtag="word-identificationkey"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{{ end }}
|
||||
{{ if and .type (eq .type "file") }}
|
||||
{
|
||||
field: 'LocalPath', //域值
|
||||
title: '<span langtag="word-localpath"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true //false表示不显示
|
||||
},
|
||||
{
|
||||
field: 'StripPre', //域值
|
||||
title: '<span langtag="word-stripprefix"></span>', //标题
|
||||
halign: 'center',
|
||||
visible: true //false表示不显示
|
||||
},
|
||||
{{ end }}
|
||||
{{ if and .type (eq .type "mixProxy") }}
|
||||
{
|
||||
field: 'HttpProxy', //域值
|
||||
title: '<span langtag="word-httpproxy"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
btn_group = '<div class="btn-group">'
|
||||
if (value) {
|
||||
btn_group += '<a onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stop\', {\'id\':' + row.Id + ', \'mode\': \'http\'})" class="btn btn-outline btn-warning"><i class="fa fa-pause"></i></a>'
|
||||
} else {
|
||||
btn_group += '<a onclick="submitform(\'start\', \'{{.web_base_url}}/index/start\', {\'id\':' + row.Id + ', \'mode\': \'http\'})" class="btn btn-outline btn-primary"><i class="fa fa-play"></i></a>'
|
||||
}
|
||||
btn_group += '</div>'
|
||||
return btn_group
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Socks5Proxy', //域值
|
||||
title: '<span langtag="word-socks5proxy"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
btn_group = '<div class="btn-group">'
|
||||
if (value) {
|
||||
btn_group += '<a onclick="submitform(\'stop\', \'{{.web_base_url}}/index/stop\', {\'id\':' + row.Id + ', \'mode\': \'socks5\'})" class="btn btn-outline btn-warning"><i class="fa fa-pause"></i></a>'
|
||||
} else {
|
||||
btn_group += '<a onclick="submitform(\'start\', \'{{.web_base_url}}/index/start\', {\'id\':' + row.Id + ', \'mode\': \'socks5\'})" class="btn btn-outline btn-primary"><i class="fa fa-play"></i></a>'
|
||||
}
|
||||
btn_group += '</div>'
|
||||
return btn_group
|
||||
}
|
||||
},
|
||||
{{ end }}
|
||||
{
|
||||
field: 'InletFlow', //域值
|
||||
title: '<span langtag="word-inletflow"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'ExportFlow', //域值
|
||||
title: '<span langtag="word-exportflow"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.ExportFlow) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'TotalFlow', //域值
|
||||
title: '<span langtag="word-totalflow"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="submitform(\'clear\', \'{{.web_base_url}}/index/clear\', {\'id\':' + row.Id + ', \'mode\': \'flow\'})">' + changeunit(row.Flow.InletFlow + row.Flow.ExportFlow) + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'NowConn', //域值
|
||||
title: '<span langtag="word-nowconn"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
return '<span onclick="oCopy(this)">' + value + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Status', //域值
|
||||
title: '<span langtag="word-status"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: false, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span class="badge badge-primary" langtag="word-open"></span>'
|
||||
} else {
|
||||
return '<span class="badge badge-badge" langtag="word-close"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'RunStatus', //域值
|
||||
title: '<span langtag="word-runstatus"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
if (row.Mode && row.Mode == "tcp") {
|
||||
return '<a href="' + 'http://{{.ip}}:' + row.Port + '" target="_blank"><span class="badge badge-primary" langtag="word-open"></span></a>'
|
||||
} else {
|
||||
return '<span class="badge badge-primary" langtag="word-open"></span>'
|
||||
}
|
||||
} else {
|
||||
return '<span class="badge badge-badge" langtag="word-close"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'Client.IsConnect', //域值
|
||||
title: '<span langtag="word-clientstatus"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
sortable: true, //启用排序
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
if (row.Mode && row.Mode == "tcp") {
|
||||
return '<a href="' + (row.IsHttp ? 'http://' : 'https://') + '{{.ip}}:' + row.Port + '" target="_blank"><span class="badge badge-primary" langtag="word-online"></span></a>'
|
||||
} else {
|
||||
return '<span class="badge badge-primary" langtag="word-online"></span>'
|
||||
}
|
||||
} else {
|
||||
return '<span class="badge badge-badge" langtag="word-offline"></span>'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'option', //域值
|
||||
title: '<span langtag="word-option"></span>', //内容
|
||||
align: 'center',
|
||||
halign: 'center',
|
||||
visible: true, //false表示不显示
|
||||
formatter: function (value, row, index) {
|
||||
btn_group = '<div class="btn-group">'
|
||||
if (row.Status) {
|
||||
btn_group += "<a onclick=\"submitform('stop', '{{.web_base_url}}/index/stop', {'id':" + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-warning"><i class="fa fa-pause"></i></a>'
|
||||
} else {
|
||||
btn_group += "<a onclick=\"submitform('start', '{{.web_base_url}}/index/start', {\'id\':" + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-primary"><i class="fa fa-play"></i></a>'
|
||||
}
|
||||
btn_group += "<a onclick=\"submitform('delete', '{{.web_base_url}}/index/del', {'id':" + row.Id
|
||||
btn_group += '})" class="btn btn-outline btn-danger"><i class="fa fa-trash"></i></a>'
|
||||
if (row.Mode && row.Mode !== "file") {
|
||||
btn_group += '<a href="{{.web_base_url}}/index/edit?id=' + row.Id + '" class="btn btn-outline btn-success"><i class="fa fa-edit"></i></a>'
|
||||
}
|
||||
btn_group += '</div>'
|
||||
return btn_group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
</script>
|
||||
136
apps/nps/v0.29.36/web/views/login/index.html
Normal file
136
apps/nps/v0.29.36/web/views/login/index.html
Normal file
@@ -0,0 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title langtag="title-login"></title>
|
||||
<!-- Mainly scripts -->
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link href="{{.web_base_url}}/static/css/fontawesome.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/solid.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/style.css?v={{.version}}" rel="stylesheet">
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="{{.web_base_url}}/static/js/jquery-3.7.1.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/bootstrap.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/jsencrypt.min.js"></script>
|
||||
<!-- Latest compiled and minified Locales -->
|
||||
<script src="{{.web_base_url}}/static/js/language.js?v={{.version}}" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body class="login-page">
|
||||
<nav class="navbar navbar-static-top navbar-right navbar-login">
|
||||
<div class="ml-auto d-flex align-items-center" style="gap: 0.5rem;">
|
||||
<button id="theme-toggle" class="btn btn-outline-secondary" onclick="toggleTheme()">
|
||||
<i class="fa fa-moon"></i>
|
||||
</button>
|
||||
<span class="btn-group dropdown">
|
||||
<button id="languagemenu" class="btn btn-outline-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-globe-asia fa-lg"></i>
|
||||
<span></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu"></ul>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="login-card">
|
||||
<div class="login-header">
|
||||
<img src="{{.web_base_url}}/static/img/nps.svg?v={{.version}}" alt="Logo" style="width: 32px; height: 32px; margin-right: 20px !important;">
|
||||
<div class="navbar-brand" style="font-weight: lighter; font-size: 2.0rem !important"><h1 langtag="title-login"></h1></div>
|
||||
</div>
|
||||
<div class="login-body">
|
||||
<form class="m-t" onsubmit="return false;">
|
||||
<div class="form-group position-relative">
|
||||
<i class="fas fa-user-circle input-icon"></i>
|
||||
<input class="form-control" langtag="word-username" name="username" placeholder="username" required="" type="text">
|
||||
</div>
|
||||
<div class="form-group position-relative">
|
||||
<i class="fas fa-key input-icon"></i>
|
||||
<input class="form-control" langtag="word-password" name="password" placeholder="password" required="" type="password">
|
||||
</div>
|
||||
{{if eq true .captcha_open}}
|
||||
<div class="form-group captcha-group position-relative">
|
||||
<div class="flex-fill">
|
||||
<i class="fas fa-shield-alt input-icon"></i>
|
||||
<input class="form-control" langtag="word-captcha" name="captcha" placeholder="captcha" required="">
|
||||
</div>
|
||||
<div class="captcha-container">
|
||||
{{create_captcha}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<button class="btn btn-primary block full-width m-b" langtag="word-login" onclick="if (this.form.reportValidity()) login()" type="submit"></button>
|
||||
{{if eq true .register_allow}}
|
||||
<p class="text-muted text-center">
|
||||
<small langtag="info-noaccount"></small>
|
||||
<small><a href="{{.web_base_url}}/login/register" langtag="word-register"></a></small>
|
||||
</p>
|
||||
{{end}}
|
||||
</form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="float-right">
|
||||
<span langtag="word-readmore"></span>
|
||||
<strong><a href="https://github.com/djylb/nps" langtag="word-go"></a></strong>
|
||||
</div>
|
||||
<div><strong langtag="word-copyright"></strong> <span langtag="application"></span> © 2018-{{.year}}</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.nps = {
|
||||
web_base_url: "{{.web_base_url}}",
|
||||
version: "{{.version}}",
|
||||
publicKey: `{{.public_key}}`,
|
||||
loginNonce: "{{.login_nonce}}"
|
||||
};
|
||||
function encryptWithRSA(plain) {
|
||||
const crypt = new JSEncrypt();
|
||||
crypt.setPublicKey(window.nps.publicKey);
|
||||
return crypt.encrypt(plain);
|
||||
}
|
||||
function login() {
|
||||
const data = {};
|
||||
$("form").serializeArray().forEach(item => {
|
||||
data[item.name] = item.value;
|
||||
});
|
||||
const ts = Date.now();
|
||||
const payload = JSON.stringify({
|
||||
n: window.nps.loginNonce,
|
||||
t: ts,
|
||||
p: data.password
|
||||
});
|
||||
data.password = encryptWithRSA(payload);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: window.nps.web_base_url + "/login/verify",
|
||||
data: data,
|
||||
success: function (res) {
|
||||
if (res.status) {
|
||||
showMsg(langreply(res.msg), 'success', 1000, function() {
|
||||
window.location.href = window.nps.web_base_url + "/index/index";
|
||||
});
|
||||
} else {
|
||||
showMsg(langreply(res.msg), 'error', 3000, function() {
|
||||
if (res.nonce) {
|
||||
window.nps.loginNonce = res.nonce;
|
||||
}
|
||||
if (res.cert) {
|
||||
window.nps.publicKey = res.cert;
|
||||
}
|
||||
{{if eq true .captcha_open}}
|
||||
var $img = $('.captcha-img');
|
||||
if ($img.length) {
|
||||
$img.trigger('click');
|
||||
}
|
||||
$('input[name="captcha"]').val('');
|
||||
{{end}}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
134
apps/nps/v0.29.36/web/views/login/register.html
Normal file
134
apps/nps/v0.29.36/web/views/login/register.html
Normal file
@@ -0,0 +1,134 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title langtag="title-register"></title>
|
||||
<!-- Mainly scripts -->
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link href="{{.web_base_url}}/static/css/fontawesome.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/solid.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/style.css?v={{.version}}" rel="stylesheet">
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="{{.web_base_url}}/static/js/jquery-3.7.1.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/bootstrap.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/jsencrypt.min.js"></script>
|
||||
<!-- Latest compiled and minified Locales -->
|
||||
<script src="{{.web_base_url}}/static/js/language.js?v={{.version}}" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body class="login-page">
|
||||
<nav class="navbar navbar-static-top navbar-right navbar-login">
|
||||
<div class="ml-auto d-flex align-items-center" style="gap: 0.5rem;">
|
||||
<button id="theme-toggle" class="btn btn-outline-secondary" onclick="toggleTheme()">
|
||||
<i class="fa fa-moon"></i>
|
||||
</button>
|
||||
<span class="btn-group dropdown">
|
||||
<button id="languagemenu" class="btn btn-outline-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-globe-asia fa-lg"></i>
|
||||
<span></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu"></ul>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="login-card">
|
||||
<div class="login-header register">
|
||||
<img src="{{.web_base_url}}/static/img/nps.svg?v={{.version}}" alt="Logo" style="width: 32px; height: 32px; margin-right: 20px !important;">
|
||||
<div class="navbar-brand" style="font-weight: lighter; font-size: 2.0rem !important"><h1 langtag="title-register"></h1></div>
|
||||
</div>
|
||||
<div class="login-body">
|
||||
<form class="m-t" onsubmit="return false;">
|
||||
<div class="form-group position-relative">
|
||||
<i class="fas fa-user-circle input-icon"></i>
|
||||
<input class="form-control" langtag="word-username" name="username" placeholder="username" required="" type="text">
|
||||
</div>
|
||||
<div class="form-group position-relative">
|
||||
<i class="fas fa-key input-icon"></i>
|
||||
<input class="form-control" langtag="word-password" name="password" placeholder="password" required="" type="password">
|
||||
</div>
|
||||
{{if eq true .captcha_open}}
|
||||
<div class="form-group captcha-group position-relative">
|
||||
<div class="flex-fill">
|
||||
<i class="fas fa-shield-alt input-icon"></i>
|
||||
<input class="form-control" langtag="word-captcha" name="captcha" placeholder="captcha" required="">
|
||||
</div>
|
||||
<div class="captcha-container">
|
||||
{{create_captcha}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<button class="btn btn-primary block full-width m-b" langtag="word-register" onclick="if (this.form.reportValidity()) register()" type="submit"></button>
|
||||
<p class="text-muted text-center">
|
||||
<small langtag="info-haveaccount"></small>
|
||||
<small><a href="{{.web_base_url}}/login/index" langtag="word-login"></a></small>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="float-right">
|
||||
<span langtag="word-readmore"></span>
|
||||
<strong><a href="https://github.com/djylb/nps" langtag="word-go"></a></strong>
|
||||
</div>
|
||||
<div><strong langtag="word-copyright"></strong> <span langtag="application"></span> © 2018-{{.year}}</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.nps = {
|
||||
web_base_url: "{{.web_base_url}}",
|
||||
version: "{{.version}}",
|
||||
publicKey: `{{.public_key}}`,
|
||||
loginNonce: "{{.login_nonce}}"
|
||||
};
|
||||
function encryptWithRSA(plain) {
|
||||
const crypt = new JSEncrypt();
|
||||
crypt.setPublicKey(window.nps.publicKey);
|
||||
return crypt.encrypt(plain);
|
||||
}
|
||||
function register() {
|
||||
const data = {};
|
||||
$("form").serializeArray().forEach(item => {
|
||||
data[item.name] = item.value;
|
||||
});
|
||||
const ts = Date.now();
|
||||
const payload = JSON.stringify({
|
||||
n: window.nps.loginNonce,
|
||||
t: ts,
|
||||
p: data.password
|
||||
});
|
||||
data.password = encryptWithRSA(payload);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: window.nps.web_base_url + "/login/register",
|
||||
data: data,
|
||||
success: function (res) {
|
||||
if (res.status) {
|
||||
showMsg(langreply(res.msg), 'success', 1000, function() {
|
||||
window.location.href = window.nps.web_base_url + "/login/index";
|
||||
});
|
||||
} else {
|
||||
showMsg(langreply(res.msg), 'error', 5000, function() {
|
||||
if (res.nonce) {
|
||||
window.nps.loginNonce = res.nonce;
|
||||
}
|
||||
if (res.cert) {
|
||||
window.nps.publicKey = res.cert;
|
||||
}
|
||||
{{if eq true .captcha_open}}
|
||||
var $img = $('.captcha-img');
|
||||
if ($img.length) {
|
||||
$img.trigger('click');
|
||||
}
|
||||
$('input[name="captcha"]').val('');
|
||||
{{end}}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
5
apps/nps/v0.29.36/web/views/public/error.html
Normal file
5
apps/nps/v0.29.36/web/views/public/error.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<div class="page-error tile">
|
||||
<h1><i class="fa fa-exclamation-circle"></i> Error 404: Page not found</h1>
|
||||
<p>The page you have requested is not found.</p>
|
||||
<p><a class="btn btn-primary" href="javascript:window.history.back();">Go Back</a></p>
|
||||
</div>
|
||||
175
apps/nps/v0.29.36/web/views/public/layout.html
Normal file
175
apps/nps/v0.29.36/web/views/public/layout.html
Normal file
@@ -0,0 +1,175 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<title langtag="title-admin"></title>
|
||||
<!-- Mainly scripts -->
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link href="{{.web_base_url}}/static/css/fontawesome.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/solid.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/bootstrap-select.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/bootstrap-table.min.css" rel="stylesheet">
|
||||
<link href="{{.web_base_url}}/static/css/style.css?v={{.version}}" rel="stylesheet">
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="{{.web_base_url}}/static/js/jquery-3.7.1.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/popper.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/bootstrap.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/bootstrap-select.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/bootstrap-table.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/bootstrap-table-cookie.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/bootstrap-table-locale-all.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/echarts.min.js"></script>
|
||||
<script src="{{.web_base_url}}/static/js/inspinia.js"></script>
|
||||
<!-- Latest compiled and minified Locales -->
|
||||
<script src="{{.web_base_url}}/static/js/language.js?v={{.version}}" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body class="pace-done fixed-nav fixed-nav-basic">
|
||||
<div id="wrapper">
|
||||
<nav class="navbar-default navbar-static-side" role="navigation">
|
||||
<div class="sidebar-collapse">
|
||||
<ul class="nav metismenu" id="side-menu">
|
||||
<li class="nav-header">
|
||||
<div class="dropdown profile-element">
|
||||
{{if eq true .isAdmin}}
|
||||
<span><i class="fa fa-user-cog fa-2x"></i></span>
|
||||
<span class="clear"> <span class="block m-t-xs"><strong class="font-bold" langtag="word-admin"></strong></span>
|
||||
<span class="text-muted text-xs block" langtag="word-system">
|
||||
{{else}}
|
||||
<span><i class="fa fa-user fa-3x"></i></span>
|
||||
<span class="clear"> <span class="block m-t-xs"><strong class="font-bold">{{.username}}</strong></span>
|
||||
<span class="text-muted text-xs block" langtag="word-user">
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="logo-element" langtag="application"></div>
|
||||
</li>
|
||||
<li class="{{if eq "index" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/" class="d-flex align-items-center">
|
||||
<i class="fa fa-tachometer-alt fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="word-dashboard"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "client" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/client/list" class="d-flex align-items-center">
|
||||
<i class="fa fa-desktop fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="word-client"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "host" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/index/hostlist" class="d-flex align-items-center">
|
||||
<i class="fa fa-globe fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="scheme-host"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "tcp" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/index/tcp" class="d-flex align-items-center">
|
||||
<i class="fa fa-retweet fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="scheme-tcp"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "udp" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/index/udp" class="d-flex align-items-center">
|
||||
<i class="fa fa-random fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="scheme-udp"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "mix" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/index/mix" class="d-flex align-items-center">
|
||||
<i class="fa fa-layer-group fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="scheme-mixproxy"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "secret" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/index/secret" class="d-flex align-items-center">
|
||||
<i class="fa fa-low-vision fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="scheme-secret"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "p2p" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/index/p2p" class="d-flex align-items-center">
|
||||
<i class="fa fa-exchange-alt fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="scheme-p2p"></span></a>
|
||||
</li>
|
||||
<li class="{{if eq "file" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/index/file" class="d-flex align-items-center">
|
||||
<i class="fa fa-briefcase fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="scheme-file"></span></a>
|
||||
</li>
|
||||
{{if eq true .isAdmin}}
|
||||
<li class="{{if eq "global" .menu}}active{{end}}">
|
||||
<a href="{{.web_base_url}}/global/index" class="d-flex align-items-center">
|
||||
<i class="fa fa-cog fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="word-globalparam"></span></a>
|
||||
</li>
|
||||
{{end}}
|
||||
<li class="{{if eq "help" .menu}}active{{end}}">
|
||||
<a href="https://d-jy.net/docs/nps/" target="_blank" class="d-flex align-items-center">
|
||||
<i class="fa fa-lightbulb fa-lg fa-fw"></i>
|
||||
<span class="nav-label" langtag="word-help"></span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="page-wrapper" class="gray-bg">
|
||||
<div class="row border-bottom">
|
||||
<nav class="navbar navbar-fixed-top" role="navigation" style="margin-bottom: 0">
|
||||
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i></a>
|
||||
</div>
|
||||
<ul class="nav navbar-top-links navbar-right">
|
||||
<li>
|
||||
<span class="m-r-sm text-muted welcome-message"><span langtag="word-welcome"></span>
|
||||
<a href="https://github.com/djylb/nps" langtag="application"></a></span>
|
||||
</li>
|
||||
<li>
|
||||
<div class="ml-auto d-flex align-items-center" style="gap: 0.5rem;">
|
||||
<button id="theme-toggle" class="btn btn-outline-secondary" onclick="toggleTheme()">
|
||||
<i class="fa fa-moon"></i>
|
||||
</button>
|
||||
<span class="btn-group dropdown">
|
||||
<button id="languagemenu" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-globe-asia fa-lg"></i>
|
||||
<span></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu"></ul>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{.web_base_url}}/login/out" onclick="localStorage.clear(); return true;">
|
||||
<i class="fa fa-sign-in-alt"></i><span langtag="word-logout"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
{{.LayoutContent}}
|
||||
</div>
|
||||
|
||||
<div class="footer fixed">
|
||||
<div class="float-right">
|
||||
<span langtag="word-readmore"></span> <strong><a href="https://github.com/djylb/nps" langtag="word-go"></a></strong>
|
||||
</div>
|
||||
<div><strong langtag="word-copyright"></strong> <span langtag="application"></span> © 2018-{{.year}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script>
|
||||
window.nps = {
|
||||
"web_base_url": "{{.web_base_url}}",
|
||||
"version": "{{.version}}"
|
||||
}
|
||||
/*
|
||||
googleTranslateElementInit()
|
||||
function googleTranslateElementInit() {
|
||||
new google.translate.TranslateElement({
|
||||
layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL
|
||||
}, 'wrapper');
|
||||
}
|
||||
*/
|
||||
</script>
|
||||
{{/*<script src="http://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>*/}}
|
||||
|
||||
Reference in New Issue
Block a user