From 980b3674b02a7f009dfb42bffa8e530916c63f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Fri, 16 Jan 2026 23:42:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E7=BC=96=E6=8E=92=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/data/template.go | 6 ++++++ internal/service/template.go | 10 +++++++++- pkg/api/template.go | 14 ++++++++++++++ web/src/api/panel/template/index.ts | 3 ++- web/src/views/app/TemplateDeployModal.vue | 2 +- web/src/views/app/TemplateView.vue | 16 +++++----------- web/src/views/project/ListView.vue | 15 ++++++++++++++- 7 files changed, 51 insertions(+), 15 deletions(-) diff --git a/internal/data/template.go b/internal/data/template.go index 83a05418..d4ce3126 100644 --- a/internal/data/template.go +++ b/internal/data/template.go @@ -67,6 +67,12 @@ func (r *templateRepo) Callback(slug string) error { // CreateCompose 创建编排 func (r *templateRepo) CreateCompose(name, compose string, envs []types.KV, autoFirewall bool) (string, error) { dir := filepath.Join(app.Root, "compose", name) + + // 检查编排是否已存在 + if _, err := os.Stat(dir); err == nil { + return "", errors.New(r.t.Get("compose %s already exists", name)) + } + if err := os.MkdirAll(dir, 0755); err != nil { return "", err } diff --git a/internal/service/template.go b/internal/service/template.go index dedf72eb..cf2496b8 100644 --- a/internal/service/template.go +++ b/internal/service/template.go @@ -26,7 +26,15 @@ func NewTemplateService(t *gotext.Locale, template biz.TemplateRepo, setting biz // List 获取所有模版 func (s *TemplateService) List(w http.ResponseWriter, r *http.Request) { - paged, total := Paginate(r, s.templateRepo.List()) + category := r.URL.Query().Get("category") + templates := s.templateRepo.List() + + // 按分类过滤 + if category != "" { + templates = templates.FilterByCategory(category) + } + + paged, total := Paginate(r, templates) Success(w, chix.M{ "total": total, "items": paged, diff --git a/pkg/api/template.go b/pkg/api/template.go index 70ca7a3b..ad5eaba9 100644 --- a/pkg/api/template.go +++ b/pkg/api/template.go @@ -27,6 +27,20 @@ type Template struct { type Templates []*Template +// FilterByCategory 按分类过滤模版 +func (t Templates) FilterByCategory(category string) Templates { + filtered := make(Templates, 0) + for _, tpl := range t { + for _, cat := range tpl.Categories { + if cat == category { + filtered = append(filtered, tpl) + break + } + } + } + return filtered +} + // Templates 返回所有模版 func (r *API) Templates() (*Templates, error) { resp, err := r.client.R().SetResult(&Response{}).Get("/templates") diff --git a/web/src/api/panel/template/index.ts b/web/src/api/panel/template/index.ts index 77d0856a..ae3f74d9 100644 --- a/web/src/api/panel/template/index.ts +++ b/web/src/api/panel/template/index.ts @@ -2,7 +2,8 @@ import { http } from '@/utils' export default { // 获取模版列表 - list: (page: number, pageSize: number): any => http.Get(`/template?page=${page}&limit=${pageSize}`), + list: (page: number, pageSize: number, category?: string): any => + http.Get(`/template`, { params: { page, limit: pageSize, category } }), // 获取模版详情 get: (slug: string): any => http.Get(`/template/${slug}`), // 使用模版创建编排 diff --git a/web/src/views/app/TemplateDeployModal.vue b/web/src/views/app/TemplateDeployModal.vue index e45e7072..48fa0ecf 100644 --- a/web/src/views/app/TemplateDeployModal.vue +++ b/web/src/views/app/TemplateDeployModal.vue @@ -262,7 +262,7 @@ const handlePrev = () => { } const resetForm = () => { - deployModel.name = '' + deployModel.name = props.template?.slug || '' deployModel.autoStart = true deployModel.autoFirewall = false deployModel.envs = {} diff --git a/web/src/views/app/TemplateView.vue b/web/src/views/app/TemplateView.vue index 14b36e64..832ec7fc 100644 --- a/web/src/views/app/TemplateView.vue +++ b/web/src/views/app/TemplateView.vue @@ -25,7 +25,7 @@ const deployModalShow = ref(false) const selectedTemplate = ref