Files
AstrBot/dashboard/src/components/shared/LanguageSwitcher.vue
Soulter 9d991c7468 perf: enhance chat components with theme and fullscreen toggles (#4116)
* perf: enhance chat components with theme and fullscreen toggles

- Added theme and fullscreen toggle functionality to Chat.vue and ConversationSidebar.vue.
- Introduced a new StyledMenu component for improved dropdown menus.
- Updated MessageList.vue and ChatInput.vue for better mobile responsiveness and UI consistency.
- Enhanced language switcher integration in ConversationSidebar.vue.
- Added new settings translations in English and Chinese locales.

* fix: streamline conversation selection handling in Chat.vue

- Updated handleSelectConversation function to immediately set the current session ID and selected sessions, reducing the need for multiple clicks.
- Adjusted padding in ConversationSidebar.vue for improved layout consistency.
2025-12-19 11:18:01 +08:00

110 lines
3.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<StyledMenu offset="12" location="bottom center">
<template v-slot:activator="{ props: activatorProps }">
<v-btn
v-bind="activatorProps"
:variant="(props.variant === 'header' || props.variant === 'chatbox') ? 'flat' : 'text'"
:color="(props.variant === 'header' || props.variant === 'chatbox') ? 'var(--v-theme-surface)' : undefined"
:rounded="(props.variant === 'header' || props.variant === 'chatbox') ? 'sm' : undefined"
icon
size="small"
:class="['language-switcher', `language-switcher--${props.variant}`, (props.variant === 'header' || props.variant === 'chatbox') ? 'action-btn' : '']"
>
<v-icon
size="18"
:color="props.variant === 'default' ? (useCustomizerStore().uiTheme === 'PurpleTheme' ? '#5e35b1' : '#d7c5fa') : undefined"
>
mdi-translate
</v-icon>
<v-tooltip activator="parent" location="top">
{{ t('core.common.language') }}
</v-tooltip>
</v-btn>
</template>
<v-list-item
v-for="lang in languages"
:key="lang.code"
:value="lang.code"
@click="changeLanguage(lang.code)"
:class="{ 'styled-menu-item-active': currentLocale === lang.code }"
class="styled-menu-item"
rounded="md"
>
<template v-slot:prepend>
<span class="language-flag">{{ lang.flag }}</span>
</template>
<v-list-item-title>{{ lang.name }}</v-list-item-title>
</v-list-item>
</StyledMenu>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n, useLanguageSwitcher } from '@/i18n/composables'
import { useCustomizerStore } from '@/stores/customizer'
import type { Locale } from '@/i18n/types'
import StyledMenu from '@/components/shared/StyledMenu.vue'
// 定义props来控制样式变体
const props = withDefaults(defineProps<{
variant?: 'default' | 'header' | 'chatbox'
}>(), {
variant: 'default'
})
// 使用新的i18n系统
const { t } = useI18n()
const { languageOptions, currentLanguage, switchLanguage, locale } = useLanguageSwitcher()
const languages = computed(() =>
languageOptions.value.map(lang => ({
code: lang.value,
name: lang.label,
flag: lang.flag
}))
)
const currentLocale = computed(() => locale.value)
const changeLanguage = async (langCode: string) => {
await switchLanguage(langCode as Locale)
}
</script>
<style scoped>
.language-flag {
font-size: 16px;
margin-right: 8px;
}
/* 默认变体样式 - 圆形按钮用于登录页 */
.language-switcher--default {
margin: 0 4px;
transition: all 0.3s ease;
border-radius: 50% !important;
min-width: 32px !important;
width: 32px !important;
height: 32px !important;
}
.language-switcher--default:hover {
transform: scale(1.05);
background: rgba(94, 53, 177, 0.08) !important;
}
/* Header变体样式 - 完全继承Vuetify和action-btn的默认样式 */
.language-switcher--header {
/* action-btn类已经处理了margin-right: 6px不需要额外样式 */
}
/* ChatBox变体样式 - 与Header保持一致 */
.language-switcher--chatbox {
/* 继承action-btn样式与工具栏主题按钮保持一致 */
}
/* 深色模式下的悬停效果仅对default变体 */
:deep(.v-theme--PurpleThemeDark) .language-switcher--default:hover {
background: rgba(114, 46, 209, 0.12) !important;
}
</style>