123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- <script setup lang="ts">
- import type {
- BuiltinThemeType,
- ContentCompactType,
- LayoutHeaderModeType,
- LayoutType,
- SupportedLanguagesType,
- ThemeModeType,
- } from '@vben/types';
- import type {
- BreadcrumbStyleType,
- NavigationStyleType,
- } from '@vben-core/preferences';
- import type { SegmentedItem } from '@vben-core/shadcn-ui';
- import { computed, ref } from 'vue';
- import { $t, loadLocaleMessages } from '@vben/locales';
- import { IcRoundFolderCopy, IcRoundRestartAlt } from '@vben-core/iconify';
- import {
- preferences,
- resetPreferences,
- usePreferences,
- } from '@vben-core/preferences';
- import {
- VbenButton,
- VbenIconButton,
- VbenSegmented,
- VbenSheet,
- toast,
- } from '@vben-core/shadcn-ui';
- import { useClipboard } from '@vueuse/core';
- import {
- Animation,
- Block,
- Breadcrumb,
- BuiltinTheme,
- ColorMode,
- Content,
- Footer,
- General,
- GlobalShortcutKeys,
- Header,
- Layout,
- Navigation,
- Radius,
- Sidebar,
- Tabbar,
- Theme,
- } from './blocks';
- import Trigger from './trigger.vue';
- import { useOpenPreferences } from './use-open-preferences';
- const appLocale = defineModel<SupportedLanguagesType>('appLocale');
- const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
- const appAiAssistant = defineModel<boolean>('appAiAssistant');
- const appLayout = defineModel<LayoutType>('appLayout');
- const appColorGrayMode = defineModel<boolean>('appColorGrayMode');
- const appColorWeakMode = defineModel<boolean>('appColorWeakMode');
- const appSemiDarkMenu = defineModel<boolean>('appSemiDarkMenu');
- const appContentCompact = defineModel<ContentCompactType>('appContentCompact');
- const transitionProgress = defineModel<boolean>('transitionProgress');
- const transitionName = defineModel<string>('transitionName');
- const transitionLoading = defineModel<boolean>('transitionLoading');
- const transitionEnable = defineModel<boolean>('transitionEnable');
- const themeColorPrimary = defineModel<string>('themeColorPrimary');
- const themeBuiltinType = defineModel<BuiltinThemeType>('themeBuiltinType');
- const themeMode = defineModel<ThemeModeType>('themeMode');
- const themeRadius = defineModel<string>('themeRadius');
- const sidebarEnable = defineModel<boolean>('sidebarEnable');
- const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
- const sidebarCollapsedShowTitle = defineModel<boolean>(
- 'sidebarCollapsedShowTitle',
- );
- const headerEnable = defineModel<boolean>('headerEnable');
- const headerMode = defineModel<LayoutHeaderModeType>('headerMode');
- const breadcrumbEnable = defineModel<boolean>('breadcrumbEnable');
- const breadcrumbShowIcon = defineModel<boolean>('breadcrumbShowIcon');
- const breadcrumbShowHome = defineModel<boolean>('breadcrumbShowHome');
- const breadcrumbStyleType = defineModel<BreadcrumbStyleType>(
- 'breadcrumbStyleType',
- );
- const breadcrumbHideOnlyOne = defineModel<boolean>('breadcrumbHideOnlyOne');
- const tabbarEnable = defineModel<boolean>('tabbarEnable');
- const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
- const navigationStyleType = defineModel<NavigationStyleType>(
- 'navigationStyleType',
- );
- const navigationSplit = defineModel<boolean>('navigationSplit');
- const navigationAccordion = defineModel<boolean>('navigationAccordion');
- // const logoVisible = defineModel<boolean>('logoVisible');
- const footerEnable = defineModel<boolean>('footerEnable');
- const footerFixed = defineModel<boolean>('footerFixed');
- const shortcutKeysEnable = defineModel<boolean>('shortcutKeysEnable');
- const shortcutKeysGlobalSearch = defineModel<boolean>(
- 'shortcutKeysGlobalSearch',
- );
- const shortcutKeysGlobalLogout = defineModel<boolean>(
- 'shortcutKeysGlobalLogout',
- );
- const shortcutKeysGlobalPreferences = defineModel<boolean>(
- 'shortcutKeysGlobalPreferences',
- );
- const {
- diffPreference,
- isDark,
- isFullContent,
- isHeaderNav,
- isMixedNav,
- isSideMixedNav,
- isSideMode,
- isSideNav,
- } = usePreferences();
- const { copy } = useClipboard();
- const activeTab = ref('appearance');
- const tabs = computed((): SegmentedItem[] => {
- return [
- {
- label: $t('preferences.appearance'),
- value: 'appearance',
- },
- {
- label: $t('preferences.layout'),
- value: 'layout',
- },
- {
- label: $t('preferences.shortcut-keys.title'),
- value: 'shortcutKey',
- },
- {
- label: $t('preferences.general'),
- value: 'general',
- },
- ];
- });
- const showBreadcrumbConfig = computed(() => {
- return (
- !isFullContent.value &&
- !isMixedNav.value &&
- !isHeaderNav.value &&
- preferences.header.enable
- );
- });
- const { openPreferences } = useOpenPreferences();
- async function handleCopy() {
- await copy(JSON.stringify(diffPreference.value, null, 2));
- toast($t('preferences.copy-success'));
- }
- async function handleReset() {
- if (!diffPreference.value) {
- return;
- }
- resetPreferences();
- await loadLocaleMessages(preferences.app.locale);
- toast($t('preferences.reset-success'));
- }
- </script>
- <template>
- <div class="z-100 fixed right-0 top-1/2">
- <VbenSheet
- v-model:open="openPreferences"
- :description="$t('preferences.subtitle')"
- :title="$t('preferences.title')"
- >
- <template #trigger>
- <Trigger />
- </template>
- <template #extra>
- <VbenIconButton
- :disabled="!diffPreference"
- :tooltip="$t('preferences.reset-tip')"
- class="relative"
- >
- <span
- v-if="diffPreference"
- class="bg-primary absolute right-0.5 top-0.5 h-2 w-2 rounded"
- ></span>
- <IcRoundRestartAlt class="size-5" @click="handleReset" />
- </VbenIconButton>
- </template>
- <div class="p-4 pt-4">
- <VbenSegmented v-model="activeTab" :tabs="tabs">
- <template #general>
- <Block :title="$t('preferences.general')">
- <General
- v-model:app-ai-assistant="appAiAssistant"
- v-model:app-dynamic-title="appDynamicTitle"
- v-model:app-locale="appLocale"
- />
- </Block>
- <Block :title="$t('preferences.animation.title')">
- <Animation
- v-model:transition-enable="transitionEnable"
- v-model:transition-loading="transitionLoading"
- v-model:transition-name="transitionName"
- v-model:transition-progress="transitionProgress"
- />
- </Block>
- </template>
- <template #appearance>
- <Block :title="$t('preferences.theme.title')">
- <Theme
- v-model="themeMode"
- v-model:app-semi-dark-menu="appSemiDarkMenu"
- />
- </Block>
- <!-- <Block :title="$t('preferences.theme-color')">
- <ThemeColor
- v-model="themeColorPrimary"
- :color-primary-presets="colorPrimaryPresets"
- />
- </Block> -->
- <Block :title="$t('preferences.theme.builtin')">
- <BuiltinTheme
- v-model="themeBuiltinType"
- v-model:theme-color-primary="themeColorPrimary"
- :is-dark="isDark"
- />
- </Block>
- <Block :title="$t('preferences.theme.radius')">
- <Radius v-model="themeRadius" />
- </Block>
- <Block :title="$t('preferences.other')">
- <ColorMode
- v-model:app-color-gray-mode="appColorGrayMode"
- v-model:app-color-weak-mode="appColorWeakMode"
- />
- </Block>
- </template>
- <template #layout>
- <Block :title="$t('preferences.layout')">
- <Layout v-model="appLayout" />
- </Block>
- <Block :title="$t('preferences.content')">
- <Content v-model="appContentCompact" />
- </Block>
- <Block :title="$t('preferences.sidebar')">
- <Sidebar
- v-model:sidebar-collapsed="sidebarCollapsed"
- v-model:sidebar-collapsed-show-title="sidebarCollapsedShowTitle"
- v-model:sidebar-enable="sidebarEnable"
- :disabled="!isSideMode"
- />
- </Block>
- <Block :title="$t('preferences.header.title')">
- <Header
- v-model:headerEnable="headerEnable"
- v-model:headerMode="headerMode"
- :disabled="isFullContent"
- />
- </Block>
- <Block :title="$t('preferences.navigation-menu')">
- <Navigation
- v-model:navigation-accordion="navigationAccordion"
- v-model:navigation-split="navigationSplit"
- v-model:navigation-style-type="navigationStyleType"
- :disabled="isFullContent"
- :disabled-navigation-split="!isMixedNav"
- />
- </Block>
- <Block :title="$t('preferences.breadcrumb.title')">
- <Breadcrumb
- v-model:breadcrumb-enable="breadcrumbEnable"
- v-model:breadcrumb-hide-only-one="breadcrumbHideOnlyOne"
- v-model:breadcrumb-show-home="breadcrumbShowHome"
- v-model:breadcrumb-show-icon="breadcrumbShowIcon"
- v-model:breadcrumb-style-type="breadcrumbStyleType"
- :disabled="
- !showBreadcrumbConfig || !(isSideNav || isSideMixedNav)
- "
- />
- </Block>
- <Block :title="$t('preferences.tabs')">
- <Tabbar
- v-model:tabbar-enable="tabbarEnable"
- v-model:tabbar-show-icon="tabbarShowIcon"
- />
- </Block>
- <Block :title="$t('preferences.footer.title')">
- <Footer
- v-model:footer-enable="footerEnable"
- v-model:footer-fixed="footerFixed"
- />
- </Block>
- </template>
- <template #shortcutKey>
- <Block :title="$t('preferences.shortcut-keys.global')">
- <GlobalShortcutKeys
- v-model:shortcut-keys-enable="shortcutKeysEnable"
- v-model:shortcut-keys-global-search="shortcutKeysGlobalSearch"
- v-model:shortcut-keys-logout="shortcutKeysGlobalLogout"
- v-model:shortcut-keys-preferences="
- shortcutKeysGlobalPreferences
- "
- />
- </Block>
- </template>
- </VbenSegmented>
- </div>
- <template #footer>
- <VbenButton
- :disabled="!diffPreference"
- class="mx-6 w-full"
- size="sm"
- variant="default"
- @click="handleCopy"
- >
- <IcRoundFolderCopy class="mr-2 size-3" />
- {{ $t('preferences.copy') }}
- </VbenButton>
- </template>
- </VbenSheet>
- </div>
- </template>
|