123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- <template>
- <div class="relative inline-block text-left" ref="dropdownContainerRef" @mouseleave="handleMouseLeave">
- <div
- @mouseenter="handleMouseEnter"
- class="flex items-center gap-1 text-white opacity-80 text-sm hover:opacity-100 cursor-pointer py-2 transition-opacity"
- >
- <i class="icon-i18n mr-1"></i>
- <span>{{ currentLocaleName || "Language" }}</span>
- <svg
- class="h-3 w-3 text-white/60 transition-transform duration-200"
- :class="{'rotate-180': isDropdownOpen}"
- fill="none" viewBox="0 0 24 24" stroke="currentColor"
- >
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M19 9l-7 7-7-7" />
- </svg>
- </div>
-
- <transition name="fade-down">
- <div
- v-if="isDropdownOpen"
- @mouseenter="handleMouseEnter"
- class="absolute right-0 top-full mt-1 w-max min-w-[120px] bg-slate-800/90 backdrop-blur-md rounded-lg shadow-xl p-2 z-10"
- >
- <ul class="space-y-1">
- <li v-for="locale in availableLocales" :key="locale.code">
- <button
- @click="selectLanguage(locale.code)"
- class="block w-full text-left text-base text-gray-200 hover:text-white hover:bg-white/10 transition-all duration-150 rounded px-3 py-1.5"
- :class="[ locale.code === currentLocale ? 'font-bold opacity-100 bg-white/15' : '' ]"
- >
- {{ locale.name }}
- </button>
- </li>
- </ul>
- </div>
- </transition>
- </div>
- </template>
-
- <script setup lang="ts">
- /**
- * 语言切换组件 - 下拉菜单样式
- * 支持切换配置的语言
- */
- import { ref, computed } from "vue";
- import { useI18n } from "#imports"; // 修正 useI18n 导入
-
- // 定义语言代码的类型,应该与 i18n 配置中的一致
- type LocaleCode = "zh" | "en" | "ja"; // 你需要根据你的 i18n 配置更新这个类型
-
- const { locale, locales, setLocale } = useI18n();
- const currentLocale = computed(() => locale.value);
- const isDropdownOpen = ref(false);
- const dropdownContainerRef = ref(null); // 保留 ref,虽然 onClickOutside 移除了,但未来可能有用
- let leaveTimeout: ReturnType<typeof setTimeout> | null = null; // Timeout for mouseleave delay
-
- // 可用语言列表
- const availableLocales = computed(() => {
- // 确保 locales.value 是一个数组并且包含 code 和 name 属性
- return (
- (locales.value as Array<{ code: string; name: string }>) || []
- ).filter((l) => l.code && l.name);
- });
-
- // 当前选中语言的名称
- const currentLocaleName = computed(() => {
- const current = availableLocales.value.find((l: { code: string; name: string }) =>
- l.code === locale.value
- );
- return current ? current.name : "";
- });
-
- /**
- * 选择语言并关闭下拉菜单
- * @param {string} langCode - 选择的语言代码
- */
- async function selectLanguage(langCode: string) {
- if (currentLocale.value !== langCode) {
- try {
- // 使用类型断言,确保 langCode 是有效的 LocaleCode
- await setLocale(langCode as LocaleCode);
- } catch (error) {
- console.error("Failed to set locale:", error);
- // 这里可以添加用户反馈,例如显示一个错误提示
- }
- }
- handleMouseLeave(); // 使用 handleMouseLeave 关闭
- }
-
- // --- Dropdown Logic (like Products dropdown) ---
- function handleMouseEnter() {
- if (leaveTimeout) {
- clearTimeout(leaveTimeout);
- leaveTimeout = null;
- }
- isDropdownOpen.value = true;
- }
-
- function handleMouseLeave() {
- // Delay closing the dropdown slightly
- leaveTimeout = setTimeout(() => {
- isDropdownOpen.value = false;
- }, 150); // 150ms delay
- }
- // --- End Dropdown Logic ---
- </script>
|