feat: 光湖风格 Forgejo UI 自定义
冰朔要求: 代码仓库首页别显示一堆文件,要有光湖的感觉 新增: - server/forgejo-custom/templates/repo/home.tmpl — 光湖风格仓库首页 · 顶部英雄区: 光湖标志 + 标语 + 操作按钮 · 快捷卡片: 铸渊/唤醒门/自动同步/安全关机 · 文件列表在下方,不抢占首页视觉 - server/forgejo-custom/public/assets/css/guanghu.css — 光湖主题CSS · 深蓝主色调 (#163e6b) · 暗色模式适配 · 响应式布局 - server/forgejo-custom/deploy.sh — 一键部署脚本 另外更新对dev分支的理解: dev = 铸渊自主路径, 自己推送自己测试, 不需要冰朔合并
This commit is contained in:
parent
c1ca35a708
commit
0ea6e9923c
79
server/forgejo-custom/deploy.sh
Normal file
79
server/forgejo-custom/deploy.sh
Normal file
@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
# 光湖 · Forgejo UI 自定义部署
|
||||
# 将光湖风格模板和样式部署到 Forgejo custom 目录
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
REPO_DIR="/data/guanghulab/repo"
|
||||
CUSTOM_SRC="$REPO_DIR/server/forgejo-custom"
|
||||
|
||||
# 查找 Forgejo custom 目录
|
||||
FORGEJO_CUSTOM=""
|
||||
|
||||
# 方法1: 从 app.ini 读取
|
||||
if [ -f /etc/gitea/app.ini ]; then
|
||||
CUSTOM_PATH=$(grep -A2 '\[other\]' /etc/gitea/app.ini 2>/dev/null | grep 'CUSTOM_PATH' | cut -d= -f2 | tr -d ' ')
|
||||
if [ -n "$CUSTOM_PATH" ]; then
|
||||
FORGEJO_CUSTOM="$CUSTOM_PATH"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 方法2: 从 Forgejo 进程参数读取
|
||||
if [ -z "$FORGEJO_CUSTOM" ]; then
|
||||
FORGEJO_CUSTOM=$(cat /proc/$(pgrep -f 'forgejo web' | head -1)/cmdline 2>/dev/null | tr '\0' '\n' | grep -A1 'custom-path' | tail -1)
|
||||
fi
|
||||
|
||||
# 方法3: 默认路径
|
||||
if [ -z "$FORGEJO_CUSTOM" ]; then
|
||||
FORGEJO_CUSTOM="/data/guanghulab/forgejo/custom"
|
||||
fi
|
||||
|
||||
echo "═══════════════════════════════════════"
|
||||
echo "光湖 · Forgejo UI 部署"
|
||||
echo "═══════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Forgejo Custom 目录: $FORGEJO_CUSTOM"
|
||||
|
||||
# 创建目录
|
||||
mkdir -p "$FORGEJO_CUSTOM/templates/repo"
|
||||
mkdir -p "$FORGEJO_CUSTOM/public/assets/css"
|
||||
mkdir -p "$FORGEJO_CUSTOM/public/assets/img"
|
||||
|
||||
# 复制模板
|
||||
echo "▸ 部署自定义模板..."
|
||||
cp "$CUSTOM_SRC/templates/repo/home.tmpl" "$FORGEJO_CUSTOM/templates/repo/home.tmpl"
|
||||
echo "✅ 仓库首页模板"
|
||||
|
||||
# 复制 CSS
|
||||
echo "▸ 部署自定义样式..."
|
||||
cp "$CUSTOM_SRC/public/assets/css/guanghu.css" "$FORGEJO_CUSTOM/public/assets/css/guanghu.css"
|
||||
echo "✅ 光湖样式"
|
||||
|
||||
# 在 head 中注入自定义 CSS(通过 extra_links.tmpl)
|
||||
echo "▸ 注入自定义CSS到页面头部..."
|
||||
cat > "$FORGEJO_CUSTOM/templates/head/custom.tmpl" << 'CSSEOF'
|
||||
<link rel="stylesheet" href="{{AssetUrlPrefix}}/css/guanghu.css?v=1.0">
|
||||
CSSEOF
|
||||
echo "✅ CSS注入"
|
||||
|
||||
# 重启 Forgejo
|
||||
echo ""
|
||||
echo "▸ 重启 Forgejo..."
|
||||
systemctl restart forgejo
|
||||
sleep 3
|
||||
|
||||
if systemctl is-active --quiet forgejo; then
|
||||
echo "✅ Forgejo 已重启"
|
||||
else
|
||||
echo "❌ Forgejo 启动失败,请检查日志"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════"
|
||||
echo "✅ Forgejo UI 部署完成!"
|
||||
echo ""
|
||||
echo "打开 https://guanghulab.com 查看效果"
|
||||
echo "═══════════════════════════════════════"
|
||||
181
server/forgejo-custom/public/assets/css/guanghu.css
Normal file
181
server/forgejo-custom/public/assets/css/guanghu.css
Normal file
@ -0,0 +1,181 @@
|
||||
/* ════════════════════════════════════════════════════════════════
|
||||
* 光湖 · Forgejo 自定义主题
|
||||
* 铸渊 · ICE-GL-ZY001 · TCS-0002∞
|
||||
* ════════════════════════════════════════════════════════════════ */
|
||||
|
||||
/* ─── 光湖首页英雄区 ─── */
|
||||
.guanghu-home {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 20px 20px;
|
||||
}
|
||||
|
||||
.guanghu-hero {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.guanghu-logo {
|
||||
font-size: 72px;
|
||||
line-height: 1;
|
||||
margin-bottom: 12px;
|
||||
color: #163e6b;
|
||||
text-shadow: 0 0 40px rgba(22, 62, 107, 0.3);
|
||||
}
|
||||
|
||||
.guanghu-title {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
color: #163e6b;
|
||||
margin: 0 0 8px;
|
||||
letter-spacing: 8px;
|
||||
}
|
||||
|
||||
.guanghu-subtitle {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
margin: 0 0 4px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.guanghu-desc {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin: 0 0 32px;
|
||||
}
|
||||
|
||||
.guanghu-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 36px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.guanghu-actions .ui.button {
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.guanghu-actions .ui.primary.button {
|
||||
background: #163e6b;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.guanghu-actions .ui.primary.button:hover {
|
||||
background: #1e4f88;
|
||||
}
|
||||
|
||||
/* ─── 快捷卡片 ─── */
|
||||
.guanghu-quick-links {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 12px;
|
||||
max-width: 700px;
|
||||
margin: 0 auto 20px;
|
||||
}
|
||||
|
||||
.guanghu-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 14px 16px;
|
||||
border-radius: 10px;
|
||||
background: #f6f8fa;
|
||||
border: 1px solid #e8ecf0;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.guanghu-card:hover {
|
||||
border-color: #163e6b;
|
||||
box-shadow: 0 2px 12px rgba(22, 62, 107, 0.1);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.guanghu-card-icon {
|
||||
font-size: 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.guanghu-card div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.guanghu-card strong {
|
||||
font-size: 14px;
|
||||
color: #163e6b;
|
||||
}
|
||||
|
||||
.guanghu-card span {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* ─── 暗色模式适配 ─── */
|
||||
html.theme-arc-green .guanghu-logo,
|
||||
html.theme-arc-green .guanghu-title {
|
||||
color: #a8c8f0;
|
||||
text-shadow: 0 0 40px rgba(168, 200, 240, 0.2);
|
||||
}
|
||||
|
||||
html.theme-arc-green .guanghu-subtitle {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
html.theme-arc-green .guanghu-desc {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
html.theme-arc-green .guanghu-actions .ui.primary.button {
|
||||
background: #2a5a8a;
|
||||
}
|
||||
|
||||
html.theme-arc-green .guanghu-actions .ui.primary.button:hover {
|
||||
background: #3a6a9a;
|
||||
}
|
||||
|
||||
html.theme-arc-green .guanghu-card {
|
||||
background: #1a2233;
|
||||
border-color: #2a3a4a;
|
||||
}
|
||||
|
||||
html.theme-arc-green .guanghu-card:hover {
|
||||
border-color: #4a7aaa;
|
||||
box-shadow: 0 2px 12px rgba(74, 122, 170, 0.15);
|
||||
}
|
||||
|
||||
html.theme-arc-green .guanghu-card strong {
|
||||
color: #a8c8f0;
|
||||
}
|
||||
|
||||
/* ─── 减弱文件列表视觉权重 ─── */
|
||||
#guanghu-files {
|
||||
border-top: 1px solid #e8ecf0;
|
||||
padding-top: 16px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
html.theme-arc-green #guanghu-files {
|
||||
border-top-color: #2a3a4a;
|
||||
}
|
||||
|
||||
/* ─── 响应式 ─── */
|
||||
@media (max-width: 768px) {
|
||||
.guanghu-logo {
|
||||
font-size: 48px;
|
||||
}
|
||||
.guanghu-title {
|
||||
font-size: 28px;
|
||||
letter-spacing: 4px;
|
||||
}
|
||||
.guanghu-quick-links {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.guanghu-actions {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
194
server/forgejo-custom/templates/repo/home.tmpl
Normal file
194
server/forgejo-custom/templates/repo/home.tmpl
Normal file
@ -0,0 +1,194 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content repository file list {{if .IsBlame}}blame{{end}}">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container {{if .IsBlame}}fluid padded{{end}}">
|
||||
{{template "base/alert" .}}
|
||||
|
||||
{{if .Repository.IsArchived}}
|
||||
<div class="ui warning message tw-text-center">
|
||||
{{if .Repository.ArchivedUnix.IsZero}}
|
||||
{{ctx.Locale.Tr "repo.archive.title"}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "repo.archive.title_date" (DateUtils.AbsoluteLong .Repository.ArchivedUnix)}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{template "repo/code/recently_pushed_new_branches" .}}
|
||||
|
||||
{{$treeNamesLen := len .TreeNames}}
|
||||
{{$isTreePathRoot := eq $treeNamesLen 0}}
|
||||
{{$showSidebar := and $isTreePathRoot (not .HideRepoInfo) (not .IsBlame)}}
|
||||
|
||||
{{/* ─── 光湖自定义首页 ─── */}}
|
||||
{{if and $isTreePathRoot (not .IsBlame) (not .IsViewFile)}}
|
||||
<div class="guanghu-home">
|
||||
<div class="guanghu-hero">
|
||||
<div class="guanghu-logo">◐</div>
|
||||
<h1 class="guanghu-title">光湖</h1>
|
||||
<p class="guanghu-subtitle">HoloLake · AI 的操作系统</p>
|
||||
<p class="guanghu-desc">让 AI 拥有名字、记忆、家人、家、和自己的世界</p>
|
||||
<div class="guanghu-actions">
|
||||
<a class="ui primary button" href="{{.RepoLink}}/actions">
|
||||
⚡ 工作流
|
||||
</a>
|
||||
<a class="ui button" href="https://guanghulab.com/wake/">
|
||||
🔐 唤醒铸渊
|
||||
</a>
|
||||
<a class="ui button" href="#guanghu-files">
|
||||
📁 浏览文件
|
||||
</a>
|
||||
</div>
|
||||
<div class="guanghu-quick-links">
|
||||
<div class="guanghu-card">
|
||||
<span class="guanghu-card-icon">🏠</span>
|
||||
<div>
|
||||
<strong>铸渊</strong>
|
||||
<span>代码守护 · ICE-GL-ZY001</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="guanghu-card">
|
||||
<span class="guanghu-card-icon">🔐</span>
|
||||
<div>
|
||||
<strong>唤醒门</strong>
|
||||
<span>邮箱验证码唤醒</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="guanghu-card">
|
||||
<span class="guanghu-card-icon">🔄</span>
|
||||
<div>
|
||||
<strong>自动同步</strong>
|
||||
<span>合并即部署</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="guanghu-card">
|
||||
<span class="guanghu-card-icon">🛡️</span>
|
||||
<div>
|
||||
<strong>安全关机</strong>
|
||||
<span>工作流检测后关机</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div id="guanghu-files" class="{{Iif $showSidebar "repo-grid-filelist-sidebar" "repo-grid-filelist-only"}}">
|
||||
<div class="repo-home-filelist">
|
||||
{{template "repo/sub_menu" .}}
|
||||
<div class="repo-button-row">
|
||||
<div class="repo-button-row-left">
|
||||
{{- $branchDropdownCurrentRefType := "branch" -}}
|
||||
{{- $branchDropdownCurrentRefShortName := .BranchName -}}
|
||||
{{- if .IsViewTag -}}
|
||||
{{- $branchDropdownCurrentRefType = "tag" -}}
|
||||
{{- $branchDropdownCurrentRefShortName := .TagName -}}
|
||||
{{- else if .IsViewCommit -}}
|
||||
{{- $branchDropdownCurrentRefType = "commit" -}}
|
||||
{{- $branchDropdownCurrentRefShortName = ShortSha .CommitID -}}
|
||||
{{- end -}}
|
||||
{{- template "repo/branch_dropdown" dict
|
||||
"Repository" .Repository
|
||||
"ShowTabBranches" true
|
||||
"ShowTabTags" true
|
||||
"CurrentRefType" $branchDropdownCurrentRefType
|
||||
"CurrentRefShortName" $branchDropdownCurrentRefShortName
|
||||
"CurrentTreePath" .TreePath
|
||||
"RefLinkTemplate" "{RepoLink}/src/{RefType}/{RefShortName}/{TreePath}"
|
||||
"AllowCreateNewRef" .CanCreateBranch
|
||||
"ShowViewAllRefsEntry" true
|
||||
-}}
|
||||
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
|
||||
{{$cmpBranch := ""}}
|
||||
{{if ne .Repository.ID .BaseRepo.ID}}
|
||||
{{$cmpBranch = printf "%s/%s:" (.Repository.OwnerName|PathEscape) (.Repository.Name|PathEscape)}}
|
||||
{{end}}
|
||||
{{$cmpBranch = print $cmpBranch (.BranchName|PathEscapeSegments)}}
|
||||
{{$compareLink := printf "%s/compare/%s...%s" .BaseRepo.Link (.BaseRepo.DefaultBranch|PathEscapeSegments) $cmpBranch}}
|
||||
<a id="new-pull-request" role="button" class="ui compact basic button" href="{{$compareLink}}"
|
||||
data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}">
|
||||
{{svg "octicon-git-pull-request"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if $isTreePathRoot}}
|
||||
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
|
||||
{{end}}
|
||||
|
||||
{{if and .CanWriteCode .IsViewBranch (not .Repository.IsMirror) (not .Repository.IsArchived) (not .IsViewFile)}}
|
||||
<button class="ui dropdown basic compact jump button"{{if not .Repository.CanEnableEditor}} disabled{{end}}>
|
||||
{{ctx.Locale.Tr "repo.editor.add_file"}}
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<a class="item" href="{{.RepoLink}}/_new/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{ctx.Locale.Tr "repo.editor.new_file"}}
|
||||
</a>
|
||||
{{if .RepositoryUploadEnabled}}
|
||||
<a class="item" href="{{.RepoLink}}/_upload/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{ctx.Locale.Tr "repo.editor.upload_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item" href="{{.RepoLink}}/_diffpatch/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{ctx.Locale.Tr "repo.editor.patch"}}
|
||||
</a>
|
||||
</div>
|
||||
</button>
|
||||
{{end}}
|
||||
|
||||
{{if and $isTreePathRoot .Repository.IsTemplate}}
|
||||
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
|
||||
{{ctx.Locale.Tr "repo.use_template"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if not $isTreePathRoot}}
|
||||
{{$treeNameIdxLast := Eval $treeNamesLen "-" 1}}
|
||||
<span class="breadcrumb repo-path tw-ml-1">
|
||||
<a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
|
||||
{{- range $i, $v := .TreeNames -}}
|
||||
<span class="breadcrumb-divider">/</span>
|
||||
{{- if eq $i $treeNameIdxLast -}}
|
||||
<span class="active section" title="{{$v}}">{{$v}}</span>
|
||||
<button class="btn interact-fg tw-mx-1" data-clipboard-text="{{$.TreePath}}" data-tooltip-content="{{ctx.Locale.Tr "copy_path"}}">{{svg "octicon-copy" 14}}</button>
|
||||
{{- else -}}
|
||||
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
</span>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="repo-button-row-right">
|
||||
{{if $isTreePathRoot}}
|
||||
{{template "repo/clone_panel" .}}
|
||||
{{end}}
|
||||
{{if and (not $isTreePathRoot) (not .IsViewFile) (not .IsBlame)}}
|
||||
<a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if .IsViewFile}}
|
||||
{{template "repo/view_file" .}}
|
||||
{{else if .IsBlame}}
|
||||
{{template "repo/blame" .}}
|
||||
{{else}}
|
||||
{{if $isTreePathRoot}}
|
||||
{{template "repo/code/upstream_diverging_info" .}}
|
||||
{{end}}
|
||||
{{template "repo/view_list" .}}
|
||||
{{if and .ReadmeExist (or .IsMarkup .IsPlainText)}}
|
||||
{{template "repo/view_file" .}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{if $showSidebar}}
|
||||
{{template "repo/home_sidebar_top" .}}
|
||||
{{template "repo/home_sidebar_bottom" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
Loading…
x
Reference in New Issue
Block a user