perf: simplify the writing of preferences
parent
c319317217
commit
41d0495630
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { DropdownMenuProps } from '@vben-core/shadcn-ui';
|
import type { DropdownMenuProps } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
import { IcRoundMoreVert } from '@vben-core/iconify';
|
import { IcRoundKeyboardArrowDown } from '@vben-core/iconify';
|
||||||
import { VbenDropdownMenu } from '@vben-core/shadcn-ui';
|
import { VbenDropdownMenu } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
defineProps<DropdownMenuProps>();
|
defineProps<DropdownMenuProps>();
|
||||||
|
@ -10,9 +10,9 @@ defineProps<DropdownMenuProps>();
|
||||||
<template>
|
<template>
|
||||||
<VbenDropdownMenu :menus="menus" :modal="false">
|
<VbenDropdownMenu :menus="menus" :modal="false">
|
||||||
<div
|
<div
|
||||||
class="flex-center hover:bg-accent hover:text-foreground text-muted-foreground border-border h-full cursor-pointer border-l px-2 text-lg font-semibold"
|
class="flex-center hover:bg-accent hover:text-foreground text-muted-foreground border-border h-full cursor-pointer border-l px-1.5 text-lg font-semibold"
|
||||||
>
|
>
|
||||||
<IcRoundMoreVert />
|
<IcRoundKeyboardArrowDown class="size-5" />
|
||||||
</div>
|
</div>
|
||||||
</VbenDropdownMenu>
|
</VbenDropdownMenu>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';
|
||||||
import { mapTree } from '@vben-core/toolkit';
|
import { mapTree } from '@vben-core/toolkit';
|
||||||
import { MenuRecordRaw } from '@vben-core/typings';
|
import { MenuRecordRaw } from '@vben-core/typings';
|
||||||
|
|
||||||
import { Breadcrumb, CozeAssistant, PreferencesWidget } from '../widgets';
|
import { Breadcrumb, CozeAssistant, Preferences } from '../widgets';
|
||||||
import { LayoutContent } from './content';
|
import { LayoutContent } from './content';
|
||||||
import { Copyright } from './copyright';
|
import { Copyright } from './copyright';
|
||||||
import { LayoutFooter } from './footer';
|
import { LayoutFooter } from './footer';
|
||||||
|
@ -153,9 +153,7 @@ function clearPreferencesAndLogout() {
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template v-if="preferences.app.enablePreferences" #preferences>
|
<template v-if="preferences.app.enablePreferences" #preferences>
|
||||||
<PreferencesWidget
|
<Preferences @clear-preferences-and-logout="clearPreferencesAndLogout" />
|
||||||
@clear-preferences-and-logout="clearPreferencesAndLogout"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #floating-groups>
|
<template #floating-groups>
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export { default as PreferencesWidget } from './preferences-widget.vue';
|
export { default as Preferences } from './preferences.vue';
|
||||||
|
export * from './use-open-preferences';
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
<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 { IcRoundFolderCopy, IcRoundRestartAlt } from '@vben-core/iconify';
|
||||||
|
import { $t, loadLocaleMessages } from '@vben-core/locales';
|
||||||
|
import {
|
||||||
|
clearPreferencesCache,
|
||||||
|
preferences,
|
||||||
|
resetPreferences,
|
||||||
|
usePreferences,
|
||||||
|
} from '@vben-core/preferences';
|
||||||
|
import {
|
||||||
|
VbenButton,
|
||||||
|
VbenIconButton,
|
||||||
|
VbenSegmented,
|
||||||
|
VbenSheet,
|
||||||
|
useToast,
|
||||||
|
} from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
|
import { useClipboard } from '@vueuse/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Animation,
|
||||||
|
Block,
|
||||||
|
Breadcrumb,
|
||||||
|
BuiltinTheme,
|
||||||
|
ColorMode,
|
||||||
|
Content,
|
||||||
|
Copyright,
|
||||||
|
Footer,
|
||||||
|
General,
|
||||||
|
GlobalShortcutKeys,
|
||||||
|
Header,
|
||||||
|
Layout,
|
||||||
|
Navigation,
|
||||||
|
Radius,
|
||||||
|
Sidebar,
|
||||||
|
Tabbar,
|
||||||
|
Theme,
|
||||||
|
} from './blocks';
|
||||||
|
import IconSetting from './icons/setting.vue';
|
||||||
|
import { useOpenPreferences } from './use-open-preferences';
|
||||||
|
|
||||||
|
const emit = defineEmits<{ clearPreferencesAndLogout: [] }>();
|
||||||
|
const { toast } = useToast();
|
||||||
|
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 sidebarWidth = defineModel<number>('sidebarWidth');
|
||||||
|
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 copyrightEnable = defineModel<boolean>('copyrightEnable');
|
||||||
|
const copyrightCompanyName = defineModel<string>('copyrightCompanyName');
|
||||||
|
const copyrightCompanySiteLink = defineModel<string>(
|
||||||
|
'copyrightCompanySiteLink',
|
||||||
|
);
|
||||||
|
const copyrightDate = defineModel<string>('copyrightDate');
|
||||||
|
const copyrightIcp = defineModel<string>('copyrightIcp');
|
||||||
|
const copyrightIcpLink = defineModel<string>('copyrightIcpLink');
|
||||||
|
|
||||||
|
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({
|
||||||
|
description: $t('preferences.copy'),
|
||||||
|
title: $t('preferences.copy-success'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleClearCache() {
|
||||||
|
resetPreferences();
|
||||||
|
clearPreferencesCache();
|
||||||
|
emit('clearPreferencesAndLogout');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleReset() {
|
||||||
|
if (!diffPreference.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resetPreferences();
|
||||||
|
await loadLocaleMessages(preferences.app.locale);
|
||||||
|
toast({
|
||||||
|
description: $t('preferences.reset-title'),
|
||||||
|
title: $t('preferences.reset-success'),
|
||||||
|
});
|
||||||
|
toast({
|
||||||
|
description: $t('preferences.reset-title'),
|
||||||
|
title: $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>
|
||||||
|
<VbenButton
|
||||||
|
:title="$t('preferences.title')"
|
||||||
|
class="bg-primary flex-col-center h-12 w-12 cursor-pointer rounded-l-lg rounded-r-none border-none"
|
||||||
|
>
|
||||||
|
<IconSetting
|
||||||
|
class="duration-3000 fill-primary-foreground animate-spin text-2xl"
|
||||||
|
/>
|
||||||
|
</VbenButton>
|
||||||
|
</template>
|
||||||
|
<template #extra>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</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.title')">
|
||||||
|
<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.title')">
|
||||||
|
<Sidebar
|
||||||
|
v-model:sidebar-collapsed="sidebarCollapsed"
|
||||||
|
v-model:sidebar-collapsed-show-title="sidebarCollapsedShowTitle"
|
||||||
|
v-model:sidebar-enable="sidebarEnable"
|
||||||
|
v-model:sidebar-width="sidebarWidth"
|
||||||
|
: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.title')">
|
||||||
|
<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.tabbar.title')">
|
||||||
|
<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>
|
||||||
|
<Block :title="$t('preferences.copyright.title')">
|
||||||
|
<Copyright
|
||||||
|
v-model:copyright-company-name="copyrightCompanyName"
|
||||||
|
v-model:copyright-company-site-link="copyrightCompanySiteLink"
|
||||||
|
v-model:copyright-date="copyrightDate"
|
||||||
|
v-model:copyright-enable="copyrightEnable"
|
||||||
|
v-model:copyright-icp="copyrightIcp"
|
||||||
|
v-model:copyright-icp-link="copyrightIcpLink"
|
||||||
|
:disabled="!footerEnable"
|
||||||
|
/>
|
||||||
|
</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-4 w-full"
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
@click="handleClearCache"
|
||||||
|
>
|
||||||
|
<IcRoundRestartAlt class="mr-2 size-4" />
|
||||||
|
{{ $t('preferences.clear-and-logout') }}
|
||||||
|
</VbenButton>
|
||||||
|
<VbenButton
|
||||||
|
:disabled="!diffPreference"
|
||||||
|
class="mr-4 w-full"
|
||||||
|
size="sm"
|
||||||
|
variant="default"
|
||||||
|
@click="handleCopy"
|
||||||
|
>
|
||||||
|
<IcRoundFolderCopy class="mr-2 size-3" />
|
||||||
|
{{ $t('preferences.copy') }}
|
||||||
|
</VbenButton>
|
||||||
|
</template>
|
||||||
|
</VbenSheet>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,185 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { loadLocaleMessages } from '@vben-core/locales';
|
|
||||||
import { preferences, updatePreferences } from '@vben-core/preferences';
|
|
||||||
|
|
||||||
import Preferences from './preferences.vue';
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Preferences
|
|
||||||
:app-ai-assistant="preferences.app.aiAssistant"
|
|
||||||
:app-color-gray-mode="preferences.app.colorGrayMode"
|
|
||||||
:app-color-weak-mode="preferences.app.colorWeakMode"
|
|
||||||
:app-content-compact="preferences.app.contentCompact"
|
|
||||||
:app-dynamic-title="preferences.app.dynamicTitle"
|
|
||||||
:app-layout="preferences.app.layout"
|
|
||||||
:app-locale="preferences.app.locale"
|
|
||||||
:app-semi-dark-menu="preferences.app.semiDarkMenu"
|
|
||||||
:breadcrumb-enable="preferences.breadcrumb.enable"
|
|
||||||
:breadcrumb-hide-only-one="preferences.breadcrumb.hideOnlyOne"
|
|
||||||
:breadcrumb-show-home="preferences.breadcrumb.showHome"
|
|
||||||
:breadcrumb-show-icon="preferences.breadcrumb.showIcon"
|
|
||||||
:breadcrumb-style-type="preferences.breadcrumb.styleType"
|
|
||||||
:copyright-company-name="preferences.copyright.companyName"
|
|
||||||
:copyright-company-site-link="preferences.copyright.companySiteLink"
|
|
||||||
:copyright-date="preferences.copyright.date"
|
|
||||||
:copyright-enable="preferences.copyright.enable"
|
|
||||||
:copyright-icp="preferences.copyright.icp"
|
|
||||||
:copyright-icp-link="preferences.copyright.icpLink"
|
|
||||||
:footer-enable="preferences.footer.enable"
|
|
||||||
:footer-fixed="preferences.footer.fixed"
|
|
||||||
:header-enable="preferences.header.enable"
|
|
||||||
:header-mode="preferences.header.mode"
|
|
||||||
:navigation-accordion="preferences.navigation.accordion"
|
|
||||||
:navigation-split="preferences.navigation.split"
|
|
||||||
:navigation-style-type="preferences.navigation.styleType"
|
|
||||||
:shortcut-keys-enable="preferences.shortcutKeys.enable"
|
|
||||||
:shortcut-keys-global-logout="preferences.shortcutKeys.globalLogout"
|
|
||||||
:shortcut-keys-global-preferences="
|
|
||||||
preferences.shortcutKeys.globalPreferences
|
|
||||||
"
|
|
||||||
:shortcut-keys-global-search="preferences.shortcutKeys.globalSearch"
|
|
||||||
:sidebar-collapsed="preferences.sidebar.collapsed"
|
|
||||||
:sidebar-collapsed-show-title="preferences.sidebar.collapsedShowTitle"
|
|
||||||
:sidebar-enable="preferences.sidebar.enable"
|
|
||||||
:sidebar-width="preferences.sidebar.width"
|
|
||||||
:tabbar-enable="preferences.tabbar.enable"
|
|
||||||
:tabbar-show-icon="preferences.tabbar.showIcon"
|
|
||||||
:theme-builtin-type="preferences.theme.builtinType"
|
|
||||||
:theme-color-primary="preferences.theme.colorPrimary"
|
|
||||||
:theme-mode="preferences.theme.mode"
|
|
||||||
:theme-radius="preferences.theme.radius"
|
|
||||||
:transition-enable="preferences.transition.enable"
|
|
||||||
:transition-loading="preferences.transition.loading"
|
|
||||||
:transition-name="preferences.transition.name"
|
|
||||||
:transition-progress="preferences.transition.progress"
|
|
||||||
@update:app-ai-assistant="
|
|
||||||
(val) => updatePreferences({ app: { aiAssistant: val } })
|
|
||||||
"
|
|
||||||
@update:app-color-gray-mode="
|
|
||||||
(val) => updatePreferences({ app: { colorGrayMode: val } })
|
|
||||||
"
|
|
||||||
@update:app-color-weak-mode="
|
|
||||||
(val) => updatePreferences({ app: { colorWeakMode: val } })
|
|
||||||
"
|
|
||||||
@update:app-content-compact="
|
|
||||||
(val) => updatePreferences({ app: { contentCompact: val } })
|
|
||||||
"
|
|
||||||
@update:app-dynamic-title="
|
|
||||||
(val) => updatePreferences({ app: { dynamicTitle: val } })
|
|
||||||
"
|
|
||||||
@update:app-layout="(val) => updatePreferences({ app: { layout: val } })"
|
|
||||||
@update:app-locale="
|
|
||||||
(val) => {
|
|
||||||
updatePreferences({ app: { locale: val } });
|
|
||||||
loadLocaleMessages(val);
|
|
||||||
}
|
|
||||||
"
|
|
||||||
@update:app-semi-dark-menu="
|
|
||||||
(val) => updatePreferences({ app: { semiDarkMenu: val } })
|
|
||||||
"
|
|
||||||
@update:breadcrumb-enable="
|
|
||||||
(val) => updatePreferences({ breadcrumb: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:breadcrumb-hide-only-one="
|
|
||||||
(val) => updatePreferences({ breadcrumb: { hideOnlyOne: val } })
|
|
||||||
"
|
|
||||||
@update:breadcrumb-show-home="
|
|
||||||
(val) => updatePreferences({ breadcrumb: { showHome: val } })
|
|
||||||
"
|
|
||||||
@update:breadcrumb-show-icon="
|
|
||||||
(val) => updatePreferences({ breadcrumb: { showIcon: val } })
|
|
||||||
"
|
|
||||||
@update:breadcrumb-style-type="
|
|
||||||
(val) => updatePreferences({ breadcrumb: { styleType: val } })
|
|
||||||
"
|
|
||||||
@update:copyright-company-name="
|
|
||||||
(val) => updatePreferences({ copyright: { companyName: val } })
|
|
||||||
"
|
|
||||||
@update:copyright-company-site-link="
|
|
||||||
(val) => updatePreferences({ copyright: { companySiteLink: val } })
|
|
||||||
"
|
|
||||||
@update:copyright-date="
|
|
||||||
(val) => updatePreferences({ copyright: { date: val } })
|
|
||||||
"
|
|
||||||
@update:copyright-enable="
|
|
||||||
(val) => updatePreferences({ copyright: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:copyright-icp="
|
|
||||||
(val) => updatePreferences({ copyright: { icp: val } })
|
|
||||||
"
|
|
||||||
@update:copyright-icp-link="
|
|
||||||
(val) => updatePreferences({ copyright: { icpLink: val } })
|
|
||||||
"
|
|
||||||
@update:footer-enable="
|
|
||||||
(val) => updatePreferences({ footer: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:footer-fixed="
|
|
||||||
(val) => updatePreferences({ footer: { fixed: val } })
|
|
||||||
"
|
|
||||||
@update:header-enable="
|
|
||||||
(val) => updatePreferences({ header: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:header-mode="(val) => updatePreferences({ header: { mode: val } })"
|
|
||||||
@update:navigation-accordion="
|
|
||||||
(val) => updatePreferences({ navigation: { accordion: val } })
|
|
||||||
"
|
|
||||||
@update:navigation-split="
|
|
||||||
(val) => updatePreferences({ navigation: { split: val } })
|
|
||||||
"
|
|
||||||
@update:navigation-style-type="
|
|
||||||
(val) => updatePreferences({ navigation: { styleType: val } })
|
|
||||||
"
|
|
||||||
@update:shortcut-keys-enable="
|
|
||||||
(val) => updatePreferences({ shortcutKeys: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:shortcut-keys-global-logout="
|
|
||||||
(val) => updatePreferences({ shortcutKeys: { globalLogout: val } })
|
|
||||||
"
|
|
||||||
@update:shortcut-keys-global-preferences="
|
|
||||||
(val) => updatePreferences({ shortcutKeys: { globalPreferences: val } })
|
|
||||||
"
|
|
||||||
@update:shortcut-keys-global-search="
|
|
||||||
(val) => updatePreferences({ shortcutKeys: { globalSearch: val } })
|
|
||||||
"
|
|
||||||
@update:sidebar-collapsed="
|
|
||||||
(val) => updatePreferences({ sidebar: { collapsed: val } })
|
|
||||||
"
|
|
||||||
@update:sidebar-collapsed-show-title="
|
|
||||||
(val) => updatePreferences({ sidebar: { collapsedShowTitle: val } })
|
|
||||||
"
|
|
||||||
@update:sidebar-enable="
|
|
||||||
(val) => updatePreferences({ sidebar: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:sidebar-width="
|
|
||||||
(val) => updatePreferences({ sidebar: { width: val } })
|
|
||||||
"
|
|
||||||
@update:tabbar-enable="
|
|
||||||
(val) => updatePreferences({ tabbar: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:tabbar-show-icon="
|
|
||||||
(val) => updatePreferences({ tabbar: { showIcon: val } })
|
|
||||||
"
|
|
||||||
@update:theme-builtin-type="
|
|
||||||
(val) => updatePreferences({ theme: { builtinType: val } })
|
|
||||||
"
|
|
||||||
@update:theme-color-primary="
|
|
||||||
(val) => updatePreferences({ theme: { colorPrimary: val } })
|
|
||||||
"
|
|
||||||
@update:theme-mode="(val) => updatePreferences({ theme: { mode: val } })"
|
|
||||||
@update:theme-radius="
|
|
||||||
(val) => updatePreferences({ theme: { radius: val } })
|
|
||||||
"
|
|
||||||
@update:transition-enable="
|
|
||||||
(val) => updatePreferences({ transition: { enable: val } })
|
|
||||||
"
|
|
||||||
@update:transition-loading="
|
|
||||||
(val) => updatePreferences({ transition: { loading: val } })
|
|
||||||
"
|
|
||||||
@update:transition-name="
|
|
||||||
(val) => updatePreferences({ transition: { name: val } })
|
|
||||||
"
|
|
||||||
@update:transition-progress="
|
|
||||||
(val) => updatePreferences({ transition: { progress: val } })
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</template>
|
|
|
@ -1,398 +1,44 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import type {
|
import { computed } from 'vue';
|
||||||
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 { preferences, updatePreferences } from '@vben-core/preferences';
|
||||||
|
import { capitalizeFirstLetter } from '@vben-core/toolkit';
|
||||||
|
|
||||||
import { IcRoundFolderCopy, IcRoundRestartAlt } from '@vben-core/iconify';
|
import Preferences from './preferences-sheet.vue';
|
||||||
import { $t, loadLocaleMessages } from '@vben-core/locales';
|
|
||||||
import {
|
|
||||||
clearPreferencesCache,
|
|
||||||
preferences,
|
|
||||||
resetPreferences,
|
|
||||||
usePreferences,
|
|
||||||
} from '@vben-core/preferences';
|
|
||||||
import {
|
|
||||||
VbenButton,
|
|
||||||
VbenIconButton,
|
|
||||||
VbenSegmented,
|
|
||||||
VbenSheet,
|
|
||||||
useToast,
|
|
||||||
} from '@vben-core/shadcn-ui';
|
|
||||||
|
|
||||||
import { useClipboard } from '@vueuse/core';
|
/**
|
||||||
|
* preferences 转成 vue props
|
||||||
import {
|
* preferences.app.aiAssistant=>appAiAssistant
|
||||||
Animation,
|
*/
|
||||||
Block,
|
const attrs = computed(() => {
|
||||||
Breadcrumb,
|
const result: Record<string, any> = {};
|
||||||
BuiltinTheme,
|
for (const [key, value] of Object.entries(preferences)) {
|
||||||
ColorMode,
|
for (const [subKey, subValue] of Object.entries(value)) {
|
||||||
Content,
|
result[`${key}${capitalizeFirstLetter(subKey)}`] = subValue;
|
||||||
Copyright,
|
}
|
||||||
Footer,
|
|
||||||
General,
|
|
||||||
GlobalShortcutKeys,
|
|
||||||
Header,
|
|
||||||
Layout,
|
|
||||||
Navigation,
|
|
||||||
Radius,
|
|
||||||
Sidebar,
|
|
||||||
Tabbar,
|
|
||||||
Theme,
|
|
||||||
} from './blocks';
|
|
||||||
import Trigger from './trigger.vue';
|
|
||||||
import { useOpenPreferences } from './use-open-preferences';
|
|
||||||
|
|
||||||
const emit = defineEmits<{ clearPreferencesAndLogout: [] }>();
|
|
||||||
const { toast } = useToast();
|
|
||||||
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 sidebarWidth = defineModel<number>('sidebarWidth');
|
|
||||||
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 copyrightEnable = defineModel<boolean>('copyrightEnable');
|
|
||||||
const copyrightCompanyName = defineModel<string>('copyrightCompanyName');
|
|
||||||
const copyrightCompanySiteLink = defineModel<string>(
|
|
||||||
'copyrightCompanySiteLink',
|
|
||||||
);
|
|
||||||
const copyrightDate = defineModel<string>('copyrightDate');
|
|
||||||
const copyrightIcp = defineModel<string>('copyrightIcp');
|
|
||||||
const copyrightIcpLink = defineModel<string>('copyrightIcpLink');
|
|
||||||
|
|
||||||
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({
|
|
||||||
description: $t('preferences.copy'),
|
|
||||||
title: $t('preferences.copy-success'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleClearCache() {
|
|
||||||
resetPreferences();
|
|
||||||
clearPreferencesCache();
|
|
||||||
emit('clearPreferencesAndLogout');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleReset() {
|
|
||||||
if (!diffPreference.value) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
resetPreferences();
|
return result;
|
||||||
await loadLocaleMessages(preferences.app.locale);
|
});
|
||||||
toast({
|
|
||||||
description: $t('preferences.reset-title'),
|
/**
|
||||||
title: $t('preferences.reset-success'),
|
* preferences 转成 vue listener
|
||||||
});
|
* preferences.app.aiAssistant=>@update:appAiAssistant
|
||||||
toast({
|
*/
|
||||||
description: $t('preferences.reset-title'),
|
const listen = computed(() => {
|
||||||
title: $t('preferences.reset-success'),
|
const result: Record<string, any> = {};
|
||||||
});
|
for (const [key, value] of Object.entries(preferences)) {
|
||||||
}
|
if (typeof value === 'object') {
|
||||||
|
for (const subKey of Object.keys(value)) {
|
||||||
|
result[`update:${key}${capitalizeFirstLetter(subKey)}`] = (val: any) =>
|
||||||
|
updatePreferences({ [key]: { [subKey]: val } });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="z-100 fixed right-0 top-1/2">
|
<Preferences v-bind="attrs" v-on="listen" />
|
||||||
<VbenSheet
|
|
||||||
v-model:open="openPreferences"
|
|
||||||
:description="$t('preferences.subtitle')"
|
|
||||||
:title="$t('preferences.title')"
|
|
||||||
>
|
|
||||||
<template #trigger>
|
|
||||||
<Trigger />
|
|
||||||
</template>
|
|
||||||
<template #extra>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
</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.title')">
|
|
||||||
<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.title')">
|
|
||||||
<Sidebar
|
|
||||||
v-model:sidebar-collapsed="sidebarCollapsed"
|
|
||||||
v-model:sidebar-collapsed-show-title="sidebarCollapsedShowTitle"
|
|
||||||
v-model:sidebar-enable="sidebarEnable"
|
|
||||||
v-model:sidebar-width="sidebarWidth"
|
|
||||||
: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.title')">
|
|
||||||
<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.tabbar.title')">
|
|
||||||
<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>
|
|
||||||
<Block :title="$t('preferences.copyright.title')">
|
|
||||||
<Copyright
|
|
||||||
v-model:copyright-company-name="copyrightCompanyName"
|
|
||||||
v-model:copyright-company-site-link="copyrightCompanySiteLink"
|
|
||||||
v-model:copyright-date="copyrightDate"
|
|
||||||
v-model:copyright-enable="copyrightEnable"
|
|
||||||
v-model:copyright-icp="copyrightIcp"
|
|
||||||
v-model:copyright-icp-link="copyrightIcpLink"
|
|
||||||
:disabled="!footerEnable"
|
|
||||||
/>
|
|
||||||
</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-4 w-full"
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
@click="handleClearCache"
|
|
||||||
>
|
|
||||||
<IcRoundRestartAlt class="mr-2 size-4" />
|
|
||||||
{{ $t('preferences.clear-and-logout') }}
|
|
||||||
</VbenButton>
|
|
||||||
<VbenButton
|
|
||||||
:disabled="!diffPreference"
|
|
||||||
class="mr-4 w-full"
|
|
||||||
size="sm"
|
|
||||||
variant="default"
|
|
||||||
@click="handleCopy"
|
|
||||||
>
|
|
||||||
<IcRoundFolderCopy class="mr-2 size-3" />
|
|
||||||
{{ $t('preferences.copy') }}
|
|
||||||
</VbenButton>
|
|
||||||
</template>
|
|
||||||
</VbenSheet>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { $t } from '@vben-core/locales';
|
|
||||||
import { VbenButton } from '@vben-core/shadcn-ui';
|
|
||||||
|
|
||||||
import IconSetting from './icons/setting.vue';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'PreferenceTrigger',
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VbenButton
|
|
||||||
:title="$t('preferences.title')"
|
|
||||||
class="bg-primary flex-col-center h-12 w-12 cursor-pointer rounded-l-lg rounded-r-none border-none"
|
|
||||||
>
|
|
||||||
<IconSetting
|
|
||||||
class="duration-3000 fill-primary-foreground animate-spin text-2xl"
|
|
||||||
/>
|
|
||||||
</VbenButton>
|
|
||||||
</template>
|
|
|
@ -24,7 +24,7 @@ import { isWindowsOs } from '@vben-core/toolkit';
|
||||||
|
|
||||||
import { useMagicKeys, whenever } from '@vueuse/core';
|
import { useMagicKeys, whenever } from '@vueuse/core';
|
||||||
|
|
||||||
import { useOpenPreferences } from '../preferences/use-open-preferences';
|
import { useOpenPreferences } from '../preferences';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue