From 7a5eb3210c245335772ec514e6794fe516d46ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Wed, 7 Jan 2026 03:35:21 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/environment.go | 1 + internal/biz/setting.go | 2 +- internal/data/app.go | 6 +-- internal/data/environment.go | 64 +++++++++++++++++++-------- internal/data/website.go | 6 +-- internal/service/environment.go | 14 +++--- pkg/types/environment.go | 14 +++--- web/src/views/app/EnvironmentView.vue | 10 +++-- web/src/views/app/VersionModal.vue | 21 +++++++-- 9 files changed, 94 insertions(+), 44 deletions(-) diff --git a/internal/biz/environment.go b/internal/biz/environment.go index 59de0d5b..388edd29 100644 --- a/internal/biz/environment.go +++ b/internal/biz/environment.go @@ -9,6 +9,7 @@ type EnvironmentRepo interface { Types() []types.LV All(typ ...string) api.Environments IsInstalled(typ, slug string) bool + InstalledVersion(typ, slug string) string HasUpdate(typ, slug string) bool Install(typ, slug string) error Uninstall(typ, slug string) error diff --git a/internal/biz/setting.go b/internal/biz/setting.go index 910e4be6..9458b525 100644 --- a/internal/biz/setting.go +++ b/internal/biz/setting.go @@ -19,7 +19,7 @@ const ( SettingKeyMySQLRootPassword SettingKey = "mysql_root_password" SettingKeyOfflineMode SettingKey = "offline_mode" SettingKeyAutoUpdate SettingKey = "auto_update" - SettingKeyWebServer SettingKey = "web_server" + SettingKeyWebserver SettingKey = "webserver" ) type Setting struct { diff --git a/internal/data/app.go b/internal/data/app.go index 1c73c565..0ca5f98f 100644 --- a/internal/data/app.go +++ b/internal/data/app.go @@ -201,7 +201,7 @@ func (r *appRepo) Install(channel, slug string) error { if vs.GreaterThan(panel) && !r.conf.App.Debug { return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version)) } - shellUrl = ch.Install + shellUrl = fmt.Sprintf("https://%s%s", r.conf.App.DownloadEndpoint, ch.Install) shellChannel = ch.Slug shellVersion = ch.Version break @@ -261,7 +261,7 @@ func (r *appRepo) UnInstall(slug string) error { if vs.GreaterThan(panel) && !r.conf.App.Debug { return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version)) } - shellUrl = ch.Uninstall + shellUrl = fmt.Sprintf("https://%s%s", r.conf.App.DownloadEndpoint, ch.Uninstall) shellChannel = ch.Slug shellVersion = installed.Version break @@ -316,7 +316,7 @@ func (r *appRepo) Update(slug string) error { if vs.GreaterThan(panel) && !r.conf.App.Debug { return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version)) } - shellUrl = ch.Update + shellUrl = fmt.Sprintf("https://%s%s", r.conf.App.DownloadEndpoint, ch.Update) shellChannel = ch.Slug shellVersion = ch.Version break diff --git a/internal/data/environment.go b/internal/data/environment.go index 8ac4c1b3..7534bda4 100644 --- a/internal/data/environment.go +++ b/internal/data/environment.go @@ -2,6 +2,7 @@ package data import ( "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -69,43 +70,70 @@ func (r *environmentRepo) GetByTypeAndSlug(typ, slug string) *api.Environment { func (r *environmentRepo) IsInstalled(typ, slug string) bool { path := filepath.Join(app.Root, "server", typ, slug) - exist, _ := os.Stat(path) - return exist != nil && exist.IsDir() + var binFile string + switch typ { + case "php": + binFile = filepath.Join(path, "bin", "php") + default: + return false + } + + _, err := os.Stat(binFile) + return err == nil +} + +func (r *environmentRepo) InstalledVersion(typ, slug string) string { + if !r.IsInstalled(typ, slug) { + return "" + } + + var basePath = filepath.Join(app.Root, "server", typ, slug) + + switch typ { + case "php": + version, err := shell.Exec(filepath.Join(basePath, "bin", "php") + " -v | head -n 1 | awk '{print $2}'") + if err != nil { + return "" + } + return version + default: + return "" + } } func (r *environmentRepo) HasUpdate(typ, slug string) bool { if !r.IsInstalled(typ, slug) { return false } - - var basePath = filepath.Join(app.Root, "server", typ, slug) env := r.GetByTypeAndSlug(typ, slug) if env == nil { return false } - mainlineVersion := env.Version - switch typ { - case "php": - installedVersion, err := shell.Exec(filepath.Join(basePath, "bin", "php") + " -v | head -n 1 | awk '{print $2}'") - if err != nil { - return false - } - return installedVersion != mainlineVersion - default: - return false - } + mainlineVersion := env.Version + installedVersion := r.InstalledVersion(typ, slug) + + return mainlineVersion != installedVersion && mainlineVersion != "" && installedVersion != "" } func (r *environmentRepo) Install(typ, slug string) error { + if installed := r.IsInstalled(typ, slug); installed { + return errors.New(r.t.Get("environment %s-%s already installed", typ, slug)) + } return r.do(typ, slug, "install") } func (r *environmentRepo) Uninstall(typ, slug string) error { + if installed := r.IsInstalled(typ, slug); !installed { + return errors.New(r.t.Get("environment %s-%s not installed", typ, slug)) + } return r.do(typ, slug, "uninstall") } func (r *environmentRepo) Update(typ, slug string) error { + if installed := r.IsInstalled(typ, slug); !installed { + return errors.New(r.t.Get("environment %s-%s not installed", typ, slug)) + } return r.do(typ, slug, "update") } @@ -118,7 +146,7 @@ func (r *environmentRepo) do(typ, slug, action string) error { shellUrl := fmt.Sprintf("https://%s/%s/%s.sh", r.conf.App.DownloadEndpoint, typ, action) if app.IsCli { - return shell.ExecfWithOutput(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s"`, shellUrl, slug) + return shell.ExecfWithOutput(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s" "%s"`, shellUrl, env.Slug, env.Version) } var name string @@ -134,8 +162,8 @@ func (r *environmentRepo) do(typ, slug, action string) error { task := new(biz.Task) task.Name = name task.Status = biz.TaskStatusWaiting - task.Shell = fmt.Sprintf(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s" >> /tmp/%s-%s.log 2>&1`, shellUrl, slug, typ, slug) - task.Log = fmt.Sprintf("/tmp/%s-%s.log", typ, slug) + task.Shell = fmt.Sprintf(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s" "%s" >> /tmp/%s-%s.log 2>&1`, shellUrl, env.Slug, env.Version, env.Type, env.Slug) + task.Log = fmt.Sprintf("/tmp/%s-%s.log", env.Type, env.Slug) return r.task.Push(task) } diff --git a/internal/data/website.go b/internal/data/website.go index 437d249b..12feda48 100644 --- a/internal/data/website.go +++ b/internal/data/website.go @@ -768,7 +768,7 @@ func (r *websiteRepo) ObtainCert(ctx context.Context, id uint) error { } func (r *websiteRepo) getVhost(website *biz.Website) (webservertypes.Vhost, error) { - webServer, err := r.setting.Get(biz.SettingKeyWebServer) + webServer, err := r.setting.Get(biz.SettingKeyWebserver) if err != nil { return nil, err } @@ -800,7 +800,7 @@ func (r *websiteRepo) getPHPVersion(name string) uint { } func (r *websiteRepo) reloadWebServer() error { - webServer, err := r.setting.Get(biz.SettingKeyWebServer) + webServer, err := r.setting.Get(biz.SettingKeyWebserver, "unknown") if err != nil { return err } @@ -816,5 +816,5 @@ func (r *websiteRepo) reloadWebServer() error { return err } } - return nil + return errors.New(r.t.Get("unsupported web server: %s", webServer)) } diff --git a/internal/service/environment.go b/internal/service/environment.go index 6b0de53c..a21fc0c6 100644 --- a/internal/service/environment.go +++ b/internal/service/environment.go @@ -38,12 +38,14 @@ func (s *EnvironmentService) List(w http.ResponseWriter, r *http.Request) { continue } environments = append(environments, types.EnvironmentDetail{ - Type: item.Type, - Name: item.Name, - Description: item.Description, - Slug: item.Slug, - Installed: s.environmentRepo.IsInstalled(item.Type, item.Slug), - HasUpdate: s.environmentRepo.HasUpdate(item.Type, item.Slug), + Type: item.Type, + Name: item.Name, + Description: item.Description, + Slug: item.Slug, + Version: item.Version, + InstalledVersion: s.environmentRepo.InstalledVersion(item.Type, item.Slug), + Installed: s.environmentRepo.IsInstalled(item.Type, item.Slug), + HasUpdate: s.environmentRepo.HasUpdate(item.Type, item.Slug), }) } diff --git a/pkg/types/environment.go b/pkg/types/environment.go index 8352629b..b511782b 100644 --- a/pkg/types/environment.go +++ b/pkg/types/environment.go @@ -2,10 +2,12 @@ package types // EnvironmentDetail 环境详情 type EnvironmentDetail struct { - Type string `json:"type"` - Name string `json:"name"` - Description string `json:"description"` - Slug string `json:"slug"` - Installed bool `json:"installed"` - HasUpdate bool `json:"has_update"` + Type string `json:"type"` + Name string `json:"name"` + Description string `json:"description"` + Slug string `json:"slug"` + Version string `json:"version"` + InstalledVersion string `json:"installed_version"` + Installed bool `json:"installed"` + HasUpdate bool `json:"has_update"` } diff --git a/web/src/views/app/EnvironmentView.vue b/web/src/views/app/EnvironmentView.vue index aa3d5aed..2c40c8f2 100644 --- a/web/src/views/app/EnvironmentView.vue +++ b/web/src/views/app/EnvironmentView.vue @@ -6,10 +6,8 @@ import { useGettext } from 'vue3-gettext' const { $gettext } = useGettext() -// 当前选中的类型(默认为全部) const selectedType = ref('') -// 环境类型列表 const { data: types } = useRequest(environment.types, { initialData: [] }) @@ -36,6 +34,12 @@ const columns: any = [ minWidth: 300, ellipsis: { tooltip: true } }, + { + title: $gettext('Latest Version'), + key: 'version', + width: 160, + ellipsis: { tooltip: true } + }, { title: $gettext('Installed Version'), key: 'installed_version', @@ -45,7 +49,7 @@ const columns: any = [ { title: $gettext('Actions'), key: 'actions', - width: 350, + width: 240, hideInExcel: true, render(row: any) { return h(NFlex, null, { diff --git a/web/src/views/app/VersionModal.vue b/web/src/views/app/VersionModal.vue index 352e635c..dd6dcd85 100644 --- a/web/src/views/app/VersionModal.vue +++ b/web/src/views/app/VersionModal.vue @@ -13,7 +13,8 @@ const doSubmit = ref(false) const model = ref({ channel: null, - version: '' + version: '', + log: '' }) const options = computed(() => { @@ -37,7 +38,8 @@ const handleSubmit = () => { show.value = false model.value = { channel: null, - version: '' + version: '', + log: '' } }) } @@ -46,6 +48,7 @@ const handleChannelUpdate = (value: string) => { const channel = info.value.channels.find((channel) => channel.slug === value) if (channel) { model.value.version = channel.version + model.value.log = channel.log } } @@ -53,7 +56,8 @@ const handleClose = () => { show.value = false model.value = { channel: null, - version: '' + version: '', + log: '' } } @@ -86,6 +90,15 @@ const handleClose = () => { disabled /> + + + +
{{
+              model.log
+            }}
+
+
+
{ :disabled="model.channel == null || doSubmit" @click="handleSubmit" > - {{ $gettext('Submit') }} + {{ operation }}