refactor: implementation of browser tab title (#5794)

#### What type of PR is this?

/area ui
/kind improvement
/milestone 2.15.x

#### What this PR does / why we need it:

重构 Console 和 UC 的浏览器标题切换。

1. 将代码逻辑封装为统一的 Hook。
2. 移除 index.html 默认的标题,防止加载中的时候显示不正确。

#### Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/5752

#### Special notes for your reviewer:

测试各个页面的标题显示正常即可。

#### Does this PR introduce a user-facing change?

```release-note
重构 Console 和 UC 的浏览器标题切换。
```
pull/5796/head^2
Ryan Wang 2024-04-25 11:43:10 +08:00 committed by GitHub
parent fbf2b06432
commit a644c40cfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 28 deletions

View File

@ -5,14 +5,11 @@ import { useRouteQuery } from "@vueuse/router";
import SignupForm from "@/components/signup/SignupForm.vue"; import SignupForm from "@/components/signup/SignupForm.vue";
import SocialAuthProviders from "@/components/login/SocialAuthProviders.vue"; import SocialAuthProviders from "@/components/login/SocialAuthProviders.vue";
import { useGlobalInfoFetch } from "@console/composables/use-global-info"; import { useGlobalInfoFetch } from "@console/composables/use-global-info";
import { useTitle } from "@vueuse/core";
import { useI18n } from "vue-i18n";
import { AppName } from "@/constants/app";
import MdiKeyboardBackspace from "~icons/mdi/keyboard-backspace"; import MdiKeyboardBackspace from "~icons/mdi/keyboard-backspace";
import LocaleChange from "@/components/common/LocaleChange.vue"; import LocaleChange from "@/components/common/LocaleChange.vue";
import { useAppTitle } from "@/composables/use-title";
const { globalInfo } = useGlobalInfoFetch(); const { globalInfo } = useGlobalInfoFetch();
const { t } = useI18n();
const SIGNUP_TYPE = "signup"; const SIGNUP_TYPE = "signup";
@ -32,14 +29,10 @@ function handleChangeType() {
const isLoginType = computed(() => type.value !== SIGNUP_TYPE); const isLoginType = computed(() => type.value !== SIGNUP_TYPE);
useTitle( useAppTitle(
computed(() => { computed(
const siteTitle = globalInfo.value?.siteTitle || AppName; () => `core.${type.value === SIGNUP_TYPE ? SIGNUP_TYPE : "login"}.title`
const routeTitle = t( )
`core.${type.value === SIGNUP_TYPE ? SIGNUP_TYPE : "login"}.title`
);
return [routeTitle, siteTitle].join(" - ");
})
); );
</script> </script>
<template> <template>

View File

@ -9,7 +9,7 @@
name="viewport" name="viewport"
/> />
<meta content="noindex,nofollow" name="robots" /> <meta content="noindex,nofollow" name="robots" />
<title>Halo</title> <title></title>
<link rel="icon" href="/favicon.ico" type="image/png" /> <link rel="icon" href="/favicon.ico" type="image/png" />
<link rel="icon" href="/favicon.ico" type="image/svg+xml" /> <link rel="icon" href="/favicon.ico" type="image/svg+xml" />
<meta name="msapplication-TileColor" content="#da532c" /> <meta name="msapplication-TileColor" content="#da532c" />

View File

@ -1,32 +1,21 @@
<script lang="ts" setup> <script lang="ts" setup>
import { RouterView, useRoute } from "vue-router"; import { RouterView } from "vue-router";
import { computed, reactive, onMounted, inject } from "vue"; import { computed, inject, onMounted, reactive } from "vue";
import { useTitle } from "@vueuse/core";
import { useFavicon } from "@vueuse/core"; import { useFavicon } from "@vueuse/core";
import { useI18n } from "vue-i18n";
import { import {
useOverlayScrollbars, useOverlayScrollbars,
type UseOverlayScrollbarsParams, type UseOverlayScrollbarsParams,
} from "overlayscrollbars-vue"; } from "overlayscrollbars-vue";
import type { FormKitConfig } from "@formkit/core"; import type { FormKitConfig } from "@formkit/core";
import { i18n } from "@/locales"; import { i18n } from "@/locales";
import { AppName } from "@/constants/app";
import { useGlobalInfoStore } from "@/stores/global-info"; import { useGlobalInfoStore } from "@/stores/global-info";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { useAppTitle } from "@/composables/use-title";
const { t } = useI18n(); useAppTitle();
const { globalInfo } = storeToRefs(useGlobalInfoStore()); const { globalInfo } = storeToRefs(useGlobalInfoStore());
const route = useRoute();
useTitle(
computed(() => {
const { title: routeTitle } = route.meta;
const siteTitle = globalInfo.value?.siteTitle || AppName;
return [t(routeTitle || ""), siteTitle].filter(Boolean).join(" - ");
})
);
// Favicon // Favicon
const defaultFavicon = "/console/favicon.ico"; const defaultFavicon = "/console/favicon.ico";
const favicon = computed(() => { const favicon = computed(() => {
@ -66,6 +55,7 @@ formkitConfig.locale = formkitLocales[i18n.global.locale.value] || "zh";
function setViewportProperty(doc: HTMLElement) { function setViewportProperty(doc: HTMLElement) {
let prevClientHeight: number; let prevClientHeight: number;
const customVar = "--vh"; const customVar = "--vh";
function handleResize() { function handleResize() {
const clientHeight = doc.clientHeight; const clientHeight = doc.clientHeight;
if (clientHeight === prevClientHeight) return; if (clientHeight === prevClientHeight) return;
@ -74,9 +64,11 @@ function setViewportProperty(doc: HTMLElement) {
prevClientHeight = clientHeight; prevClientHeight = clientHeight;
}); });
} }
handleResize(); handleResize();
return handleResize; return handleResize;
} }
window.addEventListener( window.addEventListener(
"resize", "resize",
setViewportProperty(document.documentElement) setViewportProperty(document.documentElement)

View File

@ -0,0 +1,24 @@
import { storeToRefs } from "pinia";
import { useGlobalInfoStore } from "@/stores/global-info";
import { useRoute } from "vue-router";
import { useTitle } from "@vueuse/core";
import { computed, type Ref } from "vue";
import { AppName } from "@/constants/app";
import { useI18n } from "vue-i18n";
export function useAppTitle(baseTitle?: Ref<string>) {
const { globalInfo } = storeToRefs(useGlobalInfoStore());
const { t } = useI18n();
const route = useRoute();
useTitle(
computed(() => {
const { title: routeTitle } = route.meta;
const siteTitle = globalInfo.value?.siteTitle || AppName;
return [t(baseTitle?.value || routeTitle || ""), siteTitle]
.filter(Boolean)
.join(" - ");
})
);
}