From 110b40edd775c3190d687aaa1e5076c175c5e278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Thu, 28 Nov 2024 23:51:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=BD=91=E7=AB=99):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E4=BC=AA=E9=9D=99=E6=80=81=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/app.go | 1 - internal/biz/cache.go | 2 ++ internal/biz/website.go | 1 + internal/data/app.go | 25 +----------------- internal/data/cache.go | 42 +++++++++++++++++++++++++++++- internal/data/init.go | 8 +++--- internal/data/setting.go | 1 + internal/data/website.go | 21 +++++++++++++++ internal/job/panel_task.go | 15 ++++++++--- internal/route/cli.go | 5 ++++ internal/route/http.go | 1 + internal/service/app.go | 4 ++- internal/service/cli.go | 20 ++++++++++++-- internal/service/website.go | 10 +++++++ web/src/api/panel/website/index.ts | 4 ++- web/src/views/website/EditView.vue | 33 ++++++++++++++++++----- 16 files changed, 149 insertions(+), 44 deletions(-) diff --git a/internal/biz/app.go b/internal/biz/app.go index fa227bdc..cfeff386 100644 --- a/internal/biz/app.go +++ b/internal/biz/app.go @@ -30,5 +30,4 @@ type AppRepo interface { UnInstall(slug string) error Update(slug string) error UpdateShow(slug string, show bool) error - UpdateCache() error } diff --git a/internal/biz/cache.go b/internal/biz/cache.go index cd3faf75..01a23159 100644 --- a/internal/biz/cache.go +++ b/internal/biz/cache.go @@ -19,4 +19,6 @@ type Cache struct { type CacheRepo interface { Get(key CacheKey, defaultValue ...string) (string, error) Set(key CacheKey, value string) error + UpdateApps() error + UpdateRewrites() error } diff --git a/internal/biz/website.go b/internal/biz/website.go index 00827697..756b2fbc 100644 --- a/internal/biz/website.go +++ b/internal/biz/website.go @@ -22,6 +22,7 @@ type Website struct { } type WebsiteRepo interface { + GetRewrites() (map[string]string, error) UpdateDefaultConfig(req *request.WebsiteDefaultConfig) error Count() (int64, error) Get(id uint) (*types.WebsiteSetting, error) diff --git a/internal/data/app.go b/internal/data/app.go index fc3cbdf5..046a0e9e 100644 --- a/internal/data/app.go +++ b/internal/data/app.go @@ -15,13 +15,10 @@ import ( "github.com/TheTNB/panel/internal/app" "github.com/TheTNB/panel/internal/biz" "github.com/TheTNB/panel/pkg/api" - "github.com/TheTNB/panel/pkg/apploader" "github.com/TheTNB/panel/pkg/shell" ) -type appRepo struct { - api *api.API -} +type appRepo struct{} func NewAppRepo() biz.AppRepo { return do.MustInvoke[biz.AppRepo](injector) @@ -309,26 +306,6 @@ func (r *appRepo) UpdateShow(slug string, show bool) error { return app.Orm.Save(item).Error } -func (r *appRepo) UpdateCache() error { - remote, err := r.api.Apps() - if err != nil { - return err - } - - // 去除本地不存在的应用 - *remote = slices.Clip(slices.DeleteFunc(*remote, func(app *api.App) bool { - _, err = apploader.Get(app.Slug) - return err != nil - })) - - encoded, err := json.Marshal(remote) - if err != nil { - return err - } - - return NewCacheRepo().Set(biz.CacheKeyApps, string(encoded)) -} - func (r *appRepo) preCheck(app *api.App) error { var apps []string var installed []string diff --git a/internal/data/cache.go b/internal/data/cache.go index fc38ea6f..962442d3 100644 --- a/internal/data/cache.go +++ b/internal/data/cache.go @@ -1,16 +1,22 @@ package data import ( + "encoding/json" "errors" + "slices" "github.com/samber/do/v2" "gorm.io/gorm" "github.com/TheTNB/panel/internal/app" "github.com/TheTNB/panel/internal/biz" + "github.com/TheTNB/panel/pkg/api" + "github.com/TheTNB/panel/pkg/apploader" ) -type cacheRepo struct{} +type cacheRepo struct { + api *api.API +} func NewCacheRepo() biz.CacheRepo { return do.MustInvoke[biz.CacheRepo](injector) @@ -40,3 +46,37 @@ func (r *cacheRepo) Set(key biz.CacheKey, value string) error { cache.Value = value return app.Orm.Save(cache).Error } + +func (r *cacheRepo) UpdateApps() error { + remote, err := r.api.Apps() + if err != nil { + return err + } + + // 去除本地不存在的应用 + *remote = slices.Clip(slices.DeleteFunc(*remote, func(app *api.App) bool { + _, err = apploader.Get(app.Slug) + return err != nil + })) + + encoded, err := json.Marshal(remote) + if err != nil { + return err + } + + return r.Set(biz.CacheKeyApps, string(encoded)) +} + +func (r *cacheRepo) UpdateRewrites() error { + rewrites, err := r.api.RewritesByType("nginx") + if err != nil { + return err + } + + encoded, err := json.Marshal(rewrites) + if err != nil { + return err + } + + return r.Set(biz.CacheKeyRewrites, string(encoded)) +} diff --git a/internal/data/init.go b/internal/data/init.go index 6fcdb6db..ac56e759 100644 --- a/internal/data/init.go +++ b/internal/data/init.go @@ -20,15 +20,15 @@ var injector = do.New() func init() { do.Provide(injector, func(i do.Injector) (biz.AppRepo, error) { - return &appRepo{ - api: api.NewAPI(app.Version), - }, nil + return &appRepo{}, nil }) do.Provide(injector, func(i do.Injector) (biz.BackupRepo, error) { return &backupRepo{}, nil }) do.Provide(injector, func(i do.Injector) (biz.CacheRepo, error) { - return &cacheRepo{}, nil + return &cacheRepo{ + api: api.NewAPI(app.Version), + }, nil }) do.Provide(injector, func(i do.Injector) (biz.CertRepo, error) { return &certRepo{}, nil diff --git a/internal/data/setting.go b/internal/data/setting.go index a18045a0..36fa56e0 100644 --- a/internal/data/setting.go +++ b/internal/data/setting.go @@ -378,6 +378,7 @@ func (r *settingRepo) FixPanel() error { if app.IsCli { fmt.Println("|-开始修复面板...") } + // 检查关键文件是否正常 flag := false if !io.Exists(filepath.Join(app.Root, "panel", "web")) { diff --git a/internal/data/website.go b/internal/data/website.go index 7acd45f3..9f456861 100644 --- a/internal/data/website.go +++ b/internal/data/website.go @@ -2,6 +2,7 @@ package data import ( "context" + "encoding/json" "errors" "fmt" "path/filepath" @@ -18,6 +19,7 @@ import ( "github.com/TheTNB/panel/internal/embed" "github.com/TheTNB/panel/internal/http/request" "github.com/TheTNB/panel/pkg/acme" + "github.com/TheTNB/panel/pkg/api" "github.com/TheTNB/panel/pkg/cert" "github.com/TheTNB/panel/pkg/io" "github.com/TheTNB/panel/pkg/nginx" @@ -33,6 +35,25 @@ func NewWebsiteRepo() biz.WebsiteRepo { return do.MustInvoke[biz.WebsiteRepo](injector) } +func (r *websiteRepo) GetRewrites() (map[string]string, error) { + cached, err := NewCacheRepo().Get(biz.CacheKeyRewrites) + if err != nil { + return nil, err + } + + var rewrites api.Rewrites + if err = json.Unmarshal([]byte(cached), &rewrites); err != nil { + return nil, err + } + + rw := make(map[string]string) + for rewrite := range slices.Values(rewrites) { + rw[rewrite.Name] = rewrite.Content + } + + return rw, nil +} + func (r *websiteRepo) UpdateDefaultConfig(req *request.WebsiteDefaultConfig) error { if err := io.Write(filepath.Join(app.Root, "server/nginx/html/index.html"), req.Index, 0644); err != nil { return err diff --git a/internal/job/panel_task.go b/internal/job/panel_task.go index 30509adb..ddcb4fa8 100644 --- a/internal/job/panel_task.go +++ b/internal/job/panel_task.go @@ -14,15 +14,15 @@ import ( // PanelTask 面板每日任务 type PanelTask struct { - appRepo biz.AppRepo backupRepo biz.BackupRepo + cacheRepo biz.CacheRepo settingRepo biz.SettingRepo } func NewPanelTask() *PanelTask { return &PanelTask{ - appRepo: data.NewAppRepo(), backupRepo: data.NewBackupRepo(), + cacheRepo: data.NewCacheRepo(), settingRepo: data.NewSettingRepo(), } } @@ -56,12 +56,21 @@ func (r *PanelTask) Run() { // 更新商店缓存 time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() { if offline, err := r.settingRepo.GetBool(biz.SettingKeyOfflineMode); err == nil && !offline { - if err = r.appRepo.UpdateCache(); err != nil { + if err = r.cacheRepo.UpdateApps(); err != nil { app.Logger.Warn("更新商店缓存失败", slog.Any("err", err)) } } }) + // 更新伪静态缓存 + time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() { + if offline, err := r.settingRepo.GetBool(biz.SettingKeyOfflineMode); err == nil && !offline { + if err = r.cacheRepo.UpdateRewrites(); err != nil { + app.Logger.Warn("更新伪静态缓存失败", slog.Any("err", err)) + } + } + }) + // 回收内存 runtime.GC() debug.FreeOSMemory() diff --git a/internal/route/cli.go b/internal/route/cli.go index 9debfd58..db4c72d4 100644 --- a/internal/route/cli.go +++ b/internal/route/cli.go @@ -29,6 +29,11 @@ func Cli() []*cli.Command { Usage: "更新面板", Action: cliService.Update, }, + { + Name: "sync", + Usage: "同步数据", + Action: cliService.Sync, + }, { Name: "fix", Usage: "修复面板", diff --git a/internal/route/http.go b/internal/route/http.go index 58bbf4c6..e9d55432 100644 --- a/internal/route/http.go +++ b/internal/route/http.go @@ -48,6 +48,7 @@ func Http(r chi.Router) { r.Route("/website", func(r chi.Router) { website := service.NewWebsiteService() + r.Get("/rewrites", website.GetRewrites) r.Get("/defaultConfig", website.GetDefaultConfig) r.Post("/defaultConfig", website.UpdateDefaultConfig) r.Get("/", website.List) diff --git a/internal/service/app.go b/internal/service/app.go index 3b9a3300..d43e205a 100644 --- a/internal/service/app.go +++ b/internal/service/app.go @@ -13,12 +13,14 @@ import ( type AppService struct { appRepo biz.AppRepo + cacheRepo biz.CacheRepo settingRepo biz.SettingRepo } func NewAppService() *AppService { return &AppService{ appRepo: data.NewAppRepo(), + cacheRepo: data.NewCacheRepo(), settingRepo: data.NewSettingRepo(), } } @@ -170,7 +172,7 @@ func (s *AppService) UpdateCache(w http.ResponseWriter, r *http.Request) { return } - if err := s.appRepo.UpdateCache(); err != nil { + if err := s.cacheRepo.UpdateApps(); err != nil { Error(w, http.StatusInternalServerError, "%v", err) return } diff --git a/internal/service/cli.go b/internal/service/cli.go index f9fadff1..5c1257c3 100644 --- a/internal/service/cli.go +++ b/internal/service/cli.go @@ -34,6 +34,7 @@ type CliService struct { hr string api *api.API appRepo biz.AppRepo + cacheRepo biz.CacheRepo userRepo biz.UserRepo settingRepo biz.SettingRepo backupRepo biz.BackupRepo @@ -47,6 +48,7 @@ func NewCliService() *CliService { hr: `+----------------------------------------------------`, api: api.NewAPI(app.Version), appRepo: data.NewAppRepo(), + cacheRepo: data.NewCacheRepo(), userRepo: data.NewUserRepo(), settingRepo: data.NewSettingRepo(), backupRepo: data.NewBackupRepo(), @@ -98,6 +100,18 @@ func (s *CliService) Update(ctx context.Context, cmd *cli.Command) error { return s.settingRepo.UpdatePanel(ver, url, checksum) } +func (s *CliService) Sync(ctx context.Context, cmd *cli.Command) error { + if err := s.cacheRepo.UpdateApps(); err != nil { + return fmt.Errorf("同步应用数据失败:%v", err) + } + if err := s.cacheRepo.UpdateRewrites(); err != nil { + return fmt.Errorf("同步伪静态规则失败:%v", err) + } + + fmt.Println("数据同步成功") + return nil +} + func (s *CliService) Fix(ctx context.Context, cmd *cli.Command) error { return s.settingRepo.FixPanel() } @@ -847,6 +861,8 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error { return err } - // 初始化应用中心缓存 - return s.appRepo.UpdateCache() + // 初始化缓存 + _ = s.cacheRepo.UpdateApps() + _ = s.cacheRepo.UpdateRewrites() + return nil } diff --git a/internal/service/website.go b/internal/service/website.go index fa385d6d..50909fc1 100644 --- a/internal/service/website.go +++ b/internal/service/website.go @@ -25,6 +25,16 @@ func NewWebsiteService() *WebsiteService { } } +func (s *WebsiteService) GetRewrites(w http.ResponseWriter, r *http.Request) { + rewrites, err := s.websiteRepo.GetRewrites() + if err != nil { + Error(w, http.StatusInternalServerError, "%v", err) + return + } + + Success(w, rewrites) +} + func (s *WebsiteService) GetDefaultConfig(w http.ResponseWriter, r *http.Request) { index, err := io.Read(filepath.Join(app.Root, "server/nginx/html/index.html")) if err != nil { diff --git a/web/src/api/panel/website/index.ts b/web/src/api/panel/website/index.ts index bd2faeec..b20c12ed 100644 --- a/web/src/api/panel/website/index.ts +++ b/web/src/api/panel/website/index.ts @@ -1,6 +1,6 @@ import type { AxiosResponse } from 'axios' -import { request } from '@/utils' +import { http, request } from '@/utils' export default { // 列表 @@ -11,6 +11,8 @@ export default { // 删除 delete: (id: number, path: boolean, db: boolean): Promise> => request.delete(`/website/${id}`, { data: { path, db } }), + // 伪静态 + rewrites: () => http.Get(`/website/rewrites`), // 获取默认配置 defaultConfig: (): Promise> => request.get('/website/defaultConfig'), // 保存默认配置 diff --git a/web/src/views/website/EditView.vue b/web/src/views/website/EditView.vue index 46c4168b..a6a35c09 100644 --- a/web/src/views/website/EditView.vue +++ b/web/src/views/website/EditView.vue @@ -59,6 +59,16 @@ const installedDbAndPhp = ref({ ] }) const certs = ref([] as Cert[]) +const { data: rewrites }: { data: any } = useRequest(website.rewrites, { + initialData: {} +}) +const rewriteOptions = computed(() => { + return Object.keys(rewrites.value).map((key) => ({ + label: key, + value: key + })) +}) +const rewriteValue = ref(null) const title = computed(() => { if (setting.value) { @@ -121,6 +131,10 @@ const handleReset = async () => { }) } +const handleRewrite = (value: string) => { + setting.value.rewrite = rewrites.value[value] || '' +} + const handleObtainCert = async () => { messageReactive = window.$message.loading('请稍后...', { duration: 0 @@ -239,13 +253,13 @@ onMounted(async () => { - + { - - 设置伪静态规则,填入 - location - 部分即可 - + + + + +