!82 feat: 自定义logo功能
* !1 fixed-bug:更正操作结果提示信息与操作页面不一致,更改为都在/admin/config/settings 页面上 * fixed-bug:更正操作结果提示信息与操作页面不一致,更改为都在/admin/config/settings 页面上 * refactor(admin): 移动自定义logo上传表单位置 * style: 还原管理后台仪表盘模板代码格式 * style: 调整注释格式和规范国际化语言文件的标签文本 * style: 还原管理后台仪表盘模板代码格式 * feat: 添加单个设置的获取和设置函数 * feat: 自定义logo功能
This commit is contained in:
repo.diff.committed_by
孟宁
repo.diff.parent
aa01ae3e39
repo.diff.commit
8b77dbb369
@@ -99,6 +99,21 @@ func SetSettings(ctx context.Context, settings map[string]string) error {
|
||||
})
|
||||
}
|
||||
|
||||
func SetSetting(ctx context.Context, key, value string) error {
|
||||
return SetSettings(ctx, map[string]string{key: value})
|
||||
}
|
||||
|
||||
func GetSetting(ctx context.Context, key string) (string, error) {
|
||||
setting, exist, err := db.Get[Setting](ctx, builder.Eq{"setting_key": key})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !exist {
|
||||
return "", nil
|
||||
}
|
||||
return setting.SettingValue, nil
|
||||
}
|
||||
|
||||
type dbConfigCachedGetter struct {
|
||||
mu sync.RWMutex
|
||||
|
||||
|
||||
@@ -2885,6 +2885,9 @@ dashboard.delete_missing_repos.started = Delete all repositories missing their G
|
||||
dashboard.delete_generated_repository_avatars = Delete generated repository avatars
|
||||
dashboard.sync_repo_branches = Sync missed branches from git data to databases
|
||||
dashboard.sync_repo_tags = Sync tags from git data to database
|
||||
dashboard.app_logo_config = Application Logo Configuration
|
||||
dashboard.choose_new_logo = Choose New Logo
|
||||
dashboard.update_logo = Update Logo
|
||||
dashboard.update_mirrors = Update Mirrors
|
||||
dashboard.repo_health_check = Health check all repositories
|
||||
dashboard.check_repo_stats = Check all repository statistics
|
||||
|
||||
@@ -2880,6 +2880,9 @@ dashboard.delete_missing_repos.started=删除所有丢失 Git 文件的仓库任
|
||||
dashboard.delete_generated_repository_avatars=删除生成的仓库头像
|
||||
dashboard.sync_repo_branches=将缺少的分支从 git 数据同步到数据库
|
||||
dashboard.sync_repo_tags=从 git 数据同步标签到数据库
|
||||
dashboard.app_logo_config = 应用图标设置
|
||||
dashboard.choose_new_logo = 选择新的图标
|
||||
dashboard.update_logo = 更新图标
|
||||
dashboard.update_mirrors=更新镜像仓库
|
||||
dashboard.repo_health_check=健康检查所有仓库
|
||||
dashboard.check_repo_stats=检查所有仓库统计
|
||||
|
||||
@@ -6,14 +6,19 @@ package admin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
system_model "code.gitea.io/gitea/models/system"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
@@ -277,3 +282,46 @@ func MonitorStats(ctx *context.Context) {
|
||||
ctx.Data["StatsCounter"] = statsCounter
|
||||
ctx.HTML(http.StatusOK, tplStats)
|
||||
}
|
||||
|
||||
func LogoPost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.AvatarForm)
|
||||
if form.Avatar == nil || form.Avatar.Filename == "" {
|
||||
ctx.Flash.Error("No file uploaded")
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/config/settings")
|
||||
return
|
||||
}
|
||||
|
||||
ext := filepath.Ext(form.Avatar.Filename)
|
||||
if ext != ".png" && ext != ".jpg" && ext != ".jpeg" && ext != ".gif" && ext != ".webp" {
|
||||
ctx.Flash.Error("Invalid file type")
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/config/settings")
|
||||
return
|
||||
}
|
||||
|
||||
// 生成唯一文件名
|
||||
filename := "logo_" + strconv.FormatInt(time.Now().Unix(), 10) + ext
|
||||
savePath := filepath.Join(setting.CustomPath, "public", "assets", "img", filename)
|
||||
os.MkdirAll(filepath.Dir(savePath), os.ModePerm)
|
||||
out, err := os.Create(savePath)
|
||||
if err != nil {
|
||||
ctx.Flash.Error("Failed to save file")
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/config/settings")
|
||||
return
|
||||
}
|
||||
defer out.Close()
|
||||
fr, _ := form.Avatar.Open()
|
||||
defer fr.Close()
|
||||
io.Copy(out, fr)
|
||||
|
||||
// 保存路径到数据库
|
||||
relPath := "/assets/img/" + filename
|
||||
err = system_model.SetSetting(ctx, "custom_logo_path", relPath)
|
||||
if err != nil {
|
||||
ctx.Flash.Error("Failed to update database")
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/config/settings")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success("Logo updated successfully")
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/config/settings")
|
||||
}
|
||||
|
||||
@@ -733,6 +733,7 @@ func registerRoutes(m *web.Router) {
|
||||
m.Get("", admin.Dashboard)
|
||||
m.Get("/system_status", admin.SystemStatus)
|
||||
m.Post("", web.Bind(forms.AdminDashboardForm{}), admin.DashboardPost)
|
||||
m.Post("/logo", web.Bind(forms.AvatarForm{}), admin.LogoPost)
|
||||
|
||||
m.Get("/self_check", admin.SelfCheck)
|
||||
m.Post("/self_check", admin.SelfCheckPost)
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
system_model "code.gitea.io/gitea/models/system"
|
||||
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/httpcache"
|
||||
@@ -220,6 +222,13 @@ func Contexter() func(next http.Handler) http.Handler {
|
||||
ctx.Data["ManifestData"] = setting.ManifestData
|
||||
ctx.Data["AllLangs"] = translation.AllLangs()
|
||||
|
||||
// 保存logo路径到模板数据
|
||||
if logoPath, _ := system_model.GetSetting(ctx, "custom_logo_path"); logoPath != "" {
|
||||
ctx.Data["CustomLogoPath"] = logoPath
|
||||
} else {
|
||||
ctx.Data["CustomLogoPath"] = ""
|
||||
}
|
||||
|
||||
next.ServeHTTP(ctx.Resp, ctx.Req)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,36 @@
|
||||
{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin config")}}
|
||||
<!-- 自定义logo upload -->
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "admin.dashboard.app_logo_config"}}
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<form
|
||||
class="ui form"
|
||||
action="{{ AppSubUrl }}/admin/logo"
|
||||
method="post"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="inline field tw-pl-4">
|
||||
<label
|
||||
for="avatar"
|
||||
>{{ctx.Locale.Tr "admin.dashboard.choose_new_logo"}}</label
|
||||
>
|
||||
<input
|
||||
name="avatar"
|
||||
type="file"
|
||||
accept="image/png,image/jpeg,image/gif,image/webp"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<button class="ui primary button">
|
||||
{{ctx.Locale.Tr "admin.dashboard.update_logo"}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "admin.config.picture_config"}}
|
||||
</h4>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="navbar-left">
|
||||
<!-- the logo -->
|
||||
<a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}">
|
||||
<img width="auto" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true">
|
||||
<img width="auto" height="30" src="{{if .CustomLogoPath}}{{.CustomLogoPath}}{{else}}{{AssetUrlPrefix}}/img/logo.svg{{end}}" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true">
|
||||
</a>
|
||||
|
||||
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
|
||||
|
||||
Reference in New Issue
Block a user