2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 06:47:20 +08:00

fix: 优化容器模版

This commit is contained in:
2026-01-14 03:15:48 +08:00
parent f745e33d98
commit d29e3d4d87
10 changed files with 83 additions and 64 deletions

View File

@@ -128,7 +128,7 @@ func initWeb() (*app.Web, error) {
toolboxLogService := service.NewToolboxLogService(locale, db, containerImageRepo, settingRepo)
webHookRepo := data.NewWebHookRepo(locale, db, logger)
webHookService := service.NewWebHookService(webHookRepo)
templateRepo := data.NewTemplateRepo()
templateRepo := data.NewTemplateRepo(locale, cacheRepo)
templateService := service.NewTemplateService(locale, templateRepo, settingRepo)
apacheApp := apache.NewApp(locale)
codeserverApp := codeserver.NewApp()

View File

@@ -8,6 +8,7 @@ const (
CacheKeyCategories CacheKey = "categories"
CacheKeyApps CacheKey = "apps"
CacheKeyEnvironment CacheKey = "environment"
CacheKeyTemplates CacheKey = "templates"
CacheKeyRewrites CacheKey = "rewrites"
)
@@ -24,5 +25,6 @@ type CacheRepo interface {
UpdateCategories() error
UpdateApps() error
UpdateEnvironments() error
UpdateTemplates() error
UpdateRewrites() error
}

View File

@@ -6,7 +6,7 @@ import (
)
type TemplateRepo interface {
List() (api.Templates, error)
List() api.Templates
Get(slug string) (*api.Template, error)
Callback(slug string) error
CreateCompose(name, compose string, envs []types.KV, autoFirewall bool) error

View File

@@ -97,6 +97,20 @@ func (r *cacheRepo) UpdateEnvironments() error {
return r.Set(biz.CacheKeyEnvironment, string(encoded))
}
func (r *cacheRepo) UpdateTemplates() error {
templates, err := r.api.Templates()
if err != nil {
return err
}
encoded, err := json.Marshal(templates)
if err != nil {
return err
}
return r.Set(biz.CacheKeyTemplates, string(encoded))
}
func (r *cacheRepo) UpdateRewrites() error {
rewrites, err := r.api.RewritesByType("nginx")
if err != nil {

View File

@@ -1,6 +1,7 @@
package data
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
@@ -12,43 +13,50 @@ import (
"github.com/acepanel/panel/pkg/api"
"github.com/acepanel/panel/pkg/firewall"
"github.com/acepanel/panel/pkg/types"
"github.com/leonelquinteros/gotext"
)
type templateRepo struct {
t *gotext.Locale
cache biz.CacheRepo
api *api.API
firewall *firewall.Firewall
}
func NewTemplateRepo() biz.TemplateRepo {
func NewTemplateRepo(t *gotext.Locale, cache biz.CacheRepo) biz.TemplateRepo {
return &templateRepo{
t: t,
cache: cache,
api: api.NewAPI(app.Version, app.Locale),
firewall: firewall.NewFirewall(),
}
}
// List 获取所有模版
func (r *templateRepo) List() (api.Templates, error) {
templates, err := r.api.Templates()
func (r *templateRepo) List() api.Templates {
cached, err := r.cache.Get(biz.CacheKeyTemplates)
if err != nil {
return nil, err
return nil
}
return *templates, nil
templates := make(api.Templates, 0)
if err = json.Unmarshal([]byte(cached), &templates); err != nil {
return nil
}
return templates
}
// Get 获取模版详情
func (r *templateRepo) Get(slug string) (*api.Template, error) {
templates, err := r.api.Templates()
if err != nil {
return nil, err
}
templates := r.List()
for _, t := range *templates {
for _, t := range templates {
if t.Slug == slug {
return t, nil
}
}
return nil, fmt.Errorf("template %s not found", slug)
return nil, fmt.Errorf(r.t.Get("template %s not found", slug))
}
// Callback 模版下载回调

View File

@@ -219,6 +219,10 @@ func (s *AppService) UpdateCache(w http.ResponseWriter, r *http.Request) {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
if err := s.cacheRepo.UpdateTemplates(); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
Success(w, nil)
}

View File

@@ -127,6 +127,9 @@ func (s *CliService) Sync(ctx context.Context, cmd *cli.Command) error {
if err := s.cacheRepo.UpdateEnvironments(); err != nil {
return errors.New(s.t.Get("Failed to synchronize app data: %v", err))
}
if err := s.cacheRepo.UpdateTemplates(); err != nil {
return errors.New(s.t.Get("Failed to synchronize app data: %v", err))
}
if err := s.cacheRepo.UpdateRewrites(); err != nil {
return errors.New(s.t.Get("Failed to synchronize rewrite rules: %v", err))
}

View File

@@ -30,13 +30,7 @@ func (s *TemplateService) List(w http.ResponseWriter, r *http.Request) {
return
}
templates, err := s.templateRepo.List()
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
Success(w, templates)
Success(w, s.templateRepo.List())
}
// Get 获取模版详情
@@ -47,11 +41,6 @@ func (s *TemplateService) Get(w http.ResponseWriter, r *http.Request) {
return
}
if offline, _ := s.settingRepo.GetBool(biz.SettingKeyOfflineMode); offline {
Error(w, http.StatusForbidden, s.t.Get("Unable to get template in offline mode"))
return
}
template, err := s.templateRepo.Get(req.Slug)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
@@ -69,11 +58,6 @@ func (s *TemplateService) Create(w http.ResponseWriter, r *http.Request) {
return
}
if offline, _ := s.settingRepo.GetBool(biz.SettingKeyOfflineMode); offline {
Error(w, http.StatusForbidden, s.t.Get("Unable to create compose from template in offline mode"))
return
}
// 获取模版
template, err := s.templateRepo.Get(req.Slug)
if err != nil {

View File

@@ -61,34 +61,35 @@ const handleSubmit = async () => {
doSubmit.value = true
try {
// 构建环境变量数组
const envs = Object.entries(deployModel.envs).map(([key, value]) => ({
key,
value: String(value)
}))
// 构建环境变量数组
const envs = Object.entries(deployModel.envs).map(([key, value]) => ({
key,
value: String(value)
}))
// 创建 compose
await templateApi.create({
// 创建 compose
useRequest(
templateApi.create({
slug: props.template.slug,
name: deployModel.name,
envs,
auto_firewall: deployModel.autoFirewall
})
window.$message.success($gettext('Created successfully'))
if (deployModel.autoStart) {
// 自动启动
upCommand.value = `docker compose -f /opt/ace/server/compose/${deployModel.name}/docker-compose.yml up -d`
upModal.value = true
} else {
show.value = false
emit('success')
}
} finally {
doSubmit.value = false
}
)
.onSuccess(() => {
window.$message.success($gettext('Created successfully'))
if (deployModel.autoStart) {
// 自动启动
upCommand.value = `docker compose -f /opt/ace/server/compose/${deployModel.name}/docker-compose.yml up -d`
upModal.value = true
} else {
show.value = false
emit('success')
}
})
.onComplete(() => {
doSubmit.value = false
})
}
// 启动完成
@@ -180,6 +181,7 @@ watch(
v-for="env in template.environments"
:key="env.name"
:label="env.description"
:required="env.default == ''"
>
<!-- Select 类型 -->
<n-select

View File

@@ -2,6 +2,7 @@
import { NButton, NCard, NEllipsis, NFlex, NGrid, NGridItem, NSpin, NTag } from 'naive-ui'
import { useGettext } from 'vue3-gettext'
import app from '@/api/panel/app'
import template from '@/api/panel/template'
import TemplateDeployModal from './TemplateDeployModal.vue'
import type { Template } from './types'
@@ -17,12 +18,8 @@ const { loading, data, refresh } = usePagination(template.list, {
})
// 获取所有分类
const categories = computed(() => {
const cats = new Set<string>()
data.value?.forEach((t: Template) => {
t.categories?.forEach((c) => cats.add(c))
})
return Array.from(cats)
const { data: categories } = useRequest(app.categories, {
initialData: []
})
// 过滤后的模版列表
@@ -33,6 +30,11 @@ const filteredTemplates = computed(() => {
return (data.value || []).filter((t: Template) => t.categories?.includes(selectedCategory.value))
})
const getCategoryLabel = (catValue: string) => {
const cat = categories.value.find((c: any) => c.value === catValue)
return cat ? cat.label : catValue
}
const handleCategoryChange = (category: string) => {
selectedCategory.value = category
}
@@ -60,13 +62,13 @@ onMounted(() => {
</n-tag>
<n-tag
v-for="cat in categories"
:key="cat"
:type="selectedCategory === cat ? 'primary' : 'default'"
:bordered="selectedCategory !== cat"
:key="cat.value"
:type="selectedCategory === cat.value ? 'primary' : 'default'"
:bordered="selectedCategory !== cat.value"
style="cursor: pointer"
@click="handleCategoryChange(cat)"
@click="handleCategoryChange(cat.value)"
>
{{ cat }}
{{ cat.label }}
</n-tag>
</n-flex>
@@ -84,7 +86,7 @@ onMounted(() => {
</n-ellipsis>
<n-flex :size="4" style="margin-top: auto">
<n-tag v-for="cat in tpl.categories" :key="cat" size="small">
{{ cat }}
{{ getCategoryLabel(cat) }}
</n-tag>
</n-flex>
</n-flex>