feat: dynamic language change
This commit is contained in:
2
components.d.ts
vendored
2
components.d.ts
vendored
@@ -13,6 +13,7 @@ export {}
|
|||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
AnimatePresence: typeof import('motion-v')['AnimatePresence']
|
AnimatePresence: typeof import('motion-v')['AnimatePresence']
|
||||||
|
AnimText: typeof import('./src/components/special/AnimText.vue')['default']
|
||||||
AuthDialog: typeof import('./src/components/dialog/AuthDialog.vue')['default']
|
AuthDialog: typeof import('./src/components/dialog/AuthDialog.vue')['default']
|
||||||
Button: typeof import('./src/components/ui/button/Button.vue')['default']
|
Button: typeof import('./src/components/ui/button/Button.vue')['default']
|
||||||
Calendar: typeof import('./src/components/ui/calendar/Calendar.vue')['default']
|
Calendar: typeof import('./src/components/ui/calendar/Calendar.vue')['default']
|
||||||
@@ -52,6 +53,7 @@ declare module 'vue' {
|
|||||||
// For TSX support
|
// For TSX support
|
||||||
declare global {
|
declare global {
|
||||||
const AnimatePresence: typeof import('motion-v')['AnimatePresence']
|
const AnimatePresence: typeof import('motion-v')['AnimatePresence']
|
||||||
|
const AnimText: typeof import('./src/components/special/AnimText.vue')['default']
|
||||||
const AuthDialog: typeof import('./src/components/dialog/AuthDialog.vue')['default']
|
const AuthDialog: typeof import('./src/components/dialog/AuthDialog.vue')['default']
|
||||||
const Button: typeof import('./src/components/ui/button/Button.vue')['default']
|
const Button: typeof import('./src/components/ui/button/Button.vue')['default']
|
||||||
const Calendar: typeof import('./src/components/ui/calendar/Calendar.vue')['default']
|
const Calendar: typeof import('./src/components/ui/calendar/Calendar.vue')['default']
|
||||||
|
|||||||
27
src/components/special/AnimText.vue
Normal file
27
src/components/special/AnimText.vue
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { motion, useAnimate } from "motion-v";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { languageChangeBus } from "@/hooks/bus/languageChangeBus";
|
||||||
|
import type { Key, ResourceKeys } from "vue-i18n";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
text: Key | ResourceKeys;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const [scope, animate] = useAnimate();
|
||||||
|
|
||||||
|
languageChangeBus.on(async () => {
|
||||||
|
await animate(scope.current, { opacity: 0, y: "-20px" });
|
||||||
|
await animate(scope.current, { opacity: 1, y: "0" });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<motion.span ref="scope">
|
||||||
|
{{ t(props.text) }}
|
||||||
|
</motion.span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
4
src/hooks/bus/index.ts
Normal file
4
src/hooks/bus/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export const keys = {
|
||||||
|
user: "user",
|
||||||
|
language: "language",
|
||||||
|
};
|
||||||
4
src/hooks/bus/languageChangeBus.ts
Normal file
4
src/hooks/bus/languageChangeBus.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { useEventBus } from "@vueuse/core";
|
||||||
|
import { keys } from "./index";
|
||||||
|
|
||||||
|
export const languageChangeBus = useEventBus<string>(keys.language);
|
||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
GlobalLanguage,
|
GlobalLanguage,
|
||||||
languageMap,
|
languageMap,
|
||||||
} from "@/stores/LanguageStore";
|
} from "@/stores/LanguageStore";
|
||||||
|
import { languageChangeBus } from "./bus/languageChangeBus";
|
||||||
|
|
||||||
const languageStore = useLanguageStore();
|
const languageStore = useLanguageStore();
|
||||||
|
|
||||||
@@ -20,8 +21,13 @@ function changeGlobalLanguage(
|
|||||||
language: GlobalLanguage,
|
language: GlobalLanguage,
|
||||||
locale: WritableComputedRef<string>,
|
locale: WritableComputedRef<string>,
|
||||||
) {
|
) {
|
||||||
|
// 延迟切换先通知其他组件播放动画
|
||||||
|
languageChangeBus.emit("language changed");
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
languageStore.setLanguage(language);
|
languageStore.setLanguage(language);
|
||||||
locale.value = language;
|
locale.value = language;
|
||||||
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGlobalLanguageHook = () => ({
|
export const useGlobalLanguageHook = () => ({
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import DatePickerDisplayCard from "@/components/card/DatePickerDisplayCard.vue";
|
|||||||
import DevelopProgressCard from "@/components/card/DevelopProgressCard.vue";
|
import DevelopProgressCard from "@/components/card/DevelopProgressCard.vue";
|
||||||
import FooterBar from "@/components/layout/FooterBar.vue";
|
import FooterBar from "@/components/layout/FooterBar.vue";
|
||||||
import NavBar from "@/components/menu/NavBar.vue";
|
import NavBar from "@/components/menu/NavBar.vue";
|
||||||
|
import AnimText from "@/components/special/AnimText.vue";
|
||||||
import { navigateTo } from "@/utils/navigator";
|
import { navigateTo } from "@/utils/navigator";
|
||||||
|
|
||||||
const progress = ref([
|
const progress = ref([
|
||||||
@@ -46,17 +47,24 @@ const progress = ref([
|
|||||||
<div class="hero flex-1">
|
<div class="hero flex-1">
|
||||||
<div class="hero-content text-center">
|
<div class="hero-content text-center">
|
||||||
<div class="max-w-md">
|
<div class="max-w-md">
|
||||||
<h1 class="text-5xl font-bold">{{ $t("home.welcome") }}</h1>
|
<!-- <h1 class="text-5xl font-bold">{{ $t("home.welcome") }}</h1> -->
|
||||||
<p class="py-6">
|
<h1 class="text-5xl font-bold">
|
||||||
{{ $t("home.intro_line1") }}<br />
|
<AnimText text="home.welcome" />
|
||||||
|
</h1>
|
||||||
|
<div class="py-6">
|
||||||
|
<!-- {{ $t("home.intro_line1") }}<br />
|
||||||
{{ $t("home.intro_line2") }}<br />
|
{{ $t("home.intro_line2") }}<br />
|
||||||
{{ $t("home.intro_line3") }}
|
{{ $t("home.intro_line3") }} -->
|
||||||
</p>
|
<AnimText text="home.intro_line1" /><br />
|
||||||
|
<AnimText text="home.intro_line2" /><br />
|
||||||
|
<AnimText text="home.intro_line3" />
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
class="btn btn-primary"
|
class="btn btn-primary"
|
||||||
@click="navigateTo('http://localhost:5174')"
|
@click="navigateTo('http://localhost:5174')"
|
||||||
>
|
>
|
||||||
{{ $t("home.read_doc") }}
|
<!-- {{ $t("home.read_doc") }} -->
|
||||||
|
<AnimText text="home.read_doc" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,8 +9,9 @@
|
|||||||
|
|
||||||
@plugin "daisyui/theme" {
|
@plugin "daisyui/theme" {
|
||||||
name: "light";
|
name: "light";
|
||||||
--color-primary: blue;
|
--color-primary: #5092d4;
|
||||||
--color-secondary: teal;
|
--color-secondary: #bfd7f1;
|
||||||
|
--color-accent: #76b9ef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Custom Scrollbar Styles */
|
/* Custom Scrollbar Styles */
|
||||||
|
|||||||
Reference in New Issue
Block a user