admin-vben5/packages/business/common-ui/src/preferences/preferences.vue

329 lines
9.9 KiB
Vue
Raw Normal View History

2024-05-19 21:20:42 +08:00
<script setup lang="ts">
2024-06-09 12:53:38 +08:00
import type {
ContentCompactType,
LayoutHeaderModeType,
LayoutType,
SupportedLanguagesType,
ThemeModeType,
} from '@vben/types';
import type {
BreadcrumbStyleType,
NavigationStyleType,
} from '@vben-core/preferences';
2024-05-19 21:20:42 +08:00
import type { SegmentedItem } from '@vben-core/shadcn-ui';
2024-06-08 19:49:06 +08:00
import { computed } from 'vue';
import { $t } from '@vben/locales';
2024-05-19 21:20:42 +08:00
import { IcRoundFolderCopy, IcRoundRestartAlt } from '@vben-core/iconify';
2024-06-01 23:15:29 +08:00
import {
preferences,
resetPreferences,
usePreferences,
} from '@vben-core/preferences';
2024-05-19 21:20:42 +08:00
import {
VbenButton,
VbenIconButton,
VbenSegmented,
VbenSheet,
toast,
} from '@vben-core/shadcn-ui';
import { useClipboard } from '@vueuse/core';
import {
Animation,
Block,
Breadcrumb,
ColorMode,
Content,
Footer,
General,
2024-06-16 13:43:33 +08:00
GlobalShortcutKeys,
2024-05-19 21:20:42 +08:00
Header,
Layout,
Navigation,
Sidebar,
2024-06-09 12:53:38 +08:00
Tabbar,
2024-05-19 21:20:42 +08:00
Theme,
ThemeColor,
} from './blocks';
import Trigger from './trigger.vue';
2024-06-01 23:15:29 +08:00
import { useOpenPreferences } from './use-open-preferences';
2024-05-19 21:20:42 +08:00
withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
colorPrimaryPresets: () => [],
});
2024-06-09 12:53:38 +08:00
const appThemeMode = defineModel<ThemeModeType>('appThemeMode');
const appLocale = defineModel<SupportedLanguagesType>('appLocale');
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
2024-06-16 23:17:40 +08:00
const appAiAssistant = defineModel<boolean>('appAiAssistant');
2024-06-09 12:53:38 +08:00
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 transitionEnable = defineModel<boolean>('transitionEnable');
const themeColorPrimary = defineModel<string>('themeColorPrimary');
const sidebarEnable = defineModel<boolean>('sidebarEnable');
2024-06-09 15:39:11 +08:00
const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
const sidebarCollapsedShowTitle = defineModel<boolean>(
'sidebarCollapsedShowTitle',
2024-06-09 12:53:38 +08:00
);
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',
);
2024-05-19 21:20:42 +08:00
const breadcrumbHideOnlyOne = defineModel<boolean>('breadcrumbHideOnlyOne');
2024-06-09 12:53:38 +08:00
const tabbarEnable = defineModel<boolean>('tabbarEnable');
const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
const navigationStyleType = defineModel<NavigationStyleType>(
'navigationStyleType',
);
2024-05-22 22:38:01 +08:00
const navigationSplit = defineModel<boolean>('navigationSplit');
const navigationAccordion = defineModel<boolean>('navigationAccordion');
2024-06-09 12:53:38 +08:00
2024-05-19 21:20:42 +08:00
// const logoVisible = defineModel<boolean>('logoVisible');
2024-06-09 12:53:38 +08:00
const footerEnable = defineModel<boolean>('footerEnable');
2024-05-19 21:20:42 +08:00
const footerFixed = defineModel<boolean>('footerFixed');
2024-06-09 12:53:38 +08:00
const shortcutKeysEnable = defineModel<boolean>('shortcutKeysEnable');
2024-06-16 13:43:33 +08:00
const shortcutKeysGlobalSearch = defineModel<boolean>(
'shortcutKeysGlobalSearch',
);
const shortcutKeysGlobalLogout = defineModel<boolean>(
'shortcutKeysGlobalLogout',
);
const shortcutKeysGlobalPreferences = defineModel<boolean>(
'shortcutKeysGlobalPreferences',
);
2024-06-09 12:53:38 +08:00
2024-05-22 22:38:01 +08:00
const {
diffPreference,
isFullContent,
isHeaderNav,
isMixedNav,
isSideMixedNav,
isSideMode,
isSideNav,
2024-06-01 23:15:29 +08:00
} = usePreferences();
2024-05-19 21:20:42 +08:00
const { copy } = useClipboard();
const tabs = computed((): SegmentedItem[] => {
return [
2024-06-16 15:45:15 +08:00
{
label: $t('preferences.general'),
value: 'general',
},
2024-05-19 21:20:42 +08:00
{
2024-06-16 13:43:33 +08:00
label: $t('preferences.appearance'),
2024-05-19 21:20:42 +08:00
value: 'appearance',
},
{
2024-06-16 13:43:33 +08:00
label: $t('preferences.layout'),
2024-05-19 21:20:42 +08:00
value: 'layout',
},
2024-06-16 15:45:15 +08:00
2024-06-16 13:43:33 +08:00
{
label: $t('preferences.shortcut-keys.title'),
value: 'shortcutKey',
},
2024-05-19 21:20:42 +08:00
];
});
const showBreadcrumbConfig = computed(() => {
return (
!isFullContent.value &&
!isMixedNav.value &&
!isHeaderNav.value &&
2024-06-01 23:15:29 +08:00
preferences.header.enable
2024-05-19 21:20:42 +08:00
);
});
2024-06-01 23:15:29 +08:00
const { openPreferences } = useOpenPreferences();
2024-05-19 21:20:42 +08:00
async function handleCopy() {
await copy(JSON.stringify(diffPreference.value, null, 2));
2024-06-16 13:43:33 +08:00
toast($t('preferences.copy-success'));
2024-05-19 21:20:42 +08:00
}
function handleReset() {
if (!diffPreference.value) {
return;
}
2024-06-01 23:15:29 +08:00
resetPreferences();
2024-06-16 13:43:33 +08:00
toast($t('preferences.reset-success'));
2024-05-19 21:20:42 +08:00
}
</script>
<template>
2024-06-16 23:17:40 +08:00
<div class="z-100 fixed right-0 top-1/2">
2024-05-19 21:20:42 +08:00
<VbenSheet
2024-06-01 23:15:29 +08:00
v-model:open="openPreferences"
2024-06-16 13:43:33 +08:00
:description="$t('preferences.preferences-subtitle')"
:title="$t('preferences.preferences')"
2024-05-19 21:20:42 +08:00
>
<template #trigger>
2024-05-24 23:11:03 +08:00
<Trigger />
2024-05-19 21:20:42 +08:00
</template>
<template #extra>
<VbenIconButton
:disabled="!diffPreference"
2024-06-16 13:43:33 +08:00
:tooltip="$t('preferences.reset-tip')"
2024-06-09 13:31:43 +08:00
class="relative"
2024-05-19 21:20:42 +08:00
>
<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>
2024-06-16 15:45:15 +08:00
<div class="p-4 pt-4">
<VbenSegmented :tabs="tabs" default-value="general">
2024-05-19 21:20:42 +08:00
<template #appearance>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.theme')">
2024-06-09 12:53:38 +08:00
<Theme
v-model="appThemeMode"
v-model:app-semi-dark-menu="appSemiDarkMenu"
/>
2024-05-19 21:20:42 +08:00
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.theme-color')">
2024-05-19 21:20:42 +08:00
<ThemeColor
2024-06-09 12:53:38 +08:00
v-model="themeColorPrimary"
2024-05-19 21:20:42 +08:00
:color-primary-presets="colorPrimaryPresets"
/>
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.other')">
2024-05-19 21:20:42 +08:00
<ColorMode
2024-06-09 12:53:38 +08:00
v-model:app-color-gray-mode="appColorGrayMode"
v-model:app-color-weak-mode="appColorWeakMode"
2024-05-19 21:20:42 +08:00
/>
</Block>
</template>
<template #layout>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.layout')">
2024-06-09 12:53:38 +08:00
<Layout v-model="appLayout" />
2024-05-19 21:20:42 +08:00
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.content')">
2024-06-09 12:53:38 +08:00
<Content v-model="appContentCompact" />
2024-05-19 21:20:42 +08:00
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.sidebar')">
2024-05-19 21:20:42 +08:00
<Sidebar
2024-06-09 15:39:11 +08:00
v-model:sidebar-collapsed="sidebarCollapsed"
v-model:sidebar-collapsed-show-title="sidebarCollapsedShowTitle"
2024-06-09 13:31:43 +08:00
v-model:sidebar-enable="sidebarEnable"
2024-05-19 21:20:42 +08:00
:disabled="!isSideMode"
/>
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.header')">
2024-05-19 21:20:42 +08:00
<Header
2024-06-09 12:53:38 +08:00
v-model:headerEnable="headerEnable"
2024-05-19 21:20:42 +08:00
v-model:headerMode="headerMode"
:disabled="isFullContent"
/>
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.navigation-menu')">
2024-05-22 22:38:01 +08:00
<Navigation
v-model:navigation-accordion="navigationAccordion"
2024-06-09 13:31:43 +08:00
v-model:navigation-split="navigationSplit"
v-model:navigation-style-type="navigationStyleType"
2024-05-22 22:38:01 +08:00
:disabled="isFullContent"
:disabled-navigation-split="!isMixedNav"
/>
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.breadcrumb')">
2024-05-19 21:20:42 +08:00
<Breadcrumb
2024-06-09 12:53:38 +08:00
v-model:breadcrumb-enable="breadcrumbEnable"
2024-06-09 13:31:43 +08:00
v-model:breadcrumb-hide-only-one="breadcrumbHideOnlyOne"
v-model:breadcrumb-show-home="breadcrumbShowHome"
2024-06-09 12:53:38 +08:00
v-model:breadcrumb-show-icon="breadcrumbShowIcon"
v-model:breadcrumb-style-type="breadcrumbStyleType"
2024-05-22 22:38:01 +08:00
:disabled="
!showBreadcrumbConfig || !(isSideNav || isSideMixedNav)
"
2024-05-19 21:20:42 +08:00
/>
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.tabs')">
2024-06-09 12:53:38 +08:00
<Tabbar
v-model:tabbar-enable="tabbarEnable"
v-model:tabbar-show-icon="tabbarShowIcon"
2024-05-19 21:20:42 +08:00
/>
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.footer')">
2024-05-19 21:20:42 +08:00
<Footer
2024-06-09 12:53:38 +08:00
v-model:footer-enable="footerEnable"
2024-05-19 21:20:42 +08:00
v-model:footer-fixed="footerFixed"
/>
</Block>
</template>
<template #general>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.general')">
2024-05-22 22:03:41 +08:00
<General
2024-06-16 23:17:40 +08:00
v-model:app-ai-assistant="appAiAssistant"
2024-06-09 12:53:38 +08:00
v-model:app-dynamic-title="appDynamicTitle"
2024-06-09 13:31:43 +08:00
v-model:app-locale="appLocale"
2024-05-25 20:02:21 +08:00
/>
</Block>
2024-06-16 13:43:33 +08:00
<Block :title="$t('preferences.animation')">
2024-05-25 20:02:21 +08:00
<Animation
2024-06-09 12:53:38 +08:00
v-model:transition-enable="transitionEnable"
2024-06-09 13:31:43 +08:00
v-model:transition-name="transitionName"
v-model:transition-progress="transitionProgress"
2024-05-25 20:02:21 +08:00
/>
</Block>
</template>
2024-06-16 13:43:33 +08:00
<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
"
2024-05-19 21:20:42 +08:00
/>
</Block>
2024-06-16 13:43:33 +08:00
</template>
2024-05-19 21:20:42 +08:00
</VbenSegmented>
</div>
<template #footer>
<VbenButton
2024-06-09 13:31:43 +08:00
:disabled="!diffPreference"
2024-05-19 21:20:42 +08:00
class="mx-6 w-full"
size="sm"
2024-06-09 13:31:43 +08:00
variant="default"
2024-05-19 21:20:42 +08:00
@click="handleCopy"
>
<IcRoundFolderCopy class="mr-2 size-3" />
2024-06-16 13:43:33 +08:00
{{ $t('preferences.copy') }}
2024-05-19 21:20:42 +08:00
</VbenButton>
</template>
</VbenSheet>
</div>
</template>