提交 ece971fd 编写于 作者: F fengfei

i18n支持

上级 34cab564
lanproxy
--------
[README EN](README_en.md) | [中文文档](README.md)
lanproxy是一个将局域网个人电脑、服务器代理到公网的内网穿透工具,目前仅支持tcp流量转发,可支持任何tcp上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面...)。目前市面上提供类似服务的有花生壳、TeamView、GoToMyCloud等等,但要使用第三方的公网服务器就必须为第三方付费,并且这些服务都有各种各样的限制,此外,由于数据包会流经第三方,因此对数据安全也是一大隐患。
### 相关地址
......@@ -49,9 +51,11 @@ config.admin.password=admin
代理配置,打开地址 http://ip:8090 ,使用上面配置中配置的用户名密码登录,进入如下代理配置界面
![webconfig](webconfig01.jpeg)
![webconfig](readme_zh_client_list.png)
![webconfig](readme_zh_proxy_list.png)
![webconfig](webconfig02.jpeg)
![webconfig](readme_zh_stat_list.png)
> 一个server可以支持多个客户端连接
> 配置数据存放在 ~/.lanproxy/config.json 文件中
......
### Lanproxy
[README](README_en.md) | [中文文档](README.md)
Lanproxy is a reverse proxy to help you expose a local server behind a NAT or firewall to the internet. it supports any protocols over tcp (http https ssh ...)
### Features
- Secure tunnels to localhost
- Supports any protocols over tcp (http https ssh ...)
- Supports web config pages, easy to configure management
- Written by java netty framework, high performance
### What can I do with Lanproxy
- Demo without deploying
- Simplify mobile device testing
- Build webhook integrations with ease
- Run personal cloud services from your own private network
### Architecture
![lanproxy](lanproxy.png)
### Configure
#### Server
proxy-server config file is **conf/config.properties**
```properties
server.bind=0.0.0.0
#Plain tcp port
server.port=4900
#ssl
server.ssl.enable=true
server.ssl.bind=0.0.0.0
server.ssl.port=4993
server.ssl.jksPath=test.jks
server.ssl.keyStorePassword=123456
server.ssl.keyManagerPassword=123456
server.ssl.needsClientAuth=false
#web config pages
config.server.bind=0.0.0.0
config.server.port=8090
config.admin.username=admin
config.admin.password=admin
```
> Visit your config web service using url http://ip:8090
![webconfig](readme_en_client_list.png)
![webconfig](readme_en_proxy_list.png)
![webconfig](readme_en_stat_list.png)
#### client
proxy-client config file is **conf/config.properties**
```properties
#get from proxy-server client list page
client.key=
ssl.enable=true
ssl.jksPath=test.jks
ssl.keyStorePassword=123456
#your proxy server ip
server.host=
#proxy-server ssl port is 4993,plain port is 4900
server.port=4993
```
### Run
- Get release package from https://github.com/ffay/lanproxy/releases
- Java env is required
- Linux(mac)run bin/startup.sh
- Windows run bin/startup.bat
\ No newline at end of file
......@@ -211,13 +211,15 @@ public class ProxyConfig implements Serializable {
this.inetPortLanInfoMapping = inetPortLanInfoMapping;
this.clients = clients;
try {
FileOutputStream out = new FileOutputStream(file);
out.write(proxyMappingConfigJson.getBytes(Charset.forName("UTF-8")));
out.flush();
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
if (proxyMappingConfigJson != null) {
try {
FileOutputStream out = new FileOutputStream(file);
out.write(proxyMappingConfigJson.getBytes(Charset.forName("UTF-8")));
out.flush();
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
notifyconfigChangedListeners();
......
login=Sign in
logout=Sign out
username=Username
password=Password
title=LanProxy - help you expose a local server behind a NAT or firewall to the internet
menu.client.list=Client list
menu.client.add=New client
menu.client.config=Client config
menu.client.statistics=Statistics
public.confirm.delete=Delete?
public.options=Options
public.edit=Edit
public.submit=Submit
public.delete=Delete
public.ok=Ok
public.cancel=Cancel
public.back=Back
public.notice.updatesuccess=Update successfully
public.notice.addsuccess=Add successfully
public.tips=Tips
client.list=Client list
client.name=Client name
client.key=Client key
client.add=New client
client.name.placeholder=
client.key.placeholder=
client.randomkey=Generate a random key
client.notice.inputname=Client name is required
client.notice.inputkey=Client key is required
client.notice.addsuccess=New client has been added successfully
client.edit=Edit client
lan.proxyconfig=Proxy config
lan.addnewconfig=New proxy config
lan.editconfig=Edit proxy config
lan.name=Proxy name
lan.inetport=Internet port
lan.inetport.placeholder=
lan.ip=Backend ip
lan.ip.placeholder=127.0.0.1:80
lan.notice.inputname=Proxy config name is required
lan.notice.inputinetport=Internet port is required
lan.notice.inputlan=Backend server ip:port is required
lan.notice.errorlan=Error backend info, should be ip:port
lan.notice.errorport=Error port
statistics.inetport=Internet port
statistics.inflow=Inflow data
statistics.outflow=Outflow data
statistics.channels=Current channels
\ No newline at end of file
login=登录
logout=退出
username=用户名
password=密码
title=LanProxy-内网穿透工具
menu.client.list=客户端管理
menu.client.add=添加客户端
menu.client.config=配置管理
menu.client.statistics=数据统计
public.confirm.delete=确定删除?
public.options=操作
public.submit=提交
public.edit=编辑
public.delete=删除
public.ok=确定
public.cancel=取消
public.back=返回
public.notice.updatesuccess=更新成功
public.tips=提示
client.list=客户端列表
client.name=客户端名称
client.key=客户端密钥
client.add=添加客户端
client.name.placeholder=请输入客户端名称
client.key.placeholder=请输入客户端密钥
client.randomkey=生成随机密钥
client.notice.inputname=请输入客户端备注名称
client.notice.inputkey=请输入客户端通信密钥
client.notice.addsuccess=客户端添加成功
client.edit=编辑客户端
lan.proxyconfig=代理配置
lan.addnewconfig=添加配置
lan.editconfig=编辑配置
lan.name=代理名称
lan.inetport=公网端口
lan.inetport.placeholder=请输入公网出口端口,请确保端口没有被其他程序占用
lan.ip=后端IP端口
lan.ip.placeholder=请输入后端代理信息,格式:127.0.0.1:80
lan.notice.inputname=请输入代理信息备注名称
lan.notice.inputinetport=请输入公网出口端口
lan.notice.inputlan=请输入后端代理信息
lan.notice.errorlan=后端代理信息格式错误
lan.notice.errorport=端口错误
statistics.inetport=出口端口
statistics.inflow=流入数据
statistics.outflow=流出数据
statistics.channels=当前连接
\ No newline at end of file
......@@ -51,7 +51,7 @@ body :-ms-input-placeholder {
}
.wrapper {
background: #393D49!important;
background: #393D49 !important;
background: -webkit-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
background: linear-gradient(to bottom right, #50a3a2 0%, #53e3a6 100%);
opacity: 0.8;
......@@ -150,21 +150,25 @@ body :-ms-input-placeholder {
<h1>LanProxy.org</h1>
<div class="form">
<input type="text" class="username" placeholder="用户名">
<input type="password" class="password" placeholder="密码">
<button type="submit" id="login-button">登录</button>
<input type="text" class="username" placeholder="">
<input type="password" class="password" placeholder="">
<button type="submit" id="login-button"></button>
</div>
</div>
</div>
<script src="jquery/jquery-3.1.1.min.js" type="text/javascript"></script>
<script src="jquery/jquery.i18n.properties.min.js" type="text/javascript"></script>
<script>
$('#login-button').click(function(event) {
$('#login-button').click(function(event) {
$.ajax({
type : "POST",
url : "/login",
contentType : "application/json; charset=utf-8",
data : JSON.stringify({username: $(".username").val(), password:$(".password").val()}),
data : JSON.stringify({
username : $(".username").val(),
password : $(".password").val()
}),
dataType : "json",
success : function(data) {
if (data.code == 20000) {
......@@ -185,10 +189,48 @@ body :-ms-input-placeholder {
document.cookie = name + "=" + escape(value) + ";expires="
+ exp.toGMTString();
}
$(document).keyup(function(event){
if(event.keyCode ==13){
$("#login-button").trigger("click");
$(document).keyup(function(event) {
if (event.keyCode == 13) {
$("#login-button").trigger("click");
}
});
/**
* 设置语言类型: 默认为英文
*/
var i18nLanguage = "en";
/*
设置一下网站支持的语言种类
zh-CN(中文简体)、en(英语)
*/
var webLanguage = [ 'zh-CN', 'en' ];
function initWebLanguage() {
var navLanguage = navigator.language;
console.log("user set browser language is " + navLanguage);
if (navLanguage) {
var charSize = $.inArray(navLanguage, webLanguage);
if (charSize > -1) {
i18nLanguage = navLanguage;
}
}
}
initWebLanguage();
jQuery.i18n.properties({
name : 'lang', //资源文件名称
path : '/i18n/', //资源文件路径
mode : 'map', //用Map的方式使用资源文件中的值
language : i18nLanguage,
encoding: 'UTF-8',
callback : function() {//加载成功后设置显示内容
$('title').html($.i18n.prop('login')+" - LanProxy");
$('#login-button').html($.i18n.prop('login'));
$(".username").attr("placeholder", $.i18n.prop('username'));
$(".password").attr("placeholder", $.i18n.prop('password'));
}
});
</script>
......
(function(k){function t(a){a.debug&&(g("callbackIfComplete()"),g("totalFiles: "+a.totalFiles),g("filesLoaded: "+a.filesLoaded));a.async&&a.filesLoaded===a.totalFiles&&a.callback&&a.callback()}function n(a,d){d.debug&&g("loadAndParseFiles");null!==a&&0<a.length?u(a[0],d,function(){a.shift();n(a,d)}):t(d)}function u(a,d,b){d.debug&&(g("loadAndParseFile('"+a+"')"),g("totalFiles: "+d.totalFiles),g("filesLoaded: "+d.filesLoaded));null!==a&&"undefined"!==typeof a&&k.ajax({url:a,async:d.async,cache:d.cache,
dataType:"text",success:function(h,c){d.debug&&(g("Succeeded in downloading "+a+"."),g(h));v(h,d);b()},error:function(h,c,e){d.debug&&g("Failed to download or parse "+a+". errorThrown: "+e);404===h.status&&--d.totalFiles;b()}})}function v(a,d){var b="",h=a.split(/\n/),c=/(\{\d+})/g,e=/\{(\d+)}/g,g=/(\\u.{4})/ig;h.forEach(function(a,w){a=a.trim();if(0<a.length&&"#"!=a.match("^#")){var l=a.split("=");if(0<l.length){for(var m=decodeURI(l[0]).trim(),f=1==l.length?"":l[1];"\\"===f.match(/\\$/);)f=f.substring(0,
f.length-1),f+=h[++w].trimRight();for(var p=2;p<l.length;p++)f+="="+l[p];f=f.trim();if("map"==d.mode||"both"==d.mode)(l=f.match(g))&&l.forEach(function(a){f=f.replace(a,x(a))}),k.i18n.map[m]=f;if("vars"==d.mode||"both"==d.mode)if(f=f.replace(/"/g,'\\"'),y(m),c.test(f)){var n=!0,q="",r=[];f.split(c).forEach(function(a){!c.test(a)||0!==r.length&&-1!=r.indexOf(a)||(n||(q+=","),q+=a.replace(e,"v$1"),r.push(a),n=!1)});b+=m+"=function("+q+"){";m='"'+f.replace(e,'"+v$1+"')+'"';b+="return "+m+";};"}else b+=
m+'="'+f+'";'}}});eval(b);d.filesLoaded+=1}function y(a){if(/\./.test(a)){var d="";a.split(/\./).forEach(function(a,h){0<h&&(d+=".");d+=a;eval("typeof "+d+' == "undefined"')&&eval(d+"={};")})}}function x(a){var d=[];a=parseInt(a.substr(2),16);0<=a&&a<Math.pow(2,16)&&d.push(a);return d.reduce(function(a,d){return a+String.fromCharCode(d)},"")}k.i18n={};k.i18n.map={};var g=function(a){window.console&&console.log("i18n::"+a)};k.i18n.properties=function(a){a=k.extend({name:"Messages",language:"",path:"",
mode:"vars",cache:!1,debug:!1,encoding:"UTF-8",async:!1,callback:null},a);a.path.match(/\/$/)||(a.path+="/");a.language=this.normaliseLanguageCode(a.language);var d=a.name&&a.name.constructor===Array?a.name:[a.name];a.totalFiles=2*d.length+(5<=a.language.length?d.length:0);a.debug&&g("totalFiles: "+a.totalFiles);a.filesLoaded=0;d.forEach(function(b){var d=a.path+b+".properties";var c=a.language.substring(0,2);c=a.path+b+"_"+c+".properties";if(5<=a.language.length){var e=a.language.substring(0,5);
b=a.path+b+"_"+e+".properties";d=[d,c,b]}else d=[d,c];n(d,a)});a.callback&&!a.async&&a.callback()};k.i18n.prop=function(a){var d,b=k.i18n.map[a];if(null===b)return"["+a+"]";var h;2==arguments.length&&k.isArray(arguments[1])&&(h=arguments[1]);var c;if("string"==typeof b){for(c=0;-1!=(c=b.indexOf("\\",c));)b="t"==b.charAt(c+1)?b.substring(0,c)+"\t"+b.substring(c++ +2):"r"==b.charAt(c+1)?b.substring(0,c)+"\r"+b.substring(c++ +2):"n"==b.charAt(c+1)?b.substring(0,c)+"\n"+b.substring(c++ +2):"f"==b.charAt(c+
1)?b.substring(0,c)+"\f"+b.substring(c++ +2):"\\"==b.charAt(c+1)?b.substring(0,c)+"\\"+b.substring(c++ +2):b.substring(0,c)+b.substring(c+1);var e=[];for(c=0;c<b.length;)if("'"==b.charAt(c))if(c==b.length-1)b=b.substring(0,c);else if("'"==b.charAt(c+1))b=b.substring(0,c)+b.substring(++c);else{for(d=c+2;-1!=(d=b.indexOf("'",d));)if(d==b.length-1||"'"!=b.charAt(d+1)){b=b.substring(0,c)+b.substring(c+1,d)+b.substring(d+1);c=d-1;break}else b=b.substring(0,d)+b.substring(++d);-1==d&&(b=b.substring(0,c)+
b.substring(c+1))}else if("{"==b.charAt(c))if(d=b.indexOf("}",c+1),-1==d)c++;else{var g=parseInt(b.substring(c+1,d));!isNaN(g)&&0<=g?(c=b.substring(0,c),""!==c&&e.push(c),e.push(g),c=0,b=b.substring(d+1)):c=d+1}else c++;""!==b&&e.push(b);b=e;k.i18n.map[a]=e}if(0===b.length)return"";if(1==b.length&&"string"==typeof b[0])return b[0];e="";c=0;for(d=b.length;c<d;c++)e="string"==typeof b[c]?e+b[c]:h&&b[c]<h.length?e+h[b[c]]:!h&&b[c]+1<arguments.length?e+arguments[b[c]+1]:e+("{"+b[c]+"}");return e};k.i18n.normaliseLanguageCode=
function(a){if(!a||2>a.length)a=navigator.languages&&0<navigator.languages.length?navigator.languages[0]:navigator.language||navigator.userLanguage||"en";a=a.toLowerCase();a=a.replace(/-/,"_");3<a.length&&(a=a.substring(0,3)+a.substring(3).toUpperCase());return a}})(jQuery);
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title">
<li class="layui-this">添加客户端</li>
<li class="layui-this add-client-title"></li>
</ul>
<div class="main-content">
<div class="layui-form-item">
<label class="layui-form-label">备注名称</label>
<label class="layui-form-label i18n-client-name"></label>
<div class="layui-input-inline">
<input type="text" name="name" autocomplete="off" placeholder="请输入客户端备注名称" class="layui-input">
<input type="text" name="name" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">通信密钥</label>
<label class="layui-form-label i18n-client-key"></label>
<div class="layui-input-inline">
<input type="text" name="clientKey" autocomplete="off" placeholder="请输入客户端通信密钥" class="layui-input">
<input type="text" name="clientKey" autocomplete="off" placeholder="" class="layui-input">
</div>
<div class="layui-form-mid"><a class="layui-btn layui-btn-mini random-key random">生成随机密钥</a></div>
<div class="layui-form-mid"><a class="layui-btn layui-btn-mini random-key random"></a></div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn add">提交添加</button>
<button class="layui-btn add"></button>
</div>
</div>
</div>
</div>
<script>
$(".add-client-title").html($.i18n.prop('client.add'));
$(".i18n-client-name").html($.i18n.prop('client.name'));
$(".i18n-client-key").html($.i18n.prop('client.key'));
$("input[name='name']").attr("placeholder", $.i18n.prop('client.name.placeholder'));
$("input[name='clientKey']").attr("placeholder", $.i18n.prop('client.key.placeholder'));
$(".random").html($.i18n.prop('client.randomkey'));
$(".add").html($.i18n.prop('public.submit'));
$(".random").click(function(){
$("input[name='clientKey']").val(uuid());
});
......@@ -31,12 +38,16 @@ $(".random").click(function(){
$(".add").click(function(){
var name = $("input[name='name']").val();
if(name == ""){
layer.alert("请输入客户端备注名称");
layer.alert($.i18n.prop('client.notice.inputname'), {
title: $.i18n.prop('public.tips')
});
return;
}
var clientKey = $("input[name='clientKey']").val();
if(clientKey == ""){
layer.alert("请输入客户端密钥");
layer.alert($.i18n.prop('client.notice.inputkey'), {
title: $.i18n.prop('public.tips')
});
return;
}
clientList.push({
......@@ -47,7 +58,7 @@ $(".add").click(function(){
api_invoke("/config/update", clientList, function(data) {
if (data.code == 20000) {
layer.alert('客户端添加成功', function(index){
layer.alert($.i18n.prop('client.notice.addsuccess'), {title: $.i18n.prop('public.tips')}, function(index){
layer.close(index);
location.reload();
});
......
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title">
<li class="layui-this">编辑客户端</li>
<li class="layui-this edit-client-title"></li>
</ul>
<div class="main-content">
<div class="layui-form-item">
<label class="layui-form-label">备注名称</label>
<label class="layui-form-label i18n-client-name"></label>
<div class="layui-input-inline">
<input type="text" name="name" autocomplete="off" placeholder="请输入客户端备注名称" class="layui-input">
<input type="text" name="name" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">通信密钥</label>
<label class="layui-form-label i18n-client-key"></label>
<div class="layui-input-inline">
<input type="text" name="clientKey" autocomplete="off" placeholder="请输入客户端通信密钥" class="layui-input">
<input type="text" name="clientKey" autocomplete="off" placeholder="" class="layui-input">
</div>
<div class="layui-form-mid"><a class="layui-btn layui-btn-mini random-key random">生成随机密钥</a></div>
<div class="layui-form-mid"><a class="layui-btn layui-btn-mini random-key random"></a></div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn update">提交更新</button>
<button class="layui-btn layui-btn-primary back">返回</button>
<button class="layui-btn update"></button>
<button class="layui-btn layui-btn-primary back"></button>
</div>
</div>
</div>
</div>
<script>
$(".edit-client-title").html($.i18n.prop('client.edit'));
$(".i18n-client-name").html($.i18n.prop('client.name'));
$(".i18n-client-key").html($.i18n.prop('client.key'));
$("input[name='name']").attr("placeholder", $.i18n.prop('client.name.placeholder'));
$("input[name='clientKey']").attr("placeholder", $.i18n.prop('client.key.placeholder'));
$(".random").html($.i18n.prop('client.randomkey'));
$(".update").html($.i18n.prop('public.submit'));
$(".back").html($.i18n.prop('public.back'));
$("input[name='name']").val(clientList[clientIndex].name);
$("input[name='clientKey']").val(clientList[clientIndex].clientKey);
......@@ -37,7 +45,7 @@ $(".update").click(function(){
clientList[clientIndex]['clientKey'] = $("input[name='clientKey']").val();
api_invoke("/config/update", clientList, function(data) {
if (data.code == 20000) {
layer.alert('更新成功', function(index){
layer.alert($.i18n.prop('public.notice.updatesuccess'), {title: $.i18n.prop('public.tips')}, function(index){
layer.close(index);
location.reload();
});
......
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title">
<li class="layui-this">客户端列表</li>
<li class="layui-this detail-page"></li>
</ul>
<div class="main-content"></div>
</div>
<script>
$(".layui-this.detail-page").html($.i18n.prop('client.list'));
window.clientList = [];
api_invoke("/config/detail", {}, function(data) {
if (data.code == 20000) {
......@@ -21,7 +22,10 @@
});
$(".client-delete").click(function() {
window.clientIndex = $(this).attr("data-index");
layer.confirm('确定删除?', function(i) {
layer.confirm($.i18n.prop('public.confirm.delete'), {
title: $.i18n.prop('public.tips'),
btn : [ $.i18n.prop('public.ok'), $.i18n.prop('public.cancel') ]
}, function(i) {
layer.close(i);
clientList.splice(clientIndex, 1);
api_invoke("/config/update", clientList, function(data) {
......@@ -33,6 +37,11 @@
})
});
});
$(".th-client-name").html($.i18n.prop('client.name'));
$(".th-client-key").html($.i18n.prop('client.key'));
$(".th-options").html($.i18n.prop('public.options'));
$(".client-edit").html($.i18n.prop('public.edit'));
$(".client-delete").html($.i18n.prop('public.delete'));
} else {
alert(data.message);
}
......@@ -42,9 +51,9 @@
<table class="layui-table" lay-skin="line">
<thead>
<tr>
<th>客户端名称</th>
<th>密钥(客户端client.key配置该值)</th>
<th>操作</th>
<th class="th-client-name"></th>
<th class="th-client-key"></th>
<th class="th-options"></th>
</tr>
</thead>
<tbody>
......@@ -53,11 +62,8 @@
<td><%:=data[i].name%></td>
<td><%:=data[i].clientKey%></td>
<td>
<!--
<a data-index="<%:=i%>" class="layui-btn layui-btn-mini mapping-config">代理配置</a>
-->
<a data-index="<%:=i%>" class="layui-btn layui-btn-mini client-edit">编辑</a>
<a data-index="<%:=i%>" class="layui-btn layui-btn-danger layui-btn-mini client-delete">删除</a>
<a data-index="<%:=i%>" class="layui-btn layui-btn-mini client-edit"></a>
<a data-index="<%:=i%>" class="layui-btn layui-btn-danger layui-btn-mini client-delete"></a>
</td>
</tr>
<%}%>
......
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title">
<li class="layui-this">添加代理</li>
<li class="layui-this i18n-new-proxy"></li>
</ul>
<div class="main-content">
<div class="layui-form-item">
<label class="layui-form-label">代理名称</label>
<label class="layui-form-label i18n-lan-name"></label>
<div class="layui-input-block">
<input type="text" name="name" autocomplete="off" placeholder="请输入代理备注名称" class="layui-input">
<input type="text" name="name" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">公网端口</label>
<label class="layui-form-label i18n-lan-inetport"></label>
<div class="layui-input-block">
<input type="text" name="inetPort" autocomplete="off" placeholder="请输入公网出口端口,请确保端口没有被其他程序占用" class="layui-input">
<input type="text" name="inetPort" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">代理IP端口</label>
<label class="layui-form-label i18n-lan-ip"></label>
<div class="layui-input-block">
<input type="text" name="lan" autocomplete="off" placeholder="请输入后端代理信息,格式:127.0.0.1:80" class="layui-input">
<input type="text" name="lan" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn add">提交添加</button>
<button class="layui-btn layui-btn-primary back">返回</button>
<button class="layui-btn add"></button>
<button class="layui-btn layui-btn-primary back"></button>
</div>
</div>
</div>
</div>
<script>
$(".i18n-new-proxy").html($.i18n.prop('lan.addnewconfig'));
$(".i18n-lan-name").html($.i18n.prop('lan.name'));
$(".i18n-lan-inetport").html($.i18n.prop('lan.inetport'));
$(".i18n-lan-ip").html($.i18n.prop('lan.ip'));
$("input[name='inetPort']").attr("placeholder", $.i18n.prop('lan.inetport.placeholder'));
$("input[name='lan']").attr("placeholder", $.i18n.prop('lan.ip.placeholder'));
$(".add").html($.i18n.prop('public.submit'));
$(".back").html($.i18n.prop('public.back'));
$(".add").click(function(){
var name = $("input[name='name']").val();
if(name == ""){
layer.alert("请输入代理备注名称");
layer.alert($.i18n.prop('lan.notice.inputname'), {title:"Tips"});
return;
}
var inetPort = $("input[name='inetPort']").val();
if(inetPort == ""){
layer.alert("请输入公网出口端口");
layer.alert($.i18n.prop('lan.notice.inputinetport'), {title:"Tips"});
return;
}
if(!check_port(inetPort)){
layer.alert("端口格式错误");
layer.alert($.i18n.prop('lan.notice.errorport'), {title:"Tips"});
return;
}
var lan = $("input[name='lan']").val();
if(lan == ""){
layer.alert("请输入后端代理信息");
layer.alert($.i18n.prop('lan.notice.inputlan'), {title:"Tips"});
return;
}
if(!check_lan(lan)){
layer.alert("后端代理信息格式错误");
layer.alert($.i18n.prop('lan.notice.errorlan'), {title:"Tips"});
return;
}
......@@ -64,7 +72,7 @@ $(".add").click(function(){
api_invoke("/config/update", clientList, function(data) {
if (data.code == 20000) {
layer.alert('添加成功', function(index){
layer.alert($.i18n.prop('public.notice.addsuccess'), {title:"Tips"}, function(index){
layer.close(index);
load_page("html/lan/list.html");
});
......
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title">
<li class="layui-this">编辑代理</li>
<li class="layui-this i18n-lan-title"></li>
</ul>
<div class="main-content">
<div class="layui-form-item">
<label class="layui-form-label">代理名称</label>
<label class="layui-form-label i18n-lan-name"></label>
<div class="layui-input-block">
<input type="text" name="name" autocomplete="off" placeholder="请输入代理备注名称" class="layui-input">
<input type="text" name="name" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">公网端口</label>
<label class="layui-form-label i18n-lan-inetport"></label>
<div class="layui-input-block">
<input type="text" name="inetPort" autocomplete="off" placeholder="请输入公网出口端口,请确保端口没有被其他程序占用" class="layui-input">
<input type="text" name="inetPort" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">代理IP端口</label>
<label class="layui-form-label i18n-lan-ip"></label>
<div class="layui-input-block">
<input type="text" name="lan" autocomplete="off" placeholder="请输入后端代理信息,格式:127.0.0.1:80" class="layui-input">
<input type="text" name="lan" autocomplete="off" placeholder="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn update">提交更新</button>
<button class="layui-btn layui-btn-primary back">返回</button>
<button class="layui-btn update"></button>
<button class="layui-btn layui-btn-primary back"></button>
</div>
</div>
</div>
......@@ -34,30 +34,38 @@ $(function(){
$("input[name='name']").val(clientList[clientIndex].proxyMappings[mappingIndex].name);
$("input[name='inetPort']").val(clientList[clientIndex].proxyMappings[mappingIndex].inetPort);
$("input[name='lan']").val(clientList[clientIndex].proxyMappings[mappingIndex].lan);
$(".i18n-lan-title").html($.i18n.prop('lan.editconfig'));
$(".i18n-lan-name").html($.i18n.prop('lan.name'));
$(".i18n-lan-inetport").html($.i18n.prop('lan.inetport'));
$(".i18n-lan-ip").html($.i18n.prop('lan.ip'));
$("input[name='inetPort']").attr("placeholder", $.i18n.prop('lan.inetport.placeholder'));
$("input[name='lan']").attr("placeholder", $.i18n.prop('lan.ip.placeholder'));
$(".update").html($.i18n.prop('public.submit'));
$(".back").html($.i18n.prop('public.back'));
});
$(".update").click(function(){
var name = $("input[name='name']").val();
if(name == ""){
layer.alert("请输入代理备注名称");
layer.alert($.i18n.prop('lan.notice.inputname'), {title:"Tips"});
return;
}
var inetPort = $("input[name='inetPort']").val();
if(inetPort == ""){
layer.alert("请输入公网出口端口");
layer.alert($.i18n.prop('lan.notice.inputinetport'), {title:"Tips"});
return;
}
if(!check_port(inetPort)){
layer.alert("端口格式错误");
layer.alert($.i18n.prop('lan.notice.errorport'), {title:"Tips"});
return;
}
var lan = $("input[name='lan']").val();
if(lan == ""){
layer.alert("请输入后端代理信息");
layer.alert($.i18n.prop('lan.notice.inputlan'), {title:"Tips"});
return;
}
if(!check_lan(lan)){
layer.alert("后端代理信息格式错误");
layer.alert($.i18n.prop('lan.notice.errorlan'), {title:"Tips"});
return;
}
......@@ -69,7 +77,7 @@ $(".update").click(function(){
api_invoke("/config/update", clientList, function(data) {
if (data.code == 20000) {
layer.alert('更新成功', function(index){
layer.alert($.i18n.prop('public.notice.updatesuccess'), {title:"Tips"}, function(index){
layer.close(index);
load_page("html/lan/list.html");
});
......
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title">
<li class="layui-this tab-title">代理配置列表</li>
<li class="layui-this tab-title"></li>
</ul>
<div class="main-content"></div>
<div class="layui-input-block" style="float: left; margin-left: 15px;">
<button class="layui-btn mapping-add">添加配置</button>
<button class="layui-btn mapping-add"></button>
</div>
</div>
<script id="mapping-tpl" type="text/html">
<table class="layui-table" lay-skin="line">
<thead>
<tr>
<th class="i18n-lan-name"></th>
<th class="i18n-lan-inetport"></th>
<th class="i18n-lan-ip"></th>
<th class="i18n-lan-options"></th>
</tr>
</thead>
<tbody>
<%for(var i = 0; i < data.length; i++) {%>
<tr>
<td><%:=data[i].name%></td>
<td><%:=data[i].inetPort%></td>
<td><%:=data[i].lan%></td>
<td>
<a data-index="<%:=i%>" class="layui-btn layui-btn-mini mapping-edit"></a>
<a data-index="<%:=i%>" class="layui-btn layui-btn-danger layui-btn-mini mapping-delete"></a>
</td>
</tr>
<%}%>
</tbody>
</table>
</script>
<script>
$(".tab-title").html(clientList[clientIndex].name+" - 代理配置");
$(".tab-title").html(clientList[clientIndex].name + " - " + $.i18n.prop('lan.proxyconfig'));
$(".mapping-add").html($.i18n.prop('lan.addnewconfig'));
var html = template($("#mapping-tpl").html(), {
data : clientList[clientIndex].proxyMappings
});
$(".main-content").html(html);
$(".i18n-lan-name").html($.i18n.prop('lan.name'));
$(".i18n-lan-inetport").html($.i18n.prop('lan.inetport'));
$(".i18n-lan-ip").html($.i18n.prop('lan.ip'));
$(".i18n-lan-options").html($.i18n.prop('public.options'));
$(".mapping-edit").html($.i18n.prop('public.edit'));
$(".mapping-delete").html($.i18n.prop('public.delete'));
$(".mapping-config").click(function() {
window.clientIndex = $(this).attr("data-index");
load_page("html/lan/list.html");
......@@ -23,7 +55,10 @@
});
$(".mapping-delete").click(function() {
var mappingIndex = $(this).attr("data-index");
layer.confirm('确定删除?', function(i) {
layer.confirm($.i18n.prop('public.confirm.delete'), {
title: $.i18n.prop('public.tips'),
btn : [ $.i18n.prop('public.ok'), $.i18n.prop('public.cancel') ]
}, function(i) {
layer.close(i);
clientList[clientIndex].proxyMappings.splice(mappingIndex, 1);
api_invoke("/config/update", clientList, function(data) {
......@@ -42,29 +77,4 @@
$(".mapping-add").click(function() {
load_page("html/lan/add.html");
});
</script>
<script id="mapping-tpl" type="text/html">
<table class="layui-table" lay-skin="line">
<thead>
<tr>
<th>代理名称</th>
<th>公网出口端口</th>
<th>后端IP端口</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%for(var i = 0; i < data.length; i++) {%>
<tr>
<td><%:=data[i].name%></td>
<td><%:=data[i].inetPort%></td>
<td><%:=data[i].lan%></td>
<td>
<a data-index="<%:=i%>" class="layui-btn layui-btn-mini mapping-edit">编辑</a>
<a data-index="<%:=i%>" class="layui-btn layui-btn-danger layui-btn-mini mapping-delete">删除</a>
</td>
</tr>
<%}%>
</tbody>
</table>
</script>
\ No newline at end of file
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title">
<li class="layui-this tab-title">数据统计</li>
<li class="layui-this tab-title"></li>
</ul>
<div class="main-content"></div>
</div>
<script>
function bytesToSize(bytes) {
if (bytes === 0)
return '0 B';
var k = 1000, // or 1024
sizes = [ 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ], i = Math
.floor(Math.log(bytes) / Math.log(k));
return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
}
api_invoke("/metrics/get", {}, function(data) {
var html = template($("#stat-tpl").html(), {
data : data.data
});
$(".main-content").html(html);
});
</script>
<script id="stat-tpl" type="text/html">
<table class="layui-table" lay-skin="line">
<thead>
<tr>
<th>出口端口</th>
<th>流入数据</th>
<th>流出数据</th>
<th>当前连接数</th>
<th class="i18n-inetport"></th>
<th class="i18n-inflow"></th>
<th class="i18n-outflow"></th>
<th class="i18n-channels"></th>
</tr>
</thead>
<tbody>
......@@ -43,4 +25,27 @@
<%}%>
</tbody>
</table>
</script>
<script>
$(".tab-title").html($.i18n.prop('menu.client.statistics'));
function bytesToSize(bytes) {
if (bytes === 0)
return '0 B';
var k = 1000, // or 1024
sizes = [ 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ], i = Math
.floor(Math.log(bytes) / Math.log(k));
return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
}
api_invoke("/metrics/get", {}, function(data) {
var html = template($("#stat-tpl").html(), {
data : data.data
});
$(".main-content").html(html);
$(".i18n-inetport").html($.i18n.prop('statistics.inetport'));
$(".i18n-inflow").html($.i18n.prop('statistics.inflow'));
$(".i18n-outflow").html($.i18n.prop('statistics.outflow'));
$(".i18n-channels").html($.i18n.prop('statistics.channels'));
});
</script>
\ No newline at end of file
......@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1">
<title>LanProxy-内网穿透工具</title>
<title></title>
<link rel="stylesheet" href="/lanproxy-config/layui/css/layui.css">
<style type="text/css">
.main-content {
......@@ -15,10 +15,10 @@
<body>
<div class="layui-layout layui-layout-admin">
<div class="layui-header">
<div class="layui-logo">LanProxy内网穿透</div>
<div class="layui-logo">LanProxy Configuration</div>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item"><a href="javascript:;"
class="logout">退出</a></li>
class="logout"></a></li>
</ul>
</div>
......@@ -28,21 +28,14 @@
<div class="layui-body"></div>
<div class="layui-footer">
<!-- 底部固定区域 -->
LanProxy内网穿透工具
</div>
<div class="layui-footer"></div>
</div>
<script src="/lanproxy-config/layui/layui.js"></script>
<script src="/jquery/jquery-3.1.1.min.js"></script>
<script src="/jquery/jquery.i18n.properties.min.js" type="text/javascript"></script>
<script src="/template/template.js"></script>
<script>
window.clientList = [];
layui.use('layer', function() {
window.layer = layui.layer;
update_menu();
load_page("html/client/list.html");
});
function api_invoke(uri, params, callback) {
var index = layer.load(1, {
......@@ -131,6 +124,11 @@
layui.use('element', function() {
var element = layui.element;
});
$(".client-list").html($.i18n.prop('menu.client.list'));
$(".client-list-sub").html($.i18n.prop('menu.client.list'));
$(".client-add").html($.i18n.prop('menu.client.add'));
$(".client-config").html($.i18n.prop('menu.client.config'));
$(".statistics").html($.i18n.prop('menu.client.statistics'));
$(".menu-item").click(function() {
window.clientIndex = $(this).attr("data-index");
load_page("html/lan/list.html");
......@@ -140,22 +138,56 @@
}
});
}
var i18nLanguage = "en";
var webLanguage = [ 'zh-CN', 'en' ];
function initWebLanguage() {
var navLanguage = navigator.language;
if (navLanguage) {
var charSize = $.inArray(navLanguage, webLanguage);
if (charSize > -1) {
i18nLanguage = navLanguage;
}
}
}
initWebLanguage();
jQuery.i18n.properties({
name : 'lang', //资源文件名称
path : '/i18n/', //资源文件路径
mode : 'map', //用Map的方式使用资源文件中的值
language : i18nLanguage,
encoding: 'UTF-8',
callback : function() {//加载成功后设置显示内容
$('title').html($.i18n.prop('title'));
$(".layui-footer").html($.i18n.prop('title'));
$(".logout").html($.i18n.prop('logout'));
layui.use('layer', function() {
window.layer = layui.layer;
update_menu();
load_page("html/client/list.html");
});
}
});
</script>
<script id="menu-tpl" type="text/html">
<ul class="layui-nav layui-nav-tree">
<li class="layui-nav-item layui-nav-itemed"><a class=""
href="javascript:;">客户端管理</a>
<li class="layui-nav-item layui-nav-itemed"><a class="client-list"
href="javascript:;"></a>
<dl class="layui-nav-child">
<dd class="layui-this">
<a href="javascript:load_page('html/client/list.html');">客户端列表</a>
<a href="javascript:load_page('html/client/list.html');" class="client-list-sub"></a>
</dd>
<dd>
<a href="javascript:load_page('html/client/add.html');">添加客户端</a>
<a href="javascript:load_page('html/client/add.html');" class="client-add"></a>
</dd>
</dl>
</li>
<li class="layui-nav-item layui-nav-itemed">
<a class="" href="javascript:;">配置管理</a>
<a class="client-config" href="javascript:;"></a>
<dl class="layui-nav-child">
<%for(var i = 0; i < list.length; i++) {%>
<dd>
......@@ -164,8 +196,8 @@
<%}%>
</dl>
</li>
<li class="layui-nav-item layui-nav-itemed"><a class=""
href="javascript:load_page('html/statistics/list.html');">数据统计</a>
<li class="layui-nav-item layui-nav-itemed"><a class="statistics"
href="javascript:load_page('html/statistics/list.html');"></a>
</li>
</ul>
</script>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册