mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-04 05:00:25 +08:00
初步实现安装界面
This commit is contained in:
1
build/.gitignore
vendored
Normal file
1
build/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
edge-api/
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
rpc:
|
rpc:
|
||||||
endpoints: [ "http://127.0.0.1:8003" ]
|
endpoints: [ "http://127.0.0.1:8003" ]
|
||||||
nodeId: ""
|
nodeId: ""
|
||||||
secret: ""
|
secret: ""
|
||||||
@@ -7,8 +7,11 @@ import (
|
|||||||
"github.com/iwind/TeaGo"
|
"github.com/iwind/TeaGo"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
_ "github.com/iwind/TeaGo/bootstrap"
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"github.com/iwind/TeaGo/logs"
|
||||||
"github.com/iwind/TeaGo/rands"
|
"github.com/iwind/TeaGo/rands"
|
||||||
"github.com/iwind/TeaGo/sessions"
|
"github.com/iwind/TeaGo/sessions"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -26,6 +29,16 @@ func main() {
|
|||||||
secret = "8f983f4d69b83aaa0d74b21a212f6967"
|
secret = "8f983f4d69b83aaa0d74b21a212f6967"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 启动API节点
|
||||||
|
_, err := os.Stat(Tea.Root + "/edge-api/configs/api.yaml")
|
||||||
|
if err == nil {
|
||||||
|
logs.Println("start edge-api")
|
||||||
|
err = exec.Command(Tea.Root + "/edge-api/bin/edge-api").Start()
|
||||||
|
if err != nil {
|
||||||
|
logs.Println("[ERROR]start edge-api failed: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
server := TeaGo.NewServer(false).
|
server := TeaGo.NewServer(false).
|
||||||
AccessLog(false).
|
AccessLog(false).
|
||||||
EndAll().
|
EndAll().
|
||||||
|
|||||||
11
go.mod
11
go.mod
@@ -6,15 +6,10 @@ replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
|
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
|
||||||
github.com/go-redis/redis v6.15.8+incompatible // indirect
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||||
github.com/golang/protobuf v1.4.2 // indirect
|
github.com/iwind/TeaGo v0.0.0-20201010005321-430e836dee8a
|
||||||
github.com/iwind/TeaGo v0.0.0-20200924024009-d088df3778a6
|
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
|
||||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect
|
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa
|
|
||||||
google.golang.org/grpc v1.32.0
|
google.golang.org/grpc v1.32.0
|
||||||
google.golang.org/protobuf v1.25.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
|
||||||
)
|
)
|
||||||
|
|||||||
26
go.sum
26
go.sum
@@ -3,7 +3,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
|
|||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
|
||||||
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
@@ -20,8 +19,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
|
||||||
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
|
||||||
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
|
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
@@ -49,23 +46,12 @@ github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
|||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/iwind/TeaGo v0.0.0-20200723131229-30dff10543ad h1:EVwLRNPYoCNCinN/J9FylGBpKdCilvzUFykKtQABfNA=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200723131229-30dff10543ad/go.mod h1:zjM7k+b+Jthhf0T0fKwuF0iy4TWb5SsU1gmKR2l+OmE=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200816132655-f784df8e9c42 h1:X58QYxjoTstHR4sQEwx4ChAFRYtlWAfqwimQ3d2osT0=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200816132655-f784df8e9c42/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200822074248-b1cf7248c98a h1:VaWcMNOzHHT1y8MeTA2fWhG6GEfAdy6CwF2tW+KiY5Y=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200822074248-b1cf7248c98a/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200909062051-96811444bb22 h1:bCv4Emo49CZyZFbnq9lWNr8nYM1yrfhjuaM7KJEc0jk=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200909062051-96811444bb22/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200910072805-729cffe36729 h1:/v0WhSFVeNay/dA5zU9iCBXlgVDfxnztuanlauXE0gM=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200910072805-729cffe36729/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
|
||||||
github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e h1:/xn7wUvlwaoA5IkdBUctv2OQbJSZ0/Dw8qRJmn55sJk=
|
github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e h1:/xn7wUvlwaoA5IkdBUctv2OQbJSZ0/Dw8qRJmn55sJk=
|
||||||
github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||||
github.com/iwind/TeaGo v0.0.0-20200924024009-d088df3778a6 h1:7OZC/Qy7Z/hK9vG6YQOwHNOUPunSImYYJMiIfvuDQZ0=
|
github.com/iwind/TeaGo v0.0.0-20201010005321-430e836dee8a h1:sO6uDbQOEe6/tIB3o31vn6eD/JmkKGErKgcOA/Cpb+Q=
|
||||||
github.com/iwind/TeaGo v0.0.0-20200924024009-d088df3778a6/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
github.com/iwind/TeaGo v0.0.0-20201010005321-430e836dee8a/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
@@ -89,14 +75,9 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
|||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/sftp v1.12.0/go.mod h1:fUqqXB5vEgVCZ131L+9say31RAri6aF6KDViawhxKK8=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
|
|
||||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
@@ -104,7 +85,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
|
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||||
@@ -145,6 +125,8 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
|
||||||
|
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// API配置
|
||||||
type APIConfig struct {
|
type APIConfig struct {
|
||||||
RPC struct {
|
RPC struct {
|
||||||
Endpoints []string `yaml:"endpoints"`
|
Endpoints []string `yaml:"endpoints"`
|
||||||
@@ -14,6 +15,7 @@ type APIConfig struct {
|
|||||||
Secret string `yaml:"secret"`
|
Secret string `yaml:"secret"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载API配置
|
||||||
func LoadAPIConfig() (*APIConfig, error) {
|
func LoadAPIConfig() (*APIConfig, error) {
|
||||||
data, err := ioutil.ReadFile(Tea.ConfigFile("api.yaml"))
|
data, err := ioutil.ReadFile(Tea.ConfigFile("api.yaml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -28,3 +30,12 @@ func LoadAPIConfig() (*APIConfig, error) {
|
|||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 写入API配置
|
||||||
|
func (this *APIConfig) WriteFile(path string) error {
|
||||||
|
data, err := yaml.Marshal(this)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(path, data, 0666)
|
||||||
|
}
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ func (this *RPCClient) SysSettingRPC() pb.SysSettingServiceClient {
|
|||||||
return pb.NewSysSettingServiceClient(this.pickConn())
|
return pb.NewSysSettingServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构造上下文
|
// 构造Admin上下文
|
||||||
func (this *RPCClient) Context(adminId int64) context.Context {
|
func (this *RPCClient) Context(adminId int64) context.Context {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
m := maps.Map{
|
m := maps.Map{
|
||||||
@@ -198,6 +198,29 @@ func (this *RPCClient) Context(adminId int64) context.Context {
|
|||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 构造API上下文
|
||||||
|
func (this *RPCClient) APIContext(apiNodeId int64) context.Context {
|
||||||
|
ctx := context.Background()
|
||||||
|
m := maps.Map{
|
||||||
|
"timestamp": time.Now().Unix(),
|
||||||
|
"type": "api",
|
||||||
|
"userId": apiNodeId,
|
||||||
|
}
|
||||||
|
method, err := encrypt.NewMethodInstance(teaconst.EncryptMethod, this.apiConfig.Secret, this.apiConfig.NodeId)
|
||||||
|
if err != nil {
|
||||||
|
utils.PrintError(err)
|
||||||
|
return context.Background()
|
||||||
|
}
|
||||||
|
data, err := method.Encrypt(m.AsJSON())
|
||||||
|
if err != nil {
|
||||||
|
utils.PrintError(err)
|
||||||
|
return context.Background()
|
||||||
|
}
|
||||||
|
token := base64.StdEncoding.EncodeToString(data)
|
||||||
|
ctx = metadata.AppendToOutgoingContext(ctx, "nodeId", this.apiConfig.NodeId, "token", token)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
// 随机选择一个连接
|
// 随机选择一个连接
|
||||||
func (this *RPCClient) pickConn() *grpc.ClientConn {
|
func (this *RPCClient) pickConn() *grpc.ClientConn {
|
||||||
if len(this.conns) == 0 {
|
if len(this.conns) == 0 {
|
||||||
|
|||||||
18
internal/setup/utils.go
Normal file
18
internal/setup/utils.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
|
)
|
||||||
|
|
||||||
|
var isConfigured bool
|
||||||
|
|
||||||
|
// 判断系统是否已经配置过
|
||||||
|
func IsConfigured() bool {
|
||||||
|
if isConfigured {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := configs.LoadAPIConfig()
|
||||||
|
isConfigured = err == nil
|
||||||
|
return isConfigured
|
||||||
|
}
|
||||||
@@ -4,10 +4,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||||
@@ -25,6 +26,12 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
|
|
||||||
Auth *helpers.UserShouldAuth
|
Auth *helpers.UserShouldAuth
|
||||||
}) {
|
}) {
|
||||||
|
// 检查系统是否已经配置过
|
||||||
|
if !setup.IsConfigured() {
|
||||||
|
this.RedirectURL("/setup")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 已登录跳转到dashboard
|
// 已登录跳转到dashboard
|
||||||
if params.Auth.IsUser() {
|
if params.Auth.IsUser() {
|
||||||
this.RedirectURL("/dashboard")
|
this.RedirectURL("/dashboard")
|
||||||
|
|||||||
@@ -41,16 +41,15 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.DBs == nil {
|
if config.DBs == nil {
|
||||||
this.Data["error"] = "can not find valid database config: api_db.yaml"
|
this.Data["error"] = "no database configured in config file: api_db.yaml"
|
||||||
this.Show()
|
this.Show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dbConfig, ok := config.DBs[config.Default.DB]
|
var dbConfig *dbs.DBConfig
|
||||||
if !ok {
|
for _, db := range config.DBs {
|
||||||
this.Data["error"] = "can not find valid database config: api_db.yaml"
|
dbConfig = db
|
||||||
this.Show()
|
break
|
||||||
return
|
|
||||||
}
|
}
|
||||||
dsn := dbConfig.Dsn
|
dsn := dbConfig.Dsn
|
||||||
dsn = regexp.MustCompile(`tcp\((.+)\)`).ReplaceAllString(dsn, "$1")
|
dsn = regexp.MustCompile(`tcp\((.+)\)`).ReplaceAllString(dsn, "$1")
|
||||||
|
|||||||
@@ -50,11 +50,12 @@ func (this *UpdateAction) RunGet(params struct{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dbConfig, ok := config.DBs[config.Default.DB]
|
var dbConfig *dbs.DBConfig
|
||||||
if !ok {
|
for _, db := range config.DBs {
|
||||||
this.Show()
|
dbConfig = db
|
||||||
return
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
dsn := dbConfig.Dsn
|
dsn := dbConfig.Dsn
|
||||||
dsn = regexp.MustCompile(`tcp\((.+)\)`).ReplaceAllString(dsn, "$1")
|
dsn = regexp.MustCompile(`tcp\((.+)\)`).ReplaceAllString(dsn, "$1")
|
||||||
dsnURL, err := url.Parse("mysql://" + dsn)
|
dsnURL, err := url.Parse("mysql://" + dsn)
|
||||||
|
|||||||
17
internal/web/actions/default/setup/helper.go
Normal file
17
internal/web/actions/default/setup/helper.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Helper struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Helper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool) {
|
||||||
|
if setup.IsConfigured() {
|
||||||
|
actionPtr.Object().RedirectURL("/")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
46
internal/web/actions/default/setup/index.go
Normal file
46
internal/web/actions/default/setup/index.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"net"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
|
// 当前服务器的IP
|
||||||
|
serverIPs := []string{}
|
||||||
|
addrs, _ := net.InterfaceAddrs()
|
||||||
|
for _, addr := range addrs {
|
||||||
|
netAddr, ok := addr.(*net.IPNet)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
serverIPs = append(serverIPs, netAddr.IP.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对IP进行排序,我们希望IPv4排在前面,而且希望127.0.0.1排在IPv4里的最后
|
||||||
|
sort.Slice(serverIPs, func(i, j int) bool {
|
||||||
|
ip1 := serverIPs[i]
|
||||||
|
|
||||||
|
if ip1 == "127.0.0.1" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if regexp.MustCompile(`^\d+\.\d+\.\d+.\d+$`).MatchString(ip1) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
this.Data["serverIPs"] = serverIPs
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
17
internal/web/actions/default/setup/init.go
Normal file
17
internal/web/actions/default/setup/init.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import "github.com/iwind/TeaGo"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(new(Helper)).
|
||||||
|
Prefix("/setup").
|
||||||
|
Get("", new(IndexAction)).
|
||||||
|
Post("/validateApi", new(ValidateApiAction)).
|
||||||
|
Post("/validateDb", new(ValidateDbAction)).
|
||||||
|
Post("/validateAdmin", new(ValidateAdminAction)).
|
||||||
|
Post("/install", new(InstallAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
203
internal/web/actions/default/setup/install.go
Normal file
203
internal/web/actions/default/setup/install.go
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/go-yaml/yaml"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InstallAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *InstallAction) RunPost(params struct {
|
||||||
|
ApiNodeJSON []byte
|
||||||
|
DbJSON []byte
|
||||||
|
AdminJSON []byte
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
// API节点配置
|
||||||
|
apiNodeMap := maps.Map{}
|
||||||
|
err := json.Unmarshal(params.ApiNodeJSON, &apiNodeMap)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("API节点配置数据解析错误,请刷新页面后重新尝试安装,错误信息:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据库
|
||||||
|
dbMap := maps.Map{}
|
||||||
|
err = json.Unmarshal(params.DbJSON, &dbMap)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("数据库配置数据解析错误,请刷新页面后重新尝试安装,错误信息:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 管理员
|
||||||
|
adminMap := maps.Map{}
|
||||||
|
err = json.Unmarshal(params.AdminJSON, &adminMap)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("管理员数据解析错误,请刷新页面后重新尝试安装,错误信息:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 安装API节点
|
||||||
|
mode := apiNodeMap.GetString("mode")
|
||||||
|
if mode == "new" {
|
||||||
|
// 整个系统目录结构为:
|
||||||
|
// edge-admin/
|
||||||
|
// edge-api/
|
||||||
|
// bin/
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// 检查环境
|
||||||
|
apiNodeDir := Tea.Root + "/edge-api"
|
||||||
|
for _, dir := range []string{"edge-api", "edge-api/configs", "edge-api/bin"} {
|
||||||
|
apiNodeDir := Tea.Root + "/" + dir
|
||||||
|
_, err = os.Stat(apiNodeDir)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
this.Fail("在当前目录下找不到" + dir + "目录,请将" + dir + "目录上传或者重新下载解压")
|
||||||
|
}
|
||||||
|
this.Fail("无法检查" + dir + "目录,发生错误:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存数据库配置
|
||||||
|
dsn := dbMap.GetString("username") + ":" + dbMap.GetString("password") + "@tcp(" + dbMap.GetString("host") + ":" + dbMap.GetString("port") + ")/" + dbMap.GetString("database") + "?charset=utf8mb4&timeout=30s"
|
||||||
|
dbConfig := &dbs.Config{
|
||||||
|
DBs: map[string]*dbs.DBConfig{
|
||||||
|
"prod": {
|
||||||
|
Driver: "mysql",
|
||||||
|
Dsn: dsn,
|
||||||
|
Prefix: "edge",
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
dbConfigData, err := yaml.Marshal(dbConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("生成数据库配置失败:" + err.Error())
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(apiNodeDir+"/configs/db.yaml", dbConfigData, 0666)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("保存数据库配置失败:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(Tea.ConfigFile("/api_db.yaml"), dbConfigData, 0666)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("保存数据库配置失败:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始安装
|
||||||
|
var resultMap = maps.Map{}
|
||||||
|
{
|
||||||
|
cmd := exec.Command(apiNodeDir+"/bin/edge-api", "setup", "-api-node-protocol=http", "-api-node-host=\""+apiNodeMap.GetString("newHost")+"\"", "-api-node-port=\""+apiNodeMap.GetString("newPort")+"\"")
|
||||||
|
output := bytes.NewBuffer([]byte{})
|
||||||
|
cmd.Stdout = output
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("安装失败:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
resultData := output.Bytes()
|
||||||
|
err = json.Unmarshal(resultData, &resultMap)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("安装节点时返回数据错误:" + err.Error() + "(" + string(resultData) + ")")
|
||||||
|
}
|
||||||
|
if !resultMap.GetBool("isOk") {
|
||||||
|
this.Fail("节点安装错误:" + resultMap.GetString("error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动API节点
|
||||||
|
{
|
||||||
|
cmd := exec.Command(apiNodeDir + "/bin/edge-api")
|
||||||
|
err = cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("API节点启动失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入API节点配置,完成安装
|
||||||
|
apiConfig := &configs.APIConfig{
|
||||||
|
RPC: struct {
|
||||||
|
Endpoints []string `yaml:"endpoints"`
|
||||||
|
}{
|
||||||
|
Endpoints: []string{"http://" + apiNodeMap.GetString("newHost") + ":" + apiNodeMap.GetString("newPort")},
|
||||||
|
},
|
||||||
|
NodeId: resultMap.GetString("adminNodeId"),
|
||||||
|
Secret: resultMap.GetString("adminNodeSecret"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置管理员
|
||||||
|
client, err := rpc.NewRPCClient(apiConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.FailField("oldHost", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
||||||
|
}
|
||||||
|
ctx := client.Context(0)
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
_, err = client.AdminRPC().CreateOrUpdateAdmin(ctx, &pb.CreateOrUpdateAdminRequest{
|
||||||
|
Username: adminMap.GetString("username"),
|
||||||
|
Password: adminMap.GetString("password"),
|
||||||
|
})
|
||||||
|
// 这里我们尝试多次是为了当代API节点启动完毕
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("设置管理员账号出错:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = apiConfig.WriteFile(Tea.ConfigFile("api.yaml"))
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("保存配置失败,原因:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
} else if mode == "old" {
|
||||||
|
// 构造RPC
|
||||||
|
apiConfig := &configs.APIConfig{
|
||||||
|
RPC: struct {
|
||||||
|
Endpoints []string `yaml:"endpoints"`
|
||||||
|
}{
|
||||||
|
Endpoints: []string{apiNodeMap.GetString("oldProtocol") + "://" + apiNodeMap.GetString("oldHost") + ":" + apiNodeMap.GetString("oldPort")},
|
||||||
|
},
|
||||||
|
NodeId: apiNodeMap.GetString("oldNodeId"),
|
||||||
|
Secret: apiNodeMap.GetString("oldNodeSecret"),
|
||||||
|
}
|
||||||
|
client, err := rpc.NewRPCClient(apiConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.FailField("oldHost", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置管理员
|
||||||
|
ctx := client.APIContext(0)
|
||||||
|
_, err = client.AdminRPC().CreateOrUpdateAdmin(ctx, &pb.CreateOrUpdateAdminRequest{
|
||||||
|
Username: adminMap.GetString("username"),
|
||||||
|
Password: adminMap.GetString("password"),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("设置管理员账号出错:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入API节点配置,完成安装
|
||||||
|
err = apiConfig.WriteFile(Tea.ConfigFile("api.yaml"))
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("保存配置失败,原因:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 成功
|
||||||
|
this.Success()
|
||||||
|
} else {
|
||||||
|
this.Fail("错误的API节点模式:'" + mode + "'")
|
||||||
|
}
|
||||||
|
}
|
||||||
38
internal/web/actions/default/setup/validateAdmin.go
Normal file
38
internal/web/actions/default/setup/validateAdmin.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidateAdminAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ValidateAdminAction) RunPost(params struct {
|
||||||
|
AdminUsername string
|
||||||
|
AdminPassword string
|
||||||
|
AdminPassword2 string
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
params.Must.
|
||||||
|
Field("adminUsername", params.AdminUsername).
|
||||||
|
Require("请输入登录用户名").
|
||||||
|
Match(`^[a-zA-Z0-9_]+$`, "用户名中只能包含英文、数字或下划线").
|
||||||
|
Field("adminPassword", params.AdminPassword).
|
||||||
|
Require("请输入登录密码").
|
||||||
|
Match(`^[a-zA-Z0-9_]+$`, "密码中只能包含英文、数字或下划线").
|
||||||
|
Field("adminPassword2", params.AdminPassword2).
|
||||||
|
Require("请输入确认密码").
|
||||||
|
Equal(params.AdminPassword, "两次输入的密码不一致")
|
||||||
|
|
||||||
|
this.Data["admin"] = maps.Map{
|
||||||
|
"username": params.AdminUsername,
|
||||||
|
"password": params.AdminPassword,
|
||||||
|
"passwordMask": strings.Repeat("*", len(params.AdminPassword)),
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
105
internal/web/actions/default/setup/validateApi.go
Normal file
105
internal/web/actions/default/setup/validateApi.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidateApiAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ValidateApiAction) RunPost(params struct {
|
||||||
|
Mode string
|
||||||
|
NewPort string
|
||||||
|
NewHost string
|
||||||
|
OldProtocol string
|
||||||
|
OldHost string
|
||||||
|
OldPort string
|
||||||
|
OldNodeId string
|
||||||
|
OldNodeSecret string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
params.OldNodeId = strings.Trim(params.OldNodeId, "\"' ")
|
||||||
|
params.OldNodeSecret = strings.Trim(params.OldNodeSecret, "\"' ")
|
||||||
|
|
||||||
|
this.Data["apiNode"] = maps.Map{
|
||||||
|
"mode": params.Mode,
|
||||||
|
|
||||||
|
"newPort": params.NewPort,
|
||||||
|
"newHost": params.NewHost,
|
||||||
|
|
||||||
|
"oldProtocol": params.OldProtocol,
|
||||||
|
"oldHost": params.OldHost,
|
||||||
|
"oldPort": params.OldPort,
|
||||||
|
"oldNodeId": params.OldNodeId,
|
||||||
|
"oldNodeSecret": params.OldNodeSecret,
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.Mode == "new" {
|
||||||
|
params.Must.
|
||||||
|
Field("newPort", params.NewPort).
|
||||||
|
Require("请输入节点端口").
|
||||||
|
Match(`^\d+$`, "节点端口只能是数字").
|
||||||
|
MinLength(4, "请输入4位以上的数字").
|
||||||
|
MaxLength(5, "请输入5位以下的数字")
|
||||||
|
newPort := types.Int(params.NewPort)
|
||||||
|
if newPort < 1024 {
|
||||||
|
this.FailField("newPort", "端口号不能小于1024")
|
||||||
|
}
|
||||||
|
if newPort > 65534 {
|
||||||
|
this.FailField("newPort", "端口号不能大于65534")
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", "127.0.0.1:"+params.NewPort)
|
||||||
|
if err == nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
this.FailField("newPort", "此端口已经被别的服务占用,请换一个")
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("newHost", params.NewHost).
|
||||||
|
Require("请输入节点主机地址")
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用已有的API节点
|
||||||
|
params.Must.
|
||||||
|
Field("oldHost", params.OldHost).
|
||||||
|
Require("请输入主机地址").
|
||||||
|
Field("oldPort", params.OldPort).
|
||||||
|
Require("请输入服务端口").
|
||||||
|
Match(`^\d+$`, "服务端口只能是数字").
|
||||||
|
Field("oldNodeId", params.OldNodeId).
|
||||||
|
Require("请输入节点nodeId").
|
||||||
|
Field("oldNodeSecret", params.OldNodeSecret).
|
||||||
|
Require("请输入节点secret")
|
||||||
|
client, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||||
|
RPC: struct {
|
||||||
|
Endpoints []string `yaml:"endpoints"`
|
||||||
|
}{
|
||||||
|
Endpoints: []string{params.OldProtocol + "://" + params.OldHost + ":" + params.OldPort},
|
||||||
|
},
|
||||||
|
NodeId: params.OldNodeId,
|
||||||
|
Secret: params.OldNodeSecret,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.FailField("oldHost", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
||||||
|
}
|
||||||
|
_, err = client.APINodeRPC().FindCurrentAPINodeVersion(client.APIContext(0), &pb.FindCurrentAPINodeVersionRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.FailField("oldHost", "无法连接此API节点,错误信息:"+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
78
internal/web/actions/default/setup/validateDb.go
Normal file
78
internal/web/actions/default/setup/validateDb.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package setup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidateDbAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ValidateDbAction) RunPost(params struct {
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
Database string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
params.Must.
|
||||||
|
Field("host", params.Host).
|
||||||
|
Require("请输入主机地址").
|
||||||
|
Match(`^[\w\.-]+$`, "主机地址中不能包含特殊字符").
|
||||||
|
Field("port", params.Port).
|
||||||
|
Require("请输入端口").
|
||||||
|
Match(`^\d+$`, "端口中只能包含数字").
|
||||||
|
Field("database", params.Database).
|
||||||
|
Require("请输入数据库名称").
|
||||||
|
Match(`^[\w\.-]+$`, "数据库名称中不能包含特殊字符").
|
||||||
|
Field("username", params.Username).
|
||||||
|
Require("请输入连接数据库的用户名").
|
||||||
|
Match(`^[\w\.-]+$`, "用户名中不能包含特殊字符")
|
||||||
|
|
||||||
|
// 测试连接
|
||||||
|
db, err := dbs.NewInstanceFromConfig(&dbs.DBConfig{
|
||||||
|
Driver: "mysql",
|
||||||
|
Dsn: params.Username + ":" + params.Password + "@tcp(" + params.Host + ":" + params.Port + ")/" + params.Database,
|
||||||
|
Prefix: "",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("数据库信息错误:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Raw().Ping()
|
||||||
|
if err != nil {
|
||||||
|
// 是否是数据库不存在
|
||||||
|
if strings.Contains(err.Error(), "Error 1049") {
|
||||||
|
db, err := dbs.NewInstanceFromConfig(&dbs.DBConfig{
|
||||||
|
Driver: "mysql",
|
||||||
|
Dsn: params.Username + ":" + params.Password + "@tcp(" + params.Host + ":" + params.Port + ")/",
|
||||||
|
Prefix: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = db.Exec("CREATE DATABASE `" + params.Database + "`")
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("尝试创建数据库失败:" + err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.Fail("无法连接到数据库,请检查配置:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["db"] = maps.Map{
|
||||||
|
"host": params.Host,
|
||||||
|
"port": params.Port,
|
||||||
|
"database": params.Database,
|
||||||
|
"username": params.Username,
|
||||||
|
"password": params.Password,
|
||||||
|
"passwordMask": strings.Repeat("*", len(params.Password)),
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"compress/gzip"
|
||||||
"github.com/iwind/TeaGo"
|
"github.com/iwind/TeaGo"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
)
|
)
|
||||||
@@ -12,7 +13,7 @@ func init() {
|
|||||||
Get("/download", new(DownloadAction)).
|
Get("/download", new(DownloadAction)).
|
||||||
|
|
||||||
// 以下的需要压缩
|
// 以下的需要压缩
|
||||||
Helper(new(actions.Gzip)).
|
Helper(&actions.Gzip{Level: gzip.BestCompression}).
|
||||||
Get("/components.js", new(ComponentsAction)).
|
Get("/components.js", new(ComponentsAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package helpers
|
|||||||
import (
|
import (
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
nodes "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
nodes "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
@@ -23,6 +24,12 @@ func NewUserMustAuth() *UserMustAuth {
|
|||||||
func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramName string) (goNext bool) {
|
func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramName string) (goNext bool) {
|
||||||
var action = actionPtr.Object()
|
var action = actionPtr.Object()
|
||||||
|
|
||||||
|
// 检查系统是否已经配置过
|
||||||
|
if !setup.IsConfigured() {
|
||||||
|
action.RedirectURL("/setup")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var session = action.Session()
|
var session = action.Session()
|
||||||
var adminId = session.GetInt("adminId")
|
var adminId = session.GetInt("adminId")
|
||||||
if adminId <= 0 {
|
if adminId <= 0 {
|
||||||
@@ -33,6 +40,7 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
// 检查用户是否存在
|
// 检查用户是否存在
|
||||||
rpc, err := nodes.SharedRPC()
|
rpc, err := nodes.SharedRPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
action.WriteString("setup rpc error: " + err.Error())
|
||||||
utils.PrintError(err)
|
utils.PrintError(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -40,7 +48,7 @@ func (this *UserMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
rpcResp, err := rpc.AdminRPC().CheckAdminExists(rpc.Context(0), &pb.CheckAdminExistsRequest{AdminId: int64(adminId)})
|
rpcResp, err := rpc.AdminRPC().CheckAdminExists(rpc.Context(0), &pb.CheckAdminExistsRequest{AdminId: int64(adminId)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.PrintError(err)
|
utils.PrintError(err)
|
||||||
actionPtr.Object().WriteString(teaconst.ErrServer)
|
action.WriteString(teaconst.ErrServer)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,5 +71,6 @@ import (
|
|||||||
_ "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"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/upgrade"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/upgrade"
|
||||||
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/setup"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ui"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ui"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -138,8 +138,8 @@ window.teaweb = {
|
|||||||
if (message.length > 30) {
|
if (message.length > 30) {
|
||||||
width = "30em";
|
width = "30em";
|
||||||
}
|
}
|
||||||
Swal.fire({
|
|
||||||
text: message,
|
let config = {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
buttonsStyling: false,
|
buttonsStyling: false,
|
||||||
icon: "success",
|
icon: "success",
|
||||||
@@ -154,9 +154,19 @@ window.teaweb = {
|
|||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
} else if (typeof (callback) == "string") {
|
||||||
|
window.location = callback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (message.startsWith("html:")) {
|
||||||
|
config.html = message.substring(5)
|
||||||
|
} else {
|
||||||
|
config.text = message
|
||||||
|
}
|
||||||
|
|
||||||
|
Swal.fire(config);
|
||||||
},
|
},
|
||||||
successToast: function (message, timeout) {
|
successToast: function (message, timeout) {
|
||||||
if (timeout == null) {
|
if (timeout == null) {
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ p.comment,
|
|||||||
div.comment {
|
div.comment {
|
||||||
color: rgba(0, 0, 0, 0.3);
|
color: rgba(0, 0, 0, 0.3);
|
||||||
padding-top: 0.4em;
|
padding-top: 0.4em;
|
||||||
font-size: 0.9em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
p.comment em,
|
p.comment em,
|
||||||
div.comment em {
|
div.comment em {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -23,7 +23,7 @@
|
|||||||
<!-- 顶部导航 -->
|
<!-- 顶部导航 -->
|
||||||
<div class="ui menu top-nav blue inverted small borderless" v-cloak="">
|
<div class="ui menu top-nav blue inverted small borderless" v-cloak="">
|
||||||
<a href="/" class="item">
|
<a href="/" class="item">
|
||||||
<i class="ui icon leaf"></i> {{teaName}}管理员系统
|
<i class="ui icon leaf"></i> {{teaName}}管理员系统 <sup>v{{teaVersion}}</sup>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="right menu">
|
<div class="right menu">
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ tbody {
|
|||||||
p.comment, div.comment {
|
p.comment, div.comment {
|
||||||
color: rgba(0, 0, 0, 0.3);
|
color: rgba(0, 0, 0, 0.3);
|
||||||
padding-top: 0.4em;
|
padding-top: 0.4em;
|
||||||
font-size: 0.9em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.comment em, div.comment em {
|
p.comment em, div.comment em {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<td>外部访问地址 *</td>
|
<td>外部访问地址 *</td>
|
||||||
<td>
|
<td>
|
||||||
<api-node-addresses-box :v-name="'accessAddrsJSON'"></api-node-addresses-box>
|
<api-node-addresses-box :v-name="'accessAddrsJSON'"></api-node-addresses-box>
|
||||||
<p class="comment">外部访问API节点的网络地址。</p>
|
<p class="comment">边缘节点和管理平台等外部节点访问API节点的网络地址。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<td>外部访问地址 *</td>
|
<td>外部访问地址 *</td>
|
||||||
<td>
|
<td>
|
||||||
<api-node-addresses-box :v-name="'accessAddrsJSON'" :v-addrs="node.accessAddrs"></api-node-addresses-box>
|
<api-node-addresses-box :v-name="'accessAddrsJSON'" :v-addrs="node.accessAddrs"></api-node-addresses-box>
|
||||||
<p class="comment">外部访问API节点的网络地址。</p>
|
<p class="comment">边缘节点和管理平台等外部节点访问API节点的网络地址。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{$template "menu"}
|
{$template "menu"}
|
||||||
|
|
||||||
<p class="ui message error" v-if="error.length > 0">{{error}}</p>
|
<p class="ui message error" v-if="error.length > 0">{{error}}</p>
|
||||||
<div v-show="error.length == 0 && dbConfig != null">
|
<div v-if="error.length == 0 && dbConfig != null">
|
||||||
<table class="ui table selectable definition">
|
<table class="ui table selectable definition">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">主机地址</td>
|
<td class="title">主机地址</td>
|
||||||
|
|||||||
0
web/views/@default/setup/@install.css
Normal file
0
web/views/@default/setup/@install.css
Normal file
1
web/views/@default/setup/@install.css.map
Normal file
1
web/views/@default/setup/@install.css.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
undefined
|
||||||
67
web/views/@default/setup/@install.less
Normal file
67
web/views/@default/setup/@install.less
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
.install-box {
|
||||||
|
@width: 50em;
|
||||||
|
|
||||||
|
width: @width;
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -@width/2;
|
||||||
|
top: 1em;
|
||||||
|
bottom: 1em;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.button.margin {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button.primary {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
td.title {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio {
|
||||||
|
margin-right: 1em;
|
||||||
|
|
||||||
|
label {
|
||||||
|
cursor: pointer !important;
|
||||||
|
font-size: 0.9em !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-box {
|
||||||
|
overflow-y: auto;
|
||||||
|
position: fixed;
|
||||||
|
top: 5em;
|
||||||
|
bottom: 5em;
|
||||||
|
left: 50%;
|
||||||
|
width: @width;
|
||||||
|
padding-right: 1em;
|
||||||
|
margin-left: -@width/2;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-box::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -@width/2;
|
||||||
|
z-index: 1;
|
||||||
|
width: @width;
|
||||||
|
bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.install-box::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
54
web/views/@default/setup/index.css
Normal file
54
web/views/@default/setup/index.css
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
.install-box {
|
||||||
|
width: 50em;
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -25em;
|
||||||
|
top: 1em;
|
||||||
|
bottom: 1em;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.install-box .button.margin {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.install-box .button.primary {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.install-box table td.title {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
.install-box .radio {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
.install-box .radio label {
|
||||||
|
cursor: pointer !important;
|
||||||
|
font-size: 0.9em !important;
|
||||||
|
}
|
||||||
|
.install-box h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.install-box .content-box {
|
||||||
|
overflow-y: auto;
|
||||||
|
position: fixed;
|
||||||
|
top: 5em;
|
||||||
|
bottom: 5em;
|
||||||
|
left: 50%;
|
||||||
|
width: 50em;
|
||||||
|
padding-right: 1em;
|
||||||
|
margin-left: -25em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.install-box .content-box::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
.install-box .button-group {
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -25em;
|
||||||
|
z-index: 1;
|
||||||
|
width: 50em;
|
||||||
|
bottom: 1em;
|
||||||
|
}
|
||||||
|
.install-box::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=index.css.map */
|
||||||
1
web/views/@default/setup/index.css.map
Normal file
1
web/views/@default/setup/index.css.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["@install.less"],"names":[],"mappings":"AAAA;EAGC,WAAA;EACA,eAAA;EACA,SAAA;EACA,kBAAA;EACA,QAAA;EACA,WAAA;EACA,gBAAA;;AATD,YAWC,QAAO;EACN,eAAA;;AAZF,YAeC,QAAO;EACN,YAAA;;AAhBF,YAmBC,MACC,GAAE;EACD,WAAA;;AArBH,YAyBC;EACC,iBAAA;;AA1BF,YAyBC,OAGC;EACC,0BAAA;EACA,2BAAA;;AA9BH,YAkCC;EACC,mBAAA;;AAnCF,YAsCC;EACC,gBAAA;EACA,eAAA;EACA,QAAA;EACA,WAAA;EACA,SAAA;EACA,WAAA;EACA,kBAAA;EACA,kBAAA;EACA,UAAA;;AA/CF,YAkDC,aAAY;EACX,UAAA;;AAnDF,YAsDC;EACC,eAAA;EACA,SAAA;EACA,kBAAA;EACA,UAAA;EACA,WAAA;EACA,WAAA;;AAIF,YAAY;EACX,UAAA","file":"index.css"}
|
||||||
346
web/views/@default/setup/index.html
Normal file
346
web/views/@default/setup/index.html
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
|
<link rel="shortcut icon" href="/images/favicon.png"/>
|
||||||
|
<title>安装Edge管理系统</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||||
|
{$TEA.VUE}
|
||||||
|
{$TEA.SEMANTIC}
|
||||||
|
<script type="text/javascript" src="/js/md5.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/utils.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/sweetalert2/dist/sweetalert2.all.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/ui/components.js"></script>
|
||||||
|
<link rel="stylesheet" href="/_/@default/@layout.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="install-box">
|
||||||
|
<!-- 步骤列表 -->
|
||||||
|
<div class="ui steps fluid small">
|
||||||
|
<div class="ui step" :class="{active: step == STEP_INTRO}">
|
||||||
|
<div class="content">
|
||||||
|
<div :class="{title: step == STEP_INTRO}">1. 介绍</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui step" :class="{active: step == STEP_API}">
|
||||||
|
<div class="content">
|
||||||
|
<div :class="{title: step == STEP_API}">2. 设置API节点</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui step" :class="{active: step == STEP_DB}">
|
||||||
|
<div class="content">
|
||||||
|
<div :class="{title: step == STEP_DB}">3. 设置MySQL数据库</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui step" :class="{active: step == STEP_ADMIN}">
|
||||||
|
<div class="content">
|
||||||
|
<div :class="{title: step == STEP_ADMIN}">4. 设置管理员账号</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui step" :class="{active: step == STEP_FINISH}">
|
||||||
|
<div class="content">
|
||||||
|
<div :class="{title: step == STEP_FINISH}">5. 完成安装</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 介绍 -->
|
||||||
|
<div v-show="step == STEP_INTRO">
|
||||||
|
<div>感谢你选择使用<strong>Edge</strong>集群服务系统,下面让我们一起开始配置系统。</div>
|
||||||
|
<div class="margin">在这之前如果你还没有可用的MySQL数据库,请先安装数据库再进行。</div>
|
||||||
|
<button class="ui button primary" style="margin-top: 10em" type="button" @click.prevent="goIntroNext()">开始<i class="icon long arrow right"></i></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 设置API节点 -->
|
||||||
|
<div v-show="step == STEP_API">
|
||||||
|
<div class="ui message"><strong>API节点</strong>是管理系统和数据库之间通讯的桥梁,新安装时可以先使用自动启动的API节点,等系统变得庞大时再扩展新的API节点。</div>
|
||||||
|
<form class="ui form" data-tea-action=".validateApi" data-tea-success="apiSuccess" data-tea-before="apiSubmit" data-tea-done="apiDone">
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">API节点类型</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
<input type="radio" name="mode" value="new" id="auto-start-api-node" v-model="apiNodeMode"/>
|
||||||
|
<label for="auto-start-api-node">自动启动新API节点</label>
|
||||||
|
</div>
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
<input type="radio" name="mode" value="old" id="use-old-api-node" v-model="apiNodeMode"/>
|
||||||
|
<label for="use-old-api-node">使用已安装节点</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tbody v-show="apiNodeMode == 'new'">
|
||||||
|
<tr>
|
||||||
|
<td>节点端口 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="newPort" style="width:6em" maxlength="5" v-model="newAPINodePort"/>
|
||||||
|
<p class="comment">选一个在1024-65535之间并且没有正在使用的端口作为要启动的节点端口。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>节点主机地址</td>
|
||||||
|
<td>
|
||||||
|
<div v-if="serverIPs.length > 0">
|
||||||
|
<select name="newHost" class="ui dropdown auto-width">
|
||||||
|
<option v-for="ip in serverIPs" :value="ip">{{ip}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div v-else="">
|
||||||
|
<input type="text" name="newHost" value=""/>
|
||||||
|
</div>
|
||||||
|
<p class="comment">其他节点访问此API节点的主机地址,可以是IP或者域名,第一次安装时通常是<strong>当前服务器</strong>的IP地址。后期可以修改这个地址。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<tbody v-show="apiNodeMode == 'old'">
|
||||||
|
<tr>
|
||||||
|
<td>节点协议 *</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown auto-width" name="oldProtocol">
|
||||||
|
<option value="http">HTTP</option>
|
||||||
|
<option value="https">HTTPS</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment">API节点使用的协议。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>主机地址 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="oldHost" maxlength="100" style="width:20em"/>
|
||||||
|
<p class="comment">API节点所在主机地址。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>服务端口 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="oldPort" style="width:6em" maxlength="5"/>
|
||||||
|
<p class="comment">API节点启动的端口。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>节点nodeId *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="oldNodeId" maxlength="100"/>
|
||||||
|
<p class="comment">在节点的配置文件中<code-label>configs/api.yaml</code-label>中获取,不需要带双引号。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>节点secret *</td>
|
||||||
|
<td>
|
||||||
|
<input type="password" name="oldNodeSecret" maxlength="100"/>
|
||||||
|
<p class="comment">在节点的配置文件中<code-label>configs/api.yaml</code-label>中获取,不需要带双引号。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<button class="ui button" type="button" @click.prevent="goBackIntro"><i class="icon long arrow left"></i>上一步</button>
|
||||||
|
<button class="ui button primary" type="submit" v-if="!apiRequesting">下一步<i class="icon long arrow right"></i></button>
|
||||||
|
<button class="ui button primary" type="button" v-if="apiRequesting">提交中</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 设置数据库 -->
|
||||||
|
<div v-show="step == STEP_DB">
|
||||||
|
<div v-show="apiNodeMode == 'new'">
|
||||||
|
<form class="ui form" data-tea-action=".validateDb" data-tea-success="dbSuccess" data-tea-before="dbSubmit" data-tea-done="dbDone">
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">MySQL主机地址 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="host" maxlength="100" placeholder="比如 192.168.1.100" style="width:16em" ref="dbHost"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>数据库连接端口 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="port" maxlength="5" placeholder="比如 3306" style="width:7em"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>数据库名称 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="database" value="edges" style="width:16em"/>
|
||||||
|
<p class="comment">请事先创建好此数据库,如果不存在,则会尝试自动创建。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>连接用户名 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="username" style="width:16em" maxlength="100"/>
|
||||||
|
<p class="comment">此用户需要可以在数据库中有操作数据和创建数据表的权限。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>连接密码</td>
|
||||||
|
<td>
|
||||||
|
<input type="password" name="password" style="width:16em" maxlength="100"/>
|
||||||
|
<p class="comment">连接数据库所需密码,没有密码的话就不需要填写。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<button class="ui button" type="button" @click.prevent="goBackAPI"><i class="icon long arrow left"></i>上一步</button>
|
||||||
|
<button class="ui button primary" v-if="!dbRequesting" type="submit">下一步<i class="icon long arrow right"></i></button>
|
||||||
|
<button class="ui button primary" v-if="dbRequesting" type="button">提交中...</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-show="apiNodeMode == 'old'">
|
||||||
|
<div style="margin-bottom: 2em">你选择使用了已安装节点,无需重新配置数据库。</div>
|
||||||
|
<button class="ui button margin" type="button" @click.prevent="goBackAPI"><i class="icon long arrow left"></i>上一步</button>
|
||||||
|
<button class="ui button primary margin" type="button" @click.prevent="goDBNext()">下一步<i class="icon long arrow right"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 设置管理员账号 -->
|
||||||
|
<div v-show="step == STEP_ADMIN">
|
||||||
|
<form class="ui form" data-tea-action=".validateAdmin" data-tea-success="adminSuccess">
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">登录用户名 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="adminUsername" style="width:16em" maxlength="100" value="admin"/>
|
||||||
|
<p class="comment">只能是英文、数字和下划线的组合。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>登录密码 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="password" name="adminPassword" maxlength="100" style="width:16em" v-model="adminPassword" v-show="!adminPasswordVisible"/>
|
||||||
|
<input type="text" value="" v-model="adminPassword" style="width:16em" v-show="adminPasswordVisible"/>
|
||||||
|
<p class="comment">只能是英文、数字和下划线的组合 <a href="" title="显示明文密码" @click.prevent="showAdminPassword"><i class="icon eye grey"></i></a>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>确认密码 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="password" name="adminPassword2" maxlength="100" style="width:16em" v-model="adminPassword2" v-show="!adminPasswordVisible"/>
|
||||||
|
<input type="text" value="" v-model="adminPassword2" style="width:16em" v-show="adminPasswordVisible"/>
|
||||||
|
<p class="comment">再次输入密码以便于确认 <a href="" title="显示明文密码" @click.prevent="showAdminPassword"><i class="icon eye grey"></i></a>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<button class="ui button margin" type="button" @click.prevent="goBackDB"><i class="icon long arrow left"></i>上一步</button>
|
||||||
|
<button class="ui button primary margin" type="submit">下一步<i class="icon long arrow right"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 完成安装 -->
|
||||||
|
<div v-show="step == STEP_FINISH">
|
||||||
|
<form class="ui form" data-tea-action=".install" data-tea-success="finishSuccess" data-tea-before="finishSubmit" data-tea-done="finishDone">
|
||||||
|
<input type="hidden" name="apiNodeJSON" :value="JSON.stringify(apiNodeInfo)"/>
|
||||||
|
<input type="hidden" name="dbJSON" :value="JSON.stringify(dbInfo)"/>
|
||||||
|
<input type="hidden" name="adminJSON" :value="JSON.stringify(adminInfo)"/>
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
<h3>API节点信息</h3>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">API节点类型</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="apiNodeInfo.mode == 'new'">自动启动新API节点</span>
|
||||||
|
<span v-if="apiNodeInfo.mode == 'old'">使用已安装节点</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tbody v-show="apiNodeInfo.mode == 'new'">
|
||||||
|
<tr>
|
||||||
|
<td>节点端口 *</td>
|
||||||
|
<td>
|
||||||
|
{{apiNodeInfo.newPort}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>节点主机地址</td>
|
||||||
|
<td>
|
||||||
|
{{apiNodeInfo.newHost}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<tbody v-show="apiNodeInfo.mode == 'old'">
|
||||||
|
<tr>
|
||||||
|
<td>节点协议 *</td>
|
||||||
|
<td>
|
||||||
|
{{apiNodeInfo.oldProtocol}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>主机地址 *</td>
|
||||||
|
<td>
|
||||||
|
{{apiNodeInfo.oldHost}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>服务端口 *</td>
|
||||||
|
<td>
|
||||||
|
{{apiNodeInfo.oldPort}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3 v-if="apiNodeMode == 'new'">数据库信息</h3>
|
||||||
|
<table class="ui table definition selectable" v-if="apiNodeMode == 'new'">
|
||||||
|
<tr>
|
||||||
|
<td class="title">MySQL主机地址 *</td>
|
||||||
|
<td>
|
||||||
|
{{dbInfo.host}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>数据库连接端口 *</td>
|
||||||
|
<td>
|
||||||
|
{{dbInfo.port}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>数据库名称 *</td>
|
||||||
|
<td>
|
||||||
|
{{dbInfo.database}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>连接用户名 *</td>
|
||||||
|
<td>
|
||||||
|
{{dbInfo.username}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>连接密码</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="dbInfo.passwordMask != null && dbInfo.passwordMask.length > 0">{{dbInfo.passwordMask}}</span>
|
||||||
|
<span v-else class="disabled">未填入密码</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>管理员信息</h3>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">登录用户名</td>
|
||||||
|
<td>{{adminInfo.username}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>登录密码</td>
|
||||||
|
<td>{{adminInfo.passwordMask}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<button class="ui button" type="button" @click.prevent="goBackAdmin"><i class="icon long arrow left"></i>上一步</button>
|
||||||
|
<button class="ui button primary" type="submit" v-if="!isInstalling">确认并开始安装</button>
|
||||||
|
<button class="ui button primary" type="button" v-if="isInstalling">安装中...</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
106
web/views/@default/setup/index.js
Normal file
106
web/views/@default/setup/index.js
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.STEP_INTRO = "intro"
|
||||||
|
this.STEP_API = "api"
|
||||||
|
this.STEP_DB = "db"
|
||||||
|
this.STEP_ADMIN = "admin"
|
||||||
|
this.STEP_FINISH = "finish"
|
||||||
|
|
||||||
|
this.step = this.STEP_INTRO
|
||||||
|
|
||||||
|
// 介绍
|
||||||
|
this.goIntroNext = function () {
|
||||||
|
this.step = this.STEP_API
|
||||||
|
}
|
||||||
|
|
||||||
|
// API节点
|
||||||
|
this.apiNodeInfo = {}
|
||||||
|
this.apiNodeMode = "new"
|
||||||
|
this.newAPINodePort = "8001"
|
||||||
|
this.apiRequesting = false
|
||||||
|
|
||||||
|
this.apiSubmit = function () {
|
||||||
|
this.apiRequesting = true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.apiDone = function () {
|
||||||
|
this.apiRequesting = false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.apiSuccess = function (resp) {
|
||||||
|
this.step = this.STEP_DB
|
||||||
|
this.apiNodeInfo = resp.data.apiNode
|
||||||
|
|
||||||
|
if (this.apiNodeMode == "new") {
|
||||||
|
this.$delay(function () {
|
||||||
|
this.$refs.dbHost.focus()
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.goBackIntro = function () {
|
||||||
|
this.step = this.STEP_INTRO
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据库
|
||||||
|
this.dbInfo = {}
|
||||||
|
this.dbRequesting = false
|
||||||
|
this.dbSubmit = function () {
|
||||||
|
this.dbRequesting = true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dbSuccess = function (resp) {
|
||||||
|
this.step = this.STEP_ADMIN
|
||||||
|
this.dbInfo = resp.data.db
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dbDone = function () {
|
||||||
|
this.dbRequesting = false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.goBackAPI = function () {
|
||||||
|
this.step = this.STEP_API
|
||||||
|
}
|
||||||
|
|
||||||
|
this.goDBNext = function () {
|
||||||
|
this.step = this.STEP_ADMIN
|
||||||
|
}
|
||||||
|
|
||||||
|
// 管理员
|
||||||
|
this.goBackDB = function () {
|
||||||
|
this.step = this.STEP_DB
|
||||||
|
}
|
||||||
|
|
||||||
|
this.adminInfo = {}
|
||||||
|
this.adminPassword = ""
|
||||||
|
this.adminPassword2 = ""
|
||||||
|
this.adminPasswordVisible = false
|
||||||
|
|
||||||
|
this.showAdminPassword = function () {
|
||||||
|
this.adminPasswordVisible = !this.adminPasswordVisible
|
||||||
|
|
||||||
|
// TODO 切换密码显示的时候应该focus输入框
|
||||||
|
}
|
||||||
|
|
||||||
|
this.adminSuccess = function (resp) {
|
||||||
|
this.step = this.STEP_FINISH
|
||||||
|
this.adminInfo = resp.data.admin
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结束
|
||||||
|
this.goBackAdmin = function () {
|
||||||
|
this.step = this.STEP_ADMIN
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isInstalling = false
|
||||||
|
this.finishSubmit = function () {
|
||||||
|
this.isInstalling = true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.finishDone = function () {
|
||||||
|
this.isInstalling = false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.finishSuccess = function () {
|
||||||
|
teaweb.success("html:恭喜你!安装完成!<br/>请记住你创建的管理员账号,现在跳转到登录界面。", "/")
|
||||||
|
}
|
||||||
|
})
|
||||||
2
web/views/@default/setup/index.less
Normal file
2
web/views/@default/setup/index.less
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
@import "@install";
|
||||||
|
|
||||||
Reference in New Issue
Block a user