mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-12 19:30:26 +08:00
增加API节点安装配置界面
This commit is contained in:
2
build/configs/.gitignore
vendored
2
build/configs/.gitignore
vendored
@@ -1,3 +1,3 @@
|
|||||||
server.yaml
|
server.yaml
|
||||||
db.yaml
|
api_db.yaml
|
||||||
api.yaml
|
api.yaml
|
||||||
11
build/configs/api_db.template.yaml
Normal file
11
build/configs/api_db.template.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
default:
|
||||||
|
db: "prod"
|
||||||
|
prefix: ""
|
||||||
|
|
||||||
|
dbs:
|
||||||
|
prod:
|
||||||
|
driver: "mysql"
|
||||||
|
dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge?charset=utf8mb4&timeout=30s"
|
||||||
|
prefix: "edge"
|
||||||
|
models:
|
||||||
|
package: internal/web/models
|
||||||
@@ -12,7 +12,7 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(helpers.NewUserMustAuth()).
|
Helper(helpers.NewUserMustAuth()).
|
||||||
Helper(NewHelper()).
|
Helper(NewHelper()).
|
||||||
Helper(settingutils.NewHelper("api")).
|
Helper(settingutils.NewHelper("apiNodes")).
|
||||||
Prefix("/api").
|
Prefix("/api").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
GetPost("/node/createPopup", new(node.CreatePopupAction)).
|
GetPost("/node/createPopup", new(node.CreatePopupAction)).
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/logs"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Helper struct {
|
type Helper struct {
|
||||||
@@ -22,43 +17,5 @@ func (this *Helper) BeforeAction(action *actions.ActionObject) (goNext bool) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
action.Data["teaMenu"] = "api"
|
|
||||||
|
|
||||||
nodeId := action.ParamInt64("nodeId")
|
|
||||||
nodeIdString := strconv.FormatInt(nodeId, 10)
|
|
||||||
|
|
||||||
// 节点信息
|
|
||||||
rpcClient, err := rpc.SharedRPC()
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
nodeResp, err := rpcClient.APINodeRPC().FindEnabledAPINode(rpcClient.Context(action.Context.GetInt64("adminId")), &pb.FindEnabledAPINodeRequest{NodeId: nodeId})
|
|
||||||
if err != nil {
|
|
||||||
action.WriteString(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if nodeResp.Node == nil {
|
|
||||||
action.WriteString("node not found")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 左侧菜单栏
|
|
||||||
secondMenuItem := action.Data.GetString("secondMenuItem")
|
|
||||||
switch action.Data.GetString("firstMenuItem") {
|
|
||||||
case "setting":
|
|
||||||
action.Data["leftMenuItems"] = this.createSettingMenu(nodeIdString, secondMenuItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置相关菜单
|
|
||||||
func (this *Helper) createSettingMenu(nodeIdString string, selectedItem string) (items []maps.Map) {
|
|
||||||
items = append(items, maps.Map{
|
|
||||||
"name": "基础设置",
|
|
||||||
"url": "/api/node/settings?nodeId=" + nodeIdString,
|
|
||||||
"isActive": selectedItem == "basic",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|||||||
102
internal/web/actions/default/api/node/index.go
Normal file
102
internal/web/actions/default/api/node/index.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package node
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "", "index")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
NodeId int64
|
||||||
|
}) {
|
||||||
|
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{NodeId: params.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
node := nodeResp.Node
|
||||||
|
if node == nil {
|
||||||
|
this.NotFound("apiNode", params.NodeId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听地址
|
||||||
|
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||||
|
if len(node.HttpJSON) > 0 {
|
||||||
|
err = json.Unmarshal(node.HttpJSON, httpConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||||
|
if len(node.HttpsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(node.HttpsJSON, httpsConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听地址
|
||||||
|
listens := []*serverconfigs.NetworkAddressConfig{}
|
||||||
|
listens = append(listens, httpConfig.Listen...)
|
||||||
|
listens = append(listens, httpsConfig.Listen...)
|
||||||
|
|
||||||
|
// 证书信息
|
||||||
|
certs := []*sslconfigs.SSLCertConfig{}
|
||||||
|
sslPolicyId := int64(0)
|
||||||
|
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
|
||||||
|
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{SslPolicyId: httpsConfig.SSLPolicyRef.SSLPolicyId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sslPolicyConfigJSON := sslPolicyConfigResp.SslPolicyJSON
|
||||||
|
if len(sslPolicyConfigJSON) > 0 {
|
||||||
|
sslPolicyId = httpsConfig.SSLPolicyRef.SSLPolicyId
|
||||||
|
|
||||||
|
sslPolicy := &sslconfigs.SSLPolicy{}
|
||||||
|
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
certs = sslPolicy.Certs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 访问地址
|
||||||
|
accessAddrs := []*serverconfigs.NetworkAddressConfig{}
|
||||||
|
if len(node.AccessAddrsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(node.AccessAddrsJSON, &accessAddrs)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["node"] = maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
"description": node.Description,
|
||||||
|
"isOn": node.IsOn,
|
||||||
|
"listens": listens,
|
||||||
|
"accessAddrs": accessAddrs,
|
||||||
|
"hasHTTPS": sslPolicyId > 0,
|
||||||
|
"certs": certs,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ func init() {
|
|||||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
server.
|
server.
|
||||||
Helper(helpers.NewUserMustAuth()).
|
Helper(helpers.NewUserMustAuth()).
|
||||||
Helper(settingutils.NewHelper("api")).
|
Helper(settingutils.NewHelper("apiNodes")).
|
||||||
Prefix("/api/node").
|
Prefix("/api/node").
|
||||||
|
|
||||||
// 这里不受Helper的约束
|
// 这里不受Helper的约束
|
||||||
@@ -19,8 +19,9 @@ func init() {
|
|||||||
|
|
||||||
// 节点相关
|
// 节点相关
|
||||||
Helper(NewHelper()).
|
Helper(NewHelper()).
|
||||||
GetPost("/settings", new(SettingsAction)).
|
Get("", new(IndexAction)).
|
||||||
|
GetPost("/update", new(UpdateAction)).
|
||||||
|
Get("/install", new(InstallAction)).
|
||||||
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
58
internal/web/actions/default/api/node/install.go
Normal file
58
internal/web/actions/default/api/node/install.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package node
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InstallAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *InstallAction) Init() {
|
||||||
|
this.Nav("", "", "install")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *InstallAction) RunGet(params struct {
|
||||||
|
NodeId int64
|
||||||
|
}) {
|
||||||
|
// API节点信息
|
||||||
|
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{NodeId: params.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
node := nodeResp.Node
|
||||||
|
if node == nil {
|
||||||
|
this.NotFound("apiNode", params.NodeId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["node"] = maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
"uniqueId": node.UniqueId,
|
||||||
|
"secret": node.Secret,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据库配置
|
||||||
|
dbConfigMap := maps.Map{
|
||||||
|
"config": "",
|
||||||
|
"error": "",
|
||||||
|
"isNotFound": false,
|
||||||
|
}
|
||||||
|
dbConfigFile := Tea.ConfigFile("api_db.yaml")
|
||||||
|
data, err := ioutil.ReadFile(dbConfigFile)
|
||||||
|
dbConfigMap["config"] = string(data)
|
||||||
|
if err != nil {
|
||||||
|
dbConfigMap["error"] = err.Error()
|
||||||
|
dbConfigMap["isNotFound"] = os.IsNotExist(err)
|
||||||
|
}
|
||||||
|
this.Data["dbConfig"] = dbConfigMap
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -10,16 +10,15 @@ import (
|
|||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SettingsAction struct {
|
type UpdateAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SettingsAction) Init() {
|
func (this *UpdateAction) Init() {
|
||||||
this.Nav("", "setting", "setting")
|
this.Nav("", "", "update")
|
||||||
this.SecondMenu("basic")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SettingsAction) RunGet(params struct {
|
func (this *UpdateAction) RunGet(params struct {
|
||||||
NodeId int64
|
NodeId int64
|
||||||
}) {
|
}) {
|
||||||
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{
|
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{
|
||||||
@@ -104,7 +103,7 @@ func (this *SettingsAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保存基础设置
|
// 保存基础设置
|
||||||
func (this *SettingsAction) RunPost(params struct {
|
func (this *UpdateAction) RunPost(params struct {
|
||||||
NodeId int64
|
NodeId int64
|
||||||
Name string
|
Name string
|
||||||
SslPolicyId int64
|
SslPolicyId int64
|
||||||
@@ -11,7 +11,7 @@ func init() {
|
|||||||
server.
|
server.
|
||||||
Helper(new(helpers.UserMustAuth)).
|
Helper(new(helpers.UserMustAuth)).
|
||||||
Helper(new(Helper)).
|
Helper(new(Helper)).
|
||||||
Helper(settingutils.NewHelper("db")).
|
Helper(settingutils.NewHelper("dbNodes")).
|
||||||
Prefix("/db").
|
Prefix("/db").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
GetPost("/createPopup", new(CreatePopupAction)).
|
||||||
|
|||||||
15
internal/web/actions/default/settings/database/index.go
Normal file
15
internal/web/actions/default/settings/database/index.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package profile
|
||||||
|
|
||||||
|
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
18
internal/web/actions/default/settings/database/init.go
Normal file
18
internal/web/actions/default/settings/database/init.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package profile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/settingutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/iwind/TeaGo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(helpers.NewUserMustAuth()).
|
||||||
|
Helper(settingutils.NewHelper("database")).
|
||||||
|
Prefix("/settings/database").
|
||||||
|
Get("", new(IndexAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -27,12 +27,13 @@ func (this *Helper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool)
|
|||||||
tabbar := actionutils.NewTabbar()
|
tabbar := actionutils.NewTabbar()
|
||||||
tabbar.Add("管理界面", "", "/settings", "", this.tab == "console")
|
tabbar.Add("管理界面", "", "/settings", "", this.tab == "console")
|
||||||
tabbar.Add("安全设置", "", "/settings/security", "", this.tab == "security")
|
tabbar.Add("安全设置", "", "/settings/security", "", this.tab == "security")
|
||||||
tabbar.Add("API节点", "", "/api", "exchange", this.tab == "api")
|
tabbar.Add("数据库", "", "/settings/database", "", this.tab == "database")
|
||||||
tabbar.Add("日志数据库节点", "", "/db", "database", this.tab == "db")
|
tabbar.Add("API节点", "", "/api", "", this.tab == "apiNodes")
|
||||||
|
tabbar.Add("日志数据库", "", "/db", "", this.tab == "dbNodes")
|
||||||
tabbar.Add("备份", "", "/settings/backup", "", this.tab == "backup")
|
tabbar.Add("备份", "", "/settings/backup", "", this.tab == "backup")
|
||||||
tabbar.Add("个人资料", "", "/settings/profile", "", this.tab == "profile")
|
tabbar.Add("个人资料", "", "/settings/profile", "", this.tab == "profile")
|
||||||
tabbar.Add("登录设置", "", "/settings/login", "", this.tab == "login")
|
tabbar.Add("登录设置", "", "/settings/login", "", this.tab == "login")
|
||||||
tabbar.Add("检查版本更新", "", "/settings/upgrade", "", this.tab == "upgrade")
|
tabbar.Add("检查新版本", "", "/settings/upgrade", "", this.tab == "upgrade")
|
||||||
actionutils.SetTabbar(actionPtr, tabbar)
|
actionutils.SetTabbar(actionPtr, tabbar)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
23
internal/web/actions/default/ui/download.go
Normal file
23
internal/web/actions/default/ui/download.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 下载指定的文本内容
|
||||||
|
type DownloadAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DownloadAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DownloadAction) RunGet(params struct {
|
||||||
|
File string
|
||||||
|
Text string
|
||||||
|
}) {
|
||||||
|
this.AddHeader("Content-Disposition", "attachment; filename=\""+params.File+"\";")
|
||||||
|
this.WriteString(params.Text)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,8 +8,11 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
server.
|
server.
|
||||||
Helper(new(actions.Gzip)).
|
|
||||||
Prefix("/ui").
|
Prefix("/ui").
|
||||||
|
Get("/download", new(DownloadAction)).
|
||||||
|
|
||||||
|
// 以下的需要压缩
|
||||||
|
Helper(new(actions.Gzip)).
|
||||||
Get("/components.js", new(ComponentsAction)).
|
Get("/components.js", new(ComponentsAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import (
|
|||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/stat"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/stat"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/backup"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/backup"
|
||||||
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/database"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/login"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/login"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/profile"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/profile"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/security"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/security"
|
||||||
|
|||||||
37
web/public/js/components/common/download-link.js
Normal file
37
web/public/js/components/common/download-link.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
Vue.component("download-link", {
|
||||||
|
props: ["v-element", "v-file"],
|
||||||
|
created: function () {
|
||||||
|
let that = this
|
||||||
|
setTimeout(function () {
|
||||||
|
that.url = that.composeURL()
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
data: function () {
|
||||||
|
let filename = this.vFile
|
||||||
|
if (filename == null || filename.length == 0) {
|
||||||
|
filename = "unknown-file"
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
file: filename,
|
||||||
|
url: this.composeURL()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
composeURL: function () {
|
||||||
|
let e = document.getElementById(this.vElement)
|
||||||
|
if (e == null) {
|
||||||
|
teaweb.warn("<download-link>找不到要下载的内容")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let text = e.innerText
|
||||||
|
if (text == null) {
|
||||||
|
text = e.textContent
|
||||||
|
}
|
||||||
|
return Tea.url("/ui/download", {
|
||||||
|
file: this.file,
|
||||||
|
text: text
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<a :href="url" target="_blank"><slot></slot></a>`,
|
||||||
|
})
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
|
// 启用状态标签
|
||||||
Vue.component("label-on", {
|
Vue.component("label-on", {
|
||||||
props: ["v-is-on"],
|
props: ["v-is-on"],
|
||||||
template: '<div><span v-if="vIsOn" class="ui label tiny green basic">已启用</span><span v-if="!vIsOn" class="ui label tiny red basic">已停用</span></div>'
|
template: '<div><span v-if="vIsOn" class="ui label tiny green basic">已启用</span><span v-if="!vIsOn" class="ui label tiny red basic">已停用</span></div>'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 文字代码标签
|
||||||
|
Vue.component("code-label", {
|
||||||
|
template: `<span class="ui label basic tiny" style="padding: 3px;margin-left:2px;margin-right:2px"><slot></slot></span>`
|
||||||
|
})
|
||||||
@@ -29,7 +29,9 @@ Vue.component("network-addresses-box", {
|
|||||||
methods: {
|
methods: {
|
||||||
addAddr: function () {
|
addAddr: function () {
|
||||||
let that = this
|
let that = this
|
||||||
|
window.UPDATING_ADDR = null
|
||||||
teaweb.popup("/servers/addPortPopup?serverType=" + this.vServerType + "&protocol=" + this.protocol, {
|
teaweb.popup("/servers/addPortPopup?serverType=" + this.vServerType + "&protocol=" + this.protocol, {
|
||||||
|
height: "16em",
|
||||||
callback: function (resp) {
|
callback: function (resp) {
|
||||||
var addr = resp.data.address
|
var addr = resp.data.address
|
||||||
that.addresses.push(addr)
|
that.addresses.push(addr)
|
||||||
@@ -47,6 +49,29 @@ Vue.component("network-addresses-box", {
|
|||||||
removeAddr: function (index) {
|
removeAddr: function (index) {
|
||||||
this.addresses.$remove(index);
|
this.addresses.$remove(index);
|
||||||
|
|
||||||
|
// 发送事件
|
||||||
|
this.$emit("change", this.addresses)
|
||||||
|
},
|
||||||
|
updateAddr: function (index, addr) {
|
||||||
|
let that = this
|
||||||
|
window.UPDATING_ADDR = addr
|
||||||
|
teaweb.popup("/servers/addPortPopup?serverType=" + this.vServerType + "&protocol=" + this.protocol, {
|
||||||
|
height: "16em",
|
||||||
|
callback: function (resp) {
|
||||||
|
var addr = resp.data.address
|
||||||
|
Vue.set(that.addresses, index, addr)
|
||||||
|
|
||||||
|
if (["https", "https4", "https6"].$contains(addr.protocol)) {
|
||||||
|
this.tlsProtocolName = "HTTPS"
|
||||||
|
} else if (["tls", "tls4", "tls6"].$contains(addr.protocol)) {
|
||||||
|
this.tlsProtocolName = "TLS"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送事件
|
||||||
|
that.$emit("change", that.addresses)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 发送事件
|
// 发送事件
|
||||||
this.$emit("change", this.addresses)
|
this.$emit("change", this.addresses)
|
||||||
}
|
}
|
||||||
@@ -56,6 +81,7 @@ Vue.component("network-addresses-box", {
|
|||||||
<div v-if="addresses.length > 0">
|
<div v-if="addresses.length > 0">
|
||||||
<div class="ui label small" v-for="(addr, index) in addresses">
|
<div class="ui label small" v-for="(addr, index) in addresses">
|
||||||
{{addr.protocol}}://<span v-if="addr.host.length > 0">{{addr.host}}</span><span v-if="addr.host.length == 0">*</span>:{{addr.portRange}}
|
{{addr.protocol}}://<span v-if="addr.host.length > 0">{{addr.host}}</span><span v-if="addr.host.length == 0">*</span>:{{addr.portRange}}
|
||||||
|
<a href="" @click.prevent="updateAddr(index, addr)" title="修改"><i class="icon pencil small"></i></a>
|
||||||
<a href="" @click.prevent="removeAddr(index)" title="删除"><i class="icon remove"></i></a> </div>
|
<a href="" @click.prevent="removeAddr(index)" title="删除"><i class="icon remove"></i></a> </div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Vue.component("network-addresses-view", {
|
||||||
|
props: ["v-addresses"],
|
||||||
|
template: `<div>
|
||||||
|
<div class="ui label tiny" v-if="vAddresses != null" v-for="addr in vAddresses">
|
||||||
|
{{addr.protocol}}://{{addr.host}}:{{addr.portRange}}
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
33
web/public/js/components/server/ssl-certs-view.js
Normal file
33
web/public/js/components/server/ssl-certs-view.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Vue.component("ssl-certs-view", {
|
||||||
|
props: ["v-certs"],
|
||||||
|
data: function () {
|
||||||
|
let certs = this.vCerts
|
||||||
|
if (certs == null) {
|
||||||
|
certs = []
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
certs: certs
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 格式化时间
|
||||||
|
formatTime: function (timestamp) {
|
||||||
|
return new Date(timestamp * 1000).format("Y-m-d")
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查看详情
|
||||||
|
viewCert: function (certId) {
|
||||||
|
teaweb.popup("/servers/components/ssl/certPopup?certId=" + certId, {
|
||||||
|
height: "28em",
|
||||||
|
width: "48em"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<div v-if="certs != null && certs.length > 0">
|
||||||
|
<div class="ui label small" v-for="(cert, index) in certs">
|
||||||
|
{{cert.name}} / {{cert.dnsNames}} / 有效至{{formatTime(cert.timeEndAt)}} <a href="" title="查看" @click.prevent="viewCert(cert.id)"><i class="icon external alternate"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -354,6 +354,8 @@ body.expanded .main {
|
|||||||
.main .tab-menu {
|
.main .tab-menu {
|
||||||
margin-top: 1em !important;
|
margin-top: 1em !important;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
.main .tab-menu .item {
|
.main .tab-menu .item {
|
||||||
padding: 1em !important;
|
padding: 1em !important;
|
||||||
@@ -365,14 +367,11 @@ body.expanded .main {
|
|||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
padding-left: 0.3em;
|
padding-left: 0.3em;
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 512px) {
|
.main .tab-menu .item .icon {
|
||||||
.main .tab-menu {
|
margin-left: 0.6em;
|
||||||
overflow-x: auto;
|
}
|
||||||
overflow-y: hidden;
|
.main .tab-menu::-webkit-scrollbar {
|
||||||
}
|
|
||||||
.main .tab-menu::-webkit-scrollbar {
|
|
||||||
height: 4px;
|
height: 4px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.main .go-top-btn {
|
.main .go-top-btn {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -76,7 +76,7 @@
|
|||||||
<!-- 操作菜单 -->
|
<!-- 操作菜单 -->
|
||||||
<div class="ui top menu tabular tab-menu small" v-if="teaTabbar.length > 0">
|
<div class="ui top menu tabular tab-menu small" v-if="teaTabbar.length > 0">
|
||||||
<a class="item" v-for="item in teaTabbar" :class="{'active':item.active,right:item.right}" :href="item.url">
|
<a class="item" v-for="item in teaTabbar" :class="{'active':item.active,right:item.right}" :href="item.url">
|
||||||
<var>{{item.name}}<span v-if="item.subName.length > 0">({{item.subName}})</span> <i class="icon small" :class="item.icon" v-if="item.icon != null"></i> </var>
|
<var>{{item.name}}<span v-if="item.subName.length > 0">({{item.subName}})</span><i class="icon small" :class="item.icon" v-if="item.icon != null && item.icon.length > 0"></i> </var>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -341,35 +341,38 @@ body.expanded .main {
|
|||||||
width: 2px;
|
width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main .tab-menu {
|
.main {
|
||||||
|
|
||||||
|
.tab-menu {
|
||||||
margin-top: 1em !important;
|
margin-top: 1em !important;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
|
||||||
|
|
||||||
.main .tab-menu .item {
|
|
||||||
padding: 1em !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main .tab-menu .item var {
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main .tab-menu .item span {
|
|
||||||
font-size: 0.8em;
|
|
||||||
padding-left: 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 512px) {
|
|
||||||
.main .tab-menu {
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 1em !important;
|
||||||
|
|
||||||
|
var {
|
||||||
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main .tab-menu::-webkit-scrollbar {
|
span {
|
||||||
|
font-size: 0.8em;
|
||||||
|
padding-left: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-left: 0.6em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-menu::-webkit-scrollbar {
|
||||||
height: 4px;
|
height: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.main .go-top-btn {
|
.main .go-top-btn {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 2.6em;
|
right: 2.6em;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<label-on :v-is-on="node.isOn"></label-on>
|
<label-on :v-is-on="node.isOn"></label-on>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a :href="'/api/node/settings?nodeId=' + node.id">设置</a>
|
<a :href="'/api/node?nodeId=' + node.id">详情</a>
|
||||||
<a href="" @click.prevent="deleteNode(node.id)">删除</a>
|
<a href="" @click.prevent="deleteNode(node.id)">删除</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<first-menu>
|
<first-menu>
|
||||||
<menu-item href="/api" code="index">节点列表</menu-item>
|
<menu-item href="/api">节点列表</menu-item>
|
||||||
<span class="item">|</span>
|
<span class="item">|</span>
|
||||||
<menu-item :href="'/api/node/settings?nodeId=' + node.id" active="true">{{node.name}}</menu-item>
|
<menu-item :href="'/api/node?nodeId=' + node.id" code="index">"{{node.name}}"详情</menu-item>
|
||||||
|
<menu-item :href="'/api/node/update?nodeId=' + node.id" code="update">修改节点</menu-item>
|
||||||
|
<menu-item :href="'/api/node/install?nodeId=' + node.id" code="install">安装节点</menu-item>
|
||||||
</first-menu>
|
</first-menu>
|
||||||
|
|||||||
44
web/views/@default/api/node/index.html
Normal file
44
web/views/@default/api/node/index.html
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<table class="ui table selectable definition">
|
||||||
|
<tr>
|
||||||
|
<td class="title">节点名称</td>
|
||||||
|
<td>
|
||||||
|
{{node.name}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>状态</td>
|
||||||
|
<td>
|
||||||
|
<label-on :v-is-on="node.isOn"></label-on>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>进程监听端口</td>
|
||||||
|
<td>
|
||||||
|
<network-addresses-view :v-addresses="node.listens"></network-addresses-view>
|
||||||
|
<p class="comment">API节点进程监听的网络端口。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="node.hasHTTPS">
|
||||||
|
<td>HTTPS证书</td>
|
||||||
|
<td>
|
||||||
|
<ssl-certs-view :v-certs="node.certs"></ssl-certs-view>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>外部访问地址</td>
|
||||||
|
<td>
|
||||||
|
<network-addresses-view :v-addresses="node.accessAddrs"></network-addresses-view>
|
||||||
|
<p class="comment">外部访问API节点的网络地址。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>描述</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="node.description.length > 0">{{node.description}}</span>
|
||||||
|
<span v-else class="disabled">暂时还没有描述。</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
33
web/views/@default/api/node/install.html
Normal file
33
web/views/@default/api/node/install.html
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<h3>安装步骤</h3>
|
||||||
|
<ol class="ui list">
|
||||||
|
<li>按照下面的配置信息替换<code-label>configs/api.yaml</code-label>内容</li>
|
||||||
|
<li>按照下面的配置信息替换<code-label>configs/db.yaml</code-label>内容</li>
|
||||||
|
<li>使用<code-label>bin/edge-api start</code-label>启动节点</li>
|
||||||
|
<li>可以在<code-label>logs/run.log</code-label>中查看启动是否有异常</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<h3>配置信息</h3>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">configs/api.yaml<em><br/><download-link :v-element="'api-code'" :v-file="'api.yaml'">[下载]</download-link></em></td>
|
||||||
|
<td>
|
||||||
|
<pre id="api-code">nodeId: "{{node.uniqueId}}"
|
||||||
|
secret: "{{node.secret}}"</pre>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>configs/db.yaml<em><br/><download-link :v-element="'db-code'" :v-file="'db.yaml'">[下载]</download-link></em></td>
|
||||||
|
<td>
|
||||||
|
<span class="red" v-if="dbConfig.error.length > 0">
|
||||||
|
<span v-if="dbConfig.isNotFound">找不到数据库配置文件:configs/api_db.yaml ,请重新 <a href="/settings/database">[配置数据库]</a>:</span>
|
||||||
|
<span v-else class="red">无法生成配置内容,错误原因:</span>
|
||||||
|
{{dbConfig.error}}
|
||||||
|
</span>
|
||||||
|
<pre v-show="dbConfig.config.length > 0" id="db-code">{{dbConfig.config}}</pre>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
{$layout}
|
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "menu"}
|
|
||||||
|
|
||||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
|
||||||
<input type="hidden" name="nodeId" :value="node.id"/>
|
|
||||||
<input type="hidden" name="sslPolicyId" :value="node.sslPolicyId"/>
|
|
||||||
<table class="ui table selectable definition">
|
|
||||||
<tr>
|
|
||||||
<td class="title">节点名称 *</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" name="name" maxlength="100" ref="focus" v-model="node.name"/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>进程监听端口 *</td>
|
|
||||||
<td>
|
|
||||||
<network-addresses-box :v-name="'listensJSON'" :v-server-type="'httpWeb'" :v-addresses="node.listens" @change="changeListens"></network-addresses-box>
|
|
||||||
<p class="comment">API节点进程监听的网络端口。</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr v-if="hasHTTPS">
|
|
||||||
<td>HTTPS证书 *</td>
|
|
||||||
<td>
|
|
||||||
<ssl-certs-box :v-certs="node.certs" :v-protocol="'https'"></ssl-certs-box>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>外部访问地址 *</td>
|
|
||||||
<td>
|
|
||||||
<api-node-addresses-box :v-name="'accessAddrsJSON'" :v-addrs="node.accessAddrs"></api-node-addresses-box>
|
|
||||||
<p class="comment">外部访问API节点的网络地址。</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
|
||||||
</tr>
|
|
||||||
<tbody v-show="moreOptionsVisible">
|
|
||||||
<tr>
|
|
||||||
<td>描述</td>
|
|
||||||
<td>
|
|
||||||
<textarea name="description" maxlength="200" rows="3" v-model="node.description"></textarea>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>是否启用</td>
|
|
||||||
<td>
|
|
||||||
<div class="ui checkbox">
|
|
||||||
<input type="checkbox" name="isOn" value="1" v-model="node.isOn"/>
|
|
||||||
<label></label>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<submit-btn></submit-btn>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
58
web/views/@default/api/node/update.html
Normal file
58
web/views/@default/api/node/update.html
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{$layout}
|
||||||
|
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<input type="hidden" name="nodeId" :value="node.id"/>
|
||||||
|
<input type="hidden" name="sslPolicyId" :value="node.sslPolicyId"/>
|
||||||
|
<table class="ui table selectable definition">
|
||||||
|
<tr>
|
||||||
|
<td class="title">节点名称 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="name" maxlength="100" ref="focus" v-model="node.name"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>进程监听端口 *</td>
|
||||||
|
<td>
|
||||||
|
<network-addresses-box :v-name="'listensJSON'" :v-server-type="'httpWeb'" :v-addresses="node.listens" @change="changeListens"></network-addresses-box>
|
||||||
|
<p class="comment">API节点进程监听的网络端口。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="hasHTTPS">
|
||||||
|
<td>HTTPS证书 *</td>
|
||||||
|
<td>
|
||||||
|
<ssl-certs-box :v-certs="node.certs" :v-protocol="'https'"></ssl-certs-box>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>外部访问地址 *</td>
|
||||||
|
<td>
|
||||||
|
<api-node-addresses-box :v-name="'accessAddrsJSON'" :v-addrs="node.accessAddrs"></api-node-addresses-box>
|
||||||
|
<p class="comment">外部访问API节点的网络地址。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
|
</tr>
|
||||||
|
<tbody v-show="moreOptionsVisible">
|
||||||
|
<tr>
|
||||||
|
<td>描述</td>
|
||||||
|
<td>
|
||||||
|
<textarea name="description" maxlength="200" rows="3" v-model="node.description"></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否启用</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" name="isOn" value="1" v-model="node.isOn"/>
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
this.success = NotifySuccess("保存成功", "/api/node/settings?nodeId=" + this.node.id)
|
this.success = NotifySuccess("保存成功", "/api/node?nodeId=" + this.node.id)
|
||||||
|
|
||||||
this.hasHTTPS = this.node.listens.$any(function (k, v) {
|
this.hasHTTPS = this.node.listens.$any(function (k, v) {
|
||||||
return v.protocol == "https"
|
return v.protocol == "https"
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{$layout "layout_popup"}
|
{$layout "layout_popup"}
|
||||||
<h3>添加端口绑定</h3>
|
|
||||||
|
|
||||||
|
<h3 v-if="!isUpdating">添加端口绑定</h3>
|
||||||
|
<h3 v-if="isUpdating">修改端口绑定</h3>
|
||||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="title">端口</td>
|
<td class="title">端口</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="address" ref="focus"/>
|
<input type="text" name="address" ref="focus" v-model="address"/>
|
||||||
<p class="comment">可以是一个数字端口(通常不超过65535),也可以是"地址:端口"的方式。</p>
|
<p class="comment">可以是一个数字端口(通常不超过65535),也可以是"地址:端口"的方式。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
this.success = NotifyPopup;
|
this.success = NotifyPopup;
|
||||||
|
|
||||||
|
this.isUpdating = false
|
||||||
|
|
||||||
|
this.address = ""
|
||||||
|
this.protocol = this.protocols[0].code
|
||||||
|
|
||||||
|
if (window.parent.UPDATING_ADDR != null) {
|
||||||
|
this.isUpdating = true
|
||||||
|
let addr = window.parent.UPDATING_ADDR
|
||||||
|
this.protocol = addr.protocol
|
||||||
|
if (addr.host.length == 0) {
|
||||||
|
this.address = addr.portRange
|
||||||
|
} else {
|
||||||
|
this.address = addr.host + ":" + addr.portRange
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
3
web/views/@default/settings/database/index.html
Normal file
3
web/views/@default/settings/database/index.html
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{$layout}
|
||||||
|
|
||||||
|
<p class="comment">此功能暂未开放,敬请期待。</p>
|
||||||
Reference in New Issue
Block a user