mirror of
https://github.com/ehang-io/nps.git
synced 2025-09-02 03:16:53 +00:00
Modular 、Functional enhancement
This commit is contained in:
@@ -49,6 +49,10 @@ func (s *BaseController) Prepare() {
|
||||
s.Data["allow_rate_limit"], _ = beego.AppConfig.Bool("allow_rate_limit")
|
||||
s.Data["allow_connection_num_limit"], _ = beego.AppConfig.Bool("allow_connection_num_limit")
|
||||
s.Data["allow_multi_ip"], _ = beego.AppConfig.Bool("allow_multi_ip")
|
||||
s.Data["system_info_display"], _ = beego.AppConfig.Bool("system_info_display")
|
||||
s.Data["allow_tunnel_num_limit"], _ = beego.AppConfig.Bool("allow_tunnel_num_limit")
|
||||
s.Data["allow_local_proxy"], _ = beego.AppConfig.Bool("allow_local_proxy")
|
||||
s.Data["allow_user_change_username"], _ = beego.AppConfig.Bool("allow_user_change_username")
|
||||
}
|
||||
|
||||
//加载模板
|
||||
|
@@ -54,6 +54,7 @@ func (s *ClientController) Add() {
|
||||
MaxConn: s.GetIntNoErr("max_conn"),
|
||||
WebUserName: s.GetString("web_username"),
|
||||
WebPassword: s.GetString("web_password"),
|
||||
MaxTunnelNum: s.GetIntNoErr("max_tunnel"),
|
||||
Flow: &file.Flow{
|
||||
ExportFlow: 0,
|
||||
InletFlow: 0,
|
||||
@@ -116,13 +117,17 @@ func (s *ClientController) Edit() {
|
||||
c.Flow.FlowLimit = int64(s.GetIntNoErr("flow_limit"))
|
||||
c.RateLimit = s.GetIntNoErr("rate_limit")
|
||||
c.MaxConn = s.GetIntNoErr("max_conn")
|
||||
c.MaxTunnelNum = s.GetIntNoErr("max_tunnel")
|
||||
}
|
||||
c.Remark = s.GetString("remark")
|
||||
c.Cnf.U = s.GetString("u")
|
||||
c.Cnf.P = s.GetString("p")
|
||||
c.Cnf.Compress = common.GetBoolByStr(s.GetString("compress"))
|
||||
c.Cnf.Crypt = s.GetBoolNoErr("crypt")
|
||||
c.WebUserName = s.GetString("web_username")
|
||||
b, err := beego.AppConfig.Bool("allow_user_change_username")
|
||||
if s.GetSession("isAdmin").(bool) || (err == nil && b) {
|
||||
c.WebUserName = s.GetString("web_username")
|
||||
}
|
||||
c.WebPassword = s.GetString("web_password")
|
||||
c.ConfigConnAllow = s.GetBoolNoErr("config_conn_allow")
|
||||
if c.Rate != nil {
|
||||
|
@@ -93,7 +93,7 @@ func (s *IndexController) Add() {
|
||||
Port: s.GetIntNoErr("port"),
|
||||
ServerIp: s.GetString("server_ip"),
|
||||
Mode: s.GetString("type"),
|
||||
Target: &file.Target{TargetStr: s.GetString("target")},
|
||||
Target: &file.Target{TargetStr: s.GetString("target"), LocalProxy: s.GetBoolNoErr("local_proxy")},
|
||||
Id: int(file.GetDb().JsonDb.GetTaskId()),
|
||||
Status: true,
|
||||
Remark: s.GetString("remark"),
|
||||
@@ -109,6 +109,9 @@ func (s *IndexController) Add() {
|
||||
if t.Client, err = file.GetDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
s.AjaxErr(err.Error())
|
||||
}
|
||||
if t.Client.MaxTunnelNum != 0 && t.Client.GetTunnelNum() >= t.Client.MaxTunnelNum {
|
||||
s.AjaxErr("The number of tunnels exceeds the limit")
|
||||
}
|
||||
if err := file.GetDb().NewTask(t); err != nil {
|
||||
s.AjaxErr(err.Error())
|
||||
}
|
||||
@@ -166,6 +169,7 @@ func (s *IndexController) Edit() {
|
||||
t.LocalPath = s.GetString("local_path")
|
||||
t.StripPre = s.GetString("strip_pre")
|
||||
t.Remark = s.GetString("remark")
|
||||
t.Target.LocalProxy = s.GetBoolNoErr("local_proxy")
|
||||
file.GetDb().UpdateTask(t)
|
||||
server.StopServer(t.Id)
|
||||
server.StartTask(t.Id)
|
||||
@@ -244,7 +248,7 @@ func (s *IndexController) AddHost() {
|
||||
h := &file.Host{
|
||||
Id: int(file.GetDb().JsonDb.GetHostId()),
|
||||
Host: s.GetString("host"),
|
||||
Target: &file.Target{TargetStr: s.GetString("target")},
|
||||
Target: &file.Target{TargetStr: s.GetString("target"), LocalProxy: s.GetBoolNoErr("local_proxy")},
|
||||
HeaderChange: s.GetString("header"),
|
||||
HostChange: s.GetString("hostchange"),
|
||||
Remark: s.GetString("remark"),
|
||||
@@ -304,6 +308,7 @@ func (s *IndexController) EditHost() {
|
||||
h.Scheme = s.GetString("scheme")
|
||||
h.KeyFilePath = s.GetString("key_file_path")
|
||||
h.CertFilePath = s.GetString("cert_file_path")
|
||||
h.Target.LocalProxy = s.GetBoolNoErr("local_proxy")
|
||||
file.GetDb().JsonDb.StoreHostToJsonFile()
|
||||
}
|
||||
s.AjaxOk("modified success")
|
||||
|
@@ -13,6 +13,7 @@ type LoginController struct {
|
||||
}
|
||||
|
||||
func (self *LoginController) Index() {
|
||||
self.Data["register_allow"], _ = beego.AppConfig.Bool("allow_user_register")
|
||||
self.TplName = "login/index.html"
|
||||
}
|
||||
func (self *LoginController) Verify() {
|
||||
@@ -55,6 +56,37 @@ func (self *LoginController) Verify() {
|
||||
}
|
||||
self.ServeJSON()
|
||||
}
|
||||
func (self *LoginController) Register() {
|
||||
if self.Ctx.Request.Method == "GET" {
|
||||
self.TplName = "login/register.html"
|
||||
} else {
|
||||
if b, err := beego.AppConfig.Bool("allow_user_register"); err != nil || !b {
|
||||
self.Data["json"] = map[string]interface{}{"status": 0, "msg": "register is not allow"}
|
||||
self.ServeJSON()
|
||||
return
|
||||
}
|
||||
if self.GetString("username") == "" || self.GetString("password") == "" || self.GetString("username") == beego.AppConfig.String("web_username") {
|
||||
self.Data["json"] = map[string]interface{}{"status": 0, "msg": "please check your input"}
|
||||
self.ServeJSON()
|
||||
return
|
||||
}
|
||||
t := &file.Client{
|
||||
Id: int(file.GetDb().JsonDb.GetClientId()),
|
||||
Status: true,
|
||||
Cnf: &file.Config{},
|
||||
WebUserName: self.GetString("username"),
|
||||
WebPassword: self.GetString("password"),
|
||||
Flow: &file.Flow{},
|
||||
}
|
||||
if err := file.GetDb().NewClient(t); err != nil {
|
||||
self.Data["json"] = map[string]interface{}{"status": 0, "msg": err.Error()}
|
||||
} else {
|
||||
self.Data["json"] = map[string]interface{}{"status": 1, "msg": "register success"}
|
||||
}
|
||||
self.ServeJSON()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *LoginController) Out() {
|
||||
self.SetSession("auth", false)
|
||||
self.Redirect("/login/index", 302)
|
||||
|
@@ -39,6 +39,15 @@
|
||||
placeholder="empty means to be unrestricted">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_tunnel_num_limit}}
|
||||
<div class="form-group" id="max_tunnel">
|
||||
<label class="control-label col-sm-2" langtag="info-max-tunnel-num">客户端最大隧道数量</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" type="text" name="max_tunnel"
|
||||
placeholder="empty means to be unrestricted">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="u">
|
||||
<label class="control-label col-sm-2" langtag="info-web-auth-username">basic权限认证用户名</label>
|
||||
|
@@ -44,6 +44,15 @@
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq true .allow_tunnel_num_limit}}
|
||||
<div class="form-group" id="max_tunnel">
|
||||
<label class="control-label col-sm-2" langtag="info-max-tunnel-num">客户端最大隧道数量</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" value="{{.c.MaxTunnelNum}}" type="text" name="max_tunnel"
|
||||
placeholder="empty means to be unrestricted">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="form-group" id="u">
|
||||
<label class="control-label col-sm-2" langtag="info-web-auth-username">basic权限认证用户名</label>
|
||||
@@ -72,6 +81,7 @@
|
||||
</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 col-sm-2" langtag="info-client-web-username">web登陆用户名</label>
|
||||
<div class="col-sm-10">
|
||||
@@ -79,6 +89,7 @@
|
||||
placeholder="empty means to be unrestricted">
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="web_password">
|
||||
<label class="control-label col-sm-2" langtag="info-client-web-password">web登陆密码</label>
|
||||
<div class="col-sm-10">
|
||||
|
@@ -127,6 +127,7 @@
|
||||
+ '<b langtag="info-now-conn-num">当前连接数</b>:' + row.NowConn + `       `
|
||||
+ '<b langtag="info-flow-limit">流量限制</b>:' + row.Flow.FlowLimit + `m       `
|
||||
+ '<b langtag="info-rate-limit">带宽限制</b>:' + row.RateLimit + `kb/s       `
|
||||
+ '<b langtag="info-max-tunnel-num">隧道数限制</b>:' + row.MaxTunnelNum + `       `
|
||||
+ '<b langtag="info-client-web-username">web登陆用户名</b>:' + row.WebUserName + `       `
|
||||
+ '<b langtag="info-client-web-password">web登陆密码</b>:' + row.WebPassword + `       `
|
||||
+ `       ` + "<br/><br>"
|
||||
|
@@ -43,8 +43,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" name="local_proxy">
|
||||
<option value="0">no</option>
|
||||
<option value="1">yes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="form-group" id="target">
|
||||
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
|
||||
<label class="col-sm-2 control-label" langtag="info-target">目标(ip:端口)</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" name="target" rows="4" placeholder="10.1.50.203:22
|
||||
10.1.50.202:22"></textarea>
|
||||
@@ -103,9 +115,9 @@
|
||||
</div>
|
||||
<script>
|
||||
var arr = []
|
||||
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "strip_pre", "local_path"]
|
||||
arr["tcp"] = ["type", "port", "target", "compress", "u", "p", "tcp隧道模式,提供一条tcp隧道,适用于ssh、远程桌面等,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的目标端口"]
|
||||
arr["udp"] = ["type", "port", "target", "compress", "udp隧道模式,提供一条udp隧道,适用于dns、内网dns访问等,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的udp目标端口"]
|
||||
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "strip_pre", "local_path", "local_proxy"]
|
||||
arr["tcp"] = ["type", "port", "target", "compress", "u", "p", "local_proxy", "tcp隧道模式,提供一条tcp隧道,适用于ssh、远程桌面等,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的目标端口"]
|
||||
arr["udp"] = ["type", "port", "target", "compress", "local_proxy", "udp隧道模式,提供一条udp隧道,适用于dns、内网dns访问等,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的udp目标端口"]
|
||||
arr["socks5"] = ["type", "port", "compress", "u", "p", "socks5代理模式,内网socks5代理,配合proxifer,可如同使用vpn一样访问内网设备或资源,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置socks5代理,即访问内网设备或者资源 "]
|
||||
arr["httpProxy"] = ["type", "port", "compress", "u", "p", " http代理模式,内网http代理,可访问内网网站,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置http代理,即访问内网站点"]
|
||||
arr["secret"] = ["type", "target", "compress", "password", "u", "p", " http代理模式,内网http代理,可访问内网网站,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置http代理,即访问内网站点"]
|
||||
|
@@ -44,6 +44,17 @@
|
||||
placeholder="such as 8024">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" name="local_proxy">
|
||||
<option {{if eq false .t.Target.LocalProxy}}selected{{end}} value="0">no</option>
|
||||
<option {{if eq true .t.Target.LocalProxy}}selected{{end}} value="1">yes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group" id="target">
|
||||
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
|
||||
<div class="col-sm-10">
|
||||
@@ -103,9 +114,9 @@
|
||||
</div>
|
||||
<script>
|
||||
var arr = []
|
||||
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "local_path", "strip_pre"]
|
||||
arr["tcp"] = ["type", "port", "target", "u", "p", "compress"]
|
||||
arr["udp"] = ["type", "port", "target", "compress"]
|
||||
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "local_path", "strip_pre", "local_proxy"]
|
||||
arr["tcp"] = ["type", "port", "target", "u", "p", "compress", "local_proxy"]
|
||||
arr["udp"] = ["type", "port", "target", "compress", "local_proxy"]
|
||||
arr["socks5"] = ["type", "port", "compress", "u", "p"]
|
||||
arr["httpProxy"] = ["type", "port", "compress", "u", "p"]
|
||||
arr["secret"] = ["type", "target", "compress", "u", "p", "password"]
|
||||
|
@@ -56,6 +56,17 @@
|
||||
placeholder="client id">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" name="local_proxy">
|
||||
<option value="0">no</option>
|
||||
<option value="1">yes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
|
||||
<div class="col-sm-10">
|
||||
|
@@ -59,6 +59,17 @@
|
||||
placeholder="client id">
|
||||
</div>
|
||||
</div>
|
||||
{{if eq true .allow_local_proxy}}
|
||||
<div class="form-group" id="local_proxy">
|
||||
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" name="local_proxy">
|
||||
<option {{if eq false .h.Target.LocalProxy}}selected{{end}} value="0">no</option>
|
||||
<option {{if eq true .h.Target.LocalProxy}}selected{{end}} value="1">yes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
|
||||
<div class="col-sm-10">
|
||||
|
@@ -242,7 +242,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{if eq true .system_info_display}}
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="ibox float-e-margins">
|
||||
@@ -340,6 +340,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
@@ -63,12 +63,19 @@
|
||||
detailView: true,
|
||||
smartDisplay: true, // 智能显示 pagination 和 cardview 等
|
||||
detailFormatter: function (index, row, element) {
|
||||
return '<b langtag="info-export-flow">出口流量</b>:' + change(row.Flow.ExportFlow) + `       `
|
||||
+ '<b langtag="info-inlet-flow">入口流量</b>:' + change(row.Flow.InletFlow) + `       ` + "<br/><br>"
|
||||
tmp = '<b langtag="info-export-flow">出口流量</b>:' + change(row.Flow.ExportFlow) + `       `
|
||||
+ '<b langtag="info-inlet-flow">入口流量</b>:' + change(row.Flow.InletFlow) + `       `
|
||||
+ '<b langtag="info-crypt">加密</b>:' + row.Client.Cnf.Crypt + `       `
|
||||
+ '<b langtag="info-compress">压缩</b>:' + row.Client.Cnf.Compress + `       `
|
||||
+ '<b langtag="info-web-auth-username">basic权限认证用户名</b>:' + row.Client.Cnf.U + `       `
|
||||
+ '<b langtag="info-web-auth-password">basic权限认证密码</b>:' + row.Client.Cnf.P + `       `
|
||||
if (row.Mode == "p2p") {
|
||||
return tmp + "<br/><br>" + '<b langtag="info-command">访问端命令</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -target=your target" + "</code>"
|
||||
}
|
||||
if (row.Mode = "secret") {
|
||||
return tmp + "<br/><br>" + '<b langtag="info-command">访问端命令</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -local_type=secret" + "</code>"
|
||||
}
|
||||
return tmp
|
||||
},
|
||||
//表格的列
|
||||
columns: [
|
||||
@@ -112,13 +119,13 @@
|
||||
field: 'Password',//域值
|
||||
title: 'secret',//标题
|
||||
visible: true,//false表示不显示
|
||||
|
||||
|
||||
},
|
||||
{
|
||||
field: 'Status',//域值
|
||||
title: 'setting',//内容
|
||||
visible: true,//false表示不显示
|
||||
|
||||
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span class="badge badge-primary">open</span>'
|
||||
@@ -131,7 +138,7 @@
|
||||
field: 'RunStatus',//域值
|
||||
title: 'run',//内容
|
||||
visible: true,//false表示不显示
|
||||
|
||||
|
||||
formatter: function (value, row, index) {
|
||||
if (value) {
|
||||
return '<span class="badge badge-primary">open</span>'
|
||||
@@ -144,7 +151,7 @@
|
||||
field: '',//域值
|
||||
title: 'client',//内容
|
||||
visible: true,//false表示不显示
|
||||
|
||||
|
||||
formatter: function (value, row, index) {
|
||||
if (row.Client.IsConnect) {
|
||||
return '<span class="badge badge-primary">online</span>'
|
||||
@@ -157,7 +164,7 @@
|
||||
field: 'option',//域值
|
||||
title: 'option',//内容
|
||||
visible: true,//false表示不显示
|
||||
|
||||
|
||||
formatter: function (value, row, index) {
|
||||
btn_group = '<div class="btn-group">'
|
||||
btn = `<button onclick="del(` + row.Id + `)" class="btn-danger"><i class="fa fa-trash"></i></button><button onclick="edit(` + row.Id + `)" class="btn-primary"><i class="fa fa-edit"></i></button></div>`
|
||||
|
@@ -48,6 +48,9 @@
|
||||
<input name="password" type="password" class="form-control" placeholder="password" required="">
|
||||
</div>
|
||||
<button onclick="login()" class="btn btn-primary block full-width m-b">login</button>
|
||||
{{if eq true .register_allow}}
|
||||
<a class="btn btn-sm btn-white btn-block" href="/login/register">register</a>
|
||||
{{end}}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
61
web/views/login/register.html
Normal file
61
web/views/login/register.html
Normal file
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>nps register</title>
|
||||
|
||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
||||
|
||||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
|
||||
<body class="gray-bg">
|
||||
|
||||
<div class="middle-box text-center loginscreen animated fadeInDown">
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<h1 class="logo-name">NPS</h1>
|
||||
|
||||
</div>
|
||||
<h3>register NPS</h3>
|
||||
<form class="m-t" role="form" onsubmit="return false">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="username" name="username" required="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" placeholder="password" name="password" required="">
|
||||
</div>
|
||||
<button onclick="register()" type="submit" class="btn btn-primary block full-width m-b">register</button>
|
||||
|
||||
<a class="btn btn-sm btn-white btn-block" href="/login/index">login</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/jquery-2.1.1.js"></script>
|
||||
<script>
|
||||
function register() {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/login/register",
|
||||
data: $("form").serializeArray(),
|
||||
success: function (res) {
|
||||
alert(res.msg)
|
||||
if (res.status) {
|
||||
window.location.href = "/login/index"
|
||||
}
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Reference in New Issue
Block a user