Skip to content

Commit 94419f4

Browse files
committed
fix: 直接访问或刷新页面时浏览器标签页显示自定义站点名称
后端 HTML 注入时同步替换 <title> 标签为自定义站点名称, 前端 fetchPublicSettings 完成后重新设置 document.title, 解决路由守卫先于设置加载导致标题回退为默认值的时序问题。
1 parent 045cba7 commit 94419f4

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

backend/internal/web/embed_on.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,37 @@ func (s *FrontendServer) injectSettings(settingsJSON []byte) []byte {
180180

181181
// Inject before </head>
182182
headClose := []byte("</head>")
183-
return bytes.Replace(s.baseHTML, headClose, append(script, headClose...), 1)
183+
result := bytes.Replace(s.baseHTML, headClose, append(script, headClose...), 1)
184+
185+
// Replace <title> with custom site name so the browser tab shows it immediately
186+
result = injectSiteTitle(result, settingsJSON)
187+
188+
return result
189+
}
190+
191+
// injectSiteTitle replaces the static <title> in HTML with the configured site name.
192+
// This ensures the browser tab shows the correct title before JS executes.
193+
func injectSiteTitle(html, settingsJSON []byte) []byte {
194+
var cfg struct {
195+
SiteName string `json:"site_name"`
196+
}
197+
if err := json.Unmarshal(settingsJSON, &cfg); err != nil || cfg.SiteName == "" {
198+
return html
199+
}
200+
201+
// Find and replace the existing <title>...</title>
202+
titleStart := bytes.Index(html, []byte("<title>"))
203+
titleEnd := bytes.Index(html, []byte("</title>"))
204+
if titleStart == -1 || titleEnd == -1 || titleEnd <= titleStart {
205+
return html
206+
}
207+
208+
newTitle := []byte("<title>" + cfg.SiteName + " - AI API Gateway</title>")
209+
var buf bytes.Buffer
210+
buf.Write(html[:titleStart])
211+
buf.Write(newTitle)
212+
buf.Write(html[titleEnd+len("</title>"):])
213+
return buf.Bytes()
184214
}
185215

186216
// replaceNoncePlaceholder replaces the nonce placeholder with actual nonce value

frontend/src/App.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { RouterView, useRouter, useRoute } from 'vue-router'
33
import { onMounted, onBeforeUnmount, watch } from 'vue'
44
import Toast from '@/components/common/Toast.vue'
55
import NavigationProgress from '@/components/common/NavigationProgress.vue'
6+
import { resolveDocumentTitle } from '@/router/title'
67
import AnnouncementPopup from '@/components/common/AnnouncementPopup.vue'
78
import { useAppStore, useAuthStore, useSubscriptionStore, useAnnouncementStore } from '@/stores'
89
import { getSetupStatus } from '@/api/setup'
@@ -104,6 +105,9 @@ onMounted(async () => {
104105
105106
// Load public settings into appStore (will be cached for other components)
106107
await appStore.fetchPublicSettings()
108+
109+
// Re-resolve document title now that siteName is available
110+
document.title = resolveDocumentTitle(route.meta.title, appStore.siteName, route.meta.titleKey as string)
107111
})
108112
</script>
109113

0 commit comments

Comments
 (0)