mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 06:47:20 +08:00
feat: 网站重构1
This commit is contained in:
@@ -78,8 +78,8 @@ func initWeb() (*app.Web, error) {
|
||||
databaseRepo := data.NewDatabaseRepo(locale, db, databaseServerRepo, databaseUserRepo)
|
||||
certRepo := data.NewCertRepo(locale, db, logger)
|
||||
certAccountRepo := data.NewCertAccountRepo(locale, db, userRepo, logger)
|
||||
websiteRepo := data.NewWebsiteRepo(locale, db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo)
|
||||
settingRepo := data.NewSettingRepo(locale, db, koanf, taskRepo)
|
||||
websiteRepo := data.NewWebsiteRepo(locale, db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo, settingRepo)
|
||||
cronRepo := data.NewCronRepo(locale, db)
|
||||
backupRepo := data.NewBackupRepo(locale, db, settingRepo, websiteRepo)
|
||||
homeService := service.NewHomeService(locale, koanf, taskRepo, websiteRepo, appRepo, settingRepo, cronRepo, backupRepo)
|
||||
|
||||
@@ -69,7 +69,7 @@ func initCli() (*app.Cli, error) {
|
||||
databaseRepo := data.NewDatabaseRepo(locale, db, databaseServerRepo, databaseUserRepo)
|
||||
certRepo := data.NewCertRepo(locale, db, logger)
|
||||
certAccountRepo := data.NewCertAccountRepo(locale, db, userRepo, logger)
|
||||
websiteRepo := data.NewWebsiteRepo(locale, db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo)
|
||||
websiteRepo := data.NewWebsiteRepo(locale, db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo, settingRepo)
|
||||
backupRepo := data.NewBackupRepo(locale, db, settingRepo, websiteRepo)
|
||||
cliService := service.NewCliService(locale, koanf, db, appRepo, cacheRepo, userRepo, settingRepo, backupRepo, websiteRepo, databaseServerRepo)
|
||||
cli := route.NewCli(locale, cliService)
|
||||
|
||||
6
go.sum
6
go.sum
@@ -167,8 +167,6 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
|
||||
@@ -464,8 +462,6 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -538,8 +534,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
SettingKeyMySQLRootPassword SettingKey = "mysql_root_password"
|
||||
SettingKeyOfflineMode SettingKey = "offline_mode"
|
||||
SettingKeyAutoUpdate SettingKey = "auto_update"
|
||||
SettingKeyWebServer SettingKey = "web_server"
|
||||
)
|
||||
|
||||
type Setting struct {
|
||||
|
||||
@@ -20,6 +20,7 @@ type Website struct {
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
CertExpire string `gorm:"-:all" json:"cert_expire"` // 仅显示
|
||||
PHP uint `gorm:"-:all" json:"php"` // 仅显示
|
||||
|
||||
Cert *Cert `gorm:"foreignKey:WebsiteID" json:"cert"`
|
||||
}
|
||||
@@ -30,7 +31,7 @@ type WebsiteRepo interface {
|
||||
Count() (int64, error)
|
||||
Get(id uint) (*types.WebsiteSetting, error)
|
||||
GetByName(name string) (*types.WebsiteSetting, error)
|
||||
List(page, limit uint) ([]*Website, int64, error)
|
||||
List(typ string, page, limit uint) ([]*Website, int64, error)
|
||||
Create(req *request.WebsiteCreate) (*Website, error)
|
||||
Update(req *request.WebsiteUpdate) error
|
||||
Delete(req *request.WebsiteDelete) error
|
||||
|
||||
@@ -29,6 +29,8 @@ import (
|
||||
"github.com/acepanel/panel/pkg/shell"
|
||||
"github.com/acepanel/panel/pkg/systemctl"
|
||||
"github.com/acepanel/panel/pkg/types"
|
||||
"github.com/acepanel/panel/pkg/webserver"
|
||||
webservertypes "github.com/acepanel/panel/pkg/webserver/types"
|
||||
)
|
||||
|
||||
type websiteRepo struct {
|
||||
@@ -40,9 +42,10 @@ type websiteRepo struct {
|
||||
databaseUser biz.DatabaseUserRepo
|
||||
cert biz.CertRepo
|
||||
certAccount biz.CertAccountRepo
|
||||
setting biz.SettingRepo
|
||||
}
|
||||
|
||||
func NewWebsiteRepo(t *gotext.Locale, db *gorm.DB, cache biz.CacheRepo, database biz.DatabaseRepo, databaseServer biz.DatabaseServerRepo, databaseUser biz.DatabaseUserRepo, cert biz.CertRepo, certAccount biz.CertAccountRepo) biz.WebsiteRepo {
|
||||
func NewWebsiteRepo(t *gotext.Locale, db *gorm.DB, cache biz.CacheRepo, database biz.DatabaseRepo, databaseServer biz.DatabaseServerRepo, databaseUser biz.DatabaseUserRepo, cert biz.CertRepo, certAccount biz.CertAccountRepo, setting biz.SettingRepo) biz.WebsiteRepo {
|
||||
return &websiteRepo{
|
||||
t: t,
|
||||
db: db,
|
||||
@@ -52,6 +55,7 @@ func NewWebsiteRepo(t *gotext.Locale, db *gorm.DB, cache biz.CacheRepo, database
|
||||
databaseUser: databaseUser,
|
||||
cert: cert,
|
||||
certAccount: certAccount,
|
||||
setting: setting,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +215,7 @@ func (r *websiteRepo) GetByName(name string) (*types.WebsiteSetting, error) {
|
||||
|
||||
}
|
||||
|
||||
func (r *websiteRepo) List(page, limit uint) ([]*biz.Website, int64, error) {
|
||||
func (r *websiteRepo) List(typ string, page, limit uint) ([]*biz.Website, int64, error) {
|
||||
websites := make([]*biz.Website, 0)
|
||||
var total int64
|
||||
|
||||
@@ -219,35 +223,56 @@ func (r *websiteRepo) List(page, limit uint) ([]*biz.Website, int64, error) {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := r.db.Offset(int((page - 1) * limit)).Limit(int(limit)).Find(&websites).Error; err != nil {
|
||||
query := r.db
|
||||
if typ != "all" {
|
||||
query = query.Where("type = ?", typ)
|
||||
}
|
||||
if err := query.Order("id DESC").Offset(int((page - 1) * limit)).Limit(int(limit)).Find(&websites).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// 取证书剩余有效时间
|
||||
// 取证书剩余有效时间和PHP版本
|
||||
for _, website := range websites {
|
||||
crt, _ := io.Read(filepath.Join(app.Root, "server/vhost/cert", website.Name+".pem"))
|
||||
if decode, err := cert.ParseCert(crt); err == nil {
|
||||
hours := time.Until(decode.NotAfter).Hours()
|
||||
website.CertExpire = fmt.Sprintf("%.2f", hours/24)
|
||||
}
|
||||
if website.Type == "php" {
|
||||
website.PHP = r.getPHPVersion(website.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return websites, total, nil
|
||||
}
|
||||
|
||||
func (r *websiteRepo) Create(req *request.WebsiteCreate) (*biz.Website, error) {
|
||||
// 初始化nginx配置
|
||||
config := nginx.DefaultConf
|
||||
p, err := nginx.NewParser(config)
|
||||
webServer, err := r.setting.Get(biz.SettingKeyWebServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 监听地址
|
||||
var listens [][]string
|
||||
for _, listen := range req.Listens {
|
||||
listens = append(listens, []string{listen})
|
||||
|
||||
var vhost webservertypes.Vhost
|
||||
switch req.Type {
|
||||
case "proxy":
|
||||
vhost, err = webserver.NewProxyVhost(webserver.Type(webServer), filepath.Join(app.Root, "sites", req.Name, "config"))
|
||||
case "php":
|
||||
vhost, err = webserver.NewPHPVhost(webserver.Type(webServer), filepath.Join(app.Root, "sites", req.Name, "config"))
|
||||
case "static":
|
||||
vhost, err = webserver.NewStaticVhost(webserver.Type(webServer), filepath.Join(app.Root, "sites", req.Name, "config"))
|
||||
default:
|
||||
return nil, errors.New(r.t.Get("unsupported website type: %s", req.Type))
|
||||
}
|
||||
if err = p.SetListen(listens); err != nil {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 监听地址
|
||||
var listens []webservertypes.Listen
|
||||
for _, listen := range req.Listens {
|
||||
listens = append(listens, webservertypes.Listen{Address: listen})
|
||||
}
|
||||
if err = vhost.SetListen(listens); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 域名
|
||||
@@ -255,37 +280,35 @@ func (r *websiteRepo) Create(req *request.WebsiteCreate) (*biz.Website, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = p.SetServerName(domains); err != nil {
|
||||
if err = vhost.SetServerName(domains); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 运行目录
|
||||
if err = p.SetRoot(req.Path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// PHP
|
||||
if err = p.SetPHP(req.PHP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 伪静态和acme
|
||||
includes, comments, err := p.GetIncludes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
includes = append(includes, filepath.Join(app.Root, "server/vhost/rewrite", req.Name+".conf"))
|
||||
includes = append(includes, filepath.Join(app.Root, "server/vhost/acme", req.Name+".conf"))
|
||||
comments = append(comments, []string{r.t.Get("# Rewrite rule")})
|
||||
comments = append(comments, []string{"# acme http-01"})
|
||||
if err = p.SetIncludes(includes, comments); err != nil {
|
||||
if err = vhost.SetRoot(req.Path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 日志
|
||||
if err = p.SetAccessLog(filepath.Join(app.Root, "wwwlogs", req.Name+".log")); err != nil {
|
||||
if err = vhost.SetAccessLog(filepath.Join(app.Root, "sites", req.Name, "log", "access.log")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = p.SetErrorLog(filepath.Join(app.Root, "wwwlogs", req.Name+".error.log")); err != nil {
|
||||
if err = vhost.SetErrorLog(filepath.Join(app.Root, "sites", req.Name, "log", "error.log")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 反向代理支持
|
||||
if proxyVhost, ok := vhost.(webservertypes.ProxyVhost); ok {
|
||||
if err = proxyVhost.SetProxies([]webservertypes.Proxy{req.Proxy}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// PHP 支持
|
||||
if phpVhost, ok := vhost.(webservertypes.PHPVhost); ok {
|
||||
if err = phpVhost.SetPHP(req.PHP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化网站目录
|
||||
if err = os.MkdirAll(req.Path, 0755); err != nil {
|
||||
return nil, err
|
||||
@@ -321,20 +344,20 @@ func (r *websiteRepo) Create(req *request.WebsiteCreate) (*biz.Website, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 写nginx配置
|
||||
if err = io.Write(filepath.Join(app.Root, "server/vhost", req.Name+".conf"), p.Dump(), 0644); err != nil {
|
||||
// 写配置
|
||||
if err = vhost.Save(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = io.Write(filepath.Join(app.Root, "server/vhost/rewrite", req.Name+".conf"), "", 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = io.Write(filepath.Join(app.Root, "server/vhost/acme", req.Name+".conf"), "", 0644); err != nil {
|
||||
if err = io.Write(filepath.Join(app.Root, "sites", req.Name, "config", "vhost", "001-acme.conf"), "", 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = io.Write(filepath.Join(app.Root, "server/vhost/cert", req.Name+".pem"), "", 0644); err != nil {
|
||||
if err = io.Write(filepath.Join(app.Root, "sites", req.Name, "config", "fullchain.pem"), "", 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = io.Write(filepath.Join(app.Root, "server/vhost/cert", req.Name+".key"), "", 0644); err != nil {
|
||||
if err = io.Write(filepath.Join(app.Root, "sites", req.Name, "config", "privatekey.key"), "", 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -347,7 +370,7 @@ func (r *websiteRepo) Create(req *request.WebsiteCreate) (*biz.Website, error) {
|
||||
}
|
||||
|
||||
// PHP 网站默认开启防跨站
|
||||
if req.PHP > 0 {
|
||||
if req.Type == "php" {
|
||||
userIni := filepath.Join(req.Path, ".user.ini")
|
||||
if !io.Exists(userIni) {
|
||||
if err = io.Write(userIni, fmt.Sprintf("open_basedir=%s:/tmp/", req.Path), 0644); err != nil {
|
||||
@@ -360,7 +383,7 @@ func (r *websiteRepo) Create(req *request.WebsiteCreate) (*biz.Website, error) {
|
||||
// 创建面板网站
|
||||
w := &biz.Website{
|
||||
Name: req.Name,
|
||||
Type: "php", // TODO 支持网站类型
|
||||
Type: req.Type,
|
||||
Status: true,
|
||||
Path: req.Path,
|
||||
Https: false,
|
||||
@@ -370,8 +393,8 @@ func (r *websiteRepo) Create(req *request.WebsiteCreate) (*biz.Website, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = systemctl.Reload("nginx"); err != nil {
|
||||
_, err = shell.Execf("nginx -t")
|
||||
// 重载 Web 服务器
|
||||
if err = vhost.Reload(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -839,3 +862,11 @@ func (r *websiteRepo) ObtainCert(ctx context.Context, id uint) error {
|
||||
|
||||
return r.cert.Deploy(newCert.ID, website.ID)
|
||||
}
|
||||
|
||||
func (r *websiteRepo) getPHPVersion(name string) uint {
|
||||
vhost, err := webserver.NewPHPVhost(webserver.TypeNginx, filepath.Join(app.Root, "sites", name, "config"))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return vhost.PHP()
|
||||
}
|
||||
|
||||
@@ -1,24 +1,35 @@
|
||||
package request
|
||||
|
||||
import "github.com/acepanel/panel/pkg/types"
|
||||
import (
|
||||
"github.com/acepanel/panel/pkg/types"
|
||||
webservertypes "github.com/acepanel/panel/pkg/webserver/types"
|
||||
)
|
||||
|
||||
type WebsiteDefaultConfig struct {
|
||||
Index string `json:"index" form:"index" validate:"required"`
|
||||
Stop string `json:"stop" form:"stop" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteList struct {
|
||||
Type string `json:"type" form:"type" validate:"required|in:all,proxy,static,php"`
|
||||
Paginate
|
||||
}
|
||||
|
||||
type WebsiteCreate struct {
|
||||
Type string `json:"type" form:"type" validate:"required|in:proxy,static,php"`
|
||||
Name string `form:"name" json:"name" validate:"required|notExists:websites,name|not_in:phpmyadmin,default|regex:^[a-zA-Z0-9_-]+$"`
|
||||
Listens []string `form:"listens" json:"listens" validate:"required|isSlice"`
|
||||
Domains []string `form:"domains" json:"domains" validate:"required|isSlice"`
|
||||
Path string `form:"path" json:"path"`
|
||||
PHP int `form:"php" json:"php"`
|
||||
DB bool `form:"db" json:"db"`
|
||||
DBType string `form:"db_type" json:"db_type" validate:"requiredIf:DB,true"`
|
||||
DBName string `form:"db_name" json:"db_name" validate:"requiredIf:DB,true"`
|
||||
DBUser string `form:"db_user" json:"db_user" validate:"requiredIf:DB,true"`
|
||||
DBPassword string `form:"db_password" json:"db_password" validate:"requiredIf:DB,true"`
|
||||
Remark string `form:"remark" json:"remark"`
|
||||
|
||||
PHP uint `form:"php" json:"php" validate:"requiredIf:Type,php"` // 仅 PHP 网站需要
|
||||
Proxy webservertypes.Proxy `form:"proxy" json:"proxy" validate:"requiredIf:Type,proxy"` // 仅反向代理网站需要
|
||||
}
|
||||
|
||||
type WebsiteDelete struct {
|
||||
|
||||
@@ -570,7 +570,7 @@ func (s *CliService) WebsiteCreate(ctx context.Context, cmd *cli.Command) error
|
||||
Domains: cmd.StringSlice("domains"),
|
||||
Listens: cmd.StringSlice("listens"),
|
||||
Path: cmd.String("path"),
|
||||
PHP: int(cmd.Int("php")),
|
||||
PHP: cmd.Uint("php"),
|
||||
DB: false,
|
||||
}
|
||||
|
||||
|
||||
@@ -83,14 +83,15 @@ func (s *WebsiteService) UpdateCert(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
// List 网站列表
|
||||
func (s *WebsiteService) List(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.Paginate](r)
|
||||
req, err := Bind[request.WebsiteList](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
websites, total, err := s.websiteRepo.List(req.Page, req.Limit)
|
||||
websites, total, err := s.websiteRepo.List(req.Type, req.Page, req.Limit)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
|
||||
@@ -137,18 +137,7 @@ func (v *baseVhost) Listen() []types.Listen {
|
||||
// Apache 的监听配置通常在 VirtualHost 的参数中
|
||||
// 例如: <VirtualHost *:80> 或 <VirtualHost 192.168.1.1:443>
|
||||
for _, arg := range v.vhost.Args {
|
||||
listen := types.Listen{
|
||||
Address: arg,
|
||||
Options: make(map[string]string),
|
||||
}
|
||||
|
||||
// 检查是否是 HTTPS
|
||||
if strings.Contains(arg, ":443") || v.HTTPS() {
|
||||
listen.Protocol = "https"
|
||||
} else {
|
||||
listen.Protocol = "http"
|
||||
}
|
||||
|
||||
listen := types.Listen{Address: arg}
|
||||
result = append(result, listen)
|
||||
}
|
||||
|
||||
@@ -583,7 +572,7 @@ func (v *baseVhost) SetRedirects(redirects []types.Redirect) error {
|
||||
|
||||
// ========== PHPVhost ==========
|
||||
|
||||
func (v *PHPVhost) PHP() int {
|
||||
func (v *PHPVhost) PHP() uint {
|
||||
// Apache 通常通过 FilesMatch 块配置 PHP
|
||||
// 或者通过 SetHandler 指令
|
||||
handler := v.vhost.GetDirectiveValue("SetHandler")
|
||||
@@ -606,7 +595,7 @@ func (v *PHPVhost) PHP() int {
|
||||
if len(parts) >= 2 {
|
||||
major, _ := strconv.Atoi(parts[0])
|
||||
minor, _ := strconv.Atoi(parts[1])
|
||||
return major*10 + minor
|
||||
return uint(major*10 + minor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -630,7 +619,7 @@ func (v *PHPVhost) PHP() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (v *PHPVhost) SetPHP(version int) error {
|
||||
func (v *PHPVhost) SetPHP(version uint) error {
|
||||
// 移除现有的 PHP 配置
|
||||
v.vhost.RemoveDirective("SetHandler")
|
||||
|
||||
|
||||
@@ -131,8 +131,8 @@ func (s *VhostTestSuite) TestIndexEmpty() {
|
||||
|
||||
func (s *VhostTestSuite) TestListen() {
|
||||
listens := []types.Listen{
|
||||
{Address: "*:80", Protocol: "http"},
|
||||
{Address: "*:443", Protocol: "https"},
|
||||
{Address: "*:80"},
|
||||
{Address: "*:443"},
|
||||
}
|
||||
err := s.vhost.SetListen(listens)
|
||||
s.NoError(err)
|
||||
@@ -345,7 +345,7 @@ func (s *VhostTestSuite) TestExportWithSSL() {
|
||||
|
||||
func (s *VhostTestSuite) TestListenProtocolDetection() {
|
||||
listens := []types.Listen{
|
||||
{Address: "*:443", Protocol: "https"},
|
||||
{Address: "*:443"},
|
||||
}
|
||||
s.NoError(s.vhost.SetListen(listens))
|
||||
|
||||
@@ -357,7 +357,7 @@ func (s *VhostTestSuite) TestListenProtocolDetection() {
|
||||
|
||||
got := s.vhost.Listen()
|
||||
s.Len(got, 1)
|
||||
s.Equal("https", got[0].Protocol)
|
||||
s.Equal("*:443", got[0].Address)
|
||||
}
|
||||
|
||||
func (s *VhostTestSuite) TestDirectoryBlock() {
|
||||
|
||||
@@ -6,47 +6,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (p *Parser) GetListen() ([][]string, error) {
|
||||
directives, err := p.Find("server.listen")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result [][]string
|
||||
for _, dir := range directives {
|
||||
result = append(result, p.parameters2Slices(dir.GetParameters()))
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetServerName() ([]string, error) {
|
||||
directive, err := p.FindOne("server.server_name")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.parameters2Slices(directive.GetParameters()), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetIndex() ([]string, error) {
|
||||
directive, err := p.FindOne("server.index")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.parameters2Slices(directive.GetParameters()), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetIndexWithComment() ([]string, []string, error) {
|
||||
directive, err := p.FindOne("server.index")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return p.parameters2Slices(directive.GetParameters()), directive.GetComment(), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetRoot() (string, error) {
|
||||
directive, err := p.FindOne("server.root")
|
||||
if err != nil {
|
||||
@@ -88,36 +47,6 @@ func (p *Parser) GetIncludes() (includes []string, comments [][]string, err erro
|
||||
return includes, comments, nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetPHP() int {
|
||||
directives, err := p.Find("server.include")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
var result int
|
||||
for _, dir := range directives {
|
||||
if slices.ContainsFunc(p.parameters2Slices(dir.GetParameters()), func(s string) bool {
|
||||
return strings.HasPrefix(s, "enable-php-") && strings.HasSuffix(s, ".conf")
|
||||
}) {
|
||||
_, _ = fmt.Sscanf(dir.GetParameters()[0].GetValue(), "enable-php-%d.conf", &result)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (p *Parser) GetHTTPS() bool {
|
||||
directive, err := p.FindOne("server.ssl_certificate")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Parser) GetHTTPSProtocols() []string {
|
||||
directive, err := p.FindOne("server.ssl_protocols")
|
||||
if err != nil {
|
||||
|
||||
@@ -15,56 +15,6 @@ func TestNginxTestSuite(t *testing.T) {
|
||||
suite.Run(t, &NginxTestSuite{})
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestListen() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
listen, err := parser.GetListen()
|
||||
s.NoError(err)
|
||||
s.Equal([][]string{{"80"}}, listen)
|
||||
s.NoError(parser.SetListen([][]string{{"80"}, {"443"}}))
|
||||
listen, err = parser.GetListen()
|
||||
s.NoError(err)
|
||||
s.Equal([][]string{{"80"}, {"443"}}, listen)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestServerName() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
serverName, err := parser.GetServerName()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"localhost"}, serverName)
|
||||
s.NoError(parser.SetServerName([]string{"example.com"}))
|
||||
serverName, err = parser.GetServerName()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"example.com"}, serverName)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestIndex() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
index, err := parser.GetIndex()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.php", "index.html"}, index)
|
||||
s.NoError(parser.SetIndex([]string{"index.html", "index.php"}))
|
||||
index, err = parser.GetIndex()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.html", "index.php"}, index)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestIndexWithComment() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
index, comment, err := parser.GetIndexWithComment()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.php", "index.html"}, index)
|
||||
s.Equal([]string(nil), comment)
|
||||
s.NoError(parser.SetIndexWithComment([]string{"index.html", "index.php"}, []string{"# 测试"}))
|
||||
index, comment, err = parser.GetIndexWithComment()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.html", "index.php"}, index)
|
||||
s.Equal([]string{"# 测试"}, comment)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestRoot() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
@@ -110,16 +60,6 @@ func (s *NginxTestSuite) TestIncludes() {
|
||||
s.Equal([][]string{{"# 伪静态规则测试"}}, comments)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestPHP() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.Equal(0, parser.GetPHP())
|
||||
s.NoError(parser.SetPHP(80))
|
||||
s.Equal(80, parser.GetPHP())
|
||||
s.NoError(parser.SetPHP(0))
|
||||
s.Equal(0, parser.GetPHP())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTP() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
@@ -128,17 +68,6 @@ func (s *NginxTestSuite) TestHTTP() {
|
||||
s.Equal(string(expect), parser.Dump())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTPS() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.False(parser.GetHTTPS())
|
||||
s.NoError(parser.SetHTTPSCert("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.True(parser.GetHTTPS())
|
||||
expect, err := os.ReadFile("testdata/https.conf")
|
||||
s.NoError(err)
|
||||
s.Equal(string(expect), parser.Dump())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTPSProtocols() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
|
||||
@@ -216,7 +216,6 @@ func generateProxyConfig(proxy types.Proxy) string {
|
||||
location = "/"
|
||||
}
|
||||
|
||||
sb.WriteString(fmt.Sprintf("# Reverse proxy: %s -> %s\n", location, proxy.Pass))
|
||||
sb.WriteString(fmt.Sprintf("location %s {\n", location))
|
||||
|
||||
// resolver 配置(如果启用自动刷新)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/acepanel/panel/pkg/webserver/types"
|
||||
@@ -123,39 +124,17 @@ func (v *baseVhost) SetEnable(enable bool, _ ...string) error {
|
||||
}
|
||||
|
||||
func (v *baseVhost) Listen() []types.Listen {
|
||||
listens, err := v.parser.GetListen()
|
||||
directives, err := v.parser.Find("server.listen")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result []types.Listen
|
||||
for _, l := range listens {
|
||||
if len(l) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
listen := types.Listen{
|
||||
Address: l[0],
|
||||
Options: make(map[string]string),
|
||||
}
|
||||
|
||||
// 解析 Nginx 特有的选项
|
||||
for _, dir := range directives {
|
||||
l := v.parser.parameters2Slices(dir.GetParameters())
|
||||
listen := types.Listen{Address: l[0]}
|
||||
for i := 1; i < len(l); i++ {
|
||||
switch l[i] {
|
||||
case "ssl":
|
||||
listen.Protocol = "https"
|
||||
case "http2":
|
||||
listen.Protocol = "http2"
|
||||
case "http3", "quic":
|
||||
listen.Protocol = "http3"
|
||||
default:
|
||||
listen.Options[l[i]] = "true"
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有指定协议,默认为 http
|
||||
if listen.Protocol == "" {
|
||||
listen.Protocol = "http"
|
||||
listen.Args = append(listen.Args, l[i])
|
||||
}
|
||||
|
||||
result = append(result, listen)
|
||||
@@ -169,26 +148,7 @@ func (v *baseVhost) SetListen(listens []types.Listen) error {
|
||||
var nginxListens [][]string
|
||||
for _, l := range listens {
|
||||
listen := []string{l.Address}
|
||||
|
||||
// 添加协议标识
|
||||
switch l.Protocol {
|
||||
case "https":
|
||||
listen = append(listen, "ssl")
|
||||
case "http2":
|
||||
listen = append(listen, "http2")
|
||||
case "http3":
|
||||
listen = append(listen, "http3")
|
||||
}
|
||||
|
||||
// 添加其他选项
|
||||
for k, v := range l.Options {
|
||||
if v == "true" {
|
||||
listen = append(listen, k)
|
||||
} else {
|
||||
listen = append(listen, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
}
|
||||
|
||||
listen = append(listen, l.Args...)
|
||||
nginxListens = append(nginxListens, listen)
|
||||
}
|
||||
|
||||
@@ -196,11 +156,12 @@ func (v *baseVhost) SetListen(listens []types.Listen) error {
|
||||
}
|
||||
|
||||
func (v *baseVhost) ServerName() []string {
|
||||
names, err := v.parser.GetServerName()
|
||||
directive, err := v.parser.FindOne("server.server_name")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return names
|
||||
|
||||
return v.parser.parameters2Slices(directive.GetParameters())
|
||||
}
|
||||
|
||||
func (v *baseVhost) SetServerName(serverName []string) error {
|
||||
@@ -208,11 +169,12 @@ func (v *baseVhost) SetServerName(serverName []string) error {
|
||||
}
|
||||
|
||||
func (v *baseVhost) Index() []string {
|
||||
index, err := v.parser.GetIndex()
|
||||
directive, err := v.parser.FindOne("server.index")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return index
|
||||
|
||||
return v.parser.parameters2Slices(directive.GetParameters())
|
||||
}
|
||||
|
||||
func (v *baseVhost) SetIndex(index []string) error {
|
||||
@@ -294,6 +256,9 @@ func (v *baseVhost) Save() error {
|
||||
func (v *baseVhost) Reload() error {
|
||||
parts := strings.Fields("systemctl reload openresty")
|
||||
if err := exec.Command(parts[0], parts[1:]...).Run(); err != nil {
|
||||
if testErr := exec.Command("nginx", "-t").Run(); testErr != nil {
|
||||
return fmt.Errorf("nginx config test failed: %w", testErr)
|
||||
}
|
||||
return fmt.Errorf("failed to reload nginx config: %w", err)
|
||||
}
|
||||
|
||||
@@ -317,7 +282,15 @@ func (v *baseVhost) Reset() error {
|
||||
}
|
||||
|
||||
func (v *baseVhost) HTTPS() bool {
|
||||
return v.parser.GetHTTPS()
|
||||
directive, err := v.parser.FindOne("server.ssl_certificate")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if len(v.parser.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *baseVhost) SSLConfig() *types.SSLConfig {
|
||||
@@ -479,11 +452,25 @@ func (v *baseVhost) SetRedirects(redirects []types.Redirect) error {
|
||||
|
||||
// ========== PHPVhost ==========
|
||||
|
||||
func (v *PHPVhost) PHP() int {
|
||||
return v.parser.GetPHP()
|
||||
func (v *PHPVhost) PHP() uint {
|
||||
directives, err := v.parser.Find("server.include")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
var result uint
|
||||
for _, dir := range directives {
|
||||
if slices.ContainsFunc(v.parser.parameters2Slices(dir.GetParameters()), func(s string) bool {
|
||||
return strings.HasPrefix(s, "enable-php-") && strings.HasSuffix(s, ".conf")
|
||||
}) {
|
||||
_, _ = fmt.Sscanf(dir.GetParameters()[0].GetValue(), "enable-php-%d.conf", &result)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *PHPVhost) SetPHP(version int) error {
|
||||
func (v *PHPVhost) SetPHP(version uint) error {
|
||||
// 先移除所有 PHP 相关的 include
|
||||
includes := v.Includes()
|
||||
var newIncludes []types.IncludeFile
|
||||
|
||||
@@ -4,21 +4,21 @@ import "time"
|
||||
|
||||
// Proxy 反向代理配置
|
||||
type Proxy struct {
|
||||
Location string // 匹配路径,如: "/", "/api", "~ ^/api/v[0-9]+/"
|
||||
AutoRefresh bool // 是否自动刷新解析
|
||||
Pass string // 代理地址,如: "http://example.com", "http://backend"
|
||||
Host string // 代理 Host,如: "example.com"
|
||||
SNI string // 代理 SNI,如: "example.com"
|
||||
Cache bool // 是否启用缓存
|
||||
Buffering bool // 是否启用缓冲
|
||||
Resolver []string // 自定义 DNS 解析器配置,如: ["8.8.8.8", "ipv6=off"]
|
||||
ResolverTimeout time.Duration // DNS 解析超时时间,如: 5 * time.Second
|
||||
Replaces map[string]string // 响应内容替换,如: map["/old"] = "/new"
|
||||
Location string `form:"location" json:"location" validate:"required"` // 匹配路径,如: "/", "/api", "~ ^/api/v[0-9]+/"
|
||||
AutoRefresh bool `form:"auto_refresh" json:"auto_refresh"` // 是否自动刷新解析
|
||||
Pass string `form:"pass" json:"pass" validate:"required"` // 代理地址,如: "http://example.com", "http://backend"
|
||||
Host string `form:"host" json:"host"` // 代理 Host,如: "example.com"
|
||||
SNI string `form:"sni" json:"sni"` // 代理 SNI,如: "example.com"
|
||||
Cache bool `form:"cache" json:"cache"` // 是否启用缓存
|
||||
Buffering bool `form:"buffering" json:"buffering"` // 是否启用缓冲
|
||||
Resolver []string `form:"resolver" json:"resolver"` // 自定义 DNS 解析器配置,如: ["8.8.8.8", "ipv6=off"]
|
||||
ResolverTimeout time.Duration `form:"resolver_timeout" json:"resolver_timeout"` // DNS 解析超时时间,如: 5 * time.Second
|
||||
Replaces map[string]string `form:"replaces" json:"replaces"` // 响应内容替换,如: map["/old"] = "/new"
|
||||
}
|
||||
|
||||
// Upstream 上游服务器配置
|
||||
type Upstream struct {
|
||||
Servers map[string]string // 上游服务器及权重,如: map["server1"] = "weight=5"
|
||||
Algo string // 负载均衡算法,如: "least_conn", "ip_hash"
|
||||
Keepalive int // 保持连接数,如: 32
|
||||
Servers map[string]string `form:"servers" json:"servers" validate:"required"` // 上游服务器及权重,如: map["server1"] = "weight=5"
|
||||
Algo string `form:"algo" json:"algo"` // 负载均衡算法,如: "least_conn", "ip_hash"
|
||||
Keepalive int `form:"keepalive" json:"keepalive"` // 保持连接数,如: 32
|
||||
}
|
||||
|
||||
@@ -92,15 +92,15 @@ type PHPVhost interface {
|
||||
type ProxyVhost interface {
|
||||
Vhost
|
||||
VhostRedirect
|
||||
VhostProxyConfig
|
||||
VhostProxy
|
||||
}
|
||||
|
||||
// VhostPHP PHP 相关接口
|
||||
type VhostPHP interface {
|
||||
// PHP 取 PHP 版本,如: 84, 81, 80, 0 表示未启用 PHP
|
||||
PHP() int
|
||||
PHP() uint
|
||||
// SetPHP 设置 PHP 版本
|
||||
SetPHP(version int) error
|
||||
SetPHP(version uint) error
|
||||
}
|
||||
|
||||
// VhostRedirect 重定向相关接口
|
||||
@@ -111,8 +111,8 @@ type VhostRedirect interface {
|
||||
SetRedirects(redirects []Redirect) error
|
||||
}
|
||||
|
||||
// VhostProxyConfig 反向代理相关接口
|
||||
type VhostProxyConfig interface {
|
||||
// VhostProxy 反向代理相关接口
|
||||
type VhostProxy interface {
|
||||
// Proxies 取所有反向代理配置
|
||||
Proxies() []Proxy
|
||||
// SetProxies 设置反向代理配置
|
||||
@@ -130,9 +130,8 @@ type VhostProxyConfig interface {
|
||||
|
||||
// Listen 监听配置
|
||||
type Listen struct {
|
||||
Address string // 监听地址,如: "80", "0.0.0.0:80", "[::]:443"
|
||||
Protocol string // 协议类型,如: "http", "https", "http2", "http3"
|
||||
Options map[string]string // 服务器特定选项,如: map["default_server"] = "true"
|
||||
Address string // 监听地址,如: "80", "0.0.0.0:80", "[::]:443"
|
||||
Args []string // 其他参数,如: ["default_server", "ssl", "quic"]
|
||||
}
|
||||
|
||||
// SSLConfig SSL/TLS 配置
|
||||
|
||||
@@ -2,7 +2,8 @@ import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 列表
|
||||
list: (page: number, limit: number): any => http.Get('/website', { params: { page, limit } }),
|
||||
list: (type: string, page: number, limit: number): any =>
|
||||
http.Get('/website', { params: { type, page, limit } }),
|
||||
// 创建
|
||||
create: (data: any): any => http.Post('/website', data),
|
||||
// 删除
|
||||
|
||||
@@ -162,7 +162,7 @@ const handleSaveWhiteList = () => {
|
||||
}
|
||||
|
||||
const getWebsiteList = async (page: number, limit: number) => {
|
||||
const data = await website.list(page, limit)
|
||||
const data = await website.list('all', page, limit)
|
||||
for (const item of data.items) {
|
||||
websites.value.push({
|
||||
label: item.name,
|
||||
|
||||
@@ -164,7 +164,7 @@ watch(
|
||||
onMounted(() => {
|
||||
useRequest(app.isInstalled('nginx')).onSuccess(({ data }) => {
|
||||
if (data) {
|
||||
useRequest(website.list(1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
useRequest(website.list('all', 1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
for (const item of data.items) {
|
||||
websites.value.push({
|
||||
label: item.name,
|
||||
|
||||
@@ -40,7 +40,7 @@ const getAsyncData = () => {
|
||||
websites.value = []
|
||||
useRequest(app.isInstalled('nginx')).onSuccess(({ data }) => {
|
||||
if (data) {
|
||||
useRequest(website.list(1, 10000)).onSuccess(({ data }) => {
|
||||
useRequest(website.list('all', 1, 10000)).onSuccess(({ data }) => {
|
||||
for (const item of data.items) {
|
||||
websites.value.push({
|
||||
label: item.name,
|
||||
|
||||
@@ -68,7 +68,7 @@ watch(createModel, (value) => {
|
||||
onMounted(() => {
|
||||
useRequest(app.isInstalled('nginx')).onSuccess(({ data }) => {
|
||||
if (data) {
|
||||
useRequest(website.list(1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
useRequest(website.list('all', 1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
for (const item of data.items) {
|
||||
websites.value.push({
|
||||
label: item.name,
|
||||
|
||||
@@ -3,7 +3,7 @@ defineOptions({
|
||||
name: 'website-index'
|
||||
})
|
||||
|
||||
import PhpView from '@/views/website/PhpView.vue'
|
||||
import ListView from '@/views/website/ListView.vue'
|
||||
import SettingView from '@/views/website/SettingView.vue'
|
||||
|
||||
const currentTab = ref('proxy')
|
||||
@@ -19,7 +19,7 @@ const currentTab = ref('proxy')
|
||||
<n-tab name="setting" :tab="$gettext('Settings')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<php-view v-if="currentTab === 'php'" />
|
||||
<list-view v-if="currentTab != 'setting'" v-model:type="currentTab" />
|
||||
<setting-view v-if="currentTab === 'setting'" />
|
||||
</common-page>
|
||||
</template>
|
||||
|
||||
@@ -8,6 +8,8 @@ import { useFileStore } from '@/store'
|
||||
import { generateRandomString, isNullOrUndef } from '@/utils'
|
||||
import BulkCreate from '@/views/website/BulkCreate.vue'
|
||||
|
||||
const type = defineModel<string>('type', { type: String, required: true }) // 网站类型
|
||||
|
||||
const fileStore = useFileStore()
|
||||
const { $gettext } = useGettext()
|
||||
const router = useRouter()
|
||||
@@ -240,7 +242,7 @@ const { data: installedDbAndPhp } = useRequest(home.installedDbAndPhp, {
|
||||
})
|
||||
|
||||
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
|
||||
(page, pageSize) => website.list(page, pageSize),
|
||||
(page, pageSize) => website.list(type.value, page, pageSize),
|
||||
{
|
||||
initialData: { total: 0, list: [] },
|
||||
initialPageSize: 20,
|
||||
Reference in New Issue
Block a user