mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-16 12:09:13 +08:00
feat: core 增加 xpack 节点管理
This commit is contained in:
parent
cabca70ee5
commit
fafa042ee9
36 changed files with 411 additions and 116 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -14,6 +14,7 @@ build/1panel
|
||||||
.vscode
|
.vscode
|
||||||
*.project
|
*.project
|
||||||
*.factorypath
|
*.factorypath
|
||||||
|
__debug*
|
||||||
|
|
||||||
# IntelliJ IDEA
|
# IntelliJ IDEA
|
||||||
.idea/*
|
.idea/*
|
||||||
|
|
@ -43,6 +44,9 @@ agent/xpack
|
||||||
agent/router/entry_xpack.go
|
agent/router/entry_xpack.go
|
||||||
agent/server/init_xpack.go
|
agent/server/init_xpack.go
|
||||||
agent/utils/xpack/xpack_xpack.go
|
agent/utils/xpack/xpack_xpack.go
|
||||||
|
core/xpack
|
||||||
|
core/router/entry_xpack.go
|
||||||
|
core/server/init_xpack.go
|
||||||
|
|
||||||
.history/
|
.history/
|
||||||
dist/
|
dist/
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func Routers() *gin.Engine {
|
||||||
PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression))
|
PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||||
setWebStatic(PublicGroup)
|
setWebStatic(PublicGroup)
|
||||||
}
|
}
|
||||||
PrivateGroup := Router.Group("/api/v1")
|
PrivateGroup := Router.Group("/api/v2")
|
||||||
PrivateGroup.Use(middleware.GlobalLoading())
|
PrivateGroup.Use(middleware.GlobalLoading())
|
||||||
for _, router := range rou.RouterGroupApp {
|
for _, router := range rou.RouterGroupApp {
|
||||||
router.InitRouter(PrivateGroup)
|
router.InitRouter(PrivateGroup)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package server
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/agent/cron"
|
"github.com/1Panel-dev/1Panel/agent/cron"
|
||||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||||
|
|
@ -38,22 +39,11 @@ func Start() {
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Handler: rootRouter,
|
Handler: rootRouter,
|
||||||
}
|
}
|
||||||
//ln, err := net.Listen("tcp4", "0.0.0.0:9998")
|
|
||||||
//if err != nil {
|
|
||||||
// panic(err)
|
|
||||||
//}
|
|
||||||
//type tcpKeepAliveListener struct {
|
|
||||||
// *net.TCPListener
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//global.LOG.Info("listen at http://0.0.0.0:9998")
|
|
||||||
//if err := server.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}); err != nil {
|
|
||||||
// panic(err)
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
_ = os.Remove("/tmp/agent.sock")
|
||||||
listener, err := net.Listen("unix", "/tmp/agent.sock")
|
listener, err := net.Listen("unix", "/tmp/agent.sock")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
server.Serve(listener)
|
_ = server.Serve(listener)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
system:
|
system:
|
||||||
db_core_file: 1Panel_Core.db
|
db_core_file: 1Panel_Core.db
|
||||||
db_file: 1Panel_Core.db
|
db_file: 1Panel.db
|
||||||
base_dir: /opt
|
base_dir: /opt
|
||||||
mode: dev
|
mode: dev
|
||||||
repo_url: https://resource.fit2cloud.com/1panel/package
|
repo_url: https://resource.fit2cloud.com/1panel/package
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import (
|
||||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/core/constant"
|
"github.com/1Panel-dev/1Panel/core/constant"
|
||||||
"github.com/1Panel-dev/1Panel/core/global"
|
"github.com/1Panel-dev/1Panel/core/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/middleware"
|
||||||
// "github.com/1Panel-dev/1Panel/core/middleware"
|
|
||||||
"github.com/1Panel-dev/1Panel/core/utils/captcha"
|
"github.com/1Panel-dev/1Panel/core/utils/captcha"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/utils/qqwry"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -124,10 +124,10 @@ func (b *BaseApi) CheckIsSafety(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if status == "unpass" {
|
if status == "unpass" {
|
||||||
// if middleware.Get.LoadErrCode("err-entrance") != 200 {
|
if middleware.LoadErrCode("err-entrance") != 200 {
|
||||||
// helper.ErrResponse(c, middleware.LoadErrCode("err-entrance"))
|
helper.ErrResponse(c, middleware.LoadErrCode("err-entrance"))
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrEntrance, constant.ErrTypeInternalServer, nil)
|
helper.ErrorWithDetail(c, constant.CodeErrEntrance, constant.ErrTypeInternalServer, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -175,12 +175,12 @@ func saveLoginLogs(c *gin.Context, err error) {
|
||||||
logs.Status = constant.StatusSuccess
|
logs.Status = constant.StatusSuccess
|
||||||
}
|
}
|
||||||
logs.IP = c.ClientIP()
|
logs.IP = c.ClientIP()
|
||||||
// qqWry, err := qqwry.NewQQwry()
|
qqWry, err := qqwry.NewQQwry()
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// global.LOG.Errorf("load qqwry datas failed: %s", err)
|
global.LOG.Errorf("load qqwry datas failed: %s", err)
|
||||||
// }
|
}
|
||||||
// res := qqWry.Find(logs.IP)
|
res := qqWry.Find(logs.IP)
|
||||||
logs.Agent = c.GetHeader("User-Agent")
|
logs.Agent = c.GetHeader("User-Agent")
|
||||||
// logs.Address = res.Area
|
logs.Address = res.Area
|
||||||
_ = logService.CreateLoginLog(logs)
|
_ = logService.CreateLoginLog(logs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
package dto
|
package dto
|
||||||
|
|
||||||
|
type SearchWithPage struct {
|
||||||
|
PageInfo
|
||||||
|
Info string `json:"info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PageInfo struct {
|
||||||
|
Page int `json:"page" validate:"required,number"`
|
||||||
|
PageSize int `json:"pageSize" validate:"required,number"`
|
||||||
|
}
|
||||||
|
|
||||||
type PageResult struct {
|
type PageResult struct {
|
||||||
Total int64 `json:"total"`
|
Total int64 `json:"total"`
|
||||||
Items interface{} `json:"items"`
|
Items interface{} `json:"items"`
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package dto
|
|
||||||
|
|
||||||
type SearchWithPage struct {
|
|
||||||
PageInfo
|
|
||||||
Info string `json:"info"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PageInfo struct {
|
|
||||||
Page int `json:"page" validate:"required,number"`
|
|
||||||
PageSize int `json:"pageSize" validate:"required,number"`
|
|
||||||
}
|
|
||||||
|
|
@ -7,14 +7,21 @@ import (
|
||||||
type DBOption func(*gorm.DB) *gorm.DB
|
type DBOption func(*gorm.DB) *gorm.DB
|
||||||
|
|
||||||
type ICommonRepo interface {
|
type ICommonRepo interface {
|
||||||
|
WithByID(id uint) DBOption
|
||||||
WithOrderBy(orderStr string) DBOption
|
WithOrderBy(orderStr string) DBOption
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommonRepo struct{}
|
type CommonRepo struct{}
|
||||||
|
|
||||||
func NewCommonRepo() ICommonRepo {
|
func NewICommonRepo() ICommonRepo {
|
||||||
return &CommonRepo{}
|
return &CommonRepo{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CommonRepo) WithByID(id uint) DBOption {
|
||||||
|
return func(g *gorm.DB) *gorm.DB {
|
||||||
|
return g.Where("id = ?", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
func (c *CommonRepo) WithOrderBy(orderStr string) DBOption {
|
func (c *CommonRepo) WithOrderBy(orderStr string) DBOption {
|
||||||
return func(g *gorm.DB) *gorm.DB {
|
return func(g *gorm.DB) *gorm.DB {
|
||||||
return g.Order(orderStr)
|
return g.Order(orderStr)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package service
|
||||||
import "github.com/1Panel-dev/1Panel/core/app/repo"
|
import "github.com/1Panel-dev/1Panel/core/app/repo"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
commonRepo = repo.NewCommonRepo()
|
commonRepo = repo.NewICommonRepo()
|
||||||
settingRepo = repo.NewISettingRepo()
|
settingRepo = repo.NewISettingRepo()
|
||||||
logRepo = repo.NewILogRepo()
|
logRepo = repo.NewILogRepo()
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,11 @@ var (
|
||||||
ErrInitialPassword = errors.New("ErrInitialPassword")
|
ErrInitialPassword = errors.New("ErrInitialPassword")
|
||||||
ErrInvalidParams = errors.New("ErrInvalidParams")
|
ErrInvalidParams = errors.New("ErrInvalidParams")
|
||||||
|
|
||||||
ErrTokenParse = errors.New("ErrTokenParse")
|
ErrTokenParse = errors.New("ErrTokenParse")
|
||||||
ErrPortInUsed = "ErrPortInUsed"
|
ErrStructTransform = errors.New("ErrStructTransform")
|
||||||
ErrCmdTimeout = "ErrCmdTimeout"
|
ErrPortInUsed = "ErrPortInUsed"
|
||||||
|
ErrCmdTimeout = "ErrCmdTimeout"
|
||||||
|
ErrGroupIsUsed = "ErrGroupIsUsed"
|
||||||
)
|
)
|
||||||
|
|
||||||
// api
|
// api
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ ErrNotSupportType: "The system does not support the current type: {{ .detail }}"
|
||||||
ErrNameIsExist: "Name is already exist"
|
ErrNameIsExist: "Name is already exist"
|
||||||
ErrDemoEnvironment: "Demo server, prohibit this operation!"
|
ErrDemoEnvironment: "Demo server, prohibit this operation!"
|
||||||
ErrEntrance: "Security entrance information error. Please check and try again!"
|
ErrEntrance: "Security entrance information error. Please check and try again!"
|
||||||
|
ErrGroupIsUsed: "The group is in use and cannot be deleted"
|
||||||
|
|
||||||
#app
|
#app
|
||||||
ErrPortInUsed: "{{ .detail }} port already in use"
|
ErrPortInUsed: "{{ .detail }} port already in use"
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}"
|
||||||
ErrNameIsExist: "名稱已存在"
|
ErrNameIsExist: "名稱已存在"
|
||||||
ErrDemoEnvironment: "演示伺服器,禁止此操作!"
|
ErrDemoEnvironment: "演示伺服器,禁止此操作!"
|
||||||
ErrEntrance: "安全入口信息錯誤,請檢查後重試!"
|
ErrEntrance: "安全入口信息錯誤,請檢查後重試!"
|
||||||
|
ErrGroupIsUsed: "分組正在使用中,無法刪除"
|
||||||
|
|
||||||
#app
|
#app
|
||||||
ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
|
ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}"
|
||||||
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
||||||
ErrCmdTimeout: "命令执行超时!"
|
ErrCmdTimeout: "命令执行超时!"
|
||||||
ErrEntrance: "安全入口信息错误,请检查后重试!"
|
ErrEntrance: "安全入口信息错误,请检查后重试!"
|
||||||
|
ErrGroupIsUsed: "分组正在使用中,无法删除"
|
||||||
|
|
||||||
#app
|
#app
|
||||||
ErrPortInUsed: "{{ .detail }} 端口已被占用!"
|
ErrPortInUsed: "{{ .detail }} 端口已被占用!"
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ var InitSetting = &gormigrate.Migration{
|
||||||
if err := tx.Create(&model.Setting{Key: "PrsoxyPasswdKeep", Value: ""}).Error; err != nil {
|
if err := tx.Create(&model.Setting{Key: "PrsoxyPasswdKeep", Value: ""}).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := tx.Create(&model.Setting{Key: "XpackHideMenu", Value: "{\"id\":\"1\",\"label\":\"/xpack\",\"isCheck\":true,\"title\":\"xpack.menu\",\"children\":[{\"id\":\"2\",\"title\":\"xpack.waf.name\",\"path\":\"/xpack/waf/dashboard\",\"label\":\"Dashboard\",\"isCheck\":true},{\"id\":\"3\",\"title\":\"xpack.tamper.tamper\",\"path\":\"/xpack/tamper\",\"label\":\"Tamper\",\"isCheck\":true},{\"id\":\"4\",\"title\":\"xpack.gpu.gpu\",\"path\":\"/xpack/gpu\",\"label\":\"GPU\",\"isCheck\":true},{\"id\":\"5\",\"title\":\"xpack.setting.setting\",\"path\":\"/xpack/setting\",\"label\":\"XSetting\",\"isCheck\":true},{\"id\":\"6\",\"title\":\"xpack.monitor.name\",\"path\":\"/xpack/monitor/dashboard\",\"label\":\"MonitorDashboard\",\"isCheck\":true},{\"id\":\"7\",\"title\":\"xpack.multihost.agentManagement\",\"path\":\"/xpack/multihost/manage\",\"label\":\"Multihost\",\"isCheck\":true}]}"}).Error; err != nil {
|
if err := tx.Create(&model.Setting{Key: "XpackHideMenu", Value: "{\"id\":\"1\",\"label\":\"/xpack\",\"isCheck\":true,\"title\":\"xpack.menu\",\"children\":[{\"id\":\"2\",\"title\":\"xpack.waf.name\",\"path\":\"/xpack/waf/dashboard\",\"label\":\"Dashboard\",\"isCheck\":true},{\"id\":\"3\",\"title\":\"xpack.tamper.tamper\",\"path\":\"/xpack/tamper\",\"label\":\"Tamper\",\"isCheck\":true},{\"id\":\"4\",\"title\":\"xpack.gpu.gpu\",\"path\":\"/xpack/gpu\",\"label\":\"GPU\",\"isCheck\":true},{\"id\":\"5\",\"title\":\"xpack.setting.setting\",\"path\":\"/xpack/setting\",\"label\":\"XSetting\",\"isCheck\":true},{\"id\":\"6\",\"title\":\"xpack.monitor.name\",\"path\":\"/xpack/monitor/dashboard\",\"label\":\"MonitorDashboard\",\"isCheck\":true},{\"id\":\"7\",\"title\":\"xpack.node.nodeManagement\",\"path\":\"/xpack/node\",\"label\":\"Node\",\"isCheck\":true}]}"}).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/cmd/server/docs"
|
"github.com/1Panel-dev/1Panel/cmd/server/docs"
|
||||||
"github.com/1Panel-dev/1Panel/cmd/server/web"
|
"github.com/1Panel-dev/1Panel/cmd/server/web"
|
||||||
"github.com/1Panel-dev/1Panel/core/global"
|
"github.com/1Panel-dev/1Panel/core/global"
|
||||||
|
|
@ -13,11 +14,6 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
swaggerfiles "github.com/swaggo/files"
|
swaggerfiles "github.com/swaggo/files"
|
||||||
ginSwagger "github.com/swaggo/gin-swagger"
|
ginSwagger "github.com/swaggo/gin-swagger"
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -62,7 +58,7 @@ func Routers() *gin.Engine {
|
||||||
PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression))
|
PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||||
setWebStatic(PublicGroup)
|
setWebStatic(PublicGroup)
|
||||||
}
|
}
|
||||||
PrivateGroup := Router.Group("/api/v1")
|
PrivateGroup := Router.Group("/api/v2/core")
|
||||||
PrivateGroup.Use(middleware.WhiteAllow())
|
PrivateGroup.Use(middleware.WhiteAllow())
|
||||||
PrivateGroup.Use(middleware.BindDomain())
|
PrivateGroup.Use(middleware.BindDomain())
|
||||||
PrivateGroup.Use(middleware.GlobalLoading())
|
PrivateGroup.Use(middleware.GlobalLoading())
|
||||||
|
|
@ -70,35 +66,6 @@ func Routers() *gin.Engine {
|
||||||
router.InitRouter(PrivateGroup)
|
router.InitRouter(PrivateGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 unix 代理
|
|
||||||
sockPath := "/tmp/agent.sock"
|
|
||||||
if _, err := os.Stat(sockPath); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
dialUnix := func(proto, addr string) (conn net.Conn, err error) {
|
|
||||||
return net.Dial("unix", sockPath)
|
|
||||||
}
|
|
||||||
transport := &http.Transport{
|
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
||||||
return dialUnix(network, addr)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
proxy := &httputil.ReverseProxy{
|
|
||||||
Director: func(req *http.Request) {
|
|
||||||
req.URL.Scheme = "http"
|
|
||||||
req.URL.Host = "unix"
|
|
||||||
},
|
|
||||||
Transport: transport,
|
|
||||||
}
|
|
||||||
Router.Use(func(c *gin.Context) {
|
|
||||||
if strings.HasPrefix(c.Request.URL.Path, "/api") {
|
|
||||||
proxy.ServeHTTP(c.Writer, c.Request)
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Next()
|
|
||||||
})
|
|
||||||
|
|
||||||
Router.NoRoute(func(c *gin.Context) {
|
Router.NoRoute(func(c *gin.Context) {
|
||||||
c.Writer.WriteHeader(http.StatusOK)
|
c.Writer.WriteHeader(http.StatusOK)
|
||||||
_, _ = c.Writer.Write(web.IndexByte)
|
_, _ = c.Writer.Write(web.IndexByte)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
@ -8,20 +13,31 @@ import (
|
||||||
|
|
||||||
func Proxy() gin.HandlerFunc {
|
func Proxy() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
if strings.HasPrefix(c.Request.URL.Path, "/api/v1/auth") ||
|
if strings.HasPrefix(c.Request.URL.Path, "/api/v2/core") {
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/v1/setting") ||
|
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/v1/log") {
|
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
sockPath := "/tmp/agent.sock"
|
||||||
|
if _, err := os.Stat(sockPath); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
dialUnix := func() (conn net.Conn, err error) {
|
||||||
|
return net.Dial("unix", sockPath)
|
||||||
|
}
|
||||||
|
transport := &http.Transport{
|
||||||
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
return dialUnix()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
proxy := &httputil.ReverseProxy{
|
||||||
|
Director: func(req *http.Request) {
|
||||||
|
req.URL.Scheme = "http"
|
||||||
|
req.URL.Host = "unix"
|
||||||
|
},
|
||||||
|
Transport: transport,
|
||||||
|
}
|
||||||
|
proxy.ServeHTTP(c.Writer, c.Request)
|
||||||
|
c.Abort()
|
||||||
}
|
}
|
||||||
//target, err := url.Parse("http://127.0.0.1:9998")
|
|
||||||
//if err != nil {
|
|
||||||
// fmt.Printf("Failed to parse target URL: %v", err)
|
|
||||||
//}
|
|
||||||
//proxy := httputil.NewSingleHostReverseProxy(target)
|
|
||||||
//c.Request.Host = target.Host
|
|
||||||
//c.Request.URL.Scheme = target.Scheme
|
|
||||||
//c.Request.URL.Host = target.Host
|
|
||||||
//proxy.ServeHTTP(c.Writer, c.Request)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
//go:build !xpack
|
||||||
|
|
||||||
package router
|
package router
|
||||||
|
|
||||||
func RouterGroups() []CommonRouter {
|
func RouterGroups() []CommonRouter {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ func Start() {
|
||||||
cache.Init()
|
cache.Init()
|
||||||
session.Init()
|
session.Init()
|
||||||
gin.SetMode("debug")
|
gin.SetMode("debug")
|
||||||
|
InitOthers()
|
||||||
hook.Init()
|
hook.Init()
|
||||||
|
|
||||||
rootRouter := router.Routers()
|
rootRouter := router.Routers()
|
||||||
|
|
|
||||||
165
core/utils/qqwry/qqwry.go
Normal file
165
core/utils/qqwry/qqwry.go
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
package qqwry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/1Panel-dev/1Panel/cmd/server/qqwry"
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
indexLen = 7
|
||||||
|
redirectMode1 = 0x01
|
||||||
|
redirectMode2 = 0x02
|
||||||
|
)
|
||||||
|
|
||||||
|
var IpCommonDictionary []byte
|
||||||
|
|
||||||
|
type QQwry struct {
|
||||||
|
Data []byte
|
||||||
|
Offset int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQQwry() (*QQwry, error) {
|
||||||
|
IpCommonDictionary := qqwry.QQwryByte
|
||||||
|
return &QQwry{Data: IpCommonDictionary}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readData 从文件中读取数据
|
||||||
|
func (q *QQwry) readData(num int, offset ...int64) (rs []byte) {
|
||||||
|
if len(offset) > 0 {
|
||||||
|
q.setOffset(offset[0])
|
||||||
|
}
|
||||||
|
nums := int64(num)
|
||||||
|
end := q.Offset + nums
|
||||||
|
dataNum := int64(len(q.Data))
|
||||||
|
if q.Offset > dataNum {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if end > dataNum {
|
||||||
|
end = dataNum
|
||||||
|
}
|
||||||
|
rs = q.Data[q.Offset:end]
|
||||||
|
q.Offset = end
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// setOffset 设置偏移量
|
||||||
|
func (q *QQwry) setOffset(offset int64) {
|
||||||
|
q.Offset = offset
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find ip地址查询对应归属地信息
|
||||||
|
func (q *QQwry) Find(ip string) (res ResultQQwry) {
|
||||||
|
res = ResultQQwry{}
|
||||||
|
res.IP = ip
|
||||||
|
if strings.Count(ip, ".") != 3 {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
offset := q.searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4()))
|
||||||
|
if offset <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var area []byte
|
||||||
|
mode := q.readMode(offset + 4)
|
||||||
|
if mode == redirectMode1 {
|
||||||
|
countryOffset := q.readUInt24()
|
||||||
|
mode = q.readMode(countryOffset)
|
||||||
|
if mode == redirectMode2 {
|
||||||
|
c := q.readUInt24()
|
||||||
|
area = q.readString(c)
|
||||||
|
} else {
|
||||||
|
area = q.readString(countryOffset)
|
||||||
|
}
|
||||||
|
} else if mode == redirectMode2 {
|
||||||
|
countryOffset := q.readUInt24()
|
||||||
|
area = q.readString(countryOffset)
|
||||||
|
} else {
|
||||||
|
area = q.readString(offset + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := simplifiedchinese.GBK.NewDecoder()
|
||||||
|
res.Area, _ = enc.String(string(area))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultQQwry struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Area string `json:"area"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// readMode 获取偏移值类型
|
||||||
|
func (q *QQwry) readMode(offset uint32) byte {
|
||||||
|
mode := q.readData(1, int64(offset))
|
||||||
|
return mode[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// readString 获取字符串
|
||||||
|
func (q *QQwry) readString(offset uint32) []byte {
|
||||||
|
q.setOffset(int64(offset))
|
||||||
|
data := make([]byte, 0, 30)
|
||||||
|
for {
|
||||||
|
buf := q.readData(1)
|
||||||
|
if buf[0] == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data = append(data, buf[0])
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// searchIndex 查找索引位置
|
||||||
|
func (q *QQwry) searchIndex(ip uint32) uint32 {
|
||||||
|
header := q.readData(8, 0)
|
||||||
|
|
||||||
|
start := binary.LittleEndian.Uint32(header[:4])
|
||||||
|
end := binary.LittleEndian.Uint32(header[4:])
|
||||||
|
|
||||||
|
for {
|
||||||
|
mid := q.getMiddleOffset(start, end)
|
||||||
|
buf := q.readData(indexLen, int64(mid))
|
||||||
|
_ip := binary.LittleEndian.Uint32(buf[:4])
|
||||||
|
|
||||||
|
if end-start == indexLen {
|
||||||
|
offset := byteToUInt32(buf[4:])
|
||||||
|
buf = q.readData(indexLen)
|
||||||
|
if ip < binary.LittleEndian.Uint32(buf[:4]) {
|
||||||
|
return offset
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if _ip > ip {
|
||||||
|
end = mid
|
||||||
|
} else if _ip < ip {
|
||||||
|
start = mid
|
||||||
|
} else if _ip == ip {
|
||||||
|
return byteToUInt32(buf[4:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readUInt24
|
||||||
|
func (q *QQwry) readUInt24() uint32 {
|
||||||
|
buf := q.readData(3)
|
||||||
|
return byteToUInt32(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMiddleOffset
|
||||||
|
func (q *QQwry) getMiddleOffset(start uint32, end uint32) uint32 {
|
||||||
|
records := ((end - start) / indexLen) >> 1
|
||||||
|
return start + records*indexLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// byteToUInt32 将 byte 转换为uint32
|
||||||
|
func byteToUInt32(data []byte) uint32 {
|
||||||
|
i := uint32(data[0]) & 0xff
|
||||||
|
i |= (uint32(data[1]) << 8) & 0xff00
|
||||||
|
i |= (uint32(data[2]) << 16) & 0xff0000
|
||||||
|
return i
|
||||||
|
}
|
||||||
142
core/utils/ssh/ssh.go
Normal file
142
core/utils/ssh/ssh.go
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
package ssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
gossh "golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConnInfo struct {
|
||||||
|
User string `json:"user"`
|
||||||
|
Addr string `json:"addr"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
AuthMode string `json:"authMode"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
PrivateKey []byte `json:"privateKey"`
|
||||||
|
PassPhrase []byte `json:"passPhrase"`
|
||||||
|
DialTimeOut time.Duration `json:"dialTimeOut"`
|
||||||
|
|
||||||
|
Client *gossh.Client `json:"client"`
|
||||||
|
Session *gossh.Session `json:"session"`
|
||||||
|
LastResult string `json:"lastResult"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnInfo) NewClient() (*ConnInfo, error) {
|
||||||
|
if strings.Contains(c.Addr, ":") {
|
||||||
|
c.Addr = fmt.Sprintf("[%s]", c.Addr)
|
||||||
|
}
|
||||||
|
config := &gossh.ClientConfig{}
|
||||||
|
config.SetDefaults()
|
||||||
|
addr := fmt.Sprintf("%s:%d", c.Addr, c.Port)
|
||||||
|
config.User = c.User
|
||||||
|
if c.AuthMode == "password" {
|
||||||
|
config.Auth = []gossh.AuthMethod{gossh.Password(c.Password)}
|
||||||
|
} else {
|
||||||
|
signer, err := makePrivateKeySigner(c.PrivateKey, c.PassPhrase)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.Auth = []gossh.AuthMethod{gossh.PublicKeys(signer)}
|
||||||
|
}
|
||||||
|
if c.DialTimeOut == 0 {
|
||||||
|
c.DialTimeOut = 5 * time.Second
|
||||||
|
}
|
||||||
|
config.Timeout = c.DialTimeOut
|
||||||
|
|
||||||
|
config.HostKeyCallback = gossh.InsecureIgnoreHostKey()
|
||||||
|
proto := "tcp"
|
||||||
|
if strings.Contains(c.Addr, ":") {
|
||||||
|
proto = "tcp6"
|
||||||
|
}
|
||||||
|
client, err := gossh.Dial(proto, addr, config)
|
||||||
|
if nil != err {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
c.Client = client
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnInfo) Run(shell string) (string, error) {
|
||||||
|
if c.Client == nil {
|
||||||
|
if _, err := c.NewClient(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session, err := c.Client.NewSession()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer session.Close()
|
||||||
|
buf, err := session.CombinedOutput(shell)
|
||||||
|
|
||||||
|
c.LastResult = string(buf)
|
||||||
|
return c.LastResult, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnInfo) Close() {
|
||||||
|
_ = c.Client.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
type SshConn struct {
|
||||||
|
StdinPipe io.WriteCloser
|
||||||
|
ComboOutput *wsBufferWriter
|
||||||
|
Session *gossh.Session
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnInfo) NewSshConn(cols, rows int) (*SshConn, error) {
|
||||||
|
sshSession, err := c.Client.NewSession()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stdinP, err := sshSession.StdinPipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
comboWriter := new(wsBufferWriter)
|
||||||
|
sshSession.Stdout = comboWriter
|
||||||
|
sshSession.Stderr = comboWriter
|
||||||
|
|
||||||
|
modes := gossh.TerminalModes{
|
||||||
|
gossh.ECHO: 1,
|
||||||
|
gossh.TTY_OP_ISPEED: 14400,
|
||||||
|
gossh.TTY_OP_OSPEED: 14400,
|
||||||
|
}
|
||||||
|
if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := sshSession.Shell(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SshConn) Close() {
|
||||||
|
if s.Session != nil {
|
||||||
|
s.Session.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type wsBufferWriter struct {
|
||||||
|
buffer bytes.Buffer
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *wsBufferWriter) Write(p []byte) (int, error) {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
return w.buffer.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePrivateKeySigner(privateKey []byte, passPhrase []byte) (gossh.Signer, error) {
|
||||||
|
if len(passPhrase) != 0 {
|
||||||
|
return gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase)
|
||||||
|
}
|
||||||
|
return gossh.ParsePrivateKey(privateKey)
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
NODE_ENV = 'development'
|
NODE_ENV = 'development'
|
||||||
|
|
||||||
# 本地环境接口地址
|
# 本地环境接口地址
|
||||||
VITE_API_URL = '/api/v1'
|
VITE_API_URL = '/api/v2'
|
||||||
|
|
||||||
# 是否生成包预览文件
|
# 是否生成包预览文件
|
||||||
VITE_REPORT = false
|
VITE_REPORT = false
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
NODE_ENV = "production"
|
NODE_ENV = "production"
|
||||||
|
|
||||||
# 线上环境接口地址
|
# 线上环境接口地址
|
||||||
VITE_API_URL = '/api/v1'
|
VITE_API_URL = '/api/v2
|
||||||
|
|
||||||
# 是否生成包预览文件
|
# 是否生成包预览文件
|
||||||
VITE_REPORT = true
|
VITE_REPORT = true
|
||||||
|
|
|
||||||
|
|
@ -2,29 +2,29 @@ import { Login } from '@/api/interface/auth';
|
||||||
import http from '@/api';
|
import http from '@/api';
|
||||||
|
|
||||||
export const loginApi = (params: Login.ReqLoginForm) => {
|
export const loginApi = (params: Login.ReqLoginForm) => {
|
||||||
return http.post<Login.ResLogin>(`/auth/login`, params);
|
return http.post<Login.ResLogin>(`/core/auth/login`, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mfaLoginApi = (params: Login.MFALoginForm) => {
|
export const mfaLoginApi = (params: Login.MFALoginForm) => {
|
||||||
return http.post<Login.ResLogin>(`/auth/mfalogin`, params);
|
return http.post<Login.ResLogin>(`/core/auth/mfalogin`, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCaptcha = () => {
|
export const getCaptcha = () => {
|
||||||
return http.get<Login.ResCaptcha>(`/auth/captcha`);
|
return http.get<Login.ResCaptcha>(`/core/auth/captcha`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const logOutApi = () => {
|
export const logOutApi = () => {
|
||||||
return http.post<any>(`/auth/logout`);
|
return http.post<any>(`/core/auth/logout`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const checkIsSafety = (code: string) => {
|
export const checkIsSafety = (code: string) => {
|
||||||
return http.get<string>(`/auth/issafety?code=${code}`);
|
return http.get<string>(`/core/auth/issafety?code=${code}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const checkIsDemo = () => {
|
export const checkIsDemo = () => {
|
||||||
return http.get<boolean>('/auth/demo');
|
return http.get<boolean>('/core/auth/demo');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLanguage = () => {
|
export const getLanguage = () => {
|
||||||
return http.get<string>(`/auth/language`);
|
return http.get<string>(`/core/auth/language`);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export const unbindLicense = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSettingInfo = () => {
|
export const getSettingInfo = () => {
|
||||||
return http.post<Setting.SettingInfo>(`/settings/search`);
|
return http.post<Setting.SettingInfo>(`/core/settings/search`);
|
||||||
};
|
};
|
||||||
export const getSystemAvailable = () => {
|
export const getSystemAvailable = () => {
|
||||||
return http.get(`/settings/search/available`);
|
return http.get(`/settings/search/available`);
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div v-if="!row.edit">
|
<div v-if="!row.edit">
|
||||||
<span v-if="row.name === 'default'">
|
<span v-if="row.name === 'default'">
|
||||||
{{ $t('website.default') }}
|
{{ $t('commons.table.default') }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="row.name !== 'default'">{{ row.name }}</span>
|
<span v-if="row.name !== 'default'">{{ row.name }}</span>
|
||||||
<span v-if="row.isDefault">({{ $t('website.default') }})</span>
|
<span v-if="row.isDefault">({{ $t('commons.table.default') }})</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-form @submit.prevent ref="groupForm" v-if="row.edit" :model="row">
|
<el-form @submit.prevent ref="groupForm" v-if="row.edit" :model="row">
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ const message = {
|
||||||
statusWaiting: 'Waiting...',
|
statusWaiting: 'Waiting...',
|
||||||
records: 'Records',
|
records: 'Records',
|
||||||
group: 'Group',
|
group: 'Group',
|
||||||
|
default: 'Default',
|
||||||
createdAt: 'Creation Time',
|
createdAt: 'Creation Time',
|
||||||
publishedAt: 'Publish Time',
|
publishedAt: 'Publish Time',
|
||||||
date: 'Date',
|
date: 'Date',
|
||||||
|
|
@ -1928,7 +1929,6 @@ const message = {
|
||||||
nginxPer: 'Performance Tuning',
|
nginxPer: 'Performance Tuning',
|
||||||
neverExpire: 'Never Expire',
|
neverExpire: 'Never Expire',
|
||||||
setDefault: 'Set as default',
|
setDefault: 'Set as default',
|
||||||
default: 'Default',
|
|
||||||
deleteHelper: 'Related application status is abnormal, please check',
|
deleteHelper: 'Related application status is abnormal, please check',
|
||||||
toApp: 'Go to the installed list',
|
toApp: 'Go to the installed list',
|
||||||
cycle: 'Cycle',
|
cycle: 'Cycle',
|
||||||
|
|
@ -2334,7 +2334,6 @@ const message = {
|
||||||
ustc: 'University of Science and Technology of China',
|
ustc: 'University of Science and Technology of China',
|
||||||
netease: 'Netease',
|
netease: 'Netease',
|
||||||
aliyun: 'Alibaba Cloud',
|
aliyun: 'Alibaba Cloud',
|
||||||
default: 'default',
|
|
||||||
tsinghua: 'Tsinghua University',
|
tsinghua: 'Tsinghua University',
|
||||||
xtomhk: 'XTOM Mirror Station (Hong Kong)',
|
xtomhk: 'XTOM Mirror Station (Hong Kong)',
|
||||||
xtom: 'XTOM Mirror Station (Global)',
|
xtom: 'XTOM Mirror Station (Global)',
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ const message = {
|
||||||
statusWaiting: '進行中...',
|
statusWaiting: '進行中...',
|
||||||
records: '任務輸出',
|
records: '任務輸出',
|
||||||
group: '分組',
|
group: '分組',
|
||||||
|
default: '默認',
|
||||||
createdAt: '創建時間',
|
createdAt: '創建時間',
|
||||||
publishedAt: '發布時間',
|
publishedAt: '發布時間',
|
||||||
date: '時間',
|
date: '時間',
|
||||||
|
|
@ -1794,7 +1795,6 @@ const message = {
|
||||||
nginxPer: '性能調整',
|
nginxPer: '性能調整',
|
||||||
neverExpire: '永不過期',
|
neverExpire: '永不過期',
|
||||||
setDefault: '設為默認',
|
setDefault: '設為默認',
|
||||||
default: '默認',
|
|
||||||
deleteHelper: '相關應用狀態不正常,請檢查',
|
deleteHelper: '相關應用狀態不正常,請檢查',
|
||||||
toApp: '去已安裝列表',
|
toApp: '去已安裝列表',
|
||||||
cycle: '周期',
|
cycle: '周期',
|
||||||
|
|
@ -2167,7 +2167,6 @@ const message = {
|
||||||
ustc: '中國科學技術大學',
|
ustc: '中國科學技術大學',
|
||||||
netease: '網易',
|
netease: '網易',
|
||||||
aliyun: '阿里雲',
|
aliyun: '阿里雲',
|
||||||
default: '默認',
|
|
||||||
tsinghua: '清華大學',
|
tsinghua: '清華大學',
|
||||||
xtomhk: 'XTOM 鏡像站(香港)',
|
xtomhk: 'XTOM 鏡像站(香港)',
|
||||||
xtom: 'XTOM 鏡像站(全球)',
|
xtom: 'XTOM 鏡像站(全球)',
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ const message = {
|
||||||
statusWaiting: '进行中...',
|
statusWaiting: '进行中...',
|
||||||
records: '任务输出',
|
records: '任务输出',
|
||||||
group: '分组',
|
group: '分组',
|
||||||
|
default: '默认',
|
||||||
createdAt: '创建时间',
|
createdAt: '创建时间',
|
||||||
publishedAt: '发布时间',
|
publishedAt: '发布时间',
|
||||||
date: '时间',
|
date: '时间',
|
||||||
|
|
@ -1796,7 +1797,6 @@ const message = {
|
||||||
nginxPer: '性能调整',
|
nginxPer: '性能调整',
|
||||||
neverExpire: '永不过期',
|
neverExpire: '永不过期',
|
||||||
setDefault: '设为默认',
|
setDefault: '设为默认',
|
||||||
default: '默认',
|
|
||||||
deleteHelper: '相关应用状态不正常,请检查',
|
deleteHelper: '相关应用状态不正常,请检查',
|
||||||
toApp: '去已安装列表',
|
toApp: '去已安装列表',
|
||||||
cycle: '周期',
|
cycle: '周期',
|
||||||
|
|
@ -2170,7 +2170,6 @@ const message = {
|
||||||
ustc: '中国科学技术大学',
|
ustc: '中国科学技术大学',
|
||||||
netease: '网易',
|
netease: '网易',
|
||||||
aliyun: '阿里云',
|
aliyun: '阿里云',
|
||||||
default: '默认',
|
|
||||||
tsinghua: '清华大学',
|
tsinghua: '清华大学',
|
||||||
xtomhk: 'XTOM 镜像站(香港)',
|
xtomhk: 'XTOM 镜像站(香港)',
|
||||||
xtom: 'XTOM 镜像站(全球)',
|
xtom: 'XTOM 镜像站(全球)',
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
<el-table-column :label="$t('commons.table.port')" prop="port" />
|
<el-table-column :label="$t('commons.table.port')" prop="port" />
|
||||||
<el-table-column :label="$t('commons.table.group')" show-overflow-tooltip prop="groupBelong">
|
<el-table-column :label="$t('commons.table.group')" show-overflow-tooltip prop="groupBelong">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="row.groupBelong === 'default'">{{ $t('website.default') }}</span>
|
<span v-if="row.groupBelong === 'default'">{{ $t('commons.table.default') }}</span>
|
||||||
<span v-else>{{ row.groupBelong }}</span>
|
<span v-else>{{ row.groupBelong }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@
|
||||||
>
|
>
|
||||||
<template #default="{ node, data }">
|
<template #default="{ node, data }">
|
||||||
<span class="custom-tree-node">
|
<span class="custom-tree-node">
|
||||||
<span v-if="node.label === 'default'">{{ $t('website.default') }}</span>
|
<span v-if="node.label === 'default'">{{ $t('commons.table.default') }}</span>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<span v-if="node.label.length <= 25">
|
<span v-if="node.label.length <= 25">
|
||||||
<a @click="onClickConn(node, data)">{{ node.label }}</a>
|
<a @click="onClickConn(node, data)">{{ node.label }}</a>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<el-form-item :label="$t('toolbox.device.syncSite')" prop="ntpSite" :rules="Rules.domain">
|
<el-form-item :label="$t('toolbox.device.syncSite')" prop="ntpSite" :rules="Rules.domain">
|
||||||
<el-input v-model="form.ntpSite" />
|
<el-input v-model="form.ntpSite" />
|
||||||
<el-button type="primary" link class="tagClass" @click="form.ntpSite = 'pool.ntp.org'">
|
<el-button type="primary" link class="tagClass" @click="form.ntpSite = 'pool.ntp.org'">
|
||||||
{{ $t('website.default') }}
|
{{ $t('commons.table.default') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" link class="tagClass" @click="form.ntpSite = 'ntp.aliyun.com'">
|
<el-button type="primary" link class="tagClass" @click="form.ntpSite = 'ntp.aliyun.com'">
|
||||||
{{ $t('toolbox.device.ntpALi') }}
|
{{ $t('toolbox.device.ntpALi') }}
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ const hasPnpm = computed(() => {
|
||||||
|
|
||||||
const imageSources = [
|
const imageSources = [
|
||||||
{
|
{
|
||||||
label: i18n.global.t('runtime.default'),
|
label: i18n.global.t('commons.table.default'),
|
||||||
value: 'https://registry.npmjs.org/',
|
value: 'https://registry.npmjs.org/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ const phpSources = [
|
||||||
value: 'mirrors.xtom.com',
|
value: 'mirrors.xtom.com',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('runtime.default'),
|
label: i18n.global.t('commons.table.default'),
|
||||||
value: 'dl-cdn.alpinelinux.org',
|
value: 'dl-cdn.alpinelinux.org',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
open: viteEnv.VITE_OPEN,
|
open: viteEnv.VITE_OPEN,
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api/v1': {
|
'/api/v2': {
|
||||||
target: 'http://localhost:9999/',
|
target: 'http://localhost:9999/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
ws: true,
|
ws: true,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue